Reputation: 1435
I have written a program that needs to be run elevated to invoke two methods of a WMI object. Works like a charm if run by an user from the administrators group in "elevated mode". But now the problem is it needs to be run by everyone and not everyone has administrative privileges on the machine they work on. So I decided to let the program restart itself impersonating a user from the "Domain Admins" group.
My code for that is as follows:
ProcessStartInfo proc = new ProcessStartInfo();
proc.WorkingDirectory = Environment.CurrentDirectory;
proc.FileName = System.Windows.Forms.Application.ExecutablePath; ;
proc.UserName = "USERNAME";
SecureString secure = new SecureString();
foreach (var item in "PASSWORD")
{
secure.AppendChar(item);
}
proc.Password = secure;
proc.Domain = "DOMAIN";
proc.UseShellExecute = false;
proc.Verb = "runas";
Process.Start(proc);
There are two problems with that when UAC is enabled.
First if I do not explicitely add the user which should be impersonated to the ACL of the installfolder of the program (user is already in Administrators group which has full access to the folder and all files contained in it) it throws a System.ComponentModel.Win32Exception: The directory name is invalid
.
I double checked the directory path and it is in fact valid (and works when user is in ACL explicitely).
Now if the user is added explicitely and there is no exception the program runs as the user but not with elevated rights so the invocations don't work.
What am I doing wrong? Thanks for your help.
I knowthere are a few questions about similar issues already but none of the solutions / answers solved my problem or they were not detailed enough and inactive for too long.
Upvotes: 2
Views: 4184
Reputation: 36
I have been having the same problem, I could not elevate AND provide credentials at the same time. In order to use 'runas' verb you have to set UseShellExecute=true but in order to provide credentials you have to have it set to false. What I ended up doing is testing for admin rights and if they are not present restarting my application as a separate user who had local admin rights. Then I would run the process.start with the 'runas' verb and without the need to provide credentials. At this point your user will receive a UAC prompt and after selecting yes the process will run elevated. I wrote mine in VB but the idea is the same, here is my code, the IsUserAdminGroup was used from:
Try
'check if user is administrator
Dim fInAdminGroup As Boolean = Me.IsUserInAdminGroup
If (Me.IsUserInAdminGroup = False) Then
'check if process is running under user you want to elevate
If Not (System.Environment.UserName = "") Then
'this process restarts the app as the desired admin user
Dim path As String = Environment.CurrentDirectory
Dim filename As String = Application.ExecutablePath
'create secure string password
Dim passwordPre As String = ""
Dim passwordChars As Char() = passwordPre.ToCharArray()
Dim password As New SecureString()
For Each c As Char In passwordChars
password.AppendChar(c)
Next
Dim procInfo As New System.Diagnostics.Process
procInfo.StartInfo.FileName = filename
procInfo.StartInfo.UserName = ""
procInfo.StartInfo.Domain = ""
procInfo.StartInfo.Password = password
procInfo.StartInfo.UseShellExecute = False
'load user profile was needed for a legacy application I used that failed without the user hive loaded
'procInfo.StartInfo.LoadUserProfile = True
procInfo.StartInfo.CreateNoWindow = True
procInfo.StartInfo.WorkingDirectory = path
procInfo.Start()
Application.Exit()
Else
MsgBox("Unable to open, call support.", MsgBoxStyle.Critical, "Run Failed")
Application.Exit()
End If
ElseIf (System.Environment.UserName = "") Then
Me.Visible = False
Me.Hide()
'this process starts the desired app elevated
Dim procInfo As New System.Diagnostics.Process
procInfo.StartInfo.FileName = "ptpublisher.exe"
procInfo.StartInfo.Verb = "runas"
procInfo.StartInfo.UseShellExecute = True
procInfo.StartInfo.CreateNoWindow = True
procInfo.StartInfo.WorkingDirectory = "C:\Program Files (x86)\Primera Technology\PTPublisher"
procInfo.StartInfo.Arguments = ""
procInfo.Start()
Application.Exit()
End If
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical, "Run Failed")
Application.Exit()
End Try
Upvotes: 2