Executing RegEdit from Delphi exe

前端 未结 3 979
日久生厌
日久生厌 2021-01-07 17:16

I am having Delphi XE2 Project to write some values in Windows Registry. I am trying to run RegEdit in Delphi Environment. I have tried the following codes :



        
相关标签:
3条回答
  • 2021-01-07 17:59

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

    As designed you write with this code always the right path to your DLL file.

    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.

    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. On x32 OS it will only install the x32 app, on x64 OS it will install both (x32/x64) apps.

    ; 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.
    
    0 讨论(0)
  • 2021-01-07 18:13

    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.

    e.g.:

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

    or write the whole string parameter in one line.

    0 讨论(0)
  • 2021-01-07 18:16

    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;
    
    0 讨论(0)
提交回复
热议问题