首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 運行時自動註冊 ActiveX 控件:LoadLibrary + DllRegisterServer 替代 RegSvr32

     編輯:Delphi

前言

Delphi 專案若使用 ActiveX 控件 (.ocx) 或含類型庫的 DLL,部署時常面臨「目標機未註冊」問題。傳統解法:安裝程式呼叫 regsvr32.exe。本文示範程式自行載入 DLL/OCX 並呼叫 DllRegisterServer,實現零依賴自動註冊。

核心原理

標準 ActiveX DLL/OCX 匯出兩個函數:

  • DllRegisterServer:註冊類別工廠、介面、類別 ID 至登錄表。
  • DllUnregisterServer:移除註冊資訊。

流程:LoadLibrary → GetProcAddress('DllRegisterServer') → 呼叫函數指標 → FreeLibrary。

通用註冊/解除註冊函數

function OLERegister(const FileName: string; Register: Boolean): Boolean;
type
  TRegisterFunc = function: HResult; stdcall;
var
  hLib: THandle;
  Proc: TRegisterFunc;
begin
  Result := False;
  hLib := LoadLibrary(PChar(FileName));
  if hLib > 0 then
  try
    if Register then
      Proc := GetProcAddress(hLib, 'DllRegisterServer')
    else
      Proc := GetProcAddress(hLib, 'DllUnregisterServer');

    if Assigned(Proc) then
      Result := Proc >= 0;  { S_OK = 0 表示成功 }
  finally
    FreeLibrary(hLib);
  end;
end;

應用場景一:視覺化控件設計時已放置於表單

應用程式初始化時會嘗試建立控件實例,若未註冊會觸發 EOleSysError (CLASS_NOT_REGISTERED)。捕獲例外並自動註冊:

type
  TAutoRegForm = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    procedure CheckException(Sender: TObject; E: Exception);
  end;

procedure TAutoRegForm.FormCreate(Sender: TObject);
begin
  Application.OnException := CheckException;
  try
    { 嘗試建立控件實例觸發例外 }
    CreateOleObject('Demo.Demo');
  except
    on E: EOleSysError do
      if HResult(E.ErrorCode) = CO_E_CLASSSTRING then
      begin
        if OLERegister('D:\Flash.ocx', True) then
          CreateOleObject('Demo.Demo')  { 重試 }
        else
        begin
          MessageBox(Handle, '控件註冊失敗,程式無法執行', '錯誤', MB_OK or MB_ICONERROR);
          Application.Terminate;
        end;
      end
      else
        raise;
  end;
end;

procedure TAutoRegForm.CheckException(Sender: TObject; E: Exception);
begin
  if E is EOleSysError then
  begin
    if HResult(EOleSysError(E).ErrorCode) = REGDB_E_CLASSNOTREG then
      OLERegister('D:\Flash.ocx', True);
  end
  else
    Application.ShowException(E);
end;

應用場景二:運行時動態建立 (CreateOleObject)

var
  Obj: Variant;
begin
  try
    Obj := CreateOleObject('MyControl.MyClass');
  except
    on E: EOleSysError do
      if HResult(E.ErrorCode) = CO_E_CLASSSTRING then
      begin
        if OLERegister('MyControl.ocx', True) then
          Obj := CreateOleObject('MyControl.MyClass')  { 重試 }
        else
          raise Exception.Create('ActiveX 控件註冊失敗');
      end
      else
        raise;
  end;
end;

注意事項

  • 管理員權限:寫入 HKCR\CLSID 需管理員權限,Manifest 需 requireAdministrator 或安裝程式處理。
  • 32/64 位元相容:32 位元 Delphi 應用程式僅能載入 32 位元 OCX/DLL。64 位元系統需確保目標控件有 32 位元版本 (SysWOW64)。
  • 相依性:目標 OCX 可能依賴其他 DLL (如 MFC、VC++ Runtime),需隨附部署。
  • 數位簽章:載入未簽章 DLL 可能被防毒軟體攔截,建議對自製 ActiveX 進行簽章。

結語

以 LoadLibrary/GetProcAddress 呼叫 DllRegisterServer 實現 ActiveX 自動註冊,是 Delphi 部署含 COM 元件應用程式的經典技巧。掌握例外捕獲與重試機制,能讓應用程式在未註冊環境下自動修復,大幅降低部署支援成本。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved