简体   繁体   English

从Delphi exe执行RegEdit

[英]Executing RegEdit from Delphi exe

I am having Delphi XE2 Project to write some values in Windows Registry. 我正在使用Delphi XE2项目在Windows注册表中编写一些值。 I am trying to run RegEdit in Delphi Environment. 我试图在Delphi环境中运行RegEdit。 I have tried the following codes : 我尝试了以下代码:

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;

But it is not compiling. 但是它没有编译。 My requirement is to write Expandable String Value for Subnode 01 as "%SystemRoot%\\System32\\Application Wizard 01.dll". 我的要求是将子节点01的可扩展字符串值编写为“%SystemRoot%\\ System32 \\ Application Wizard 01.dll”。 Active Platform for my project is 32Bit but 64Bit is also added and my application will run under both the platform as Administrator. 我的项目的Active Platform为32Bit,但还添加了64Bit,并且我的应用程序将以管理员身份在两个平台下运行。

I think my problem can be resolved by calling Wow64DisableWow64FsRedirection Function and Wow64EnableWow64FsRedirection Function . 我认为可以通过调用Wow64DisableWow64FsRedirection FunctionWow64EnableWow64FsRedirection Function来解决我的问题。 But it is not clear when to call it. 但是尚不清楚何时调用它。 Here is another details of my project . 这是我的项目的另一个细节。

Don't try to fail the redirection, just use this force to make your life easier. 不要试图使重定向失败,只需使用这种力量即可使您的生活更轻松。

If you put a DLL file to the global Windows store, you have to put it into the System32 folder. 如果将DLL文件放入全局Windows存储,则必须将其放入System32文件夹中。 But this folder differs depending on the OS platform and the platform supported by your application. 但是,此文件夹因操作系统平台和应用程序支持的平台而异。

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

For your convenience Windows has an automated redirection also when writing to the registry from a x32 app on a x64 OS so you don't have to put an extra handling for this. 为了方便起见,在从x64 OS上的x32应用程序写入注册表时,Windows也会进行自动重定向,因此您不必为此进行额外的处理。

As designed you write with this code always the right path to your DLL file. 按照设计,您始终使用此代码编写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;

One codebase for all three cases without any compiler switches or OS platform checking. 这三种情况的一个代码库,无需任何编译器切换或OS平台检查。

But you have to take care on installation, to put the files in the right place. 但是您必须小心安装,才能将文件放在正确的位置。

Here is an example script for Inno Setup which handles both platforms. 这是处理两个平台的Inno Setup的示例脚本。 On x32 OS it will only install the x32 app, on x64 OS it will install both (x32/x64) apps. 在x32 OS上,它将仅安装x32应用程序,在x64 OS上,它将安装两个(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

and this is the sample application (one codebase for both platforms). 这是示例应用程序(两个平台的一个代码库)。 There is one compiler switch, to set the form caption. 有一个编译器开关,用于设置表单标题。 That's all. 就这样。

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.

Try like that: 像这样尝试:

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;

You don't use a valid string. 您没有使用有效的字符串。 When doing a line break in a string, you need to close it and concatinate it with the + sign. 在字符串中进行换行时,需要将其关闭并用+号将其修饰。

eg: 例如:

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

or write the whole string parameter in one line. 或将整个字符串参数写在一行中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM