• Cmdlet开发与学习(七)


          到目前的例子为止,我们使用的都是不带参数的CreateRunspace()方法创建的运行空间实例,这就意味着,我们使用的都是默认的命令集合,提供程序,初始化脚本和格式信息。

          但是,这些默认的配置信息都是可以控制的,这要通过RunspaceConfiguration类实现。RunspaceConfiguration类是CreateRunspace函数的参数。创建运行空间实例后,其中的会话状态变量可以通过运行空间实例的SessionStateProxy来设置和获取。

          注意:如果运行空间处于BeforeOpen状态,可以直接修改其配置。但是在runspace.open之后,不是任何配置修改都管用。具体上说,在open之后,AddPSSnapin()函数和RemovePSSnapin()函数好使,但是直接修改Assemblies,cmdlet,Formats,Scripts和Types集合的操作却是不允许的。

          

     1         static void Main(string[] args)
     2         {
     3             RunspaceConfiguration configuration = RunspaceConfiguration.Create();
     4             PSSnapInException warning = null;
     5             //Add PSSnapIn,系统自动调用update
     6             configuration.AddPSSnapIn("MySnapin", out warning);
     7 
     8             Runspace runspace = RunspaceFactory.CreateRunspace(configuration);
     9             //通过SessionStateProxy修改会话状态变量
    10             runspace.SessionStateProxy.SetVariable("factorOne", 7);
    11             runspace.SessionStateProxy.SetVariable("factorTwo", 11);
    12 
    13             //下面是关于配置集合的修改,只有在update时候才起效
    14             //添加cmdlet GetWidgetCmdlet是实现cmdlet的.Net类型
    15             runspace.RunspaceConfiguration.Cmdlets.Append(new CmdletConfigurationEntry("get-widget", typeof(GetWidgetCmdlet),null));
    16             runspace.RunspaceConfiguration.Cmdlets.Update();
    17 
    18             //添加格式文件
    19             runspace.RunspaceConfiguration.Formats.Append(new FormatConfigurationEntry("C:\myformat.ps1xml"));
    20             runspace.RunspaceConfiguration.Formats.Update();
    21 
    22             //添加函数
    23             runspace.RunspaceConfiguration.Scripts.Append(new ScriptConfigurationEntry("add","return $args[0] + $args[1]"));
    24             runspace.RunspaceConfiguration.Scripts.Update();
    25             runspace.Open();
    26             
    27             //...
    28         }

            AddPSSnapIn()的PSConsoleLoadException类型的out参数在调用失败时,返回PSSnapInException实例。如果找不到snap-in,或者发生其他致命错误,则AddPSSnapIn()抛出异常。

            异步执行管道

            异步执行管道,调用InvokeAsync()方法,它的执行前提条件与调用Invoke类似。

            这里需要注意的是,在调用InvokeAsync后,管道得在关闭输入管道后才执行。     

    1             Runspace runspace = RunspaceFactory.CreateRunspace();
    2             runspace.Open();
    3 
    4             Pipeline pipeline = runspace.CreatePipeline("Command");
    5             pipeline.InvokeAsync();
    6             pipeline.Input.Close();

           如果输入管道已关闭,再次调用close不会产生异常,但是可以用PipelineWriter类的IsOpen属性检查管道是否处于关闭状态。

           既然执行了异步,那么重点必然就是读取输出和错误了。主要看PipelineReader提供的可用方法。

           1.Read():读取对象,如果对象不可用,就阻塞执行一直等待

           2.Read(count):读取count个对象,阻塞执行直到所有的对象都可用

           3.ReadToEnd():读取数据直到管道关闭

           4.Peek():检查是否有可用的对象

           5.NonBlockingRead():读一个对象,如果该对象不存在,则直接返回

           6.NonBlockingRead(count):读取count个对象,如果该对象不存在,则直接返回

           PipelineReader还有个有用的属性WaitHandle,可以用来等待输出和DataReady事件,DataReady事件只有当输出可用时才输出。

          下面用一个例子来演示:

          

     1   Runspace runspace = RunspaceFactory.CreateRunspace();
     2             runspace.Open();
     3 
     4             Pipeline pipeline = runspace.CreatePipeline("Command");
     5             pipeline.InvokeAsync();
     6             WaitHandle[] handles = new WaitHandle[2];
     7             handles[0] = pipeline.Output.WaitHandle;
     8             handles[1] = pipeline.Error.WaitHandle;
     9             pipeline.Input.Close();
    10 
    11             while (pipeline.PipelineStateInfo.State == PipelineState.Running)
    12             {
    13                 switch (WaitHandle.WaitAny(handles))
    14                 {
    15                     case 0:
    16                         while (pipeline.Output.Count > 0)
    17                         {
    18                             Console.WriteLine("Output: {0}", pipeline.Output.Read());
    19                         }
    20                         break;
    21                     case 1:
    22                         while (pipeline.Error.Count > 0)
    23                         {
    24                             Console.WriteLine("Error: {0}", pipeline.Error.Read());
    25                         }
    26                         break;
    27                 }
    28             }

           管道状态   

           管道存在几种状态:NotStarted,Running,Stopping,Stopped,Completed,Failed。

           可以监视管道的StateChanged事件,在管道的状态发生改变时,做出相应的处理。

           终结性错误

           当异步管道发生终结型错误时,管道状态变为Failed,抛出StateChanged事件,PipelineStateInfo对象的Reason属性包含了ErrorRecord对象,里面记录着终结型错误信息。

           停止管道

           如果希望关闭正在执行的异步管道,管道对象的Stop()和StopAsync()函数都可以实现这个效果。

           这里需要明确的是,调用上述的两个停止方法时,管道状态变为Stopping,StateChanged事件触发。如果管道线程正在调用外部代码,比如其他.Net方法,则管道处于无限Stopping状态,等待外部调用返回。如果管道成功停止,则变为Stopped状态。

  • 相关阅读:
    开源监控软件之争
    为什么很多公司都自主开发监控系统?
    为 UWP 应用提供的 .NET 网络 API
    亲,根据二八定律,你的监控工具可能白装了哦
    PHP7正式版测试,性能惊艳!
    Java Web 前端高性能优化(一)
    天下武功无坚不破,唯快不破!
    告警信息大爆炸,运维解放秘籍!
    第33节:Java面向对象中的异常
    第33节:Java面向对象中的异常
  • 原文地址:https://www.cnblogs.com/ByronsHome/p/3724521.html
Copyright © 2020-2023  润新知