3

I am using the following code to try to make a RunOnce entry:

program RunOnceTest;

{$APPTYPE CONSOLE}

uses
  SysUtils, Registry, Windows;

var
  R: TRegistry;
begin
  try
    WriteLn('Testing RunOnStartup.......');


    R := TRegistry.Create;
    try
      R.RootKey := HKEY_LOCAL_MACHINE;
      R.LazyWrite := False;
      R.OpenKey('Software\Microsoft\Windows\CurrentVersion\RunOnce', True) ;
      R.WriteString('this', 'that') ;
      R.CloseKey;
    finally
      R.free;
    end;

    WriteLn('Test Finished');

    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

I run the app, and it executes.

However, there is no entry at:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce

in my registry. Do I need administrator privileges? What else do I need to do?

ADDED: I should explain better and really ask a question about what I am trying to do. I am trying to get my app to run automatically at startup. Lot's of applications do this without appearing to require admin privileges. What is the normal way to do this?

Nick Hodges
  • 16,902
  • 11
  • 68
  • 130
  • 1
    For writing to HKEY_LOCAL_MACHINE you will need administrator privileges, yes. – martinstoeckli Aug 08 '11 at 15:22
  • Which OS version do you use? And yes, you need admin privileges. If Vista/Win7 - try right click - run as administrator. – Heinrich Ulbricht Aug 08 '11 at 15:23
  • It's Windows 7/64. And so I guess I'll now have to figure out how to get user privileges in my app, eh? Great..... – Nick Hodges Aug 08 '11 at 15:25
  • Nah, not that hard and you get used to it. – Heinrich Ulbricht Aug 08 '11 at 15:34
  • I've added more info to really ask what I want to do: How do I get my Delphi app to "Run on startup" like a ton of other apps I have? – Nick Hodges Aug 08 '11 at 15:43
  • @Nick When you were at Embarcadero, did the developers run with UAC enabled on their dev machines? – David Heffernan Aug 08 '11 at 15:45
  • 2
    Okay, found the problem: I really only want the thing to run for Current User, so I need HKEY_CURRENT_USER not HKEY_LOCAL_MACHINE. – Nick Hodges Aug 08 '11 at 15:46
  • So what is the proper etiquette? I found the answer -- is it considered okay to answer my own question after you fine people helped me so ably? – Nick Hodges Aug 08 '11 at 15:47
  • 1
    If your answer is not part of any existing answer then yes, answer it yourself and accept it. – CodesInChaos Aug 08 '11 at 15:49
  • 2
    Nick, if you have an answer to the original question you asked, then go ahead and add it as your own answer. It sounds like you have an answer to a different question, though. (Perhaps it's to the question you *should* have asked.) – Rob Kennedy Aug 08 '11 at 15:51
  • 2
    If you want your app to run at every windows start up I wouldn't use RunOnce cause they get deleted after they run, well, once... The Run key is there to be used for apps that need to run every time Windows starts. – Marjan Venema Aug 08 '11 at 18:29
  • I'm not completely familiar with TRegistry, but if you aren't getting errors then your app may be virtualized. You don't want this I can assure you. – David Heffernan Aug 08 '11 at 19:13
  • 1
    @Nick, do you really need to ensure it forces the run section every time your app runs? My approach would be to create this registry key in the installer of your application and then make the installer require admin rights. That way it is added to your registry without your application needing elevation. – R-D Aug 09 '11 at 09:29

2 Answers2

8

First of all you need to have admin rights to write there. Mostly it's just installers that write to this key and they generally run elevated. Add this to your application manifest if that's the way you want to go:

<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
  <security>
    <requestedPrivileges>
      <requestedExecutionLevel
        level="requireAdministrator"
        uiAccess="false"/>
    </requestedPrivileges>
  </security>
</trustInfo>

If this write to HKLM is being made from an application that doesn't otherwise need elevation then please consider separating out the write to HKLM into a separate process so that only that registry key write needs elevation. This is best practise with UAC.

The other thing that might bite you is that your Delphi app will be 32 bit and so subject to registry redirection. Accesses of HKLM\Software will get redirected to HKLM\Software\Wow6432Node.

On a 64 bit system I think you should endeavour to write to HKLM\Software and so you'll need to disable redirection. Do this by including KEY_WOW64_64KEY in the Access property of your TRegistry instance.

Windows will merge both views of the registry when it processes Run and RunOnce keys but your application will leave clearer trails if you write to the 64 bit area of the registry for this particular key.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Do you know if RunOnce works in both views of the registry or only in the native one? So would it work if he wrote to the 32-bit view? – Heinrich Ulbricht Aug 08 '11 at 15:41
  • @Heinrich I believe Windows merges both views of that key. It certainly does so for `HKLM\Software\...\Run`. But I would always prefer to write to the native key. My reasoning is that the key is interpreted by the system shell and the system shell is 64 bit. – David Heffernan Aug 08 '11 at 15:44
  • Reasonable thought. Not merging would also break compatibility with applications not taking care of writing to the "other side". – Heinrich Ulbricht Aug 08 '11 at 15:48
3

Yes, administrator privileges are required to modify HKEY_LOCAL_MACHINE.

Three possibilities:

  1. Don't use that key and find another way.
  2. Read here. An app manifest might be the way to go (section "Marking Required Privileges Using an Application Manifest"). This will ask the user for consent when he starts the app. That's the easy way.
  3. Let the user run your application without admin privileges and put the code requiring them in another executable. Run this on demand and only if the user requested it. That's the preferable way.

Edit for the added part:

Have you tried using HKEY_CURRENT_USER instead? This runs the app for the current user only but you don't need to have admin privileges to write to the registry.

Heinrich Ulbricht
  • 10,064
  • 4
  • 54
  • 85