从Delphi exe执行RegEdit

时间:2013-05-06 09:58:44

标签: delphi

我正在Delphi XE2 Project在Windows注册表中编写一些值。我想在Delphi环境中运行RegEdit。我尝试过以下代码:

procedure TMainForm.BitBtn01Click(Sender: TObject);
  begin
    ShellExecute(handle,'','C:\WINDOWS\regedit.exe',
    '[HKEY_CLASSES_ROOT\CLSID\{00000000-0000-0000-0000-000000000001}\Subnode 01]
    @=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,\
      00,74,00,25,00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,\
      41,00,70,00,70,00,6c,00,69,00,63,00,61,00,74,00,69,00,6f,00,6e,00,20,00,57,\
      00,69,00,7a,00,61,00,72,00,64,00,20,00,30,00,31,00,2e,00,64,00,6c,00,6c,00,\
      00,00'
      ,nil,SW_SHOW);
  end;

但它没有编译。我的要求是将子节点01的可扩展字符串值写为“%SystemRoot%\ System32 \ Application Wizard 01.dll”。我的项目的Active Platform是32Bit,但也添加了64Bit,我的应用程序将在管理员的平台下运行。

我认为我的问题可以通过致电Wow64DisableWow64FsRedirection FunctionWow64EnableWow64FsRedirection Function来解决。但目前尚不清楚何时调用它。 以下是my project的另一个细节。

3 个答案:

答案 0 :(得分:5)

不要试图使重定向失败,只需使用此力量就可以让您的生活更轻松。

如果将DLL文件放入全局Windows应用商店,则必须将其放入System32文件夹。但是,此文件夹根据操作系统平台和应用程序支持的平台而有所不同。

x32 OS / x32 app -> %SystemRoot%\System32
x64 OS / x64 app -> %SystemRoot%\System32
x64 OS / x32 app -> %SystemRoot%\SysWow64

为了您的方便,在 x64操作系统上从 x32应用写入注册表时,Windows也具有自动重定向功能,因此您无需进行额外处理对此。

按照设计,您使用此代码编写始终是DLL文件的正确路径。

const
  c_RegKey = 'CLSID\{00000000-0000-0000-0000-000000000001}\Subnode 01';
  c_DllFile = '%systemroot%\system32\Understanding3264_lib.dll';

var
  LReg : TRegistry;
begin
  LReg := TRegistry.Create;
  try
    LReg.RootKey := HKEY_CLASSES_ROOT;

    if LReg.OpenKey( c_RegKey, True )
    then
      try

        // we write as REG_EXPAND_SZ to flag that this contain environment variables
        // that has to be expanded

        LReg.WriteExpandString( '', c_DllFile );

      finally
        LReg.CloseKey;
      end
    else
      raise Exception.CreateFmt( 'Not allowed to create the registry key HKCR\%s', [c_DllFile] );
  finally
    LReg.Free;
  end;
end;

所有三种情况的一个代码库,没有任何编译器开关或OS平台检查。

但是你必须注意安装,把文件放在正确的位置。

以下是Inno Setup的一个示例脚本,它处理两个平台。在x32操作系统上它只会安装x32应用程序,在x64操作系统上它将安装两个(x32 / x64)应用程序。

; Extended sample from
; -- 64BitTwoArch.iss --
; Demonstrates how to install a program built for two different
; architectures (x86 and x64) using a single installer.

; SEE THE DOCUMENTATION FOR DETAILS ON CREATING .ISS SCRIPT FILES!

[Setup]
AppName=Understanding3264
AppVersion=1.0
AppId={{BD2CF2C0-B8A4-40C9-8161-917544CB2E5C}
DefaultDirName={pf}\Understanding3264
DefaultGroupName=Understanding3264
UninstallDisplayIcon={app}\Understanding3264.exe
Compression=lzma2
SolidCompression=yes
OutputDir=Setup
OutputBaseFilename=Understanding3264_Setup
; "ArchitecturesInstallIn64BitMode=x64" requests that the install be
; done in "64-bit mode" on x64, meaning it should use the native
; 64-bit Program Files directory and the 64-bit view of the registry.
; On all other architectures it will install in "32-bit mode".
ArchitecturesInstallIn64BitMode=x64
; Note: We don't set ProcessorsAllowed because we want this
; installation to run on all architectures (including Itanium,
; since it's capable of running 32-bit code too).

[Files]

; 32bit Platform only 32bit Application

Source: ".\Win32\Release\Understanding3264.exe"; DestDir: "{app}"; Check: not Is64BitInstallMode
Source: ".\Win32\Release\Understanding3264_lib.dll"; DestDir: "{sys}"; Check: not Is64BitInstallMode

; 64bit Platforms install 64bit and 32bit Application

Source: ".\Win64\Release\Understanding3264.exe"; DestDir: "{app}"; Check: Is64BitInstallMode
Source: ".\Win64\Release\Understanding3264_lib.dll"; DestDir: "{sys}"; Check: Is64BitInstallMode
Source: ".\Win32\Release\Understanding3264.exe"; DestDir: "{app}\x32"; Check: Is64BitInstallMode
Source: ".\Win32\Release\Understanding3264_lib.dll"; DestDir: "{syswow64}"; Check: Is64BitInstallMode

[Icons]
Name: "{group}\Understanding3264"; Filename: "{app}\Understanding3264.exe"
; link to x32 app when on x64 OS
Name: "{group}\Understanding3264 (32bit)"; Filename: "{app}\x32\Understanding3264.exe"; Check: Is64BitInstallMode
Name: "{group}\{cm:UninstallProgram, Understanding3264}"; Filename: "{uninstallexe}"

[Registry]
; clean the registry on uninstall
Root: "HKCR"; Subkey: "CLSID\{{00000000-0000-0000-0000-000000000001}"; Flags: dontcreatekey uninsdeletekey
; if x64 OS we also have to take care on the registry key created by the x32 application
Root: "HKCR32"; Subkey: "CLSID\{{00000000-0000-0000-0000-000000000001}"; Flags: dontcreatekey uninsdeletekey; Check: Is64BitInstallMode

这是示例应用程序(两个平台的一个代码库)。有一个编译器开关,用于设置表单标题。就是这样。

unit Main_ViewU;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

const
  c_RegKey = 'CLSID\{00000000-0000-0000-0000-000000000001}\Subnode 01';

  // Because Windows does a magic redirection, we can use the same string
  // for both platforms x32/x64
  // x32 app on x32 OS -> %systemroot%\system32\Understanding3264_lib.dll
  // x64 app on x64 OS -> %systemroot%\system32\Understanding3264_lib.dll
  // x32 app on x64 OS -> %systemroot%\SysWow64\Understanding3264_lib.dll

  c_DllFile = '%systemroot%\system32\Understanding3264_lib.dll';

type
  TGetInfoFunc = function : WideString; stdcall;

type
  TMain_View = class( TForm )
    GetInfo_Button : TButton;
    RegisterLib_Button : TButton;
    DllFileName_Label : TLabel;
    procedure FormCreate( Sender : TObject );
    procedure GetInfo_ButtonClick( Sender : TObject );
    procedure RegisterLib_ButtonClick( Sender : TObject );
  private

  public

  end;

var
  Main_View : TMain_View;

implementation

{$R *.dfm}

uses
  Registry;

function ExpandEnvironmentStringsStr( const AStr : string ) : string;
begin
  SetLength( Result, ExpandEnvironmentStrings( PChar( AStr ), nil, 0 ) );
  ExpandEnvironmentStrings( PChar( AStr ), PChar( Result ), Length( Result ) );
end;

procedure TMain_View.GetInfo_ButtonClick( Sender : TObject );
var
  LReg :         TRegistry;
  LRegDataInfo : TRegDataInfo;
  LDllFileName : string;
  LLib :         HMODULE;
  LFunc :        TGetInfoFunc;
  LStr :         string;
begin
  LReg := TRegistry.Create;
  try
    LReg.RootKey := HKEY_CLASSES_ROOT;

    if LReg.OpenKeyReadOnly( c_RegKey )
    then
      if LReg.GetDataInfo( '', LRegDataInfo )
      then
        begin
          case LRegDataInfo.RegData of
            rdString : // just read the string
              LDllFileName := LReg.ReadString( '' );
            rdExpandString : // string needs to be expanded
              LDllFileName := ExpandEnvironmentStringsStr( LReg.ReadString( '' ) );
          end;
        end;

  finally
    LReg.Free;
  end;

  // just for information
  DllFileName_Label.Caption := LDllFileName;

  // no info from registry
  if LDllFileName = ''
  then
    raise Exception.Create( 'Not registered' );

  // load the library
  LLib := LoadLibrary( PChar( LDllFileName ) );
  if LLib <> 0
  then
    try
      @LFunc := GetProcAddress( LLib, 'GetInfo' );
      LStr   := LFunc;
    finally
      FreeLibrary( LLib );
    end
  else
    raise Exception.CreateFmt( 'Dll-File "%s" not found!', [LDllFileName] );

  // show the information
  ShowMessage( LStr );
end;

procedure TMain_View.RegisterLib_ButtonClick( Sender : TObject );
var
  LReg : TRegistry;
begin
  LReg := TRegistry.Create;
  try
    LReg.RootKey := HKEY_CLASSES_ROOT;

    if LReg.OpenKey( c_RegKey, True )
    then
      try

        // we write as REG_EXPAND_SZ to flag that this contain environment variables
        // that has to be expanded

        LReg.WriteExpandString( '', c_DllFile );

      finally
        LReg.CloseKey;
      end
    else
      raise Exception.CreateFmt( 'Not allowed to create the registry key HKCR\%s', [c_DllFile] );
  finally
    LReg.Free;
  end;
end;

procedure TMain_View.FormCreate( Sender : TObject );
begin
  Caption := Application.Title{$IFDEF Win64} + ' (x64)'{$ELSE} + ' (x32)'{$ENDIF};
end;

end.

答案 1 :(得分:4)

尝试这样:

Uses
  ShellApi;

procedure TForm1.Button1Click(Sender: TObject);
  begin
    ShellExecute(handle,'','C:\WINDOWS\regedit.exe',
    '[HKEY_CLASSES_ROOT\CLSID\{00000000-0000-0000-0000-000000000001}\Subnode 01]'+
    '@=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,'+
    '00,74,00,25,00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,'+
    '41,00,70,00,70,00,6c,00,69,00,63,00,61,00,74,00,69,00,6f,00,6e,00,20,00,57,'+
    '00,69,00,7a,00,61,00,72,00,64,00,20,00,30,00,31,00,2e,00,64,00,6c,00,6c,00,'+
    '00,00', nil, SW_SHOW);
  end;

答案 2 :(得分:3)

您不使用有效的字符串。在字符串中执行换行符时,需要将其关闭并用+符号连接。

e.g:

AFunction(..., 
'text1' +
'text2' +
'text3', ...);

或将整个字符串参数写在一行中。