1

i tried to use this tutorial to work: https://stackoverflow.com/a/14710803/1149172

first create a file with name uac.manifest with provided content then create uac.rc width content of 1 24 "uac.manifest"

then copied the files to program folder (in delphi program sources folder) and changed the project file like this:

program Project4;

{.$R 'uac.res' 'uac.rc'} // UAC only

uses
  Vcl.Forms,
  Unit6 in 'Unit6.pas' {Form6};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm6, Form6);
  Application.Run;
end.

at last i put my registery code at the form

procedure AddEntryToRegistry;
var key: string;
     Reg: TRegIniFile;
begin
  key := 'Software\Microsoft\Windows\CurrentVersion\Run';
  Reg := TRegIniFile.Create;
  try
    Reg.RootKey:=HKEY_LOCAL_MACHINE;
    Reg.CreateKey(Key);
    if Reg.OpenKey(Key,False) then Reg.WriteString(key, 'MyApp', 'c:MyApp.exe');
  finally
    Reg.Free;
  end;
end;

every thing seems ok and i dont got any runtime rror but after clicking the button nothing happened (dont shoe any error and dont add the key to registery)!!! where is wrong with my works!?

my delphi is xe5 and working on win 8ul

Community
  • 1
  • 1
roozgar
  • 412
  • 1
  • 5
  • 19
  • 1) You don't need to call `Reg.CreateKey`, but if you do you should check the return value. 2) You can create the key using `Reg.OpenKey` if it doesn't exist by passing `True` as the second argument. 3) You don't do any testing to find out why `Reg.OpenKey` fails if it does (your `if` only does something if it succeeds, but doesn't provide any information if it fails - use GetLastError to find out why). 4) #3 would probably explain why "anything happened!!!!" (which I think probably should say "nothing happened"). 5) Are you sure only 1 manifest exists in your app? No version info added? – Ken White Apr 02 '14 at 17:57
  • 4-i just mean `dont show any error and dont added the key to registry` 5-version info added also in that tutorial said when adding `{.$R 'uac.res' 'uac.rc'}` it will compile resource and remove other resources/manifests , how can i remove the other manifests!? 1-2-3 i removed the `Reg.CreateKey` nut nothing changed... – roozgar Apr 02 '14 at 18:18

2 Answers2

2

Firstly, I'm going to take it as read that your program is running elevated. If that's not happening then there's no need to look at any code. You did not say otherwise, so let us proceed under the assumption that you are succeeding to elevate.

You are suffering from the registry redirector. Your 32 bit process is running on a 64 bit machine. And so HKLM\Software is redirected to the 32 bit view, stored at HKLM\Software\Wow6432Node.

You can, if you need, use the KEY_WOW64_64KEY flag to access the 64 bit view. Combine this with the flags in the registry object's Access property.

However, the system reads keys from both 32 and 64 bit views of the registry when enumerating the startup programs so you do not need to do this. For the sake of simplicity and predictability I would leave your 32 bit program writing to the 32 bit view.

Your call to CreateKey should be removed. The system creates that key and you can safely assume it exists. And you should not use TRegIniFile. Use TRegistry instead.

Your code should look like this:

procedure AddEntryToRegistry;
var
  Reg: TRegistry;
begin
  Reg := TRegistry.Create(KEY_ALL_ACCESS);
  try
    Reg.RootKey := HKEY_LOCAL_MACHINE;
    if Reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\Run', False) then
      Reg.WriteString('MyApp', 'C:\MyApp.exe');
  finally
    Reg.Free;
  end;
end;

Should you feel that you need to write to the 64 bit view then it is done like this:

procedure AddEntryToRegistry;
var
  Reg: TRegistry;
begin
  Reg := TRegistry.Create;
  try
    Reg.RootKey := HKEY_LOCAL_MACHINE;
    Reg.Access := KEY_ALL_ACCESS or KEY_WOW64_64KEY;
    if Reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\Run', False) then
      Reg.WriteString('MyApp', 'C:\MyApp.exe');
  finally
    Reg.Free;
  end;
end;

Judging by your comments, it looks like you might be failing to elevate. The lack of a UAC dialog when your program starts is the tell-tale sign that this is happening. Once your program starts without a UAC dialog, there's no point continuing. You will not write to HKLM without elevation.

Regarding your manifest, you can link only one. So if you want to specify a manifest other than the Enable runtime themes manifest that the IDE can provide, you need to do it all yourself.

In the project options specify that you want to use a custom manifest. That's under Project | Options | Application | Runtime themes. Set the drop down to Use custom manifest. And then supply the file name of your manifest. You'll want to add in the comctl32 v6 part to make sure that you get runtime themes. But don't worry about that now. Just concentrate on getting elevation sorted, and the registry code working.

You are also silently ignoring any errors which does make things a little harder to debug. If it so happens that you are not elevating, then running the code is rather pointless. You know it must fail. But you could at least make it easier to diagnose the problem by throwing an error if OpenKey fails.

procedure AddEntryToRegistry;
var
  Reg: TRegistry;
begin
  Reg := TRegistry.Create(KEY_ALL_ACCESS);
  try
    Reg.RootKey := HKEY_LOCAL_MACHINE;
    if not Reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\Run', False) then
      raise EMyExceptionClass.Create('Could not open registry key');
    Reg.WriteString('MyApp', 'C:\MyApp.exe');
  finally
    Reg.Free;
  end;
end;

One final point to make is that writing to this registry key is an admin task. You should require elevation once only, not every time your application starts. If you are planning to require elevation for your application just for this purpose, then you must re-design. This admin task should be performed outside your main application. The most natural place is inside your install program which users will accept requiring elevation.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • i changed key path to `key := 'Software\KEY_WOW64_64KEY\Microsoft\Windows\CurrentVersion\Run';` but nothing here too , it seems the registry dont allow the program to writing here because i can write to `HCU/software` in this project easily... – roozgar Apr 02 '14 at 18:27
  • 1
    No. That's no good. You are now trashing your registry. Read my answer again, and read the link in my answer. Don't modify the Key. It is correct. If you continue this way you will just spray rubbish all over your registry. – David Heffernan Apr 02 '14 at 18:29
  • 1
    You need to look in the Wow6432Node like I said. You'll find your value there. But mostly you need to slow down a bit. – David Heffernan Apr 02 '14 at 18:31
  • i removed `createKey` but i read more and im confounded more!! in that link msdn said i dont need to do anything.however my key dont saved on both 32 or 64 bits views... – roozgar Apr 02 '14 at 18:50
  • 1
    Run the two examples from my updated answer. First one writes to 32 bit view, second one to 64 bit view. – David Heffernan Apr 02 '14 at 18:52
  • i searched and see my application cant to write to `HKLM` and can write to `HCU` due to permissions.program to write to `HKLM` must have administrator access so i tried to change the manifest and resources.as i said my current app can add key to `HKEY_CURRENT_USER\SOFTWARE\PMP\SWCode` without changes but cant write on `HKLM`...also i added your codes to my project and None of them dont working ... – roozgar Apr 02 '14 at 19:16
  • 2
    Can you refresh your browser and read my first paragraph. Are you seeing the UAC dialog? If not it's pointless trying to run any code. You know that it will fail. You do need to understand what's going on. If the code from my answer really does fail to write then you cannot be running elevated. Which means that you are not encountering a UAC dialog. A basic pre-requisite for doing this sort of work is an understanding of UAC. If you don't have that then you should take some time off to gain the understanding. – David Heffernan Apr 02 '14 at 19:18
  • i got you Exception error `Could not open registry key`, this mean it cant open the key so my problem is regarding UAC? yes?! also i used `Project | Options | Application | Runtime themes` to provide a custom manidest file a but i dont help too! – roozgar Apr 02 '14 at 20:11
  • 1
    I've said it many times now. It's pointless running code until you are elevated. Let me ask my question again. **Are you seeing the UAC dialog?** – David Heffernan Apr 02 '14 at 20:16
  • 1
    So that's what you need to concentrate on. Forget about the code. Get the UAC manifest working. – David Heffernan Apr 02 '14 at 20:24
  • ok,i changed the manifest and got this error `Unable to create process.the requested Operation requires elevation` also i found your this post `http://stackoverflow.com/a/6108389/1149172` then tried to run output exe file (`project4.exe`) as administrator the UAC dialog appeared ,also by clicking the button added the key to 64 bit view of registry!! why delphi cant create process in ide run?!? – roozgar Apr 02 '14 at 20:52
  • 2
    I think we are not on to a different question. I believe I answered at least the original question that you asked. What you need to do is what I said at that post. Run the Delphi IDE as admin, and when it starts the process to be debugged, that will also run as admin. – David Heffernan Apr 02 '14 at 20:55
  • thank you for all of your answers and your patience.but i think its a bit stupidly, for a small part of my project (a checkbox to run in start up with windows) i must run delphi as administrator also run the output app as administrator too,i have a last question,each time i run the exe file the uac appear,how can i prevent to asking every time and just save the permission at first time!? – roozgar Apr 02 '14 at 21:19
  • 2
    You cannot. UAC dialog is shown every time. What you should be doing is not forcing your app to run elevated. That's really bad practice. Use a separate process to modify the registry. Install program is ideal. – David Heffernan Apr 02 '14 at 21:22
  • for work on this program during development i found a simple way except running delphi as administrator ...just disabled UAC from control panel... :D – roozgar Apr 04 '14 at 00:42
2

You are saving your app path to the Run key of the HKEY_LOCAL_MACHINE hive. You should be using the HKEY_CURRENT_USER hive instead, then you will not need to use UAC elevation anymore (unless your app is doing other things that require admin rights).

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • But now the app will start when just one specific user logs on. HKCU and HKLM have different meanings here. – David Heffernan Apr 03 '14 at 01:27
  • I am aware of that. But if the app is being run on a per-user basis, then it makes sense to store per-user settings, and that is where `HKCU` comes into play. – Remy Lebeau Apr 03 '14 at 01:30
  • as i said in forum because this is a service it just run on 1 account and its administrator so its not important if this program just run on current user account.however i checked my registry and in `HKCU` there isnt key `Software\Microsoft\Windows\CurrentVersion\Run` ,you mean i create it before adding my values!? – roozgar Apr 04 '14 at 00:40
  • 1
    If it is a true service, then you should not be using the `Run` key at all. Configure the service for `SERVICE_AUTO_START` instead, then the SCM will start it during system startup. If it is a plain app, then a `Run` key does indeed exist in `HKCU` and always has: `HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run`. If it does not exist, then yes, create it. A 32bit app running on a 64bit system does not use `Wow6432Node` for this particular key under `HKCU`, but it does for `HKLM`, so you have to use the `KEY_WOW64_32KEY` and `KEY_WOW64_64KEY` flags accordingly for `HKLM`. – Remy Lebeau Apr 04 '14 at 01:21