2013-04-01 41 views
6

我想允許用戶以非管理員程序內的管理員身份運行命令行實用程序,並且爲我的程序獲取輸出。該實用程序是第三方的,但隨我的程序一起分發。以管理員身份運行新進程並讀取標準輸出

我可以redirect the output of a program和我可以run a program as administrator但我不能同時做兩個。

我可以得到目前的工作通過cmd.exe將輸出重定向到一個文件,如的唯一的事:

using System.Windows.Forms; 
using System.Diagnostics; 
using System.IO; 
using System.Reflection; 

string appDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); 
string utilityPath = Path.Combine(appDirectory, "tools", "utility.exe"); 
string tempFile = Path.GetTempFileName(); 

Process p = new Process(); 
// hide the command window 
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; 
p.StartInfo.FileName = "cmd.exe"; 
// run the tool, redirect the output to the temp file and then close. 
p.StartInfo.Arguments = " /C \"\"" + utilityPath + "\" > \"" + tempFile + "\"\""; 
p.StartInfo.Verb = "runas"; // run as administrator 
p.Start(); 
p.WaitForExit(); 

// get the output, delete the file and show the output to the user 
string output = File.ReadAllText(tempFile); 
File.Delete(tempFile); 
MessageBox.Show(output); 

這有兩個問題:1)它使用的臨時文件和2)UAC是用於cmd.exe而不是utility.exe。肯定有更好的方法來做到這一點?

+0

如果你感興趣的是如何捕捉另一個進程的輸出,那麼這是一個重複的問題;見例如[如何捕獲Process.Start()的標準輸出/錯誤?](http://stackoverflow.com/questions/3633653/how-to-capture-the-standard-output-error-of-a-process -start?RQ = 1)。 – stakx

+0

我認爲我沒有說清楚的是特權差異。我的應用程序以標準用戶身份運行,實用程序以管理員身份運行據我所知,正常的重定向輸出方式在這種情況下不起作用。 – ChrisD

回答

3

而不是通過執行新的cmd,嘗試直接執行該實用程序。而不是重定向到一個文件,重定向標準輸出從您的程序中讀取它。 爲了以管理員身份運行,您需要使用管理員用戶名和密碼(取自here)。你需要設置你的方法爲unsafe

unsafe public static void Main(string[] args){ 
    Process p = new Process(); 
    p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; 
    // set admin user and password 
    p.StartInfo.UserName = "adminusername"; 
    char[] chArray = "adminpassword".ToCharArray(); 
    System.Security.SecureString str; 
    fixed (char* chRef = chArray) { 
     str = new System.Security.SecureString(chRef, chArray.Length); 
    } 
    p.StartInfo.Password = str; 
    // run and redirect as usual 
    p.StartInfo.FileName = utilityPath; 
    p.StartInfo.UseShellExecute = false; 
    p.StartInfo.RedirectStandardOutput = true; 
    p.Start(); 
    string output = p.StandardOutput.ReadToEnd(); 
    Console.WriteLine(output); 
    p.WaitForExit(); 
} 
+2

你應該在'p.WaitForExit()'後面使用'using(Process p = new Process())'或者調用'p.Dispose()'。 –

+0

我得到錯誤「Process對象必須將UseShellExecute屬性設置爲false才能重定向IO流」。所以我添加「p.StartInfo.UseShellExecute = false;」但隨後會停止以管理員身份運行:「請求的操作需要提升」。 – ChrisD

+0

檢查出新的答案 –

0

This確實神奇,雖然我沒有測試它。

它是用C++編寫的,但是通過使用DllImport,可以很容易地創建一個包裝API,以便從C#中調用。

相關問題