‏نمایش پست‌ها با برچسب VSTO. نمایش همه پست‌ها
‏نمایش پست‌ها با برچسب VSTO. نمایش همه پست‌ها

۱۳۸۸/۰۲/۳۰

ليست كردن ايميل‌هاي موجود در Global address list


Global Address List يا به اختصار GAL و يا همان Microsoft Exchange Global Address Book ، حاوي اطلاعات تمامي كاربران تعريف شده در Exchange server مايكروسافت است و زمانيكه outlook در شبكه به exchange server متصل مي‌شود، كاربران مي‌توانند با كمك آن ليست اعضاء را مشاهده كرده ، يك يا چند نفر را انتخاب نموده و به آن‌ها ايميل ارسال كنند (شكل زير):


نياز بود تا اين ليست تعريف شده در مايكروسافت اكسچنج، با اطلاعات يك ديتابيس مقايسه شوند كه آيا اين اطلاعات مطابق ركوردهاي موجود تعريف شده يا خير.
بنابراين اولين قدم، استخراج email هاي موجود در GAL بود (دسترسي به همين برگه‌ي email address كه در شكل فوق ملاحظه مي‌كنيد از طريق برنامه نويسي) كه خلاصه آن تابع زير است:
جهت استفاده از آن ابتدا بايد يك ارجاع به كتابخانه COM ايي به نام Microsoft Outlook Object Library اضافه شود.

using System.Collections.Generic;
using System.Reflection;
using Microsoft.Office.Interop.Outlook;

namespace GAL
{
//add a reference to Microsoft Outlook 12.0 Object Library
class COutLook
{
public struct User
{
public string Name;
public string Email;
}

public static List<User> ExchangeServerEmailAddresses(string userName)
{
List<User> res = new List<User>();
//Create Outlook application
Application outlookApp = new Application();
//Get Mapi NameSpace and Logon
NameSpace ns = outlookApp.GetNamespace("MAPI");
ns.Logon(userName, Missing.Value, false, true);

//Get Global Address List
AddressLists addressLists = ns.AddressLists;
AddressList globalAddressList = addressLists["Global Address List"];
AddressEntries entries = globalAddressList.AddressEntries;
foreach (AddressEntry entry in entries)
{
ExchangeUser user = entry.GetExchangeUser();
if (user != null && user.PrimarySmtpAddress != null && entry.Name != null)
res.Add(new User
{
Name = entry.Name,
Email = user.PrimarySmtpAddress
});
}

ns.Logoff();

// Clean up.
outlookApp = null;
ns = null;
addressLists = null;
globalAddressList = null;
entries = null;

return res;
}
}
}
و نحوه استفاده از آن هم به صورت زير مي‌تواند باشد:

List<COutLook.User> data = COutLook.ExchangeServerEmailAddresses("nasiri");
foreach (var list in data)
{
//....
}
در اينجا Nasiri نام كاربري شخص در دومين است (كاربر جاري لاگين كرده در سيستم).
تنها نكته‌ي مهم اين كد، مهيا نبودن فيلد ايميل در شيء AdderssEntry است كه بايد از طريق متد GetExchangeUser آن اقدام شود.


۱۳۸۷/۰۹/۰۱

بررسي جزئيات برنامه نويسي افزونه تاريخ فارسي براي outlook 2007 - قسمت دوم


اضافه كردن يك ستون در آوت لوك كار ساده‌اي است. براي مثال زمانيكه inbox باز است ، بر روي قسمت نمايش ايميل‌ها كليك راست كرده و مسير زير را طي كنيد:
در اينجا فرض بر اين است كه از منوي اصلي view->reading pane->bottom انتخاب شده است.
Customize current view -> fields -> new field

به اين صورت مي‌شود يك UserDefinedProperties را تعريف و سپس ‌آن‌را به ViewFields موجود اضافه كرد. نحوه انجام اينكار را در تابع addNewCol مي‌توانيد مشاهده نمائيد.

اما مقدار دهي رديف‌هاي اين ستون ايجاد شده كار ساده‌اي نيست و نياز است تا با نكته زير آشنا بود:
<view type="table">
<viewname>Messages</viewname>
<column>
<heading>تاريخ دريافت</heading>
<prop>http://schemas.microsoft.com/mapi/string/{00020329-0000-0000-C000-000000000046}/تاريخ%20دريافت</prop>
<type>string</type>
<width>150</width>
<style>padding-left:3px;;text-align:left</style>
<editable>1</editable>
</column>
</view>

Outlook ساختار ستون‌هاي موجود را با فرمت xml نگهداري مي‌كند و اگر نياز داشتيد تا رديف ستوني را مقدار دهي كنيد بايد ابتدا مقدار تگ prop مربوط به آن ستون را دريافت كرده و سپس بر اساس آن، كار مقدار دهي را انجام دهيد. نحوه انجام اين‌كار را در تابع getColumnProp مي‌توانيد ملاحظه نمائيد و نهايتا نحوه استفاده از اين خاصيت دريافت شده جهت مقدار دهي يك رديف در تابع expSelectionChange ارائه شده است.
اگر علاقمند بوديد كه مقدار كامل اين ساختار را مشاهده نمائيد در تابع addNewCol ، پس از تعريف curView سطر زير را اضافه كنيد:

MessageBox.Show(curView.XML);


۱۳۸۷/۰۸/۲۶

بررسي جزئيات برنامه نويسي افزونه تاريخ فارسي براي outlook 2007 - قسمت اول


قبل از شروع بحث، سورس كامل پروژه را از اينجا دريافت كنيد (يك پروژه VSTO از نوع outlook add-in در VS.Net 2008 SP1).

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

متن ايميل‌هاي دريافتي در آوت‌لوك‌هاي جديد عموما به دو فرمت HTML و يا RichText دريافت مي‌شوند. حالت‌هاي ديگري هم مانند plain و unspecified هم موجود هستند كه حتي اگر ايميلي را به صورت plain ارسال نمائيد، با فرمت RichText نمايش داده خواهد شد (بنابراين بر اساس آزمايشات من بررسي اين دو فرمت كفايت مي‌كند).

براي اينكه قسمت‌هاي sent را پيدا كنيم در ابتدا بايد سورس صفحه را بررسي نمائيم (كليك راست و view source).
در حالت فرمت HTML داريم:

<p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Tahoma","sans-serif"'>From:</span></b><span
style='font-size:10.0pt;font-family:"Tahoma","sans-serif"'> Nasiri, Vahid <br>
<b>Sent:</b> <span lang=AR-SA dir=RTL>our date goes here</span><br>
<b>To:</b> xyz<br>
<b>Subject:</b> our subject<o:p></o:p></span></p>


و در حالت ايميل‌هاي RichText خواهيم داشت:

From: tst@tst.net<br>
Sent:<span lang=AR-SA dir=RTL>our date goes here</span><br>
To: Nasiri, Vahid<br>
Subject: <span lang=AR-SA dir=RTL>xyz</span><br>

خوب، براي پيدا كردن عبارت تاريخ قسمت sent چه بايد كرد؟ (our date goes here در اينجا)
استفاده از روش‌هاي متداول كار با رشته‌ها در اينجا به علت انبوهي از تگ‌هاي HTML اصلا مقرون به صرفه نيست و كند خواهد بود. خوشبختانه با وجود كتابخانه regular expressions در دات نت، پيدا كردن عباراتي كه از يك الگوي خاص پيروي مي‌كنند به سادگي و با سرعت بسيار بالايي قابل انجام است.
پيشنهاد من براي دو فرمت بالا به صورت زير بوده: (شايد شما الگوي ديگري را يافتيد، زيبايي اوپن سورس :))

private const string REGEXHTMLPATTERN = @"(?s)>\s(.+?)<br>";
private const string REGEXPLAINTEXTPATTERN = "(?s)Sent:(.+?)<br>";

براي مثال در حالت دوم هر چيزي كه بين sent و br قرار مي‌گيرد در كل متن بررسي خواهد شد (با استفاده از MatchCollection فضاي نام System.Text.RegularExpressions). در اينجا اگر Convert.ToDateTime آن عبارت موفق بود يعني تاريخ قابل تبديل است (البته قبل از تبديل تمام تگ‌هاي HTML احتمالي هم تميز خواهند شد) و ما آنرا با استفاده از تابع DateTimeToFarsiStr در كلاس cDate به نمونه شمسي تبديل كرده (لطفا به سورس برنامه مراجعه كنيد) و نهايتا آنرا در متن جايگزين مي‌كنيم.
سرعت استفاده از RegularExpressions فوق العاده بالا است و براي نمونه در ايميلي با بيش از 20 ريپلاي در كسري از ثانيه كل اين عمليات انجام خواهد شد.

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

بيشترين وقتي كه در اين پروژه صرف شد نحوه پيدا كردن شيء MailItem جاري باز شده با استفاده از رخدادهاي آوت‌لوك بود (مدت مديدي را براي اين مورد وقت گذاشتم! چون عملا در هيچ كتابي به اين مباحث پرداخته نمي‌شود و بايد كل نت را زير و رو كرد). دو مورد را بايد بررسي كرد. الف) inspector ها (صفحه‌اي كه جهت ايجاد يك ايميل جديد يا ريپلاي به ايميل جاري باز مي‌شود، inspector نام دارد) ب) ActiveExplorer ها (صفحه‌اي كه ليست ايميل‌ها را نمايش مي‌دهد و اين صفحه مي‌تواند در فولدرهاي مختلفي كه شما ايجاد كرده‌ايد نيز نمايش داده شود بنابراين بررسي inbox به تنهايي كافي نيست)
نحوه ايجاد اشياء مربوطه و تحت نظر قرار دادن آنها را در روال ThisAddIn_Startup فايل ThisAddIn.cs مي‌توانيد مشاهده نمائيد. نكته مهمي كه اينجا وجود دارد، تعريف اين اشياء در سطح كلاس است. در غيراينصورت با اولين خانه تكاني garbage collector ، اشياء شما (بدليل نبود ارجاعي فعال به آنها) معدوم خواهند شد(!) و ديگر روال‌هاي رخداد گردان تعريف شده كار نخواهند.

۱۳۸۷/۰۸/۲۵

افزونه تاريخ فارسي براي outlook 2007


عموما در محيط كاري اگر شبكه ويندوزي و mail server مورد استفاده هم ms exchange باشد، به طور قطع از outlook براي انجام امور روزمره ارسال و دريافت ايميل استفاده مي‌شود.
طبق معمول هم مشكل ما تاريخ فارسي است! يكي از شركت‌هاي ايراني كه در اين‌باره محصولي را ارائه داده با hook كردن تاريخ ويندوز، هر جايي كه تاريخي قرار است نمايش داده شود، آنرا فارسي مي‌كند. اين محصول دو ايراد دارد: الف) رايگان نيست! ب) اين hook بر روي عملكرد ساير برنامه‌ها تاثيرگذار است. براي مثال برنامه‌هاي دات نت تاريخ قمري را نمايش خواهند داد، بر روي عملكرد و كارآيي كلي سيستم تاثير منفي دارد و مشكلاتي از اين دست.

افزونه زير بدون دستكاري تاريخ ويندوز، دو كار را در MS outlook 2007 انجام خواهد داد:

الف) اضافه كردن ستون "تاريخ دريافت" شمسي



ب) در متن دريافتي، تمام تاريخ‌هاي sent موجود را يافته و شمسي مي‌كند



دريافت افزونه:
لطفا اينجا كليك كنيد.

تذكر مهم:
نصب دو بسته به روز رساني سيستم و دات نت فريم ورك را پيش از نصب اين افزونه فراموش نكنيد.
http://vahidnasiri.blogspot.com/2008/11/word-2007.html


در كل براي من كار راه انداز بوده :)

در طي روزهاي آتي، سورس كامل و نحوه برنامه نويسي آن‌را بررسي خواهيم كرد.

۱۳۸۷/۰۸/۱۹

نصب يك اسمبلي دات نت در GAC


افزونه فارسي به پارسي را قبل از ارائه در سايت، بر روي يك ماشين مجازي هم تست كردم. براي اين منظور از Microsoft virtual pc استفاده شد. البته در مقابل امكانات VMware شايد حرفي براي گفتن نداشته باشد ولي خوب جهت مقاصد تست نرم افزار بر روي يك سيستم عاري از وسايل برنامه نويسي مناسب است. (براي نصب يك سيستم عامل توسط آن براي مثال مي‌شود از سي دي آن OS يك فايل ISO تهيه كرد و مسير اين فايل ISO را به ماشين مجازي معرفي كرد . سپس سيستم بوت شده و روال نصب مطابق معمول خواهد بود)
اولين مشكلي كه پس از تست بر روي سيستم مجازي رخ داد، پيغام يافت نشدن اسمبلي مربوط به SQLite بود. نرم افزار word هنگام اجراي افزونه‌هاي دات نت، آنها را در مسيري با يك نامگذاري منحصربفرد كپي مي‌كند و تنها هم همان اسمبلي افزونه را كپي مي‌كند و نه ساير موارد همراه را. براي پيدا كردن اين مسير مي‌شود از روش زير استفاده كرد:
using System.Reflection;
Assembly.GetExecutingAssembly().Location

در اين مسير اسمبلي SQLite وجود ندارد و به همين دليل هم بارگذاري نخواهد شد. بهترين راه حل براي رفع اين مشكل، نصب اسمبلي مربوطه در GAC يا global assembly cache است.
براي نصب اسمبلي در GAC استفاده از برنامه gacutil توصيه شده است. اين برنامه به همراه SDK دات نت فريم ورك ارائه مي‌شود و الزامي ندارد كه كاربر نهايي اين برنامه را داشته باشد. خوشبختانه با استفاده از برنامه نويسي هم مي‌شود يك نمونه از برنامه Gacutil را خودمان ايجاد كنيم (براي مثال ايجاد يك برنامه كنسول و دريافت مسير از طريق آرگومان‌هاي ارسالي به آن):

new System.EnterpriseServices.Internal.Publish().GacInstall(path);

در اينجا بايد ارجاعي از System.EnterpriseServices نيز به برنامه اضافه شود.
اين روش در مورد اسمبلي SQLite كه داراي امضاي ديجيتال است كار خواهد كرد. اما اگر قصد داشته باشيد به صورت عمومي از آن استفاده كنيد، بايد ابتدا بررسي كرد كه آيا فايل اسمبلي داراي امضاي ديجيتال است يا خير. براي اين منظور مي‌توان مقدار عبارت زير را ارزيابي كرد:
Assembly.LoadFile(path).GetName().GetPublicKey().Length

اگر اين طول بزرگتر از صفر بود به اين معنا است كه فايل اسمبلي داراي امضاي ديجيتال است و مي‌توان آنرا در GAC نصب كرد.
لازم به ذكر است كه متد معرفي شده براي نصب در GAC در صورت عدم موفقيت هيچ پيغام خطا يا exception ايي را در برنامه توليد نخواهد كرد. اما پيغام خطاي حاصل را در event log ويندوز مي‌توان مشاهده كرد.


۱۳۸۷/۰۸/۱۷

جزئيات برنامه نويسي افزونه فارسي به پارسي


اين افزونه با استفاده از ابزار Visual Studio Tools for Office كه به VSTO مشهور شده است، تهيه شد. در بسته به روز رساني سيستم كه در ذيل (معرفي افزونه) نيز معرفي شد نگارش sp1 vsto3.0 آن به صورت خودكار نصب خواهد شد.
براي ايجاد اين پروژه در VS.Net 2008 ، تنها كافي است يك پروژه جديد Word add-in را آغاز نمائيم. (شكل زير)





قبل از ادامه بحث، بهتر است در مورد بانك اطلاعاتي مورد استفاده نيز توضيح داده شود. در اينجا از SQLite استفاده شد. (بسيار سبك، كم حجم و سريع است و اساسا يك كاربر نهايي براي تنظيمات آن نيازي نيست اطلاعاتي داشته باشد). بسته به روز رساني سيستم (در مطلب قبلي)، اين مورد را نيز به صورت خودكار نصب خواهد كرد (در GAC بايد نصب شود وگرنه افزونه قادر به يافتن آن نخواهد شد).
براي ايجاد اين بانك اطلاعاتي، از افزونه SQLite manager براي فايرفاكس استفاده شد. (اين افزونه رايگان شما را از هر ابزار جانبي براي مديريت يك بانك اطلاعاتي SQLite بي‌نياز مي‌كند)
براي مثال فايل ErrorsBank.sqlite برنامه افزونه فارسي به پارسي را توسط افزونه SQLite manager فايرفاكس باز كنيد (اين فايل را در محل نصب افزونه مي‌توانيد پيدا كنيد). در اينجا مي‌توان جداول جديد را ايجاد كرد، كوئري‌هاي دلخواه را اجرا نمود و يا اطلاعات را مرور كرده، حذف يا ويرايش كرد (شكل زير).




و خوشبختانه اين بانك اطلاعاتي و محصور كننده‌هاي آن با اطلاعات يونيكد فارسي هيچ مشكلي ندارند و براي كارهايي با وسعت كم و تعداد ركورد پائين يكي از بهترين انتخاب‌ها به‌شمار مي‌روند.
نحوه استفاده از SQLite نيز در دات نت بسيار ساده است. اگر با ADO.Net كار كرده باشيد، پس از افزودن ارجاعي از اسمبلي System.Data.SQLite.DLL به پروژه و معرفي فضاي نام آن به پروژه، تنها كافي است در كدهاي قبلي خود براي مثال SqlConnection را به SQLiteConnectionتغيير دهيد و امثال آن. يعني دانش ADO.Net شما در اينجا نيز كاملا قابل استفاده خواهد بود و نيازي نيست مدتي را صرف آشنا شدن با كلاس‌ها و مفاهيم جديد نمائيد (البته اين تنها زماني معنا خواهد داشت كه به ويزاردها عادت نكرده باشيد و كارهاي خود را با كد نويسي انجام داده باشيد).
تنها يك نكته را بايد به‌خاطر داشت و آن هم مربوط است به ساز و كار دروني SQLite . هنگام انجام عمليات update يا insert حتما از transaction استفاده كنيد تا سرعت كوئري‌هاي شما در SQLite به نحو شگفت انگيزي افزايش يابد. مثالي در اين مورد را در فايل chm راهنماي SQLite.NET مي‌توانيد پيدا كنيد.

مطلب ديگري كه پيش از پرداختن به كد نويسي افزونه بايد با آن آشنا شويم، مفهوم smart tags در مجموعه آفيس است كه در اين پروژه از آن استفاده گرديد.
smart tags در مجموعه آفيس برچسب‌هايي هستند كه به صورت خودكار توسط يكي از محصولات آفيس مثلا ورد يا اكسل و امثال آن، پس از تشخيص يك كلمه خاص ايجاد مي‌شوند و مي‌توان اعمالي را به اين برچسب ايجاد شده انتساب داد. براي مثال در اينجا امكان جايگزين كردن كلمه فارسي با معادل پارسي در نظر گرفته شد.
ويديويي در مورد نحوه ايجاد اسمارت تگ‌ها در VS.Net و يا مثالي پيشرفته‌تر در مورد تشخيص دماي فارنهايت در يك متن و ايجاد smart tag مخصوص به آن براي تبديل به سلسيوس. (از regular expressions جهت يافتن يك الگو در متن استفاده شده است)

در اين پروژه، حدود 3800 واژه فارسي به‌ يك smart tag انتساب داده مي‌شود (در روال استاندارد ThisAddIn_Startup). سپس در هنگام نمايش آن، معادل پارسي كلمه نيز به منوي باز شده افزوده گشته و در روال رخداد كليك آن، تعويض كلمه تشخيص داده شده با واژه پيدا شده صورت خواهد گرفت.

در ادامه فرض بر اين است كه يك پروژه جديد word add-in را در VS.Net ايجاد كرده‌ايد و همچنين ارجاعي را به فايل System.Data.SQLite.DLL افزوده‌ايد.

using System;
using System.Diagnostics;
using Microsoft.Office.Tools.Word;
using Action = Microsoft.Office.Tools.Word.Action;

private SmartTag _st;
private void init()
{
try
{
//Enable Smart Tags in Word
if (!Application.Options.LabelSmartTags)
{
//ممكن است اسمارت تگ‌ها در ورد غيرفعال باشند. به اين صورت مي‌شود آنها را فعال كرد
Application.Options.LabelSmartTags = true;
}

_st = new SmartTag(@"www.microsoft.com/Demo#FarsiSmartTag", @"فارسى به پارسى");

//دريافت واژه‌هاي فارسي از ديتابيس و افزودن خودكار آنها به اسمارت تگ‌ها
if (!DBhelper.AddSmartTagItems(_st, "select distinct farsi from tblFarsiToParsi")) return;

Action stActions = new Action("تبديل");//تعريف يك اكشن جديد
stActions.Click += stActions_Click;//انتساب روال‌هاي رخداد گردان
stActions.BeforeCaptionShow += stActions_BeforeCaptionShow;
_st.Actions = new[] { stActions };
VstoSmartTags.Add(_st);//افزودن اسمارت تگ به مجموعه
}
catch (Exception ex)
{
EventLog.WriteEntry("FarsiToParsi", ex.ToString(), EventLogEntryType.Error, 7);
}
}

private void ThisAddIn_Startup(object sender, EventArgs e)
{
init();
}

دو روال رخداد گردان زير نيز جهت تغيير عنوان پيش فرض به واژه يافته شده در لحظه نمايش منو و روال كليك نيز ايجاد خواهد شد:

static void stActions_BeforeCaptionShow(object sender, ActionEventArgs e)
{
try
{
Action clickedAction = sender as Action;
if (clickedAction != null)
{
string parsi = DBhelper.FindParsi(e.Text);//معادل پارسي از ديتابيس دريافت مي‌شود
clickedAction.Caption = (parsi == string.Empty ? e.Text : parsi);
}
}
catch (Exception ex)
{
EventLog.WriteEntry("FarsiToParsi", ex.ToString(), EventLogEntryType.Error, 7);
}
}

static void stActions_Click(object sender, ActionEventArgs e)
{
try
{
Action clickedAction = sender as Action;
if (clickedAction != null)
{
e.Range.Text = clickedAction.Caption;//جايگزيني متن موجود با عنواني كه پيشتر پارسي شده است
}
}
catch (Exception ex)
{
EventLog.WriteEntry("FarsiToParsi", ex.ToString(), EventLogEntryType.Error, 7);
}
}

نكته‌اي را كه در اينجا بايد حتما رعايت كرد بحث exception handling‌ است. خصوصا در روال استاندارد ThisAddIn_Startup . اگر در اين روال خطايي مديريت نشده رخ دهد، word افزودني شما را به صورت غيرفعال به مجموعه اضافه خواهد كرد و فعال سازي بعدي آن پس از اصلاح كد واقعا مشكل خواهد بود. همانطور كه ملاحظه مي‌كنيد تمامي خطاها در event log‌ ويندوز نوشته مي‌شوند.
همچنين بايد دقت داشت كه اگر متغيري در سطح كلاس تعريف نشود به احتمال زياد تا دقايقي بعد توسط garbage collector به ديار باقي خواهد شتافت (تعريف st_ در اينجا). اينجاست كه شايد ساعت‌ها وقت صرف كنيد كه چرا روال‌هاي رخ‌داد گردان ديگر اجرا نمي‌شوند. چرا افزونه ديگر كار نمي‌كند.

همين! كل سورس اين add-in منهاي بحث دريافت اطلاعات از ديتابيس همين بود! وظيفه‌ي تشخيص كلمات معرفي شده به ms-word به‌عهده‌ي خود آن است و اين‌كار را نيز به‌خوبي انجام مي‌دهد. در گذشته‌هاي نچندان دور ايجاد يك افزونه براي word واقعا مشكل بود كه با اين روش بسياري از موانع برطرف شده است.

كلاس DBHelper كه كار دريافت اطلاعات واژه‌ها را از ديتابيس SQLite انجام مي‌دهد به شرح زير است:

using System;
using System.Data.SQLite;
using System.Diagnostics;
using System.Reflection;
using Microsoft.Office.Tools.Word;

namespace Farsi2Parsi
{
class DBhelper
{
#region Methods (2)

// Public Methods (2)

public static bool AddSmartTagItems(SmartTag st, string strSQL)
{
SQLiteDataReader myReader = null;
SQLiteCommand sqlCmd = null;
bool ret = false;
try
{
SQLiteConnection sqlCon = new SQLiteConnection
{
ConnectionString = "Data Source=" + ConStr.ConnectionString
};
sqlCon.Open();
sqlCmd = new SQLiteCommand(strSQL, sqlCon);
myReader = sqlCmd.ExecuteReader();

if (myReader != null)
while (myReader.Read())
{
if (myReader.GetValue(0) != DBNull.Value)
st.Terms.Add(myReader.GetValue(0).ToString());
}

ret = true;
}
catch (Exception ex)
{
EventLog.WriteEntry("FarsiToParsi", ex + "\n" + Environment.CurrentDirectory + "\n" +
Assembly.GetExecutingAssembly().Location, EventLogEntryType.Error, 7);
}
finally
{
if (myReader != null)
myReader.Close();

if (sqlCmd != null)
sqlCmd.Connection.Close();
}
return ret;
}

public static string FindParsi(string farsi)
{
SQLiteDataReader myReader = null;
SQLiteCommand sqlCmd = null;
string ret = string.Empty;
string strSQL = "select parsi from tblFarsiToParsi where farsi='" + farsi.Replace("'", "''") + "'";
try
{
SQLiteConnection sqlCon = new SQLiteConnection
{
ConnectionString = "Data Source=" + ConStr.ConnectionString
};
sqlCon.Open();
sqlCmd = new SQLiteCommand(strSQL, sqlCon);
myReader = sqlCmd.ExecuteReader();

if (myReader != null)
{
myReader.Read(); //اولين مورد كافي است
if (myReader.GetValue(0) != DBNull.Value)
ret = myReader.GetValue(0).ToString();
}
}
catch (Exception ex)
{
EventLog.WriteEntry("FarsiToParsi", ex + "\n" + Environment.CurrentDirectory + "\n" +
Assembly.GetExecutingAssembly().Location, EventLogEntryType.Error, 8);
}
finally
{
if (myReader != null)
myReader.Close();

if (sqlCmd != null)
sqlCmd.Connection.Close();
}
return ret;
}
#endregion Methods
}
}

همانطور كه پيشتر نيز عنوان شد اگر با ADO.net آشنايي داشته باشيد، هيچ نكته‌ي خاص جديدي را در اينجا مشاهده نخواهيد كرد و تنها يك سري امور روزمره كاري با ADO.net مطرح شده است، باز كردن كانكشن، اجراي كوئري، دريافت اطلاعات و پاكسازي نهايي. (قسمت finally را با استفاده از عبارت using مي‌شود حذف كرد)

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

class ConStr
{
public static string ConnectionString
{
get
{
return Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SOFTWARE\\FarsiToParsi").GetValue("folder") + "\\ErrorsBank.sqlite";
}
}
}

سورس كامل اين افزونه را به صورت يك پروژه VS.Net 2008 SP1 از اينجا مي‌توانيد دريافت كنيد.
نصاب برنامه با استفاده از NSIS ايجاد شده كه در روزي ديگر درباره‌ي آن توضيح خواهم داد.
اگر قصد داشته باشيد از روش‌هاي متداول استفاده كنيد، مشاهده ويديوي زير توصيه مي‌شود:
http://msdn.microsoft.com/en-us/office/bb851702.aspx

براي توزيع اين نوع افزونه‌ها علاوه بر دات نت فريم ورك، به چهار به روز رساني ديگر نيز نياز خواهد بود:
به روز رساني نصاب ويندوز (كه احتمالا نصب هست)
WindowsInstaller-KB893803-v2-x86.exe
Microsoft Office System Update: Redistributable Primary Interop Assemblies :
o2007pia.msi
نصب vsto و همچنين sp1 آن
vstor30.exe
vstor30sp1-KB949258-x86.exe

اين موارد را من در بسته به روز رساني سيستم قرار داده‌ام كه به صورت خودكار و يكي پس از ديگري اجرا و نصب خواهند شد.
پس از آن با كليك بر روي فايلي با پسوند vsto كه در پوشه build برنامه موجود است، مي‌توان افزونه را نصب كرد (click once installation).




ساير اطلاعات در مورد پروژه‌هاي VSTO را مي‌توان از طريق وبلاگ رسمي آنها دنبال كرد:
http://blogs.msdn.com/vsto/

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


۱۳۸۷/۰۸/۱۶

افزونه فارسي به پارسي براي word 2007


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



براي نصب آن بايد به ترتيب زير عمل كنيد (مهم)
لطفا اين سه مرحله را به ترتيب انجام دهيد در غير اينصورت نتيجه نخواهيد گرفت.
همچنين بديهي است كه برنامه بايد با دسترسي admin نصب شود.
و همانطور كه در عنوان اين موضوع نيز ذكر گرديد، اين افزونه تنها براي MS-Word 2007 طراحي شده است.

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

پس از نصب به گزينه‌ي word options مراجعه كنيد: (جهت اطمينان از نصب آن)



اين افزونه را بايد در ليست مربوطه مشاهده نمائيد:



هر زمانيكه مايل به عدم استفاده از آن باشيد با كليك بر روي دكمه Go ، در صفحه بعد مي‌توان افزونه را حذف كرد:



مثالي ديگر از نحوه‌ي بكارگيري اين افزونه: