2010-08-29 17 views
13

Voglio avviare un processo figlio (effettivamente la stessa app della console) con privilegi elevati ma con finestra nascosta.Elevare i privilegi non funziona con UseShellExecute = false

devo fare:

var info = new ProcessStartInfo(Assembly.GetEntryAssembly().Location) 
{ 
    UseShellExecute = true, // ! 
    Verb = "runas", 
}; 

var process = new Process 
{ 
    StartInfo = info 
}; 

process.Start(); 

e questo funziona:

var identity = new WindowsPrincipal(WindowsIdentity.GetCurrent()); 
identity.IsInRole(WindowsBuiltInRole.Administrator); // returns true 

Ma UseShellExecute = true crea una nuova finestra e anche io non riesco a reindirizzare l'output.

Così, quando ho Operazioni successive:

var info = new ProcessStartInfo(Assembly.GetEntryAssembly().Location) 
{ 
    RedirectStandardError = true, 
    RedirectStandardOutput = true, 
    UseShellExecute = false, // ! 
    Verb = "runas" 
}; 

var process = new Process 
{ 
    EnableRaisingEvents = true, 
    StartInfo = info 
}; 

DataReceivedEventHandler actionWrite = (sender, e) => 
{ 
    Console.WriteLine(e.Data); 
}; 

process.ErrorDataReceived += actionWrite; 
process.OutputDataReceived += actionWrite; 

process.Start(); 
process.BeginOutputReadLine(); 
process.BeginErrorReadLine(); 
process.WaitForExit(); 

Questo non elevare i privilegi e codice di cui sopra restituisce false. Perché??

+0

BTW, è possibile scrivere 'DataReceivedEventHandler actionWrite = ...' e 'process.ErrorDataReceived + = actionWrite'. – SLaks

+0

È possibile eseguire il test utilizzando gli eventi UseShellExecute = true, Verb = "runas" e ErrorDataReceived come commento @SLaks? – Kiquenet

risposta

14

ProcessStartInfo.Verb avrà un effetto solo se il processo viene avviato da ShellExecuteEx(). Che richiede UseShellExecute = true. Reindirizzare I/O e nascondere la finestra può funzionare solo se il processo viene avviato da CreateProcess(). Che richiede UseShellExecute = false.

Bene, ecco perché non funziona. Non sono sicuro se proibire l'avvio di un processo nascosto che aggira l'UAC sia intenzionale. Probabilmente. Molto probabilmente.

Controllare this Q+A per il manifest è necessario visualizzare il prompt di elevazione UAC.

+0

Grazie mille per la descrizione di WinAPI dietro le quinte. Come pensi sia possibile ottenere privilegi elevati su richiesta per un processo con finestra nascosta? O si tratta di cose che si escludono a vicenda? – abatishchev

+0

E è possibile accendere/spegnere usando manifest? Cioè quando avvio la mia app la prima volta (manualmente) - non uso un manifest, quando secondo (programmaticamente) - forza da usare. – abatishchev

+0

Avviare un processo con privilegi elevati senza che l'utente se ne accorga non è possibile. Hai bisogno di un .exe separato in modo che abbia il proprio manifest. Fondamentalmente hai solo bisogno del metodo Main(). –

0

Controllare this answer.

Questo sembra fornire una soluzione alternativa. Ma consiglio di provare altri metodi come Named Pipes quando si ha accesso al codice sorgente del processo figlio.

+1

Non ho testato l'approccio dell'articolo UAC, sebbene contenga un campione di per sé. Ma se intendi un campione per Named Pipes, puoi facilmente trovarne molti (come [this] (http://stackoverflow.com/questions/13806153/example-of-named-pipes) o [this] (http: //www.codeproject.com/Tips/492231/Csharp-Async-Named-Pipes)) con una piccola ricerca. Il punto è che, come il reindirizzamento I/O, è possibile utilizzare anche flussi testuali con Named Pipe per inviare e ricevere dati (anche se i due processi risiedono su macchine diverse). Naturalmente devi affrontare alcune sfumature per ottenere un'applicazione pienamente funzionante. –

+0

@abatishchev IMHO, meglio usare Trace to File, non reindirizzare l'output, verb = runas. Named Pipes è molto più complesso e complesso nel debugging facile. – Kiquenet

2

Nel mio caso, è stato ok per ottenere le uscite una volta che il processo secondario elevato è terminato. Ecco la soluzione che ho trovato. Esso utilizza un file temporaneo:

var output = Path.GetTempFileName(); 
var process = Process.Start(new ProcessStartInfo 
{ 
    FileName = "cmd", 
    Arguments = "/c echo I'm an admin > " + output, // redirect to temp file 
    Verb = "runas", // UAC prompt 
    UseShellExecute = true, 
}); 
process.WaitForExit(); 
string res = File.ReadAllText(output); 
// do something with the output 
File.Delete(output); 
+0

sembra funzionare per me. dettagli contorti (Windows 10, F #) - gist a https://gist.github.com/ImaginaryDevelopment/f4bc33ae75bdf29e5aad8fd4045f193d – Maslow

+0

La risposta accettata è una spiegazione, questa è una soluzione .. +1 – caesay

Problemi correlati