mgttlinger
mgttlinger

Reputation: 1435

"Win32Exception: The directory name is invalid" Impersonation & UAC

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

Answers (1)

brennemanl
brennemanl

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:

UAC self-elevation


     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

Related Questions