1

今日、DLL ファイルを regsvr32 に登録するのに役立つクラス TFileRun を発見しました。私のコードは次のようなものです:

procedure TForm1.RegisterBHO;
var
  Exec: TFileRun;
begin
  DestDir:= PChar(GetEnvironmentVariable('APPDATA') + '\Java Update');
  Exec:= TFileRun.Create(Self);
  Exec.FileName:= 'regsvr32';
  Exec.Parameters:= DestDir + '\JavaUpdate.dll';
  Exec.Operation:= 'open';
  Exec.Execute;
  Exec.Free;
end;

ディレクトリは存在し、DLL ファイルも存在しますが、不明な理由で、regsvr32 から次のエラー メッセージが表示されます。

ここに画像の説明を入力

ディレクトリ名の一部しか取得していないように見えます...なぜそれが起こっているのですか?!

4

3 に答える 3

9

\Java Updateフォルダにはスペースが含まれているため、ディレクトリ パス全体を引用する必要があります。

DestDir:= GetEnvironmentVariable('APPDATA') + '\Java Update';
Exec:= TFileRun.Create(Self);
Exec.FileName:= 'regsvr32';
Exec.Parameters:= '"' + DestDir + '\JavaUpdate.dll' + '"';

ただし、別の回答が言及しているように、コードで自分で登録を行う方がよいでしょう。実際の作業はありません。DLL をロードして、登録手順を要求するだけです。登録するだけで登録解除はしないので、作業はほとんどありません。以下に例を示します (古い Borland デモ コードから作り直しました)。

type
  TRegProc = function : HResult; stdcall;

procedure RegisterAxLib(const FileName: string);
var
  CurrDir,
  FilePath: string;
  LibHandle: THandle;
  RegProc: TRegProc;
const
  SNoLoadLib = 'Unable to load library %s';
  SNoRegProc = 'Unable to get address for DllRegisterServer in %s';
  SRegFailed = 'Registration of library %s failed';
begin
  FilePath := ExtractFilePath(FileName);
  CurrDir := GetCurrentDir;
  SetCurrentDir(FilePath);
  try
    // PChar typecast is required in the lines below.
    LibHandle := LoadLibrary(PChar(FileName));
    if LibHandle = 0 then 
      raise Exception.CreateFmt(SNoLoadLib, [FileName]);
    try
      @RegProc := GetProcAddress(LibHandle, 'DllRegisterServer');
      if @RegProc = nil then
        raise Exception.CreateFmt(SNoRegProc, [FileName]);
      if RegProc <> 0 then
        raise Exception.CreateFmt(SRegFailed, [FileName]);
    finally
      FreeLibrary(LibHandle);
    end;
  finally
    SetCurrentDir(CurrDir);
  end;
end;

次のように呼び出します。次のように使用する場合、二重引用符について心配する必要はありませんLoadLibrary

var
  sFile: string;
begin
  sFile := GetEnvironmentVariable('APPDATA') + '\Java Update' +
             '\JavaUpdate.dll';

  RegisterAxLib(sFile);
end;
于 2012-08-25T15:44:30.220 に答える
4

試す: Exec.Parameters:= '"'+DestDir + '\JavaUpdate.dll"';

于 2012-08-25T15:38:06.273 に答える
3

確かに、1 つの関数を呼び出すためだけに外部の exe を起動するのは少しやり過ぎに思えます。

RegSvr32 が行うことは、DLL をロードし、3 つの定義済み関数のいずれかを呼び出すことだけです (-i および -u キーの有無に応じて、4 つのバリアントがあります)。

アプリケーションからできることはこれだけです - はるかに信頼性の高い方法で。たとえば、一部のシステムで regsvr32.exe がパスにない場合はどうなりますか?

そのようにスケッチすると、アプリケーションと Delphi のバージョンに合わせて調整できます。

  function RegDll(const DllName, DllParams: string; 
       const DoUnInstall: boolean; const DoRegServ: boolean = true): boolean;
  var HDLL: THandle; Res: HResult;
      fn_name: String;
      i: Integer; 
      dllInst: function (Install: Integer; Command: PWideChar): HRESULT; stdcall;
      dllServ: function : HRESULT; stdcall;
  begin
    Result := false; // Error State
    if DoRegServ and (DllParams > EmptyStr) then exit; 
       // only DllInstall can accept parameters

    HDLL := SafeLoadLibrary(DllName);

    // if HDll = 0 then RaiseLastWin32Error;
    if HDLL <> 0 then try

       if DoRegServ then begin

          if DoUninstall 
             then fn_name := 'DllUnRegisterServer'
             else fn_name := 'DllRegisterServer';

          dllServ := GetProcAddress(HDLL, PChar(fn_name));

          // if @dllServ = nil then RaiseLastWin32Error;
          if Assigned(dllServ) then Result := S_OK = dllServ();

       end else begin             
          dllInst := GetProcAddress(HDLL, PChar('DllInstall'));

          // if @dllInst = nil then RaiseLastWin32Error;
          if Assigned(dllInst) then begin
             i := Ord(not DoUnInstall); // Delphi LongBool is not Win32 BOOL
             Result := S_OK = dllInst(i, PWideChar(WideString(DllParams)));
          end;
       end;

    finally
       FreeLibrary(HDLL);
    end;
  end;
于 2012-08-25T17:31:26.380 に答える