۱۳۸۷/۱۰/۱۱

بدست آوردن اندازه ViewState‌ يك صفحه ASP.Net


يكي از روش‌هاي معمولي كه براي بدست آوردن اندازه ViewState يك صفحه در ASP.Net بكار مي‌رود، نمايش صفحه، مراجعه به سورس آن و سپس ذخيره مقدار فيلد مخفي ViewState به صورت يك فايل متني و مراجعه به اندازه آن فايل است!
راه بهتري هم وجود دارد كه به شرح زير است:
زمانيكه قرار است ViewState به صفحه اضافه شود، روال رخداد گردان SavePageStateToPersistenceMedium اجرا خواهد شد. نحوه تحريف آن براي بدست آوردن اندازه ViewState به صورت زير است (چند سطر زير را به وب فرم خود اضافه كنيد):

using System;
using System.Diagnostics;
using System.IO;
using System.Web.UI;

protected override void SavePageStateToPersistenceMedium(object state)
{
if (Debugger.IsAttached)
{
using (MemoryStream stream = new MemoryStream())
{
LosFormatter formatter = new LosFormatter();
formatter.Serialize(stream, state);
int size = stream.Capacity / 1024;
if (size > 32)
{
throw new Exception("لطفا به وضعيت ويوو استيت اين صفحه رسيدگي نمائيد");
}
}
}
base.SavePageStateToPersistenceMedium(state);
}

در اينجا اگر در حال ديباگ برنامه باشيد و همچنين حجم ViewState از 32 كيلوبايت بيشتر شد، استثنايي جهت گوشزد گردن اين مطلب به شما، توليد مي‌شود.
اگر علاقمند بوديد كه اين روال را به تمامي صفحات اضافه كنيد مي‌شود يك كلاس جديد ايجاد كرد و اين كلاس را از كلاس استاندارد Page به ارث برد ( براي نمونه public class MyPage : Page ) . سپس همان چند سطر فوق را به آن اضافه نمائيد.
اكنون تغييري كه در كدها بايد صورت گيرد به صورت زير است، براي مثال تبديل:

public partial class WebForm4 : System.Web.UI.Page

به :

public partial class WebForm4 : MyPage


۱۳۸۷/۱۰/۱۰

معرفي افزونه CAT.NET


اخيرا مايكروسافت افزونه‌ رايگاني را براي آناليز امنيتي كدهاي برنامه‌هاي نوشته شده با VS.Net ارائه داده است به نام CAT.Net.
دريافت افزونه 32 بيتي، 64 بيتي

اين افزونه قابليت بررسي كدهاي شما را جهت يافتن خطرات جدي SQL Injection ، XSS و XPath Injection دارد.
نحوه استفاده:
VS.Net خود را ببنديد. در ادامه، پس از نصب، به منوي Tools و گزينه‌ي جديد CAT.NET Code Analysis مراجعه نمائيد.
صفحه‌اي ظاهر خواهد شد كه پس از كليك بر روي دكمه آغاز آناليز آن، كار بررسي امنيتي پروژه را آغاز مي‌كند (شكل زير)




اين افزونه همانند FxCop ، اسمبلي برنامه را آناليز مي‌كند. پس از پايان آناليز،‌ با كليك بر روي هر سطري كه گزارش داده، آن سطر را مي‌توان در پروژه يافت و تغييرات لازم را اعمال نمود.



همچنين پس از پايان كار بررسي، يك فايل xml هم در مسير فايل‌هاي پروژه ايجاد مي‌كند كه در آينده در صورت نياز، توسط همين افزونه قابل گشودن است.

بعلاوه پس از نصب، يك فايل chm هم در دايركتوري آن جهت آشنايي بيشتر با اجزاي مختلف اين افزونه قرار خواهد گرفت.

البته، برنامه هنوز در مراحل آزمايشي به سر مي‌برد. براي مثال پس از نصب در مسير ديگري غير از مسير پيش فرض نصب، پيغام مي‌داد كه فايل‌ها را نمي‌تواند پيدا كند. اگر اين مورد براي شما هم رخ داد، مسيري را كه گزارش مي‌دهد به صورت دستي درست كنيد و فايل‌هاي كانفيگ آن‌را از جايي كه نصب كرده‌ايد به آنجايي كه برنامه به شما گزارش مي‌دهد كپي كنيد تا كار كند!

يا مي‌توان اين افزونه را از طريق خط فرمان هم اجرا كرد (مسير پروژه، اسمبلي آن و مسير نصب cat.net‌ را لازم دارد). به صورت زير:

CATNETCmd /file:"I:\prog\bin\prog.dll" /search:"I:\prog" /report:"I:\prog\report.xsl" /rule:"J:\microsoft\cat.net\Rules"

كه نتيجه حاصل را در فايل xsl نهايي ثبت خواهد نمود.

اگر علاقمند به مطالعه تاريخچه‌ي اين برنامه هستيد به وبلاگ زير مراجعه نمائيد:
مشاهده وبلاگ

۱۳۸۷/۱۰/۰۹

آشنايي با آزمايش واحد (unit testing) در دات نت، قسمت 3


آشنايي با NUnit

NUnit يكي از فريم ورك‌هاي آزمايش واحد سورس باز مخصوص دات نت فريم ورك است. (كلا در دات نت هرجايي ديديد كه N ، به ابتداي برنامه‌اي يا كتابخانه‌اي اضافه شده يعني نمونه منتقل شده از محيط جاوا به دات نت است. براي مثال NHibernate از Hibernate جاوا گرفته شده است و الي آخر)
اين برنامه با سي شارپ نوشته شده است اما تمامي زبان‌هاي دات نتي را پشتيباني مي‌كند (اساسا با زبان نوشته شده كاري ندارد و فايل اسمبلي برنامه را آناليز مي‌كند. بنابراين فرقي نمي‌كند كه در اينجا چه زباني بكار گرفته شده است).

ابتدا NUnit را دريافت نمائيد:
http://nunit.org/index.php?p=download

يك برنامه ساده از نوع console را در VS.net آغاز كنيد.
كلاس MyList را با محتواي زير به پروژه اضافه كنيد:
using System.Collections.Generic;

namespace sample
{
public class MyList
{
public static List<int> GetListOfIntItems(int numberOfItems)
{
List<int> res = new List<int>();

for (int i = 0; i < numberOfItems; i++)
res.Add(i);

return res;
}
}

}

يكبار پروژه را كامپايل كنيد.

اكنون بر روي نام پروژه در قسمت solution explorer كليك راست كرده و گزينه add->new project را انتخاب كنيد. نوع اين پروژه را كه متدهاي آزمايش واحد ما را تشكيل خواهد داد، class library انتخاب كنيد. با نام مثلا TestLibrary (شكل زير).



با توجه به اينكه NUnit ، اسمبلي برنامه (فايل exe يا dll آن‌را) آناليز مي‌كند، بنابراين مي‌توان پروژه تست را جداي از پروژه اصلي ايجاد نمود و مورد استفاده قرار داد.
پس از ايجاد پروژه class library ، بايد ارجاعي از NUnit framework را به آن اضافه كنيم. به محل نصب NUnit مراجعه كرده (پوشه bin آن) و ارجاعي به فايل nunit.framework.dll را به پروژه اضافه نمائيد (شكل زير).



سپس فضاهاي نام مربوطه را به كلاس آزمايش واحد خود اضافه خواهيم كرد:

using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;

اولين نكته‌اي را كه بايد در نظر داشت اين است كه كلاس آزمايش واحد ما بايد Public باشد تا در حين آناليز اسمبلي پروژه توسط NUint، قابل دسترسي و بررسي باشد.
سپس بايد ويژگي جديدي به نام TestFixture را به اين كلاس اضافه كرد.

[TestFixture]
public class TestClass

اين ويژگي به NUnit‌ مي‌گويد كه در اين كلاس به دنبال متدهاي آزمايش واحد بگرد. (در NUnit از attribute ها براي توصيف عملكرد يك متد و همچنين دسترسي runtime به آن‌ها استفاده مي‌شود)
سپس هر متدي كه به عنوان متد آزمايش واحد نوشته مي‌شود، بايد داراي ويژگي Test باشد تا توسط NUnit بررسي گردد:

[Test]
public void TestGetListOfIntItems()

نكته: متد Test ما بايد public‌ و از نوع void باشد و همچنين هيچ پارامتري هم نبايد داشته باشد.

اكنون براي اينكه بتوانيم متد GetListOfIntItems برنامه خود را در پروژه ديگري تست كنيم، بايد ارجاعي را به اسمبلي آن اضافه كنيم. همانند قبل، از منوي project‌ گزينه add reference ، فايل exe برنامه كنسول خود را انتخاب كرده و ارجاعي از آن‌را به پروژه class library اضافه مي‌كنيم. بديهي است امكان اينكه كلاس تست در همان پروژه هم قرار مي‌گرفت وجود داشت و صرفا جهت جداسازي آزمايش از برنامه اصلي اين‌كار صورت گرفت.
پس از اين مقدمات، اكنون متد آزمايش واحد ساده زير را در نظر بگيريد:

[Test]
public void TestGetListOfIntItems()
{
const int count = 5;
List<int> items = sample.MyList.GetListOfIntItems(count);
Assert.That(items.Count,Is.EqualTo(5));
}

قصد داريم بررسي كنيم آيا متد GetListOfIntItems واقعا همان تعداد آيتمي را كه بايد برگرداند، بازگشت مي‌دهد؟ عدد 5 به آن پاس شده است و در ادامه قصد داريم بررسي كنيم، count شيء حاصل (items در اينجا) آيا واقعا مساوي عدد 5 است؟
اگر آن را (سطر مربوط به Assert را) كلمه به كلمه بخواهيم به فارسي ترجمه كنيم به صورت زير خواهد بود:
مي‌خواهيم اثبات كنيم كه count مربوط به شيء items مساوي 5 است.

پس از اضافه كردن متد فوق، پروژه را كامپايل نمائيد.

اكنون برنامه nunit.exe را اجرا كنيد تا NUnit IDE ظاهر شود (در همان دايركتوري bin مسير نصب NUnit قرار دارد).
از منوي File آن يك پروژه جديد را آغاز نموده و آنرا ذخيره كنيد.
سپس از منوي project آن، با استفاده از گزينه add assembly ، فايل dll كتابخانه تست خود را اضافه نمائيد.
احتمالا پس از انجام اين عمليات بلافاصله با خطاي زير مواجه خواهيد شد:

---------------------------
Assembly Not Loaded
---------------------------
System.ApplicationException : Unable to load TestLibrary because it is not located under
the AppBase
----> System.IO.FileNotFoundException : Could not load file or assembly
'TestLibrary' or one of its dependencies. The system cannot find the file specified.
For further information, use the Exception Details menu item.

اين خطا به اين معنا است كه پروژه جديد NUnit بايد دقيقا در همان پوشه خروجي پروژه، جايي كه فايل dll كتابخانه تست ما توليد شده است، ذخيره گردد. پس از افزودن اسمبلي، نماي برنامه NUnit بايد به شكل زير باشد:



همانطور كه ملاحظه مي‌كنيد، NUnit با استفاده از قابليت‌هاي reflection در دات نت، اسمبلي را بارگذاري مي‌كند و تمامي كلاس‌هايي كه داراي ويژگي TestFixture باشند در آن ليست خواهد شد.
اكنون بر روي دكمه run كليك كنيد تا اولين آزمايش ما انجام شود. (شكل زير)



رنگ سبز در اينجا به معناي با موفقيت انجام شدن آزمايش است.

ادامه دارد...

Mirror براي ويديوهاي رايگان جي كوئري


يكي از دوستان در قسمت تماس با من پيغام گذاشته بود كه لينك‌هاي معرفي شده مربوط به آموزش جي كوئري فيلتر است و با فيلتر شكن دانلود كردن هم كند است.
تمام موارد ياد شده به همراه چند مورد ديگر را به اكانت رپيدشير انتقال دادم. دريافت ليست فايل‌ها براي دانلود از رپيدشير.

موفق باشيد!

۱۳۸۷/۱۰/۰۸

آشنايي با آزمايش واحد (unit testing) در دات نت، قسمت 2


دلايل شانه خالي كردن از آزمايش واحد!

1- نوشتن آزمايشات زمان زيادي را به خود اختصاص خواهند داد.

مهمترين دليلي كه برنامه‌نويس‌ها به سبب آن از نوشتن آزمايشات واحد امتناع مي‌كنند، همين موضوع است. اكثر افراد به آزمايش به‌عنوان مرحله آخر توسعه فكر مي‌كنند. اگر اين چنين است، بله! نوشتن آزمايش‌هاي واحد واقعا سخت و زمانگير خواهند بود. به همين جهت براي جلوگيري از اين مساله روش pay-as-you-go مطرح شده است (ماخذ: كتاب Pragmatic Unit Testing در سي شارپ). يعني با اضافه شدن هر واحد كوچكي به سيستم، آزمايش واحد آن‌را نيز تهيه كنيد. به اين صورت در طول توسعه سيستم با باگ‌هاي كمتري نيز برخورد خواهيد داشت چون اجزاي آن‌را در اين حين به تفصيل مورد بررسي قرار داده‌ايد. اثر اين روش را در شكل زير مي‌توانيد ملاحظه نمائيد (تصويري از همان كتاب ذكر شده)




نوشتن آزمايشات واحد زمانبر هستند اما توسعه پيوسته آن‌ها با به تاخير انداختن آزمايشات به انتهاي پروژه، همانند تصوير فوق تاثير بسيار قابل توجهي در بهره وري شما خواهند داشت.

بنابراين اگر عنوان مي‌كنيد كه وقت نداريد آزمايش واحد بنويسيد، به چند سؤال زير پاسخ دهيد:
الف) چه مقدار زمان را صرف ديباگ كردن كدهاي خود يا ديگران مي‌كنيد؟
ب) چه ميزان زمان را صرف بازنويسي كدي كرده‌ايد كه تصور مي‌رفت درست كار مي‌كند اما اكنون بسيار مشكل زا ظاهر شده است؟
ج) چه مقدار زمان را صرف اين كرده‌ايد كه منشاء باگ گزارش شده در برنامه را كشف كنيد؟

براي افرادي كه آزمايشات واحد را در حين پروسه توسعه در نظر نمي‌گيرند، اين مقادير بالا است و با ازدياد تعداد خطوط سورس كدها، اين ارقام سير صعودي خواهند داشت.



تصويري از كتاب xUnit Test Patterns ، كه بيانگر كاهش زمان و هزينه كد نويسي در طول زمان با رعايت اصول آزمايشات واحد است

2- اجراي آزمايشات واحد زمان زيادي را تلف مي‌كند.

نبايد اينطور باشد. عموما اجراي هزاران آزمايش واحد، بايد در كسري از ثانيه صورت گيرد. (براي اطلاعات بيشتر به قسمت حد و مرز يك آزمايش واحد در قسمت قبل مراجعه نمائيد)

3- امكان تهيه آزمايشات واحد براي كدهاي قديمي ( legacy code ) من وجود ندارد

براي بسياري از برنامه نويس‌ها، تهيه آزمايش واحد براي كدهاي قديمي بسيار مشكل است زيرا شكستن آن‌ها به واحدهاي كوچكتر قابل آزمايش بسيار خطرناك و پرهزينه است و ممكن است سبب از كار افتادن سيستم آن‌ها گردد. اينجا مشكل از آزمايش واحد نيست. مشكل از ضعف برنامه نويسي آن سيستم است. روش refactoring ، طراحي مجدد و نوشتن آزمايشات واحد، به تدريج سبب طراحي بهتر برنامه از ديدگاه‌هاي شيءگرايي شده و نگهداري سيستم را در طولاني مدت ساده‌تر مي‌سازد. آزمايشات واحد اين نوع سيستم‌ها را از حالت فلج بودن خارج مي‌سازد.

4- كار من نيست كه كدهاي نوشته شده را آزمايش كنم!

بايد درنظر داشته باشيد كه اين هم كار شما نيست كه انبوهي از كدهاي مشكل دار را به واحد بررسي كننده آن تحويل دهيد! همچنين اگر تيم آزمايشات و كنترل كيفيت به اين نتيجه برسد كه عموما از كدهاي شما كمتر مي‌توان باگ گرفت، اين امر سبب معروفيت و تضمين شغلي شما خواهد شد.
همچنين اين كار شما است كه تضمين كنيد واحد تهيه شده مقصود مورد نظر را ارائه مي‌دهد و اين‌كار را با ارائه يك يا چندين آزمايش واحد مي‌توان اثبات كرد.

5- تنها قسمتي از سيستم به من واگذار شده است و من دقيقا نمي‌دانم كه رفتار كلي آن چيست. بنابراين آن را نمي‌توانم آزمايش كنم!

اگر واقعا نمي‌دانيد كه اين كد قرار است چه كاري را انجام دهيد به طور قطع الان زمان مناسبي براي كد نويسي آن نيست!

6- كد من كامپايل مي‌شود!

بايد دقت داشت كه كامپايلر فقط syntax كدهاي شما را بررسي كرده و خطاهاي آن‌را گوشزد مي‌كند و نه نحوه‌ي عملكرد آن‌را.

7- من براي نوشتن آزمايشات حقوق نمي‌گيرم!

بايد اذعان داشت كه به شما جهت صرف تمام وقت يك روز خود براي ديباگ كردن يك خطا هم حقوق نمي‌دهند! شما براي تهيه يك كد قابل قبول و قابل اجرا حقوق مي‌گيريد و آزمايش واحد نيز ابزاري است جهت نيل به اين مقصود (همانند يك IDE و يا يك كامپايلر).

8- احساس گناه خواهم كرد اگر تيم فني كنترل كيفيت و آزمايشات را از كار بي كار كنم!!

نگران نباشيد، اين اتفاق نخواهد افتاد! بحث ما در اينجا آزمايش كوچكترين اجزا و واحدهاي يك سيستم است. موارد ديگري مانند functional testing, acceptance testing, performance & environmental testing, validation & verification, formal analysis توسط تيم‌هاي كنترل كيفيت و آزمايشات هنوز بايد بررسي شوند.

9- شركت من اجازه اجراي آزمايشات واحد را بر روي سيستم‌هاي در حال اجرا نمي‌دهد.

قرار هم نيست بدهد! چون ديگر نام آن آزمايش واحد نخواهد بود. اين آزمايشات بايد بر روي سيستم شما و توسط ابزار و امكانات شما صورت گيرد.


پ.ن.
در هشتمين دليل ذكر شده، از acceptance testing نامبرده شده. تفاوت آن با unit testing به صورت زير است:

آزمايش واحد:
توسط برنامه نويس‌ها تعريف مي‌شود
سبب اطمينان خاطر برنامه نويس‌ها خواهد شد
واحدهاي كوچك سيستم را مورد بررسي قرار مي‌دهد
يك آزمايش سطح پائين ( low level ) به شمار مي‌رود
بسيار سريع اجرا مي‌شود
به صورت خودكار (100 درصد خودكار است) و با برنامه نويسي قابل كنترل است

اما در مقابل آزمايش پذيرش به صورت زير است:
توسط مصرف كنندگان تعريف مي‌شود
سبب اطمينان خاطر مصرف كنندگان مي‌شود.
كل برنامه مورد آزمايش قرار مي‌گيرد
يك آزمايش سطح بالا ( high level ) به شمار مي‌رود
ممكن است طولاني باشد
عموما به صورت دستي يا توسط يك سري اسكريپت اجرا مي‌شود
مثال : گزارش ماهيانه بايد جمع صحيحي از تمام صفحات را در آخرين برگه گزارش به همراه داشته باشد


ادامه دارد...

دايركتوري‌هاي لينك در ايران


يك سري از سايت‌هاي ايراني كه در ادامه ليست خواهند شد، نقش خوب و فعالي را در زمينه دايركتوري لينك ايفا كرده‌اند كه جاي تقدير دارد.
من فعلا اين‌ها رو مي‌شناسم، شايد موارد ديگري هم باشند:

سايت مهندس:
http://www.mohand.es
بيشتر در زمينه مباحث علوم و تكنولوژي فعال است.

سايت بالاترين:
https://balatarin.com
اگر علاقمند باشيد كه خلاصه‌ي يك روز وبلاگ‌هاي ايراني را كه در زمينه مسايل اجتماعي (و غيره!) فعاليت مي‌كنند، مطالعه كنيد، اين سايت در صدر قرار دارد.

سايت سي لينك:
http://www.30link.com/
شبيه به بالاترين كه كمتر سياسي است و بيشتر اجتماعي

سايت دنباله:
http://donbaleh.com
شبيه به سايت بالاترين

سايت oyax :
http://www.oyax.com/
كه اين روزها به نظر به دليل نظارت ناكافي، پر از اسپم و لينك‌هاي تبليغاتي شده!

لطفا اگر موارد ديگري را سراغ داريد، لينك‌ آن‌ها را به صورت كامنت قرار دهيد.
با سپاس

۱۳۸۷/۱۰/۰۷

آشنايي با آزمايش واحد (unit testing) در دات نت، قسمت 1


آزمايش واحد چيست؟

آزمايش واحد (unit testing) هنر و تمرين بررسي صحت عملكرد قطعه‌اي از كد (كه در اينجا واحد ناميده شده است)، به وسيله كدهاي ديگري است كه توسط برنامه نويس نوشته خواهند شد. عموما اين آزمايش‌ها جهت بررسي يك متد تهيه مي‌شوند. در اين مرحله بايد درنظر داشت كه هدف، بررسي كارآيي نرم افزار نيست. هدف اين است كه بررسي كنيم آيا قطعه كد جديدي كه به برنامه اضافه شده است درست كار مي‌كند و آيا هدف اصلي از توسعه آن‌را برآورده مي‌سازد؟
براي مثال متدي را توسعه داده‌ايد كه آدرس يك دومين را از آدرس اينترنتي دريافت شده، جدا مي‌سازد. با استفاده از آزمايشات واحد متعدد مي‌توان از صحت عملكرد آن اطمينان حاصل كرد.


اهميت و مزاياي آزمايش واحد كدامند؟

  • كامپايل شدن كد به معناي صحت عملكرد آن نيست. حتما نياز به روش‌هايي براي آزمايش سيستم وجود دارد. صرفا به شما حقوق داده نمي‌شود كه كد بنويسيد. به شما حقوق داده مي‌شود كه كد قابل اجرايي را تهيه كنيد.
  • نوشتن آزمايش‌هاي واحد به توليد كدهايي با كيفيت بالا در دراز مدت منجر خواهد شد. براي نمونه فرض كنيد سيستمي را توسعه داده‌ايد. امروز كارفرما از شما خواسته است كه قابليت جديدي را به برنامه اضافه كنيد. براي اعمال اين تغييرات براي مثال نياز است تا قسمتي از كدهاي موجود تغيير كند، همچنين كلاس‌ها و متدهاي جديدي نيز به برنامه افزوده گردند. پس از انجام درخواست رسيده، چگونه مي‌توانيد اطمينان حاصل كنيد كه قسمت‌هاي پيشين سيستم كه تا همين چند لحظه پيش كار مي‌كردند، اكنون نيز همانند قبل كار مي‌كنند؟ حجم كدهاي نوشته شده بالا است. آزمايش دستي تك تك موارد شايد ديگر از لحاظ زماني مقدور نباشد. آزمايش واحد روشي است براي اطمينان حاصل كردن از اينكه هنگام تحويل كار به كارفرما مرتبا سرخ و سفيد نشويم! به اين صورت عمليات refactoring كدهاي موجود بدون ترس و لرز انجام خواهد شد، چون بلافاصله مي‌توانيم آزمايشات قبلي را اجرا كرده و از صحت عملكرد سيستم اطمينان حاصل نمائيم. بدون اينكه در زمان تحويل برنامه در هنگام بروز خطا بگوئيم : "اين غيرممكنه!"
  • روال‌هاي آزمايشات صورت گرفته در آينده تبديل به مرجع مهمي جهت درك چگونگي عملكرد قسمت‌هاي مختلف سيستم خواهند شد. چگونه فراخواني شده‌اند، چگونه بايد به آن‌ها مقداري را ارجاع داد و امثال آن.
  • با استفاده از آزمايش‌هاي واحد، بدترين حالات ممكن را قبل از وقوع مي‌توان در نظر گرفت و بررسي كرد.
  • نوشتن آزمايش‌هاي واحد در حين كار، برنامه نويس را وادار مي‌كند كه كار خود را به واحدهاي كوچكتري كه قابليت بررسي مستقلي دارند، بشكند. براي مثال فرض كنيد متدي را توسعه داده‌ايد كه پس از انجام سه عمليات مختلف بر روي يك رشته، خروجي خاصي را ارائه مي‌دهد. هنگام آزمايش اين متد چگونه مي‌توان اطمينان حاصل كرد كه كدام قسمت سبب شكست آزمايش شده است؟ به همين جهت برنامه نويس جهت ساده‌تر كردن آزمايشات، مجبور خواهد شد كه كد خود را به قسمت‌هاي مستقل كوچكتري تقسيم كند.
  • با توجه به امكان اجراي خودكار اين آزمايشات، به عنوان جزئي ايده‌آل از پروسه توليد نرم افزار محسوب مي‌شوند.


حد و مرز يك آزمايش واحد كجاست؟

آزمايش شما، آزمايش واحد ناميده نخواهد شد اگر:
  • با ديتابيس سر و كار داشته باشد.
  • با شبكه در ارتباط باشد.
  • با فايل‌ها كار كند.
  • نياز به تمهيدات ويژه‌اي براي اجراي آن وجود داشته باشد. مثلا وجود يك فايل config براي اجراي آن ضروري باشد.
  • همراه و همزمان با ساير كدهاي آزمايش‌هاي واحد شما قابل اجرا نباشد.
براي مثال اگر يكي از متدهاي شما بزرگترين عدد يك ليست را از ديتابيس دريافت مي‌كند، در متدي كه براي آزمايش واحد آن تهيه خواهيد كرد نبايد هيچگونه كدي جهت برقراري ارتباط با ديتابيس نوشته شود.
اين امر سبب سريع‌تر اجرا شدن آزمايشات واحد خواهند شد و در آينده شما را از انجام آن به‌دليل كند بودن روند انجام آزمايشات، منصرف نخواهد كرد. همچنين تغييرات انجام شده در لايه دسترسي به داده‌ها سبب غيرمعتبر شدن اين نوع آزمايشات نخواهند شد. به بيان ديگر وظيفه متد آزمايش واحد، اتصال به ديتابيس يا شبكه و يا خواندن اطلاعات از يك فايل نيست.

ادامه دارد...

۱۳۸۷/۱۰/۰۶

ويديوهاي رايگان آموزش jQuery


آموزش مقدماتي jQuery

روز 1 : مشاهده سايت اصلي، دريافت
Day 1: Downloading the Library

روز 2 : مشاهده سايت اصلي، دريافت
Day 2: Fade, Slide, and Show Methods

روز 3 : مشاهده سايت اصلي، دريافت
Day 3: The Animate Method

روز 4 : مشاهده سايت اصلي، دريافت
Day 4: Advanced Selectors

روز 5 : مشاهده سايت اصلي، دريافت
Day 5: Creating and Removing Elements

روز 6 : مشاهده سايت اصلي، دريافت
Day 6: The toggle() and toggleClass() Methods

روز 7 : مشاهده سايت اصلي، دريافت
Day 7: The hover() Methods

روز 8 : مشاهده سايت اصلي، دريافت
Day 8: User Request - Image Slides

روز 9 : مشاهده سايت اصلي، دريافت
Day 9: Resizing Text

روز 10 : مشاهده سايت اصلي، دريافت
Day 10: Intro to AJAX: Using the Load Method

روز 11 : مشاهده سايت اصلي، دريافت
Day 11: Fun Image Hovering

روز 12 : مشاهده سايت اصلي، دريافت
Day 12: Advanced Tooltips: Part 1

روز 13 : مشاهده سايت اصلي، دريافت
Day 13: Submitting Information to a Database Asynchronously

۱۳۸۷/۱۰/۰۵

لينك‌هاي هفته اول دي


وبلاگ‌ها و سايت‌هاي ايراني

امنيت



ASP. Net


طراحي وب

PHP


اس‌كيوال سرور


سي شارپ


عمومي دات نت


مسايل اجتماعي و انساني برنامه نويسي


كتاب‌هاي رايگان جديد


متفرقه
  • آهن بجاي كروم! (يك برنامه نويس آلماني قسمت‌هايي از مرورگر كروم را كه در جهت جمع آوري اطلاعات براي گوگل بكار مي‌رفته، حذف كرده و مرورگر ديگري به نام آهن را ارائه داده است!)

۱۳۸۷/۱۰/۰۴

نحوه راه اندازي مجدد يك ديتابيس اس كيوال سرور پس از پر شدن هارد ديسك


امروز يكي از برنامه‌ها (برنامه ASP.Net) با مشكل زير مواجه شده بود:

پيغام خطا:
اتصال با سرور اس كيوال قطع شده است. لطفا با مسئول مربوطه هماهنگ نمائيد.
SQLErr:4060

اين خطا به معناي عدم امكان باز كردن ديتابيس است.

در طي اين مدت با موارد زيادي از اين دست (مشكلات مختلف عدم امكان برقراري ارتباط با اس كيوال سرور) برخورد داشتم كه خلاصه تمام آن‌ها تابع زير شده است:
public void CheckSQLServerStat(Exception ex)
{
try
{
SqlException ar = (SqlException) ex;
switch (ar.Number)
{
case 2:
case 11:
case 17:
case 40:
case 4060:
case 1326:
case 17142:
case 18456:
HttpContext.Current.Response.Write("<br/>" + "اتصال با سرور اس كيوال قطع شده است. لطفا با مسئول مربوطه هماهنگ نمائيد." + "<br/> SQLErr:" + ar.Number + "<br/>");
break;
}
}catch{}
}

هنگام رخ‌دادن يك خطا (در توابعي كه با اس كيوال سرور كار مي‌كنند)، exception حاصل را به اين تابع پاس كرده و خطاي حاصل را به صورت مختصر و مفيد به كاربر نشان مي‌دهم. كاربر متوجه مي‌شود كه يك مشكل اساسي در سيستم رخ داده است. برنامه نويس هم با جستجو در مورد شماره خطا مي‌تواند مشكل يابي كند. تابع Response.Write هم بالاتر از هر المان ديگري در صفحه، اين خطا را به شكل واضحي نمايش مي‌دهد. (كلا ريخت صفحه را به هم مي‌ريزد كه از لحاظ رواني لازم است! چون عملا در اين حالت سيستم از كار افتاده است)

به management studio اس كيوال سرور كه مراجعه كردم، علامت خاصي كنار نام ديتابيس نبود فقط برخلاف ساير ديتابيس‌ها كه آيكون + مربوط به باز شدن tree آن وجود دارد، اين يك مورد آن‌را نداشت. بر روي نام ديتابيس كليك راست كردم و انتخاب خواص، خطاي زير نمايش داده شد:
------------------------------
An exception occurred while executing a Transact-SQL statement or batch. (Microsoft.SqlServer.ConnectionInfo)
------------------------------
Database 'dbName' cannot be opened due to inaccessible files or insufficient memory or disk space. See the SQL Server errorlog for details. (Microsoft SQL Server, Error: 945)
------------------------------

بله! ديتابيس قابل باز شدن نبود چون درايو مربوطه پر شده بود. بعد از خالي كردن درايو و باز كردن فضاي لازم، باز هم ديتابيس به حالت اجرايي و قابل استفاده برنگشت. يك راه اين است كه كل سرويس مربوط به اس كيوال سرور را استاپ و استارت كرد. كه البته اين مورد سبب قطع ارتباط كل مجموعه مي‌شود. يا راه ديگر اجراي چند سطر زير است كه ديتابيس را مجددا راه اندازي خواهد كرد (بدون نياز به ري استارت سرويس)

use master;
alter database dbName set OFFLINE;
alter database dbName set online;

به اين صورت ديتابيس مربوطه به حالت عادي بازگشت و قابل استفاده شد.

۱۳۸۷/۱۰/۰۳

چگونه يك اسكريپت گريس مانكي بنويسيم؟


گريس مانكي يكي از افزونه‌هاي فايرفاكس است كه توسط آن مي‌توان اسكريپت‌هايي را بر روي صفحات وب در حال مشاهده، جهت تغيير آن‌ها اجرا كرد. اين نوع تغييرات بيشتر در جهت بالا بردن كارآيي يا خوانايي سايت‌ها صورت مي‌گيرد. مثلا بررسي وجود لينك‌هاي ارائه شده در يك صفحه وب (قبل از اينكه به آن‌ها رجوع كنيم، مشخص شود كه آيا وجود دارند يا خير) و هزاران مثال شبيه به اين كه در سايت اسكريپت‌هاي آن قابل دريافت هستند.
گريس مانكي به خودي خود كار خاصي را انجام نمي‌دهد و فقط ميزبان اجرايي اسكريپت‌هايي است كه براي آن تهيه شده اند. به اين اسكريپت‌ها user scripts گفته مي‌شود و جهت تهيه آن‌ها از زبان جاوا اسكريپت استفاده مي‌گردد.
مطابق اصول نامگذاري آن، فايل اين اسكريپت‌ها حتما بايد به .user.js ختم شود تا توسط افزونه گريس مانكي قابل شناسايي باشد.

اسكريپت سلام دنياي گريس مانكي!
// ==UserScript==
// @name Hello World
// @namespace http://diveintogreasemonkey.org/download/
// @description example script to alert "Hello world!" on every page
// @include *
// @exclude http://diveintogreasemonkey.org/*
// @exclude http://www.diveintogreasemonkey.org/*
// ==/UserScript==
alert('Hello world!');

فرمت كلي و آناتومي يك اسكريپت گريس مانكي مطابق چند سطر فوق است. در ابتدا نامي را كه براي اسكريپت مشخص كرده‌ايد، ذكر خواهيد نمود. سپس فضاي نام آن مشخص مي‌گردد. اين فضاي نام يك آدرس وب خواهد بود (مثلا سايت شخصي شما) . به اين طريق گريس مانكي مي‌تواند اسكريپت‌هاي هم نام را بر اساس اين فضاهاي نام مختلف مديريت كند. سپس توضيحات مربوط به اسكريپت ارائه مي‌شود. در قسمت include مشخص خواهيد كرد كه اين اسكريپت بر روي چه سايت‌ها و آدرس‌هايي اجرا شود و در قسمت exclude سايت‌هاي صرفنظر شونده را تعيين خواهيد نمود. در مثال فوق، اسكريپت بر روي تمامي سايت‌ها اجرا خواهد شد، منهاي دو سايت و زير سايت‌هايي كه در قسمت exclude مشخص شده‌اند.
در پايان مثلا نام آن‌را hello.user.js خواهيم گذاشت (همانطور كه ذكر شد قسمت user.js آن بايد رعايت شود). براي نصب آن فقط كافي است اين فايل را به درون پنجره فاير فاكس كشيده و رها كنيم (drag & drop).

استفاده از jQuery در اسكريپت‌هاي گريس مانكي

عمده كاربردهاي اسكريپت‌هاي گريس مانكي در جهت اعمال تغييرات بر روي document object model صفحه (DOM) هستند. كتابخانه jQuery اساسا براي اين منظور تهيه و بهينه سازي شده است.

مثال:
فرض كنيد قصد داريم به نتايج خروجي جستجوي گوگل، fav icon سايت‌هاي يافت شده را اضافه كنيم (در كنار هر لينك، آيكون سايت مربوطه را نمايش دهيم). گوگل اين‌كار را انجام نداده است. اما ما علاقمند هستيم كه اين قابليت را اضافه كنيم!
// ==UserScript==
// @name Google FavIcon
// @namespace http://userscripts.org
// @description Shows favicon for Google searches results
// @include http://*.google.*/search?*

// ==/UserScript==

loadJquery();

$(document).ready(function(){
$("h3.r > a.l").each(function(){
var $a = $(this);
var href = $a.attr("href");
var domain = href.replace(/<\S[^><]*>/g, "").split('/')[2];
var image = '<img src="http://' + domain + '/favicon.ico" style="border:0;padding-right:4px;" />';
//GM_log(">image:> " + image);
$(this).prepend(image);
});

});

نحوه پياده سازي تابع loadJquery را در سورس مربوطه مي‌توانيد مشاهده نمائيد.
دريافت سورس اين مثال

در اينجا ابتدا لينك‌هاي حاصل از جستجو پيدا مي‌شوند. سپس نام دومين مربوطه استخراج مي‌گردد (با استفاده از regular expressions) و در ادامه از اين نام دومين يك آدرس استاندارد http://domain/favico.ico ساخته شده و از آن يك تگ img درست مي‌شود. در آخر اين تگ به قبل از لينك‌هاي گوگل اضافه مي‌شود.

شايد سؤال بپرسيد از كجا مشخص شد كه بايد به دنبال h3.r > a.l گشت؟ به تصوير زير دقت نمائيد (نمايي است از يكي از توانايي‌هاي افزونه fireBug فايرفاكس).



هنگاميكه صفحه بارگذاري شد، بر روي آيكون سوسك موجود در status bar فايرفاكس كليك كنيد تا FireBug ظاهر شود (البته من اينجا سوسك ديدم شايد موجود ديگري باشد :) )
سپس بر روي دكمه inspect در نوار ابزار آن كليك كنيد. در همين حال اشاره‌گر ماوس را به يكي از لينك‌هاي نتيجه جستجوي گوگل نزديك كنيد. بلافاصله تگ‌ها و كلاس‌هاي مورد استفاده آن به شكل زيبايي ظاهر خواهند شد. به اين صورت صرفه جويي قابل ملاحظه‌اي در وقت صورت خواهد گرفت.

نتيجه اجراي اسكريپت فوق (پس از نصب) به صورت زير است:



نكته: نحوه ديباگ كردن اسكريپت‌هاي گريس مانكي

اگر نياز به مشاهده مقدار متغيرها در لحظه اجراي اسكريپت داشتيد، يكي از راه‌حل‌هاي موجود استفاده از تابع GM_log مربوط به API گريس مانكي است كه خروجي آن‌را در قسمت messages مربوط به error console فايرفاكس مي‌توان ديد.



۱۳۸۷/۱۰/۰۲

جمع آوري آمار لينك‌هاي خروجي از سايت توسط Google analytics


چندي قبل مطلب كوتاهي را در مورد Google analytics نوشتم. در حين جستجو درباره‌ي jQuery در وب، به نحوه رديابي لينك‌هاي خروجي از سايت توسط Google analytics برخوردم كه نحوه پياده سازي آن به صورت زير است.
بديهي است قبل از هر كاري بايد اسكريپت مربوط به Google analytics را به انتهاي صفحه و جايي كه تگ body بسته مي‌شود اضافه كنيد (قابل دريافت درقسمت Add Website Profile . شماره اين اسكريپت براي هر پروفايلي كه ايجاد مي‌كنيد متفاوت است).
سپس:
الف) افزودن ارجاعي از كتابخانه jQuery به هدر صفحه كه آن‌را در مطلب شمسي كردن تاريخ بلاگر ملاحظه كرديد.
ب) افزودن چند سطر زير به هدر صفحه
<script type="text/javascript">
$(document).ready(function() {
$("a").click(function() {
var $a = $(this);
var href = $a.attr("href");

// see if the link is external
if ( (href.match(/^http/)) && (! href.match(document.domain)) ) {

// if so, register an event
var category = "outgoing";
var event = "click";
var label = href;

pageTracker._trackPageview('/outgoing/' + href);
pageTracker._trackEvent(category, event, href);
}
});
});
</script>

البته اگر قبلا اسكريپت شمسي كردن تاريخ بلاگر را اضافه كرده بوديد فقط محتويات تابع document.ready را بايد اضافه كنيد (جهت مشاهده نمونه اعمال شده، روي صفحه جاري كليك راست كنيد و سورس صفحه را مشاهده نمائيد).

توضيحاتي در مورد كد فوق:
اين اسكريپت به روال رخ داد گردان onclick هر لينكي كه به خارج از سايت ختم مي‌شود (مثلا لينك به يك فايل يا يك سايت خارجي (خارج از سايت))، به صورت خودكار تابع trackPageview مربوط به Google analytics را اضافه مي‌كند. اين كار تاثيري در عملكرد سايت ندارد و كاربر چيزي را متوجه نخواهد شد، اما به اين طريق لينك‌هاي خروجي در آمار Google analytics ظاهر مي‌شوند (مطابق تصاوير زير).





از اين پس آمار تمام لينك‌هاي خروجي از سايت ، متمايز شده با outgoing ، جمع آوري و نمايش داده خواهند شد.

امكانات بيشتري مانند event tracking نيز قرار است به Google analytics اضافه شود كه هنوز در مرحله آزمايشي است و بر روي تمامي اكانت‌ها فعال نشده است.

۱۳۸۷/۱۰/۰۱

تشخيص غيرفعال بودن JavaScript در مرورگر كاربر


اكثر كنترل‌هاي تعيين اعتبار ASP.Net بر اساس جاوا اسكريپت كار مي‌كنند (مانند RangeValidator و امثال آن). حال اگر كاربري افزونه no script فايرفاكس را نصب كرده بود چه بايد كرد؟
با استفاده از اين افزونه، اين نوع كنترل‌ها از كار خواهند افتاد (چون ديگر كدهاي جاوا اسكريپتي آنها اجرا نخواهند شد).
خوشبختانه براي بررسي صحت عملكرد اين كنترل‌ها در ASP.Net امكان بررسي خاصيت Page.IsValid نيز وجود دارد كه در ادامه به آن خواهيم پرداخت.

صفحه‌ي بسيار ساده ASP.Net زير را در نظر بگيريد:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm3.aspx.cs" Inherits="testWebForms87.WebForm3" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="txtData" runat="server"></asp:TextBox>
<asp:RangeValidator ID="RangeValidator1" runat="server" ControlToValidate="txtData"
ErrorMessage="لطفا يك عدد وارد كنيد" MaximumValue="100000" MinimumValue="0" SetFocusOnError="True"
Type="Integer"></asp:RangeValidator>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="txtData"
ErrorMessage="لطفا مقداري را وارد نمائيد" SetFocusOnError="True"></asp:RequiredFieldValidator>
<br />
<asp:Button ID="btnSubmit" runat="server" OnClick="btnSubmit_Click" Text="Submit" />
<br />
<asp:Label ID="lblValue" runat="server"></asp:Label>
</div>
</form>
</body>
</html>

يكبار اين صفحه را با فعال كردن افزونه ياد شده بررسي كنيد.
سپس براي بررسي سمت سرور عملكرد كنترل‌هاي تعيين اعتبار در ASP.Net مي‌توان به صورت زير عملكرد:

        protected void btnSubmit_Click(object sender, EventArgs e)
{
if (btnSubmit.CausesValidation)
{
// Validate the Page
Page.Validate();

// Ensure Page is Valid
if (!Page.IsValid)
{
lblValue.Text = "لطفا جاوا اسكريپت را در مرورگر خود فعال نمائيد";
return;
}
}

lblValue.Text = txtData.Text;
}

ابتدا بررسي مي‌شود كه آيا دكمه مورد استفاده جهت ارسال مقادير صفحه به سرور سبب فعال شدن كنترل‌هاي تعيين اعتبار مي‌شود؟ اگر اينطور بود، سپس صفحه تعيين اعتبار شده و با استفاده از مقدار خاصيت Page.IsValid مشخص مي‌شود كه آيا اين عمليات به درستي صورت گرفته است يا خير.

راه ديگر بررسي غيرفعال بودن جاوا اسكريپت در يك صفحه استفاده از روش سنتي تگ noscript است:

<noscript>
<meta http-equiv="refresh" content="0;url=http://www.google.com">
</noscript>

در اين مثال اگر جاوا اسكريپت غيرفعال باشد كاربر به گوگل هدايت خواهد شد. البته بهتر است يك صفحه‌ي خطاي از پيش تعيين شده براي اين مورد در نظر گرفته شود.

در پايان بايد خاطر نشان كرد كه هيچگاه به كنترل‌هاي تعيين اعتبار سمت كاربر اطمينان نكنيد و حتما يا از روش فوق استفاده نمائيد، يا در روال submit صفحه به سرور، يكبار ديگر داده‌ها را به صورت دستي نيز بررسي كنيد. براي مثال اگر كاربر قرار است آدرس ايميلي را وارد كند، حتما يكبار ديگر با استفاده از regular expressions ، در سمت سرور نيز عبارت ورودي را بررسي كنيد.

۱۳۸۷/۰۹/۳۰

به روز رساني View ها و رويه‌هاي ذخيره شده در SQL server


يكي ديگر از معايب كوئري‌هاي select * در SQL server اين است كه تغييرات حاصل در فيلدهاي جداول يك بانك اطلاعاتي را در view هاي ساخته شده از اين نوع كوئري‌ها منعكس نمي‌كند.
براي مثال جدول tblTreeItems را با سه فيلد id ، parent و title در نظر بگيريد. فرض كنيد بر اين اساس view زير را ساخته‌ايم:

CREATE VIEW GetData
as
SELECT * FROM tblTreeItems

اكنون به جدول فوق ، فيلد جديد isActive را اضافه مي‌كنيم. پس از اين عمليات اگر كوئري ساده SELECT * FROM GetData را اجرا كنيم، فيلد جديد isActive را در آن نخواهيم ديد (برخلاف انتظار كه مي‌بايست كوئري select * ركوردهاي تمام فيلدهاي جدول را بر مي‌گرداند. در اين‌جا ممكن است مدتي وقت صرف ديباگ كردن سيستم شود كه چرا تغييرات جديد اعمال نشده و چرا سيستمي كه تا چند لحظه پيش داشت كار مي‌كرد الان از كار افتاد!).
بايد در نظر داشت كه هنگام ايجاد يك view ، تصويري از تمامي فيلدهاي مورد استفاده در آن زمان، جهت بالابردن كارآيي كوئري و عدم محاسبه مجدد فيلدها در جداول سيستمي ذخيره مي‌گردد ( * با نام فيلدهاي همان زمان ايجاد (نه زمان فعلي)، جايگزين خواهد شد). اين تصوير ايستا است و با تغيير فيلدهاي يك جدول به روز نخواهد شد.
براي به روز كردن view ها و stored procedures پس از تغييرات ساختاري در جداول، بايد مجددا آنها را كامپايل كرد. براي اين منظور راه‌هاي زيادي وجود دارد، براي مثال drop كردن يك view و ايجاد مجدد آن. يا باز كردن آن view در management studio (حالت alter query) و سپس فشردن دكمه F5 جهت اجراي مجدد كوئري كه اين‌بار بر اساس اطلاعات جديد به روز خواهد شد. يا استفاده از رويه‌هاي سيستمي sp_refreshview و sp_recompile كه براي كامپايل مجدد view ها و رويه‌هاي ذخيره شده بكار مي‌روند.

براي مديريت ساده‌تر اين موارد ، اسكريپت زير تمامي view ها و رويه‌هاي ذخيره شده يك ديتابيس را به صورت خودكار يافته و آنها را مجددا كامپايل مي‌كند: (جهت مشاهده آن نياز به ثبت نام دارد و رايگان است)
Refreshing Views and Recompiling Stored Procs

۱۳۸۷/۰۹/۲۹

اسكريپت گريس مانكي براي تاريخ فارسي بلاگر و ايميل ياهو


پيرو مطلب قبلي كه ارسال كرده بودم، خوب اگر بلاگ‌داري اين موارد را اعمال كند، تاريخ شمسي را به وبلاگ خودش اضافه كرده است. اما در مورد ديگران چطور؟ براي اين منظور، اسكريپت مطلب ارسالي را به يك اسكريپت گريس مانكي تبديل كردم كه به‌عنوان افزونه‌اي در فايرفاكس نصب خواهد شد و تمامي وبلاگ‌هاي بلاگري را پوشش مي‌دهد (حتي آنهايي كه در آدرسشان بلاگر يا بلاگ اسپات نيست).

نحوه استفاده: (همانند روش عنوان شده در اين مطلب)
  • سپس به صفحه زير مراجعه كرده و بر روي دكمه install‌ در بالاي صفحه كليك نمائيد.


همچنين ستون تاريخ انگليسي ايميل‌هاي ياهو را هم به تاريخ شمسي تبديل كردم كه جزئي از اين مجموعه است (با قالب كلاسيك ايميل ياهو (نه اين قالب جديد) درست كار مي‌كند).


مزاياي اين روش:
  • بلاگ‌دار لازم نيست چيزي را نصب كند.
  • تمام بلاگ‌هاي مربوط به بلاگر (در دومين و خارج از دومين آن) تحت پوشش قرار مي‌گيرند.
  • سريع است. (چون يكبار بر روي مرورگر شما نصب شده است و هيچ فايلي قرار نيست از اينترنت دريافت شود)

شايان ذكر است كه گريس مانكي در مرورگرهاي ديگر هم پشتيباني مي‌شود.

پ.ن.
اگر علاقمند به برنامه نويسي اسكريپت‌هاي گريس مانكي هستيد، كتابچه‌اي رايگان در اين باره را از اين آدرس مي‌توانيد دريافت نمائيد.


۱۳۸۷/۰۹/۲۸

لينك‌هاي هفته آخر آذر


وبلاگ‌ها و سايت‌هاي ايراني


امنيت


Visual Studio


ASP. Net


طراحي وب


PHP

  • Aptana PHP 1.0 منتشر شد (اگر قبلا اين IDE بسيار قابل توجه را دريافت كرده بوديد فقط كافي است به منوي aptana و گزينه my aptana مراجعه كرده و از قسمت plugins ، اين پلاگين 18 مگابايتي را دريافت كنيد.)

اس‌كيوال سرور


سي شارپ


عمومي دات نت


ويندوز


متفرقه


۱۳۸۷/۰۹/۲۷

تاريخ شمسي براي blogger !


تاريخ ميلادي بلاگر واقعا روي اعصاب بود! اين مشكل با استفاده از jQuery به صورت زير قابل حل است.

تاريخ انگليسي بلاگر به صورت زير است:
البته در قسمت تنظيمات تاريخ بلاگ ، فرمت را به اين صورت انتخاب كردم تا بدون مشكل تبديل شود.
<h2 class='date-header'>2008/12/17</h2>

يعني ما بايد متن هرچي heading شروع شده با h2 و داراي كلاس date-header را پيدا كنيم و بعد معادل فارسي آن‌را جايگزين كنيم.
اين‌كار را با استفاده از jQuery به صورت زير مي‌توان انجام داد:
<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js' type='text/javascript'></script>
<script src='http://vahid.nasiri.googlepages.com/farsidate.js' type='text/javascript'></script>
<script type='text/javascript'>
$(document).ready(function() {
$("h2.date-header").each(function() {
var obj = $(this);
obj.html(ToPersianDate(new Date(obj.text())));
});

$("a[title='comment permalink']").each(function(){
var obj = $(this);
obj.html(ToPersianDateLong(obj.text()));
});

$("a.post-count-link").each(function() {
var obj = $(this);
obj.html(getBloggerPMonthNames(obj.text()));
});

$("a.post-count-link").each(function() {
var obj = $(this);
obj.html(getBloggerPYear(obj.text()));
});
});
</script>

قسمت ويرايش html چيدمان وبلاگ را بايد ويرايش و چند سطر بالا را به آن اضافه كرد (بعد از title صفحه).

پ.ن.
Farsidate.js براي تبديل تاريخ ميلادي به شمسي جاوا اسكريپتي از اينجا قرض گرفته شد.

به روز رساني،
  • نام ماه و سال سمت راست صفحه هم فارسي شد.
  • تاريخ كامنت‌ها هم فارسي شد.

SQL Server 2005 SP3

خبر! نگارش نهايي سرويس پك 3 اس كيوال سرور 2005 ارائه شد.

۱۳۸۷/۰۹/۲۶

آشنايي با فرمت OPML


OPML يا Outline Processor Markup Language اساسا فايلي است مبتني بر XML كه امروزه بيشتر جهت توزيع لينك‌هاي تغذيه خبري سايت‌ها (RSS/Atom و امثال آن) مورد استفاده قرار مي‌گيرد.
به بياني ساده‌تر، بجاي اين‌كه بگويند ما به اين 100 وبلاگ علاقمند هستيم و لينك تك تك آنها را به شما ارائه بدهند، يك فايل OPML استاندارد از آن‌ها درست كرده و در اختيار شما قرار مي‌دهند. به اين صورت با چند كليك ساده، اين فايل در نرم افزار فيدخوان شما import شده و آدرس‌ها بلافاصله قابل استفاده خواهند بود.
نمونه‌اي از اين فرمت:
<?xml version="1.0" encoding="UTF-8"?>
<opml version="1.0">
<head>
<title>Subscriptions in Google Reader</title>
</head>
<body>
<outline title="Programming">
<outline
text="Vahid's Blog"
title="Vahid's Blog"
type="atom"
xmlUrl="http://feeds.feedburner.com/vahidnasiri"
htmlUrl="http://vahidnasiri.blogspot.com/"/>
.
.
.

چند نمونه فايل OPML مرتبط با برنامه نويسي را از سايت‌هاي مختلف جمع آوري كرده‌ام كه آنها را از اين آدرس مي‌توانيد دريافت كنيد.

نحوه استفاده از آنها در Google reader
بعد از ورود به قسمت تنظيمات Google reader ، با استفاده از قسمت import/export مي‌توان يك فايل OPML را به آن معرفي كرد (شكل زير):



و يا با استفاده از برنامه باكيفيت و رايگان FeedDemon و قسمت import feeds آن مي‌توان يك فايل OPML را به برنامه وارد كرد. البته اين‌جا امكانات بيشتري را نسبت به Google reader دراختيار شما قرار مي‌دهد و مي‌توانيد از ليست دريافتي، موارد مورد نظر را انتخاب كنيد و نه تمامي آنها را.




اگر علاقمند بوديد كه اين فايل‌ها را در برنامه‌هاي دات نت خود import كنيد، كتابخانه سورس باز Argotic Syndication Framework اين امكان را در اختيار شما قرار مي‌دهد.


۱۳۸۷/۰۹/۲۵

وادار كردن IIS به استفاده از ASP.Net 3.5


همانطور كه مطلع هستيد در تنظيمات يك دايركتوري مجازي در IIS6 يا 5، حتي پس از نصب دات نت فريم ورك سه و نيم، گزينه انتخاب نگارش 3.5 ظاهر نمي‌شود و همان تنظيمات ASP.Net 2.0 كافي است (شكل زير) (دات نت 3 و سه و نيم را مي‌توان بعنوان افزونه‌هايي با مقياس سازماني (WF ، WCF و ...) براي دات نت 2 درنظر گرفت).




هنگام استفاده از VS.Net 2008 و تنظيم نوع پروژه به دات نت فريم ورك 3.5 ، به صورت خودكار تنظيمات لازم به وب كانفيگ برنامه جهت استفاده از كامپايلرهاي مربوطه نيز اضافه مي‌شوند كه شايد از نظر دور بمانند.
براي آزمايش اين مورد، فرض كنيد صفحه زير را بدون استفاده از code behind و VS.Net ايجاد كرده ايم (جهت آزمايش سريع يك قطعه كد Linq ).

<%@ Page Language="C#" %>

<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Linq" %>

<form id="Form1" method="post" runat="server">
<asp:GridView ID="GridView1" runat="server" />
</form>


<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
string[] cities = {
"London", "Amsterdam", "San Francisco", "Las Vegas",
"Boston", "Raleigh", "Chicago", "Charlestown",
"Helsinki", "Nice", "Dublin"
};

GridView1.DataSource = from city in cities
where city.Length > 4
orderby city
select city.ToUpper();

GridView1.DataBind();
}
</script>

بلافاصله پس از اجرا با خطاي زير روبرو خواهيم شد.



اين قطعه كد چون از قابليت‌هاي كامپايلر جديد سي شارپ استفاده مي‌كند، با كامپايلر پيش فرض و تنظيم شده دات نت 2 كار نخواهد كرد و بايد براي رفع اين مشكل، فايل web.config جديدي را نيز به پوشه برنامه اضافه كنيم:

<?xml version="1.0"?>
<configuration>

<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs" warningLevel="4" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<providerOption name="CompilerVersion" value="v3.5"/>
<providerOption name="WarnAsError" value="false"/>
</compiler>
</compilers>
</system.codedom>

<system.web>
<compilation defaultLanguage="c#">
<assemblies>
<add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
</assemblies>
</compilation>
</system.web>


</configuration>

در اينجا قيد اسمبلي System.Core ضروري است و همچنين نگارش كامپايلر نيز به صورت صريح قيد شده است تا IIS را وادار كند كه از قابليت‌هاي جديد دات نت فريم ورك استفاده نمايد.

همانطور كه ذكر شد اگر از VS.Net 2008 استفاده كنيد، هيچ وقت درگير اين مباحث نخواهيد شد و همه چيز از پيش تنظيم شده است.

۱۳۸۷/۰۹/۲۴

مطلع شدن از خطاهاي مديريت نشده يك برنامه ASP.Net


راه‌هاي زيادي براي لاگ كردن خطاهاي حاصل در يك برنامه ASP.Net وجود دارند. از روش‌هاي exception handling معمول تا افزودن يك فايل global.asax به برنامه و دريافت و لاگ كردن خطاهاي مديريت نشده توسط روال رخ‌ داد گردان Application_Error آن.
بررسي اين خطاها فوق العاده مهم است ، حداقل به دو دليل : الف) قبل از اين‌ كه كاربران به شما بگويند برنامه مشكل پيدا كرده، از طريق ايميل دريافتي مطلع خواهيد شد. (فرض كنيد علاوه بر ثبت وقايع ، آنها را ايميل هم مي‌زنيد) اين مورد در جهت بالا بردن كيفيت كار تمام شده واقعا مؤثر است. ب) رفتارهاي مخرب را هم بهتر مي‌توانيد تحت نظر داشته باشيد.

تمام اين موارد مستلزم كد نويسي است. دريافت خطا در روال Application_Error و سپس كد نويسي براي ارسال ايميل. از ASP.Net 2.0 به بعد اين كار را بدون كد نويسي و با استفاده از امكانات ASP.NET health monitoring نيز مي‌توان به سادگي و دقت هرچه تمامتر انجام داد.

كار زيادي را قرار نيست انجام دهيد! فايل وب كانفيگ سايت را باز كنيد و چند سطر زير را به آن اضافه كنيد (قسمت healthMonitoring و همچنين قسمت mailSettings ):
<?xml version="1.0"?>
<configuration>
<appSettings/>
<connectionStrings/>
<system.web>
<compilation debug="true">
</compilation>
<authentication mode="Windows"/>

<healthMonitoring enabled="true">
<providers>
<add name="EmailProvider"
type="System.Web.Management.SimpleMailWebEventProvider"
from="you@domain.com"
to="you@domain.com"
subjectPrefix="Error: "
buffer="true"
bufferMode="Notification"/>
</providers>
<rules>
<add
provider="EmailProvider"
name="All App Events"
eventName="All Errors"/>
</rules>
</healthMonitoring>

</system.web>

<system.net>
<mailSettings>
<smtp deliveryMethod="SpecifiedPickupDirectory">
<specifiedPickupDirectory pickupDirectoryLocation="C:\emails"/>
</smtp>
</mailSettings>
</system.net>

</configuration>

در اين مثال قسمت mailSettings طوري تنظيم شده كه ايميل ارسالي در مسير c:\emails جهت مرور نحوه عملكرد اين سيستم، ذخيره شود.



در حالت اجرا بر روي يك سرور ، اين قسمت را مي‌توان به صورت زير تنظيم نمود و آدرس smtp server را توسط آن مشخص كرد تا به صورت خودكار مورد استفاده قرار گيرد:
<mailSettings>
<smtp from="you@domain.com">
<network host="smtp.domain.com" />
</smtp>
</mailSettings>

سيستم ارسال ايميل آن نيز هوشمند است و ميل باكس شما را به يكباره پر نخواهد كرد. اگر در طي يك دقيقه (مقدار پيش فرض) خطاهاي حاصل شده مانند هم باشند، تنها يك ايميل حاوي تمامي آنها را ارسال مي‌كند.

شايان ذكر است از ASP.Net 2.0 به بعد امكان ثبت وقايع در event log ويندوز محدود شده است و اگر نياز به انجام اين كار باشد بايد دسترسي بيشتري را به يوزر asp.net اعطاء كرد. اما با استفاده از روش فوق، جزئيات خطاي حاصل به صورت خودكار به event log ويندوز نيز اضافه مي‌شود.



اگر علاقمند باشيد كه خطاهاي حاصل را در يك ديتابيس نيز لاگ كنيد، به اين مقاله مي‌توان رجوع كرد.

۱۳۸۷/۰۹/۲۳

پيدا كردن وابستگي‌هاي اشياء در SQL Server


با بالا رفتن تعداد اشياء تعريف شده در SQL server ، نگهداري آنها نيز مشكل‌تر مي‌شود. در اين حالت تغيير كوچكي در يكي از اشياء ممكن است باعث از كار افتادن قسمتي از سيستم شود. بنابراين قبل از هر گونه تغييري در يك شيء، ابتدا بايد ساير اشياء وابسته به آن‌ را يافت و در نظر داشت ( dependencies ). براي اين منظور ( impact analysis ) راه‌كارهاي مختلفي در SQL server وجود دارد كه در ادامه به آن‌ها خواهيم پرداخت:

الف) استفاده از امكانات management studio (اس كيوال سرور 2005 به بعد)

ساده‌ترين راه ممكن كه گزارش مفصلي را نيز ارائه مي‌دهد، كليك بر روي يك شيء در management studio و انتخاب گزينه view dependencies است (شكل زير).


در صفحه ظاهر شده مي‌توان اشيايي را كه شيء مورد نظر به آنها وابسته است، مشاهده نمود يا برعكس (اشيايي كه عملكرد آنها وابسته به شيء انتخابي است را نيز مي‌توان ملاحظه كرد).

ب) كوئري گرفتن از جداول سيستمي

امكانات قسمت قبل را با استفاده از اطلاعات جدول syscomments نيز مي‌توان شبيه سازي كرد. در اين جدول اطلاعات تعاريف كليه view ، trigger ، رويه‌هاي ذخيره شده و غيره نگهداري مي‌شود. براي مثال فرض كنيد قصد داريم در جدول Orders ديتابيس Northwind ، نام فيلد OrderDate را تغيير دهيم. قبل از اين‌كار بهتر است كوئري زير را اجرا كنيم تا نام اشياء وابسته را بدست آوريم:
SELECT NAME
FROM syscomments c
JOIN sysobjects o
ON c.id = o.id
WHERE TEXT LIKE '%OrderDate%'
AND TEXT LIKE '%Orders%'


اين روش انعطاف پذيري بيشتري را نسبت به امكانات قسمت الف ، ارائه مي‌دهد. براي نمونه فرض كنيد مي‌خواهيد در يك ديتابيس كليه اشيايي كه عمليات delete را انجام مي‌دهند پيدا كنيد (جستجوي اشياء حاوي يك عبارت خاص). در اين مورد خواهيم داشت:

SELECT NAME
FROM syscomments c
JOIN Northwind.dbo.sysobjects o
ON c.id = o.id
WHERE TEXT LIKE '%delete%'

ج) استفاده از رويه ذخيره شده سيستمي sp_depends

جدول سيستمي ديگري در اس كيوال سرور به نام sysdepends وجود دارد كه اطلاعات وابستگي‌هاي اشياء در آن‌ها نگهداري مي‌شود. براي دسترسي به اطلاعات اين جدول ، اس كيوال سرور رويه ذخيره شده سيستمي sp_depends را ارائه داده است. براي مثال فرض كنيد مي‌خواهيم ليست اشيايي را كه به جدول Oredres ديتابيس Northwind وابسته هستند، پيدا كنيم. در اين حالت داريم:
USE Northwind
EXEC sp_depends 'Orders'


د) استفاده از schema view

با استفاده از view سيستمي INFORMATION_SCHEMA.ROUTINES ، كه از تركيب جداول syscolumns و sysobjects ايجاد شده است نيز مي‌توان عملكرد sp_depends را شبيه سازي كرد اما جداول و view ها از گزارش آن حذف شده‌اند.
SELECT routine_name,
routine_type
FROM INFORMATION_SCHEMA.ROUTINES
WHERE routine_definition LIKE '%Orders%'

در جدول زير مقايسه‌اي از امكانات و گزارش حاصل از اين چهار روش با هم مقايسه شده‌اند:



ه) استفاده از برنامه SQL Dependency Tracker

نسخه آزمايشي برنامه ذكر شده را از اين آدرس مي‌توان دريافت كرد.


همانطور كه ملاحظه مي‌كنيد اين جستجوها بر روي اطلاعات ذخيره شده در اس كيوال سرور صورت مي‌گيرند و اگر در كدهاي خود در خارج از اس كيوال سرور مخلوطي از عبارات اس كيوال را داشته باشيد، نگهداري آنها بسيار مشكل خواهد بود. بنابراين تا حد ممكن بايد عمليات مرتبط را در ديتابيس و توسط اشياء اس كيوال سرور مانند رويه‌هاي ذخيره شده، view ها و امثال آن‌ها انجام داد تا اين جدا سازي به‌خوبي صورت گرفته و در زمان نياز به انجام تغييرات، ردگيري اشياء وابسته به‌سادگي صورت گيرد.


۱۳۸۷/۰۹/۲۲

بررسي دقيق‌تر صفحات آبي ويندوز


حدود يك سال قبل كامپيوتري را كه داشتم (اينتل پنتيوم 4) به يك AMD دوهسته‌اي ارتقاء دادم و هفته‌ي اول پس از ارتقاء، روزگار من سياه شد! روزهاي اول 2 بار كرش ويندوز و مشاهده صفحه آبي و روزهاي بعد تا 7 بار اين اتفاق تكرار مي‌شد. حتي تا تعويض مادربرد جديد هم پيش رفتم ولي تاثيري نداشت. تست رم و غيره هم انجام شد، مشكلي نبود. خلاصه اينجا بود كه از سر ناچاري به اين فكر افتادم كه آيا اين پيغام‌هاي صفحه‌ي آبي ويندوز را مي‌شود تفسير كرد؟ مشكل دقيقا از كجاست؟ چون در اين موارد به هر كسي كه مراجعه كنيد بر اساس تجربه قبلي يك نسخه براي شما خواهد پيچيد. رمت خرابه! بايوست رو ارتقاء بده! (اين مورد تاثير داشت! ولي تعداد كرش‌ها صفر نشد) مادربردت مشكل داره و ...

تمام اين‌ها بر اساس تجربيات قبلي اين افراد است و ارزشمند. ولي آيا اين جواب‌ها قانع كننده هستند؟ چرا بايد رم را عوض كرد؟ از كجا فهميديد مادربرد مشكل داره؟



شركت‌هايي مثل apple براي اينكه با اين نوع مشكلات مواجه نشوند، به صورت انحصاري با توليد كنندگان سخت افزار قرار داد مي‌بندند و در نتيجه سيستم‌ عاملي هم كه توليد مي‌كنند بسيار پايدار خواهد بود چون بر اساس سخت افزاري كاملا مشخص، طراحي و تست شده است. اما در مورد ويندوز اين‌طور نيست.
ضمنا هيچ الزامي هم ندارد كه اين صفحه آبي ويندوز بدليل مشكلات سخت افزاري حاصل شود (وجود سخت افزار معيوب). ضعف برنامه نويسي و خصوصا درايورهاي مشكل دار هم مي‌توانند سبب ايجاد اين نوع صفحات آبي شوند كه مشكل من هم دقيقا همين مورد بود كه در ادامه نحوه بررسي آن‌را توضيح خواهم داد. (البته سطح اين مطلب را مقدماتي در نظر بگيريد)

در ويندوز اين امكان وجود دارد كه پس از هر بار كرش سيستم عامل و مشاهده صفحه آبي يك دامپ كرنل نيز به صورت خودكار حاصل شود. اين فايل دامپ را مي‌توان پس از راه اندازي مجدد سيستم با يك سري ابزار آناليز كرد و علت دقيق كرش ويندوز را بدست آورد.
براي اينكه اين فايل‌هاي دامپ توليد شوند بايد مراحل زير مطابق تصوير طي شوند:



اكنون بعد از هر كرش و صفحه آبي ويندوز يك فايل دامپ در دايركتوري C:\WINDOWS\Minidump تشكيل مي‌شود. براي آناليز اين فايلها به صورت زير مي‌شود عمل كرد:
ابتدا برنامه زير را دانلود كنيد:
Debugging Tools for Windows

پس از نصب، Debugging Tools for Windows را خواهيد داشت كه جهت ديباگ كردن سيستم و آناليز فايلهاي دامپ و غيره كاربرد دارد.

سپس مطالعه مقاله زير در مورد نحوه استفاده از اين ابزار بسيار مفيد است:
http://support.microsoft.com/kb/315263

به صورت خلاصه :
يك فايل bat درست كنيد با محتويات زير و دقيقا به همين شكل:
c:\windbg\kd -y srv*c:\symbols*http://msdl.microsoft.com/download/symbols -i c:\windows\i386 -z %1


در اين دستور سه مورد قابل ملاحظه است:
الف) مسير فايل kd.exe كه توسط پكيج Debugging Tools for Windows نصب مي‌شود. (مطابق سيستم خودتان آنرا اصلاح كنيد)
ب) مسير c:\windows\i386 بدين معنا است كه دايركتوري i386 سي دي ويندوز را در اين مسير كپي كرده‌ايد يا خواهيد كرد (نياز به يك ويندوز تر و تازه و نصب نشده خواهد بود).
ج) مسير c:\symbols خودبخود ايجاد خواهد شد و فايلهاي مربوطه از سايت مايكروسافت توسط برنامه kd.exe دانلود مي‌شود (بنابراين بايد دسترسي به اينترنت نيز داشت).

فرض كنيد نام اين فايل را test.bat گذاشته‌ايد.
براي آناليز فايل Mini102607-07.dmp در دايركتوري ميني دامپ ويندوز (07 در اينجا يعني هفتمين كرش روز مربوطه!) دستور زير را در خط فرمان صادر كنيد:
test.bat C:\WINDOWS\Minidump\Mini102607-07.dmp
پس از مدتي اين برنامه كار آناليز را تمام خواهد كرد و گزارشي را ارائه مي‌دهد (يك فايل log متني تشكيل خواهد شد).
نتيجه يك نمونه از اين آناليزهاي سيستم من به صورت زير بود:
BAD_POOL_CALLER (c2)
The current thread is making a bad pool request. Typically this is at a bad IRQL level or double freeing the same allocation, etc.
Arguments:
Arg1: 00000007, Attempt to free pool which was already freed
Arg2: 00000cd4, (reserved)
Arg3: 02060008, Memory contents of the pool block
Arg4: 88b4a118, Address of the block of pool being deallocated

Debugging Details:
------------------

POOL_ADDRESS: 88b4a118

FREED_POOL_TAG: TCPc

BUGCHECK_STR: 0xc2_7_TCPc

CUSTOMER_CRASH_COUNT: 4

DEFAULT_BUCKET_ID: COMMON_SYSTEM_FAULT

PROCESS_NAME: System

LAST_CONTROL_TRANSFER: from 8054a583 to 804f9deb

STACK_TEXT:
ba4f3874 8054a583 000000c2 00000007 00000cd4 nt!KeBugCheckEx+0x1b
ba4f38c4 b043d3ff 88b4a118 00000000 ba4f390c nt!ExFreePoolWithTag+0x2a3
ba4f38d4 b043cca3 883ae760 883ae7f4 883ae7f4 tcpip!TCPClose+0x16
ba4f390c b02f3161 8a74fe20 883ae760 b02f2a6d tcpip!TCPDispatch+0x101
WARNING: Stack unwind information not available. Following frames may be wrong.
ba4f3984 b03e2046 00000001 00000000 ba4f39d8 vsdatant+0x45161
ba4f39d8 b03e921c 00000008 ba4f3aac 00000000 ipnat!NatpRedirectQueryHandler+0x250
ba4f3a70 00000000 8837d8e8 0000000d 000005ee ipnat!NatpDirectPacket+0xd2

STACK_COMMAND: kb

FOLLOWUP_IP:
vsdatant+45161
b02f3161 ?? ???

SYMBOL_STACK_INDEX: 4

SYMBOL_NAME: vsdatant+45161

FOLLOWUP_NAME: MachineOwner

MODULE_NAME: vsdatant

IMAGE_NAME: vsdatant.sys

DEBUG_FLR_IMAGE_TIMESTAMP: 46e0766a

FAILURE_BUCKET_ID: 0xc2_7_TCPc_vsdatant+45161

BUCKET_ID: 0xc2_7_TCPc_vsdatant+45161

Followup: MachineOwner

به لاگ حاصل از دو ديدگاه مي‌توان پرداخت: الف) اگر من برنامه نويس مربوطه باشم، با trace موجود در لاگ فايل، مشخص مي‌شود كه كجاي كار مشكل داشته است ، ب) يا اينكه خير. بنده توسعه دهنده درايور نيستم. حداقل اسم دقيق درايور يا پروسه مشكل‌زا را مي‌توان از اين لاگ بدست آورد.

خوب! تا اينجا مشخص شد كه دليل كرش، درايور vsdatant.sys است. با جستجو در اينترنت مشخص شد كه اين درايور مربوط به فايروال زون آلارم است! (همين عبارت بالا يا نام درايور ذكر شده را مستقيما در گوگل جستجو كنيد)
پس از آن زون آلارم را با outpost firewall جايگزين كردم و تا الان كرشي حاصل نشده است (حتي يكبار از سال قبل تا به امروز). جدا زندگي من مختل شده بود. تصور كنيد سيستم شما روزي 7 بار كرش كند!! و چه تصورات نامربوطي را نسبت به فروشنده سخت افزار در ذهن خود مرور كرده باشيد!

خلاصه‌ي كلام:
صفحات آبي ويندوز قابل تفسير هستند. پديد آمدن آنها الزاما بدليل وجود سخت افزار معيوب نيست و به صرف اينكه شخصي به شما گفته "رمت خرابه!" اكتفا نكنيد.

پ.ن.
لاگ فوق مربوط به يك سال قبل است و احتمالا شايد زون آلارم‌هاي جديد اين مشكل را نداشته باشند.

۱۳۸۷/۰۹/۲۱

لينك‌هاي هفته سوم آذر


وبلاگ‌ها و سايت‌هاي ايراني


Visual Studio



ASP. Net


طراحي وب


اس‌كيوال سرور



Nhibernate


عمومي دات نت


ويندوز


متفرقه


۱۳۸۷/۰۹/۲۰

راهنماي رايگان 60 صفحه‌اي نصب SharePoint 2007 64-bit


راهنماي رايگان زير نحوه نصب ويندوز سرور 2003 تا اس كيوال سرور 2005 ، تنظيمات IIS و نصب SharePoint و ابزارهاي لازم براي برنامه نويسي آن‌را در يك ماشين مجازي (اين‌بار در VMware) به صورت مصور و قدم به قدم توضيح داده است.

فهرست مطالب آن:

- Introduction
- Enabling 64-bit Guest OS Support on your Motherboard (if required)
- Creating the Virtual Machine
- Editing the Virtual Machine Settings
- Building Windows
- Configuring Windows
- Patch and Backup
- Domain Promotion and Configuration
- Moss Domain Accounts Creation
- Pop 3 Email Service Configuration
- Moss 2007 Base Installation
- SQL Server 2005 64-bit Enterprise Installation and Configuration
- Create MossSetup login
- Patch and Backup
- Office Enterprise 2007 Installation and Configuration
- SharePoint Designer 2007 Installation
- Visual Studio 2005 Team Developer Edition Installation
- Development Tools Installation
- Force IIS to use 64 bit mode and disable 32 bit mode
- Complete Moss 2007 Installation
- MOSS 2007 Basic Configuration Guide
- Check Search Services and Event Log
- Backup

Download


به گفته مايكروسافت، ويندوز سرور 2008 آخرين سروري است كه هم 32 بيتي ارائه شده و هم 64 بيتي.
يا براي مثال اين روند از اكسچنج سرور 2007 شروع شد (ميل سرور مايكروسافت). نسخه سازماني اين محصول فقط 64 بيتي است.

۱۳۸۷/۰۹/۱۹

نصب و راه اندازي SharePoint 2007


اگر علاقمند باشيد كه شيرپوينت مايكروسافت را نصب و راه اندازي كنيد، مجموعه زير به صورت قدم به قدم به همراه توضيحات و تصاوير كافي نحوه انجام اين‌كار را بر روي يك virtual pc توضيح داده است:
البته اگر برنامه نويس ASP.Net باشيد بسياري از موارد آن براي شما تكراري خواهد بود.



۱۳۸۷/۰۹/۱۸

تهيه قالب براي ايميل‌هاي ارسالي يك برنامه ASP.Net


فرض كنيد ايميل اطلاع رساني برنامه ASP.Net شما قرار است ايميل زير را پس از تكميل يك فرم ارسال كند.


براي ارسال اين قالب كه مطابق تصوير هر بار بايد سه برچسب آن تغيير كند چه راهي را پيشنهاد مي‌دهيد؟

راه اول: (راه متداول)
اين فرم را در يك html editor درست كرده و جاي سه برچسب را خالي مي‌گذاريم. سپس html مورد نظر را در تابع ارسال ايميل خود به صورت يك رشته تعريف نموده و جاهاي خالي را پر خواهيم كرد. مثلا:
            string Name = "علي";
string Desc = "منابع مورد نياز";
int Number = 10;
string content =
"<div dir=\"rtl\" style=\"text-align: right; font-family:Tahoma; font-size:9pt\">" +
"با سلام<br />" +
"احتراما آقاي/خانم" +
Name +
"&nbsp;درخواست چاپ" +
Desc +
"&nbsp;داراي" +
Number +
"&nbsp;صفحه را داده‌اند. لطفا جهت تائيد درخواست ايشان به برنامه مراجعه بفرمائيد.<br />" +
"<br />" +
"با تشكر</div>";

ايرادات:
  • الف) امكان مشاهده شكل نهايي تا زمانيكه ايميل مورد نظر را دريافت نكرده باشيم، وجود ندارد.
  • ب) اعمال تغييرات جديد به اين فرمت رشته‌اي مشكل است. هميشه استفاده از ابزارهاي بصري براي بهبود كار كمك بزرگي هستند كه در اين حالت از آن‌ها محروم خواهيم شد.
  • ج)اگر تغيير رسيده جديد، درخواست اضافه كردن ليست پرينت‌هاي قبلي اين شخص بود چه بايد كرد؟ آيا جدول مورد نظر را بايد به صورت دستي ايجاد و باز هم به صورت يك رشته به اين مجموعه اضافه كرد؟ در اين حالت از كنترل‌هاي استانداردي مانند GridView و امثال آن محروم خواهيم شد.
  • د) هر بار تغيير، نياز به recompile برنامه دارد.
بنابراين همانطور كه مشاهده مي‌كنيد، نگهداري اين روش مشكل است.

راه دوم: استفاده از قالب‌ها

خوشبختانه در ASP.Net امكان رندر كردن كنترل‌ها به صورت يك string‌ نيز موجود است. در مثال ما نياز است تا چندين كنترل در كنار هم قرار گيرند تا شكل نهايي را ايجاد كنند. بنابراين مي‌توان تمام آنها را در يك يوزر كنترل قرار داد. سپس بايد كل يوزر كنترل را به صورت يك رشته، رندر كرد كه در ادامه به آن خواهيم پرداخت.

اگر قالب فوق را بخواهيم در يك يوزر كنترل طراحي كنيم، سورس صفحه html يوزر كنترل به صورت زير خواهد بود (فايل WebUserControl1.ascx) :
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="WebUserControl1.ascx.cs"
Inherits="testWebForms87.WebUserControl1" %>
<div dir="rtl" style="text-align: right; font-family:Tahoma; font-size:9pt">
با سلام<br />
احتراما آقاي/خانم
<asp:Label ID="lblName" runat="server"></asp:Label>
&nbsp;درخواست چاپ
<asp:Label ID="lblDesc" runat="server"></asp:Label>
&nbsp;داراي
<asp:Label ID="lblNumber" runat="server"></asp:Label>
&nbsp;صفحه را داده‌اند. لطفا جهت تائيد درخواست ايشان به برنامه مراجعه بفرمائيد.<br />
<br />
با تشكر</div>

همچنين مي‌توان مقادير برچسب‌ها را از طريق خواصي كه براي يوزر كنترل تعريف خواهيم كرد، در تابع ارسال ايميل خود مقدار دهي نمائيم. در اين حالت در سورس صفحه يوزر كنترل داريم (فايل WebUserControl1.ascx.cs) :
        public string Name { get; set; }
public int Number { get; set; }
public string Desc { get; set; }

protected void Page_Load(object sender, EventArgs e)
{
lblNumber.Text = Number.ToString();
lblName.Text = Name;
lblDesc.Text = Desc;
}

تا اينجا طراحي اوليه محتواي ايميل به پايان مي‌رسد. ديگر از آن رشته كذايي خبري نيست و همچنين مي‌توان از designer ويژوال استوديو براي طراحي بصري قالب مورد نظر استفاده كرد كه اين مزيت بزرگي است و در آينده اگر نياز به تغيير متن ايميل ارسالي وجود داشت، تنها كافي است فايل ascx ما ويرايش شود (بدون نياز به كامپايل مجدد پروژه). يا در اينجا به سادگي براي مثال مي‌توان يك GridView را تعريف، طراحي و bind كرد.

مرحله بعد، رندر كردن خودكار اين يوزر كنترل و سپس تبديل محتواي حاصل به يك رشته است. براي اين منظور از تابع زير مي‌توان كمك گرفت (براي مثال تعريف شده در كلاس دلخواه CLoadUC) :
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Web;
using System.Web.UI;

/// <summary>
/// تبديل يك يوزر كنترل به معادل اچ تي ام ال آن
/// </summary>
/// <param name="path">مسير يوزر كنترل</param>
/// <param name="properties">ليست خواص به همراه مقادير مورد نظر</param>
/// <returns></returns>
/// <exception cref="NotImplementedException"><c>NotImplementedException</c>.</exception>
public static string RenderUserControl(string path,
List<KeyValuePair<string,object>> properties)
{
Page pageHolder = new Page();

UserControl viewControl =
(UserControl)pageHolder.LoadControl(path);

Type viewControlType = viewControl.GetType();

foreach (var pair in properties)
{
PropertyInfo property =
viewControlType.GetProperty(pair.Key);

if (property != null)
{
property.SetValue(viewControl, pair.Value, null);
}
else
{
throw new NotImplementedException(string.Format(
"UserControl: {0} does not have a public {1} property.",
path, pair.Key));
}
}

pageHolder.Controls.Add(viewControl);
StringWriter output = new StringWriter();
HttpContext.Current.Server.Execute(pageHolder, output, false);
return output.ToString();
}

ماخذ اصلي تابع فوق اين آدرس است.
كه البته تابع نهايي آنرا كمي اصلاح كردم تا بتوان ليستي از خواص پابليك يك يوزر كنترل را به آن پاس كرد و محدود به يك خاصيت نبود.
اكنون استفاده از يوزر كنترلي كه تاكنون طراحي كرده‌ايم به سادگي زير است:
            List<KeyValuePair<string, object>> lst =
new List<KeyValuePair<string, object>>
{
new KeyValuePair<string, object>("Name", "علي"),
new KeyValuePair<string, object>("Number", 10),
new KeyValuePair<string, object>("Desc", "منابع مورد نياز")
};

string content = CLoadUC.RenderUserControl("WebUserControl1.ascx", lst);

ابتدا ليستي از خواص پابليك يوزر كنترل تهيه شده و مقدار دهي مي‌شوند . سپس مسير فايل يوزر كنترل به همراه اين ليست به تابع رندر كردن نهايي پاس خواهند شد. حاصل، رشته‌ html محتواي ايميل ما را تشكيل خواهد داد.