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