天天看點

作為平台的Windows PowerShell(二)

在此系列文章的前一篇,我們看到了怎樣使用System.Management.Automation.PowerShell 類來在c#應用程式中運作PowerShell 指令。在那些例子中,我們建立的都是預設的運作空間。在這篇文章中,我們一起來看怎樣自定義運作空間?比如,可能存在一種情況,你不想使用者可以使用那些能更改機器狀态的特定指令。這樣,你現在可以建立一個不包含那些指令的命名空間,這樣使用者就通路不到它們了。我們看看應當怎麼做。有很多類型可以被用來托管Windows PowerShell。下面列出其中最重要的幾種托管Windows PowerShell的類型(作為基本托管場景)

  • Runspace
  • InitialSessionState
  • PowerShell (前一篇文章中已經詳細介紹過)

我們來看一個非常簡單的托管Windows PowerShell的例子。

1

2

3

4

5

PowerShell ps = PowerShell.Create();

ps.AddCommand(

"Get-Command"

)

.AddParameter(

"CommandType"

,

"Cmdlet"

)

.AddParameter(

"ListImported"

,

"true"

);

ps.Invoke();

該示例建立了一個PowerShell對象。不怎麼明顯,但是當你使用Create()方法時,就已經建立了一個運作空間。預設情況下,它會把PowerShell 内置的指令全部加載進運作空間。在Windos 8上運作上面的指令(在運作空間中列出的指令),會添加259條指令。記憶體使用并不高效。

在很多情況下,人們想建立一個隻包含特定指令集合和語言元素的運作空間。隻包含了有限的指令集合的運作空間被稱為“限制運作空間”,詳細可以參考這裡。要建立一個限制運作空間,我們需要建立一個“初始會話狀态”(InitialSessionState)對象,用來限制使用者用什麼指令。

建立一個托管Windows PowerShell的限制運作空間需要4個步驟:

  1. 建立一個InitialSessionState(InitialSessionState可以認為是一個在運作空間打開時,用來存儲可用指令集的一個容器 。)
  2. 向InitialSessionState中添加你需要的指令。
  3. 為初始會話狀态建立一個運作空間 ( 一個運作空間是Windows PowerShell 能夠運作的環境。)
  4. 打開運作空間,讓運作空間就緒等待指令執行。
  5. 基于該運作空間來建立一個PowerShell對象,添加指令,然後執行指令。(這部分和上一篇文章中示範的一樣)

使用所有内置的核心指令來建立InitialSessionState

下面是一個使用限制運作空間技術根據所有核心指令來建立初始會話狀态的例子。使用 CreateDefault()方法建立一個初始會話狀态,然後根據初始會話狀态建立一個運作空間,打開這個運作空間,再運作運作空間中的指令。步驟四中的指令使用了PowerShell 對象中的Runspace屬性,指定自定義運作空間(rs)。

(在這個步驟中我們跳過了步驟二(添加我們期望的指令)。我會在下一個例子中解釋那部分。)

步驟 1

InitialSessionState iss = InitialSessionState.CreateDefault();

步驟 2

Runspace rs = RunspaceFactory.CreateRunspace(iss);

步驟 3

rs.Open();

步驟 4

PowerShell ps = PowerShell.Create();

ps.Runspace = rs;

ps.AddCommand(

"Get-Command"

);

ps.Invoke();

InitialSessionState 有三個不同的方法來建立存儲指令的容器

  • Create – 建立一個空的容器。容器中沒有添加任何指令。
  • CreateDefault – 建立一個包含了機器上所有Windows  PowerShell 内置指令的會話狀态。使用這個API,所有PowerShell内置的的指令都會被以管理單元的形式加載進去。
  • CreateDefault2 – 建立一個僅包含托管Windows PowerShell 最小集合的指令集。使用這個API,隻會有一個管理單元Microsoft.PowerShell.Core被加載。

上一個例子中建立的InitialSessionState對象,預設加載了所有Windows PowerShell内置的指令。我們可以通過建立一個空的InitialSessionState對象,然後添加我們所需的指令,來進一步限制它。

建立一個空的InitialSessionState,并添加指令

在這個示例中,我們建立一個空的初始會話狀态,然後使用SessionStateCmdletEntry  類來為初始會話狀态定義指令集。使用這個類,我們分别為Get-Command和Import-Module建立了一個指令項,然後将這些指令項添加進初始會話狀态。這就使這些指令能在會話中的管道中運作了。其結果就是那個會話中僅僅包含了Get-Command和Import-Module兩個指令。

步驟 1 – 建立一個空的InitialSessionState對象

InitialSessionState iss = InitialSessionState.Create();

步驟 2 – 添加要運作的指令

6

SessionStateCmdletEntry getCommand = 

new

SessionStateCmdletEntry(

"Get-Command"

typeof

(Microsoft.PowerShell.Commands.GetCommandCommand), 

""

);

SessionStateCmdletEntry importModule = 

new

SessionStateCmdletEntry(

"Import-Module"

typeof

(Microsoft.PowerShell.Commands.ImportModuleCommand), 

""

);

iss.Commands.Add(getCommand);

iss.Commands.Add(importModule);

步驟 3 – 建立運作空間

Runspace rs = RunspaceFactory.CreateRunspace(iss);

步驟 4 – 打開運作空間

rs.Open();

步驟 5 – 執行運作空間中的指令

7

8

PowerShell ps = PowerShell.Create();

ps.Runspace = rs;

ps.AddCommand(

"Get-Command"

);

Collection<CommandInfo> result = ps.Invoke<CommandInfo>();

foreach

(var entry 

in

result)

{

Console.WriteLine(entry.Name);

}

輸出

Get-Command

Import-Module

我們在這裡建立的運作空間僅包含了 Get-Command和Import-Module兩條指令。建立了一個空的 InitialSessionState,然後添加指令。這使得應用程式在記憶體使用上,非常高效。在上一個例子中,我們也可以通過顯式的建立一個運作空間來完成它。System.Management.Automation.PowerShell 類有一個公共的API Create,可以接收InitialSessionState參數。使用此版本,步驟3,4,和5可以被下面的指令所代替。

PowerShell ps = PowerShell.Create(iss);

ps.AddCommand(

"Get-Command"

);

Collection<CommandInfo> result = ps.Invoke<CommandInfo>();

foreach

(

var

entry 

in

result)

{

Console.WriteLine(entry.Name);

}

PowerShell 運作空間性分析

下面這張圖表展示了使用不同方法來建立InitialSessionState的執行時間。

作為平台的Windows PowerShell(二)
PowerShell 運作空間性能圖

正如在這些例子中看到的那樣,InitialSessionState提供了一個非常優秀的機制來建立一個僅包含了你想暴露的指令的運作空間。

Windows PowerShell SDK 已經包含了許多托管Windows PowerShell的例子。更多關于Windows PowerShell SDK 的資訊可以參考這裡

繼續閱讀