Click here to Skip to main content
15,888,026 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hi,

What am I trying to do:
I'm logged on as a standard User, with no admin rights.

I have an admin account that I can use to acces other laptops on the network.
I manually go to explorer fill in \\PCID\C$\Path, I get the windows-security dialog where windows asks for network authentication and where I fill in my admin credentials.

I'm trying to make an wpf application in c# where I want to automate somethings.
I have a listview with al the users at our departement and I want to be able to select some user(s) and acces a path on their laptop.

C#
try
{
foreach (INFR_Gebruiker user in ListUsers_LV.SelectedItems)
{
string pcId = user.PcId;
ProcessStartInfo psi = new ProcessStartInfo("explorer", $@"\\{pcId}\c$\programdat\Autodesk");
Process.Start(psi);
}
}
catch (Exception ex) { MessageBox.Show(ex.Message); }
}


But the moment the application tries to acces the network authentication pops-up.

Is there a way to avoid that?

What I have tried:

What I've tried to do is:
1. attach a manifest to the app so it always asks for admin cred's to startup:
XML
<pre><?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="IsUserAdmin" type="win32"/>
  <description>POA_CADControlCenter</description>
  <!-- Identify the application security requirements. -->
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
        <requestedExecutionLevel
          level="requireAdministrator"
          uiAccess="false"/>
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>


2. I've tried to implement the WindowsIdentity.Impersonate Method:

I've used this example and just added the process.start() after the impersonation succeeds:

C#
using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Security.Permissions;
using Microsoft.Win32.SafeHandles;
using System.Runtime.ConstrainedExecution;
using System.Security;


public class ImpersonationDemo
{
    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
        int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public extern static bool CloseHandle(IntPtr handle);

    // Test harness.
    // If you incorporate this code into a DLL, be sure to demand FullTrust.
    [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
    public static void Main(string[] args)
    {
        SafeTokenHandle safeTokenHandle;
        try
        {
            string userName, domainName;
            // Get the user token for the specified user, domain, and password using the
            // unmanaged LogonUser method.
            // The local machine name can be used for the domain name to impersonate a user on this machine.
            Console.Write("Enter the name of the domain on which to log on: ");
            domainName = Console.ReadLine();

            Console.Write("Enter the login of a user on {0} that you wish to impersonate: ", domainName);
            userName = Console.ReadLine();

            Console.Write("Enter the password for {0}: ", userName);

            const int LOGON32_PROVIDER_DEFAULT = 0;
            //This parameter causes LogonUser to create a primary token.
            const int LOGON32_LOGON_INTERACTIVE = 2;

            // Call LogonUser to obtain a handle to an access token.
            bool returnValue = LogonUser(userName, domainName, Console.ReadLine(),
                LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
                out safeTokenHandle);

            Console.WriteLine("LogonUser called.");

            if (false == returnValue)
            {
                int ret = Marshal.GetLastWin32Error();
                Console.WriteLine("LogonUser failed with error code : {0}", ret);
                throw new System.ComponentModel.Win32Exception(ret);
            }
            using (safeTokenHandle)
            {
                Console.WriteLine("Did LogonUser Succeed? " + (returnValue ? "Yes" : "No"));
                Console.WriteLine("Value of Windows NT token: " + safeTokenHandle);

                // Check the identity.
                Console.WriteLine("Before impersonation: "
                    + WindowsIdentity.GetCurrent().Name);
                // Use the token handle returned by LogonUser.
                using (WindowsImpersonationContext impersonatedUser = WindowsIdentity.Impersonate(safeTokenHandle.DangerousGetHandle()))
                {

                    // Check the identity.
                    Console.WriteLine("After impersonation: "
                        + WindowsIdentity.GetCurrent().Name);
                }
                // Releasing the context object stops the impersonation
                // Check the identity.
                Console.WriteLine("After closing the context: " + WindowsIdentity.GetCurrent().Name);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception occurred. " + ex.Message);
        }

    }
}
public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
{
    private SafeTokenHandle()
        : base(true)
    {
    }

    [DllImport("kernel32.dll")]
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    [SuppressUnmanagedCodeSecurity]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool CloseHandle(IntPtr handle);

    protected override bool ReleaseHandle()
    {
        return CloseHandle(handle);
    }
}
Posted
Updated 6-Apr-17 1:45am
Comments
Richard Deeming 4-Apr-17 9:08am    
Did you try setting the Domain, UserName and Password properties on the ProcessStartInfo?

You need the credentials of the remote systems which are usually not the same as on your local system. But these can't be used to start the Explorer on your local system.

If you can perform your required tasks using a network connection to the shares instead of starting the Explorer you can create such.

One option is to use the NetworkCredential Class (System.Net)[^]. See Access to remote folder[^] for an example.

There is also an article here at CP using the NetApi32: Connect to a UNC Path with Credentials[^].

More can be found by searching the web for something like "c# credentials network share".
 
Share this answer
 
I used this example: Connect to a UNC Path with Credentials[^].

I didn't need the list of all the subfolders in the UNC path, but I needed to open this location in explorer. So I adjusted this to:

C#
public void Explorer_Click(object sender, RoutedEventArgs e)
       {

           System.Windows.Forms.Application.DoEvents();

           try
           {
               foreach (INFR_Gebruiker user in ListUsers_LV.SelectedItems)
               {
                   string pcId = user.PcId;
                   string path = $@"\\{pcId}\c$";
                   var uri = new System.Uri($@"\\{pcId}\c$");

                   using (UNCAccessWithCredentials unc =
                                           new UNCAccessWithCredentials())
                   {
                       if (unc.NetUseWithCredentials(path,
                                              "username","domain","password"))
                       Process.Start("explorer", uri.AbsoluteUri);
                   }
               }
           }
           catch (Exception ex) { MessageBox.Show(ex.Message); }
       }
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900