Registry Questions - How would you do this?

Hey guys,

When my app first starts up, I need to create a registry key in HKEY_CLASSES_ROOT if it is not already there. Keys in this path can only be created from Administrator accounts. So if I throw an exception here, I use the following:

    Dim reg as new RegistryItem("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers")
    
    If Not(reg.Value(App.ExecutableFile.AbsolutePath)="RUNASADMIN") Then
      reg.Value(App.ExecutableFile.AbsolutePath)="RUNASADMIN"
  ....

I then quit then restart a new instance of the app and quit the first.

This works fine and administrator authentication is requested. I can then do my thing. The question is how to delete that registry key I created above. What I’ve been doing is when my app first starts, I check to see if that key exists and if so, I delete it. But that’s a problem. Because they key is created in the HKEY_CURRENT_USER path of the non-admin user. But as soon as my app starts, I have to authenticate to the admin user. So then the registry that is loaded in the app is the HKEY_CURRENT_USER of the admin user I have authenticated - not the default account I’ve logged into in Windows. Am, I making sense?

I’m thinking the only way to do this is by using a helper app that is running under the credentials of the logged-in user.

Is there any other way I might delete this key? An admin has access to all the user keys under HKEY_USERS, but I don’t think there’s a way to tell who is who in there.

Edit:

Actually, maybe this would work…

1.) Create a helper app that runs in a synchronous shell.
2.) If the exception is thrown, launch the helper app as administrator and create the key there.
3.) Once the shell returns continue on with the execution of the main app.

If you dont want to read/write HKEY_CURRENT_USER then stay in elevated mode.

If you do want to read/write the users HKEY_CURRENT_USER then you will need a helper app.

If your read/write fails to HKEY_CLASSES_ROOT then start your elevated app and leave it running. Have a system in it (IPC polling for example) to check if the main app is still there (to prevent rogue elevated apps when the main app crashes for example). Close the elevated app when the main app is closed (using those IPCsockets for example) just to keep everything clean.

As your elevated app is running already, you dont need to ask the user another time to elevate if you need to remove from HKEY_CLASSES_ROOT.

If you need to check for elevation in a nicer/cleaner/more robust way use the code I linked on the other post.

Getting the elevation isn’t the issue. The issue is I only need to run it elevated one time. So the first time the user starts the app, I need to create the key which needs elevated permissions. After that, every time the app runs, I don’t care.

I think the best way to do this is to have a helper console app set to run with elevated permissions and the helper app creates the key and then never runs again.

Ah, if its just a one off, that’ll work fine :slight_smile:

Can’t set it during install?

Have your installer require admin privileges for the installation and create the registry entry there.

[quote=351677:@JulianS]Ah, if its just a one off, that’ll work fine :slight_smile:

Can’t set it during install?[/quote]

You know - that’s a good idea. I see Greg just suggested that.

That’s probably a better way to do it. Makes things MUCH simpler!

Wait - can a non-admin user modify a registry key in HKEY_CLASSES_ROOT? I use this space to create a registration ID that is used for all users when starting the app. This ID is based on machine parameters and is calculated when the machine starts up. I had been using some Windows APIs to calculate this value at runtime but the Windows APIs don’t always return consistent values so I want to create this key once and then store it in a universal place. If I can edit it later, than cool - I can create it in the installer.

Yes, but only if you create the key and add access to the user group (or user) during elevation.

If you are trying to store shared application data across all users of the same machine then you should be putting it in:

SpecialFolder.SharedApplicationData

unless you’re trying to hide its existence in some way.

You can always encrypt it in some way if you put it in SpecialFolder.SharedApplicationData

Yup

Hmm, as a simple registration/security method its ok, but its so easily monitored/sniffed I’d work out another method if you’re going to use is as protection from anything other than a non-computer literate user.

Phoning home?
Steganography inside another resource you’ve just installed on the machine? (i.e. drop another exe with the install that does nothing, put a nice big string in that you can find and edit your key into that file, or use the text field inside a png that you use as an image, who check those).

Plenty of places to hide :wink: or just stick with the registry.

At the end of the day, its whatever you think will cover you the most of the time, no matter how much time you put into protection, someone else will just put in 10x the time to get around it/work it out.

Finding a keygen on the net for your hard work is a bit of a downer, been there :frowning:

I digress…

Well, my app has somewhat limited distribution as it’s not a mass market product. But I charge good money for it and I don’t want it simply copied. I realize that no matter what, someone who wants to can hack it (and I’ve verified this has happened thanks to some Chinese people who have done this - my app phones home when someone attempts to validate the license key). But as it’s not mass market, I don’t worry too much. I will notice a pattern from my integrators if someone is hacking and I’ll call them on it. It’s not happened and I tend to work fairly closely with them anyhow. But I don’t want to make it “easy” for them either. A good criminal could get into my house even though it’s locked. It’s the casual criminal I worry about and so I lock my doors. Same with my app. I get it.

:slight_smile:

So I think I have this figured out. I created a console app that runs with elevated permissions and takes the ID key my main app generates and creates the registry key and sets the default value to the ID I created. Seems to work pretty well. I then delete the app after it runs as it’s not needed after that.