چگونه كنترلهاي OLE مثل (dynamic-link library (DLL يا كنترلهاي (ActiveX (OCX را از درون دلفي Register يا UnRegister بكنيم؟


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

البته من مقاله اي ديگري نيز راجع به استفاده از Flash در دلفي نوشته ام كه در آن به خوبي نصب ActiveX فلش بر روي كامپيوتر كاربر توضيح داده شده است. ولي از آن جا كه كد آن پروژه كمي پيچيده و بزرگ است و از آن جا كه آن مقاله با وسواس تمام نوشته شده و بسيار مفصل است، تصميم گرفتم كه مقاله ديگري راجع به اين مساله بنويسم كه به طور مختصرتر به اين مقوله بپردازد و كدهاي ساده تر و قابل فهم تري نيز ارائه كنيد.
آدرس مقاله "استفاده از Flash در دلفي":

و اما اصل مطلب. بعضي مواقع شما در پروژه ها خود يك ActiveX را با استفاده از دستور "import an ActiveX control" وارد مي كنيد ولي اگر كاربر اين ActiveX را نداشته باشد با exception يا خطايي به نام EOleSysError مواجه خواهد شد و نخواهد توانست كه از برنامه شما استفاده كند.

RegSvr32.exe
دستور command-lineي يا خط فرماني RegSvr32.exe كار نصب كنترلهاي dl يا ActiveX را دارد. شما مي توانيد به طور دستي از اين ابزار استفاده كنيد. كافي است در ويندوز گزينه Run منوي Start را اجرا كرده و به راحتي اين دستور را اجرا كنيد. وقتي شما از RegSvr32.exe استفاده مي كنيد، سعي خواهد كرد كه كمپوننت را load كرده و تابع DLLSelfRegister آنرا فرا بخواند. اگر اين تلاش موفق باشد RegSvr32.exe يك پنجره با پيغام موفقيت نشان مي دهد.

RegSvr32.exe پارامترهاي زير را دارد:
کد:
Regsvr32 [/u] [/s] [/n] [/i[:cmdline]] dllname
/s - Silent; display no message boxes
/u - Unregister server
/i - Call DllInstall passing it an optional [cmdline];
when used with /u calls dll uninstall
/n - do not call DllRegisterServer; this option must
be used with /i
توجه: با استفاده از سوييچ ؟/ مي توانيد ليست تمامي پارامترهاي را ببينيد.

از درون دلفي.
براي اين كه شما اين كد را از درون دلفي اجرا كنيد به تابعي احتياج داريد كه يك فايل exe را اجرا كرده و تا اتمام اجراي آن صبر كند.

تابع RegisterOCX بايد چيزي شبيه به اين باشد:


کد:
procedure RegisterOCX(ocxPath: string);
type
TRegFunc = function : HResult; stdcall;
var
ARegFunc : TRegFunc;
aHandle : THandle;
begin
try
aHandle := LoadLibrary(PChar(ocxPath));
if aHandle <> 0 then
begin
ARegFunc := GetProcAddress(aHandle,'DllRegisterServer');
if Assigned(ARegFunc) then
begin
ExecAndWait('regsvr32','/s ' + ocxPath);
end;
FreeLibrary(aHandle);
end;
except
ShowMessage(Format('Unable to register %s', [ocxPath]));
end;
end;

توجه: متغيير ocxPath به نام ocx اشاره دارد. به عنوان مثال شما مي توانيد اين تابع را به اين شكل فرا بخوانيد:

RegisterOCX(ExtractFilePath(Application.ExeName) + 'Flash.ocx');
كه سبب نصب ActiveX مربوط به فلش مي شود.

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

در تابع بالا از تابع ديگري استفاده شده به نام ExecAndWait. اين تابع كار صدا كردن regsvr32 را با پارامتر s/ و نام فايل ocx انجام مي دهد. (پارامتر s به معناي silent سبب اجراي regsvr32 در مد خاموش مي شود. در اين مد پيغام هاي خطا و موفقيت نمايش داده نمي شود و كاربر از نصب ActiveX مطلع نخواهد شد.
و اين هم تابع ExecAndWait:
کد:
uses ShellAPI;
...
function ExecAndWait(const ExecuteFile, ParamString : string): boolean;
var
SEInfo: TShellExecuteInfo;
ExitCode: DWORD;
begin
FillChar(SEInfo, SizeOf(SEInfo), 0);
SEInfo.cbSize := SizeOf(TShellExecuteInfo);
with SEInfo do
begin
fMask := SEE_MASK_NOCLOSEPROCESS;
Wnd := Application.Handle;
lpFile := PChar(ExecuteFile);
lpParameters := PChar(ParamString);
nShow := SW_HIDE;
end;
if ShellExecuteEx(@SEInfo) then
begin
repeat
Application.ProcessMessages;
GetExitCodeProcess(SEInfo.hProcess, ExitCode);
until (ExitCode <> STILL_ACTIVE) or Application.Terminated;
Result:=True;
end
else Result:=False;
end;

البته توجه داشته باشيد كه ShellAPI بايد در ليست uses يونيت شما وجود داشته باشد.
تابع فوق از تابع APIي به نام ShellExecuteEx استفاده مي كند تا يك فايل exe را در سيستم اجرا كند. اگر شما به اطلاعات بيشتري راجع به اين تابع و توابعي مثل اين نياز داريد به مقاله "اجراي فايل exe از درون دلفي" توجه كنيد.

Flash.ocx داخل فايل exe دلفي
همه چيز به خوبي پيش رفت. تنها مسئله اي كه باقيست پنهان كردن Flash.ocx يا هر ocx ديگري از ديد كاربر است. انجام اين كار به سادگي امكان پذير است. فقط كافي است شما فايل ocx را در Resourceها اضافه كنيد. Resource مربوطه با Exe شما Compile خواهد شد و در هنگام اجراي برنامه شما به سادگي آن ocx را روي هارد ذخيره كرده و آن را نصب مي كنيد. براي اطلاعات بيشتر راجع به اين تكنيك به مقاله‌ي زير كه در ابتداي اين نوشتار هم آنرا معرفي كردم مراجعه كنيد.



خلاصه
فهميديم با استفاده از دستور خط فرماني regsvr32.exe مي توانيم يك كنترل OLE را Register يا UnRegister بكنيم.
همچنين ليست پارامتهاي اين تابع را ديديم. به علاوه تابعي به نام RegisterOCX ارائه كرديم كه كار نصب OCX را بر عهده دارد. اين تابع از تابع ديگري به نام ExecAndWait براي اجراي regsvr32.exe استفاده مي كند و تا اتمام اجراي آن صبر مي كند. به علاوه فهميديم كه اين تابع براي اجراي درست به يونيت ShellAPI احتياج داشته و از تابع ShellExecuteEx جهت اجراي فايل سود مي جويد.
به علاوه دانستيم كه به سادگي با استفاده از Resourceهاي مي توانيم فايل OCX خود را در داخل exe از ديد كاربر نهايي پنهان كنيم.