Wednesday, December 29, 2010

How to start a new process de-elevated after installation

I was trying to launch an application at the end of an installation I’ve created with Visual Studio. My problem was that the installation is running with elevated privileges as administrator (UAC) and I want the application to run as a normal user.

One problem with the application that was launched by the installer was that when reading and writing to the registry it ended up at HKEY_USERS\.DEFAULT instead of HKEY_CURRENT_USER. I noticed that the process was run by NT AUTHORITY\SYSTEM instead of the expected COMPUTERNAME\USERNAME. This will also cause problems if you want to open a webpage after the installation and there is no current Web Browser running.

I knew how to elevate the process using the verb runas.

p.StartInfo.UseShellExecute = true; p.StartInfo.Verb = "runas";

But I could not find any way to use the verb to de-elevate. I searched for a solution online but could only find convoluted ways like using CreateProcessAsUserW, Code Injection in the shell process or using the task scheduler to register a task to run as the currently logged on desktop user.

I found this post and tried using the User Account Control Helpers to no avail for some reason.

Process p = UacHelpers.UserAccountControl.CreateProcessAsStandardUser("notepad.exe", "");

Eventually I came up with this simple C# code thinking it might do the trick. It actually runs the new program with reduced permissions but not as the intended user. This could be useful in other situations though.

Process p = new Process(); p.StartInfo.FileName = "runas.exe"; p.StartInfo.WindowStyle = ProcessWindowStyle.Normal; p.StartInfo.Arguments = "/trustlevel:0x20000 notepad.exe"; p.Start();

Unfortunately it didn’t help me here.

I then turned back to the UacHelpers source code and commented out these rows because I noticed that the process was not really elevated from the start so I did not want the simple way to start the process.

//if (!IsCurrentProcessElevated) //{ // return Process::Start(exePath, arguments); //}

Using this trick it was possible to have an application like my setup that runs with administrator privileges (thanks to UAC) to start another process with standard user privileges and as the expected user.

For more details on the subject see also Aaron Margosis’ WebLog.

Please comment if this helps you or if you have any related suggestions on better approach.


Some of the latest blog posts

Subscribe to RSS headline updates from:
Powered by FeedBurner