首页 文章

从Delphi exe执行RegEdit

提问于
浏览
-1

我正在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 回答

  • 4

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

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

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

    为了您的方便,当从 x32 app 上的 x32 app 写入注册表时,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
    

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

    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.
    
  • 5

    试试这样:

    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;
    
  • 3

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

    例如 . :

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

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

相关问题