Domanda

So come lanciare un processo con privilegi di amministratore da un processo utilizzando:

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

dove proc è uno System.Diagnostics.Process. Ma come si fa a fare il contrario?

Se il processo si è in è già elevato, come si fa a lanciare il nuovo processo senza privilegi di amministratore? Più precisamente, abbiamo bisogno di lanciare il nuovo processo con lo stesso livello di autorizzazione di Windows Explorer, quindi nessun cambiamento se UAC è disabilitato, ma se UAC è abilitato, ma il nostro processo è in esecuzione elevata, abbiamo bisogno di eseguire una determinata operazione non-elevata perché stiamo creando un drive virtuale e se è creato con autorizzazioni elevate e Windows Explorer è in esecuzione terra terra non verrà visualizzato.

Sentitevi liberi di cambiare il titolo in qualcosa di meglio, non ho potuto trovare una buona descrizione.

È stato utile?

Soluzione 2

Abbiamo finito per usare l'esempio da questo articolo Codice Progetto: alta quota può essere male per la vostra applicazione: come avviare un processo non elevata al termine dell'installazione

Sembra funzionare finora, mi sembra di capire che inietta nella RunDll32.exe, il mio C ++ / Win32 è abbastanza debole e quindi non ho guardato troppo in all'effettiva attuazione, solo il suo uso. Confermato che funziona in Vista e Win7 sia x86 e x64 (almeno per noi, x86 e x64 richiedono diverso dll che è controllato per al momento dell'installazione e quello giusto è utilizzato).

Altri suggerimenti

La soluzione per voi è quella di utilizzare processo explorer.exe.

L'idea è quella di eseguire il processo in modalità UN-elevata, utilizzando il processo Esplora file explorer.exe delle finestre ( informazioni ). Diciamo il processo che vogliamo lanciare è su $TEMP\MyUnElevatedProcess.exe.

Quindi, per il codice NSIS, mi limiterò a scrivere: (ma può essere eseguito in qualsiasi lingua)

 Exec '"$WINDIR\explorer.exe" "$TEMP\MyUnElevatedProcess.exe"'

Esempio di codice ( utilizzando installazione NSIS )

Exec '"$WINDIR\explorer.exe" "$TEMP\MyUnElevatedProcess.exe"'

*** codice preso dal http://mdb-blog.blogspot.com/2013/01/nsis-lunch-program-as-user-from-uac.html

Se si desidera avviare un processo di terra terra da un'una elevata si potrebbe copiare il token di accesso del processo shell e utilizzarlo per avviare un nuovo processo.

public static class UnelevatedProcessStarter
{
    public static void Start(string cmdArgs)
    {
        // 1. Get the shell
        var shell = NativeMethods.GetShellWindow();
        if (shell == IntPtr.Zero)
        {
            throw new Exception("Could not find shell window");
        }

        // 2. Copy the access token of the process
        NativeMethods.GetWindowThreadProcessId(shell, out uint shellProcessId);
        var hShellProcess = NativeMethods.OpenProcess(0x00000400 /* QueryInformation */, false, (int)shellProcessId);
        if (!NativeMethods.OpenProcessToken(hShellProcess, 2 /* TOKEN_DUPLICATE */, out IntPtr hShellToken))
        {
            throw new Win32Exception();
        }

        // 3. Dublicate the acess token
        uint tokenAccess = 8 /*TOKEN_QUERY*/ | 1 /*TOKEN_ASSIGN_PRIMARY*/ | 2 /*TOKEN_DUPLICATE*/ | 0x80 /*TOKEN_ADJUST_DEFAULT*/ | 0x100 /*TOKEN_ADJUST_SESSIONID*/;
        var securityAttributes = new SecurityAttributes();

        NativeMethods.DuplicateTokenEx(
            hShellToken,
            tokenAccess,
            ref securityAttributes,
            2 /* SecurityImpersonation */,
            1 /* TokenPrimary */,
            out IntPtr hToken);

        // 4. Create a new process with the copied token
        var si = new Startupinfo();
        si.cb = Marshal.SizeOf(si);

        if (!NativeMethods.CreateProcessWithTokenW(
            hToken,
            0x00000002 /* LogonNetcredentialsOnly */,
            null,
            cmdArgs,
            0x00000010 /* CreateNewConsole */,
            IntPtr.Zero,
            null,
            ref si,
            out ProcessInformation _))
        {
            throw new Win32Exception();
        }
    }

    public class NativeMethods
    {

        [DllImport("user32.dll")]
        public static extern IntPtr GetShellWindow();
        [DllImport("user32.dll", SetLastError = true)]
        public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern IntPtr OpenProcess(int processAccess, bool bInheritHandle, int processId);
        [DllImport("advapi32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool OpenProcessToken(IntPtr processHandle, UInt32 desiredAccess, out IntPtr tokenHandle);
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool DuplicateTokenEx(IntPtr hExistingToken, uint dwDesiredAccess,
            ref SecurityAttributes lpTokenAttributes,
            int impersonationLevel,
            int tokenType,
            out IntPtr phNewToken);
        [DllImport("advapi32", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern bool CreateProcessWithTokenW(
            IntPtr hToken, int dwLogonFlags,
            string lpApplicationName, string lpCommandLine,
            int dwCreationFlags, IntPtr lpEnvironment,
            string lpCurrentDirectory, [In] ref Startupinfo lpStartupInfo, out ProcessInformation lpProcessInformation);
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct ProcessInformation
    {
        public IntPtr hProcess;
        public IntPtr hThread;
        public int dwProcessId;
        public int dwThreadId;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SecurityAttributes
    {
        public int nLength;
        public IntPtr lpSecurityDescriptor;
        public int bInheritHandle;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct Startupinfo
    {
        public Int32 cb;
        public string lpReserved;
        public string lpDesktop;
        public string lpTitle;
        public Int32 dwX;
        public Int32 dwY;
        public Int32 dwXSize;
        public Int32 dwYSize;
        public Int32 dwXCountChars;
        public Int32 dwYCountChars;
        public Int32 dwFillAttribute;
        public Int32 dwFlags;
        public Int16 wShowWindow;
        public Int16 cbReserved2;
        public IntPtr lpReserved2;
        public IntPtr hStdInput;
        public IntPtr hStdOutput;
        public IntPtr hStdError;
    }
}

È possibile utilizzare ProcessStartInfo.UserName e ProcessStartInfo.Password per specificare il account si desidera il processo per l'esecuzione sotto.

class Program
{
    static void Main(string[] args)
    {
        var psi = new ProcessStartInfo(@"c:\windows\system32\whoami.exe");
        var password = new SecureString();
        password.AppendChar('s');
        password.AppendChar('e');
        password.AppendChar('c');
        password.AppendChar('r');
        password.AppendChar('e');
        password.AppendChar('t');
        psi.Password = password;
        psi.UserName = "username";
        psi.UseShellExecute = false;
        psi.RedirectStandardOutput = true;

        var p = new Process();
        p.StartInfo = psi;
        p.Start();
        p.WaitForExit();

        Console.WriteLine(p.StandardOutput.ReadToEnd());
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top