The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

如何透過 C# 應用程式執行或呼叫 PowerShell 命令

如果有人嘗試在 ASP.NET 或 Console 應用程式執行 PowerShell 命令,可能會蠻挫折的,因為光是第一步「從專案加入參考」就會卡住,因此今天這篇文章將會按部就班地把專案環境設定好,並且透過一些簡單的範例程式說明如何透過一個 C# 主控台應用程式執行任意 PowerShell 命令。

我們先建立一個主控台應用程式專案,專案名稱設定為:TestPowerShell

因為我們要加入 System.Management.Automation 這個組件,不過不知為何,我們在 Visual Studio 裡面使用「加入參考」功能,是找不到這個組件的!

因此,我們改用土法煉鋼的方式,手動編輯 TestPowerShell.csproj 專案定義檔,手動加入這個組件參考,如下圖示: ( 如果不知道怎樣編輯,你也可以用 Notepad 開啟編輯這個檔案 )

這樣就可以成功載入 System.Management.Automation 組件,如下圖示:

image

※其實組件路徑位於 %ProgramFiles(x86)%\Reference Assemblies\Microsoft\WindowsPowerShell\3.0

接著我們在 Program.cs 檔案引用兩個命名空間如下:

using System.Management.Automation;
using System.Management.Automation.Runspaces;

大功告成,現在你可以將 PowerShell 指令整合到你的 C# 應用程式中了!

以下分享幾個簡單的例子,請將程式碼放進 Main() 方法,按下 Ctrl+F5 即可執行:

1. 執行 Get-Service 指令 (取得所有 Windows 服務),透過 .Invoke() 方法執行 PowerShell 命令並取得預設的 PSObject 物件集合 ( Collection<PSObject> ),在迴圈中取得 PSObject 物件的 Name 屬性。

using (PowerShell powershell = PowerShell.Create())
{
    powershell.AddScript("Get-Service");

    foreach (PSObject result in powershell.Invoke())
    {
        Console.WriteLine(result.Members["Name"].Value);
    }
}

2. 同上範例,但指令複雜一些,我們取得已經停止的 Windows 服務名稱

using (PowerShell powershell = PowerShell.Create())
{
    powershell.AddScript("Get-Service | Where-Object { $_.Status -eq 'Stopped' }");

    foreach (PSObject result in powershell.Invoke())
    {
        Console.WriteLine(result.Members["Name"].Value);
    }
}

3. 執行 Invoke 方法時,可以指定回傳的型別,所以你也可以透過強型別來開發程式。不過要選對型別才能正常運作!這邊我們把指令最後透過 Out-String 指令,將結果轉型成字串,然後用 string 型別來接資料。(這時所接到的資料將會全部都是字串,而且執行結果一樣是一個集合物件,一行文字一個項目)

using (PowerShell powershell = PowerShell.Create())
{
    powershell.AddScript("Get-Service | Out-String");

    foreach (string str in powershell.Invoke<string>())
    {
        Console.WriteLine(str);
    }
}

4. 預設 PowerShell 執行過程中所發生的例外,都不會引發應用程式的例外狀況,所以你必須自行抓取這些錯誤資訊,並適時的顯示出來。如下範例:

using (PowerShell powershell = PowerShell.Create())
{
    powershell.AddScript("Get-Service99");

    foreach (PSObject result in powershell.Invoke())
    {
        Console.WriteLine(result.Members["Name"].Value);
    }

    Console.WriteLine("執行過程中發生錯誤\n");
    PSDataCollection<ErrorRecord> errors = powershell.Streams.Error;
    if (errors != null && errors.Count > 0)
    {
        foreach (ErrorRecord err in errors)
        {
            System.Console.WriteLine("錯誤: {0}", err.ToString());
        }
    }
}



注意事項

有些 PowerShell 的 Module 只有 64 位元版本 ( x64 ),你若要執行 x64 平台才有的那些 Cmdlets 的話,必須修改專案屬性,將目標平台改為 x64 才能正常執行,如下圖示:

※ 例如在 Manage Azure AD using Windows PowerShell 文件中提到的 Windows Azure Active Directory Module ( MSOnline 與 MSOnlineExtended 模組 ) 就有區分 x64 與 x86 版本。如果你只有安裝 64-bit 版本的話,預設的專案屬性設定就會無法執行這些 Cmdlets 命令:



補充說明

如果你使用 Windows 8 作業系統,預設已經安裝 Windows PowerShell 3.0 SDK,在 SDK 裡面有非常完整的範例程式,你可以參考以下路徑取得這些範例程式,非常有用!

C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0\Samples\sysmgmt\WindowsPowerShell



相關連結