十二 042010
 

上次忘记提SDK的路径了,Windows 7中的PowerShell SDK是存放在%ProgramFiles%\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0下,64位系统则是%ProgramFiles(x86)%\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0。其中的DLL都是Managed的,在用Visual Studio添加引用的时候,要指定路径才可以。

PowerShell.Invoke函数会执行当前存放在PowerShell对象中的命令,并返回一系统PSObject(即Collection<PSObject>),这是PowerShell对象中的最后一条命令的执行结果,当于有可能整个Collection为空,比如Import-Module这种cmdlet就是不返回任何结果的。在上一个例子中:

1
2
3
4
5
6
7
Collection<PSObject> results = ps.Invoke();
Console.WriteLine("Id\tName\tCPU Time\tHandleCount");
foreach (PSObject result in results)
{
    System.Diagnostics.Process p = result.BaseObject as System.Diagnostics.Process;
    Console.WriteLine(String.Format("{0}\t{1}\t{2}\t{3}", p.Id, p.ProcessName, p.UserProcessorTime, p.HandleCount));
}

我们可以看到,PSObject可以被转换成实际的对象,比如Get-Process返回的对象实际上是System.Diagnostics.Process类的实例。转换完成后,操作起来就方便多了。当然,如果你不知道它的实际类型是什么,你也可以通过PSObject.Members属性来获得它的一些成员。

那么,出现了错误该怎么办?有两种方法,一种是通过PowerShell的公共参数ErrorVariable把某一条命令的错误存放到一个PowerShell的变量中,然后再用Write-Host命令把它当成Invoke的结果返回出来。这样做有一个坏处是,在发生错误的时候,你可能就拿不到那条命令的实际结果了。

另一种方法是,用PowerShell类中的Streams属性。Streams中保存中PowerShell脚本执行过程中出现的各种Warning和Error对象。下面看一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
class InvocationResult
{
    public InvocationResult()
    {
        Errors = new List<ErrorRecord>();
        Warnings = new List<WarningRecord>();
        Results = new List<PSObject>();
    }

    public List<ErrorRecord> Errors { get; private set; }
    public List<WarningRecord> Warnings { get; private set; }
    public List<PSObject> Results { get; private set; }
}

这是一个简单的类,于是保存Invoke之后的结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
static InvocationResult Invoke(PowerShell ps)
{
    InvocationResult result = new InvocationResult();

    try
    {
        Collection<PSObject> tmp = ps.Invoke();
        result.Results.AddRange(tmp);
    }
    catch (RuntimeException re)
    {
        result.Errors.Add(re.ErrorRecord);
    }

    result.Errors.AddRange(ps.Streams.Error);
    result.Warnings.AddRange(ps.Streams.Warning);

    return result;
}

这样我们就可以把整个PowerShell脚本执行过程中所有的Error、Warning都保存下来了,为之后要详细的检测做准备。

十二 022010
 

PowerShell是Windows中的一个强大的脚本语言,用来在将来的某一天取代传统的DOS命令行。PowerShell是一种面向对象的弱类型语言,它不同于传统Shell语言的地方在于,它的命令返回的值都是对象,而不是纯文本。相对于文本来说,用户操作这些对象更方便,更安全。PowerShell内嵌支持.Net类库、COM和Web Service的交互。

PowerShell中的命令称为Cmdlet(即小指令),如Get-Process,用于获取某个进程的信息。具体Cmdlet的用法、创建这里不多提,很多资料中都有,这里主要介绍一下Cmdlet的测试。

由于PowerShell是一个新生的语言,原生的测试框架并不太丰富,而Microsoft提供了一套PowerShell Managed SDK,于是我们就可以用C#来编写PowerShell的测试了。

PowerShell SDK主要存放于两个Namespace中,Microsoft.PowerShellSystem.Management.Automation。Microsoft.PowerShell提供了一些用于控制PowerShell窗口的类,而System.Management.Automation提供了主要的测试所需的类,其中比较常用的有:

  • Runspace:提供了执行PowerShell代码所需的运行环境。
  • PowerShell:用于模拟一段PowerShell脚本的执行。
  • PSObject:用于存放脚本执行生成的结果。

Continue reading »