How to set value of Registry Key - delphi

I am having one Delphi XE2 project to write something in registry key. So I have defined the following codes :
procedure TMainForm.BitBtn01Click(Sender: TObject);
var
RegistryEntry: TRegistry;
begin
RegistryEntry:= TRegistry.Create(KEY_READ);
RegistryEntry.RootKey:= HKEY_LOCAL_MACHINE;
if (not RegistryEntry.KeyExists('Software\MyCompanyName\MyName\')) then
begin
RegistryEntry.Access:= KEY_WRITE;
RegistryEntry.OpenKey('Software\MyCompanyName\MyName\',True);
end;
RegistryEntry.CloseKey();
RegistryEntry.Free;
end;
If any string addition I have defined the following codes :
if (not RegistryEntry.KeyExists('Licenced To')) then
begin
RegistryEntry.WriteString('Licenced To', 'MySurname MyFirstName');
end;
My requirements :
01. Setting the default value as shown :
02. In Win64 OS the node is created under HKEY_LOCAL_MACHINE\WOWSys64\Software but not under HKEY_LOCAL_MACHINE\Software.

that desired behavoir for 32-Bit applications.
If you need to write to 64-Bit root you can use KEY_WOW64_64KEY;
In any case you will need elevated rights for writung to HKEY_LOCAL_MACHINE
RegistryEntry.Access:= KEY_WRITE or KEY_WOW64_64KEY;

Related

delphi reg query doesnt output value [duplicate]

I'm trying to read HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run with OpenKeyReadOnly, and GetValueNames, but it's returning values from HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run instead.
How can I read the 64-bit values instead of from a redirect to the 32-bit key?
The program was run as an administrative account. I also tried RegOpenKeyEx and RegEnumValue.
I'm using Delphi 2010.
you must use the KEY_WOW64_64KEY value when open the Registry with the TRegistry class.
from MSDN :
KEY_WOW64_64KEY Indicates that an
application on 64-bit Windows should
operate on the 64-bit registry view.
This flag is ignored by 32-bit
Windows.
This flag must be combined using the
OR operator with the other flags in
this table that either query or access
registry values.
try this sample app.
{$APPTYPE CONSOLE}
uses
Windows,
Classes,
registry,
SysUtils;
procedure ReadRegistry;
var
Registry: TRegistry;
List : TStrings;
begin
Registry := TRegistry.Create(KEY_WRITE OR KEY_WOW64_64KEY);
//Registry := TRegistry.Create(KEY_READ OR KEY_WOW64_64KEY);
List := TStringList.Create;
try
Registry.RootKey := HKEY_LOCAL_MACHINE;
if Registry.OpenKeyReadOnly('\SOFTWARE\Microsoft\Windows\CurrentVersion\Run') then
begin
Registry.GetValueNames(List);
Writeln(List.Text);
end;
Registry.CloseKey;
finally
Registry.Free;
List.Free;
end;
end;
begin
try
ReadRegistry();
except
on E:Exception do
Writeln(E.Classname, ': ', E.Message);
end;
Readln;
end.

Write dword value in Registry with Delphi

My program has a TWebBrowser where the user can open all kinds of local documents. To avoid that for example a Word document is opened in Word instead of in the TWebBrowser (that is to say, in Internet Explorer), I successfully use a fix in the Registry, by executing a .reg file with this instruction:
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Word.Document.12]
"BrowserFlags"=dword:80000024
I am trying to introduce that instruction in the Delphi program itself, with this code:
procedure RegOpenExplorer;
var
reg: TRegistry;
begin
reg:= TRegistry.Create;
try
reg.RootKey:=HKEY_LOCAL_MACHINE;
reg.OpenKey('SOFTWARE\Classes\Word.Document.12\', true);
reg.WriteInteger('BrowserFlags',80000024);
reg.CloseKey;
finally
reg.Free;
end;
end;
It does not work, actually the effect is undoing the fix.
When successfully manipulated with the .reg file (or manually), the Registry key looks like this:
But with my unsuccessful Delphi Code, the key becomes as follows:
The difference is the number in brackets, but that is something that the Registry introduces automatically by itself.
The numeric value in the .reg file is encoded as hex. Since you are passing an integer literal to WriteInteger(), you need to prefix it with a $ to make the compiler interpret it as hex:
reg.WriteInteger('BrowserFlags', $80000024);
That being said, note that you are writing to HKEY_LOCAL_MACHINE, and more importantly you are opening the key with KEY_ALL_ACCESS access rights (the default access rights that TRegistry uses). This is going to require you to run your app elevated as an administrator, if it is not already. You should be setting the TRegistry.Access property to KEY_SET_VALUE instead, and maybe even writing to HKEY_CURRENT_USER instead.
procedure RegOpenExplorer;
var
reg: TRegistry;
begin
reg := TRegistry.Create(KEY_SET_VALUE);
try
reg.RootKey := HKEY_LOCAL_MACHINE; // or HKEY_CURRENT_USER
if reg.OpenKey('SOFTWARE\Classes\Word.Document.12\', true) then
try
reg.WriteInteger('BrowserFlags', $80000024);
finally
reg.CloseKey;
end;
finally
reg.Free;
end;
end;

Changes to TRegistry key dont 'hold'

From my Win32 app I'm reading and writing HKEY_CURRENT_USER\Software\Embarcadero\BDS\9.0\History Lists\hlRunParameters, that is where the Delphi XE2 IDE writes run-time parameters.
This is the write code:
procedure TFrmCleanIDEParams.BtnWriteClick(Sender: TObject);
var
lReg : TRegistry;
lValue,
lKey : String;
i,
lNrToWrite,
lNrRegVals: Integer;
begin
.....
lKey := Trim(EdtRegKey.Text); // '\Software\Embarcadero\BDS\9.0\History Lists\hlRunParameters'
if lKey = '' then Exit;
if lKey[1] = '\' then lKey := Copy(lKey,2);
lReg := TRegistry.Create(KEY_READ or KEY_WRITE);
lReg.RootKey := HKEY_CURRENT_USER;
if not lReg.OpenKey(lKey,false) then
begin
MessageDlg('Key not found', mtError, mbOKCancel, 0);
Exit;
end;
if not lReg.ValueExists('Count') then
begin
MessageDlg('Value ''Count'' not found', mtError, mbOKCancel, 0);
Exit;
end;
lNrRegVals := lReg.ReadInteger('Count');
lNrToWrite := CLBParams.Items.Count; // TCheckListBox
lReg.WriteInteger('Count',lNrToWrite);
for i := 0 to lNrToWrite-1 do
begin
lValue := 'Item' + IntToStr(i);
lReg.WriteString(lValue,CLBParams.Items[i]);
end;
// Remove the rest:
for i := lNrToWrite to lNrRegVals-1 do
lReg.DeleteValue('Item' + IntToStr(i));
end;
Issues:
In RegEdit I see the key contents changing as expected, but the Delphi IDE does not pick up these changes
Some time (reboot?) later the HKEY_CURRENT_USER key has its old values
I think several things could be the reason, but I'm not sure which ones to attack:
I should not use HKEY_CURRENT_USER, but HKEY_USERS. If this is the case, how do I then get the proper S-1-5-etc that I need to use?
It's a Windows 7 64-bit issue, although both my program and the Delphi IDE are 32 bit. (How) do I then need to change the TRegistry.Create?
I read this Delphi: Read 64-bits registry key from 32-bits process post but that still does not tell me if/when to use different 'access keys'.
Do I always need to use this KEY_WOW64_64KEY value regardless of my app being 32/64 bit? I see that HKEY_CURRENT_USER\Software is shared, not redirected. (How) do I need to treat these differently?
BTW UAC is off, it would be nice if my code worked with UAC on too.
The Delphi IDE will only read these values at start up. But you must make sure that you write the registry values after the IDE has finished writing to them.
You should be using HKEY_CURRENT_USER.
You should not be using an alternate registry view flag because that part of the registry is shared.
UAC won't have any impact here because HKEY_CURRENT_USER is writeable for the standard user token.
The only explanation that makes sense is that another process is modifying the values. My guess is that the Delphi IDE is that process.

How can a 32-bit program read the "real" 64-bit version of the registry?

I'm trying to read HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run with OpenKeyReadOnly, and GetValueNames, but it's returning values from HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run instead.
How can I read the 64-bit values instead of from a redirect to the 32-bit key?
The program was run as an administrative account. I also tried RegOpenKeyEx and RegEnumValue.
I'm using Delphi 2010.
you must use the KEY_WOW64_64KEY value when open the Registry with the TRegistry class.
from MSDN :
KEY_WOW64_64KEY Indicates that an
application on 64-bit Windows should
operate on the 64-bit registry view.
This flag is ignored by 32-bit
Windows.
This flag must be combined using the
OR operator with the other flags in
this table that either query or access
registry values.
try this sample app.
{$APPTYPE CONSOLE}
uses
Windows,
Classes,
registry,
SysUtils;
procedure ReadRegistry;
var
Registry: TRegistry;
List : TStrings;
begin
Registry := TRegistry.Create(KEY_WRITE OR KEY_WOW64_64KEY);
//Registry := TRegistry.Create(KEY_READ OR KEY_WOW64_64KEY);
List := TStringList.Create;
try
Registry.RootKey := HKEY_LOCAL_MACHINE;
if Registry.OpenKeyReadOnly('\SOFTWARE\Microsoft\Windows\CurrentVersion\Run') then
begin
Registry.GetValueNames(List);
Writeln(List.Text);
end;
Registry.CloseKey;
finally
Registry.Free;
List.Free;
end;
end;
begin
try
ReadRegistry();
except
on E:Exception do
Writeln(E.Classname, ': ', E.Message);
end;
Readln;
end.

Detect if an OCX class is registered in Windows

i need to know how can detect if an OCX class (ClassID) is registred in Windows
something like
function IsClassRegistered(ClassID:string):boolean;
begin
//the magic goes here
end;
begin
if IsClassRegistered('{26313B07-4199-450B-8342-305BCB7C217F}') then
// do the work
end;
you can check the existence of the CLSID under the HKEY_CLASSES_ROOT in the windows registry.
check this sample
function ExistClassID(const ClassID :string): Boolean;
var
Reg: TRegistry;
begin
try
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_CLASSES_ROOT;
Result := Reg.KeyExists(Format('CLSID\%s',[ClassID]));
finally
Reg.Free;
end;
except
Result := False;
end;
end;
The problem with (many, many) suggestions of crawling the registry is that:
there is more than one registry location you would need to look at
a class can be registered and not exist in the registry
Registration-free COM allows a class to be available without it being registered. Conceptually you don't want to know if a class is "registered", you just want to know it is registered enough to be created.
Unfortunately the only (and best) way to do that is to create it:
//Code released into public domain. No attribution required.
function IsClassRegistered(const ClassID: TGUID): Boolean;
var
unk: IUnknown;
hr: HRESULT;
begin
hr := CoCreateInstance(ClassID, nil, CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, IUnknown, {out}unk);
unk := nil;
Result := (hr <> REGDB_E_CLASSNOTREG);
end;
ActiveX/COM is a complex beast, registrations have many pieces to them, and Vista+ onward make it more complicated with UAC Registry Virtualization rules.
The best option is to simply attempt to instantiate the OCX and see if it succeeds or fails. That will tell you whether the OCX is registered correctly, all the pieces are hooked up, whether the OCX is even usable within the calling user's context, etc.

Resources