代码改变世界

PowerShell 2.0解析、格式化及显示远程输出

2010-12-14 01:32 by @天行健中国元素, ... 阅读, ... 评论, 收藏, 编辑

由于PowerShell 2.0远程管理的传输是在网络上进行,而对象是不能通过网络进行传递的,为了能够继续将PowerShell所具有的面向对象的优点进行继续保持,PowerShell2.0远程管理传输的过程中是将对象序列化为XML后进行传输,在达到目标主机后在进行反序列化解包,在客户端实现远程到本地端对端的对象传递,然而对象传递的过程中很有可能远程对象的格式化配置文件在本地并不存在,这就可能使传输到本地的输出杂乱无章,并不能体现面向对象的优点,也不方便用户的识别和阅读,最好的解决方法可能就是将远程主机的格式化文件传输到本地,在本地对接收到的对象进行格式化输出。在本文中将会介绍PowerShell远程管理的输出,包括输出是如何从远程主机传输到本地,如何显示以及如何根据自己的需要格式化输出。

1 远程输出问题的引入

首先,看看从远程线程接收的输出有何不同,如果用Invoke-Commad运行该Get-PSDrive,能够看到如下图1所示的输出:

能够看到在输出的内容比在本地执行时多了PSComputerName的参数列用于指定远程主机名。如果要在显示远程输出的时候不现实此列的信息只需要使用-HideComputerName参数禁止该列输出。

当然也有些cmdlet的执行结果是不现实PSComputerName属性的,比如Get-Date。此时如果需要显式PSComputerName列的内容就需要执行以下命令

Invoke-Command -ComputerName Server01,
Server02 -ScriptBlock {Get-Date}
 | ft DateTime, PSComputerName –Auto

2 远程输出如何传输到本地主机

PowerShell cmdlet返回的对象是无法直接通过网络传输的,所以把实时对象序列化,也就是说实时对象需要转换为XML来表现对象及其属性。随后基于XML的序列化对象通过网络传输到本地线程,并被再次反序列化为.NET对象。因为通过XML可以将对象相关的属性和数据以统一的格式从对象创建到最终的存储,也能将对象的值从一个应用程序域传递到另一个。比如,在ASP.NET中就是使用序列化存储的XML保存线程状态,同样在PowerShell远程管理中也使用XML实现对象值传递的中间件实现程序域之间的传递。

根据前面的描述,实时对象被转换为序列化后基于XML的表现形式,一旦在本地线程中反序列化后,不需要暴露任何属于对象的方法就能够直接使用。首先在本地线程中执行Get-Process的输出,并将其输出限制在方法范围内,具体效果如下图3所示。

能从上图看到返回的进程对象中有很多方法,接下来看看在远程线程中执行相同的命令会返回什么样的输出,如下图4所示:

从上图能够看到TypeName是反序列化对象,而且是找不到进程对象应有的方法。反序列化对象是在远程线程中执行Get-Process cmdlet的返回结果,这意味着此时不能对反序列化进程对象使用诸如Kill()方法杀死进程。

3 格式化远程输出

绝大多数反序列对象会根据Types.ps1xml或Formaat.ps1xml文件规定的条目自动格式化显示,然而有时候本地主机可能并没有从远程主机生成的反序列化对象。当对象没有被格式化,每个对象的所有属性都会在终端上以流列表的形式显示。为了能其他主机上格式化数据,需要使用Get-FormatData和Export-FormatData cmdlet。

为了方便解释,这里用Windows 7的主机使用Invoke-Command访问SharePoint 2010服务器的cmdlet,这里首先使用Get-SPSite cmdlet在本机获取SharePoint 2010的web前台页面,如下图5所示:

接下来通过Invoke-Command通过远程线程执行相同的命令,结果如下图6所示

能够看到通过远程线程的输出和从本地执行时的输出完全不同,因为在Windows 7上没有格式化数据可用。随后使用Get-FormatData,Export-FormatData和Update-FormatData cmdlet获取远程主机上的格式化数据到本地,命令如下:

$s = New-PSSession -ComputerName WinServ-wfe 
Invoke-Command -session $s -ScriptBlock 
{Add-PSSnapin Microsoft.SharePoint.PowerShell} 
Invoke-Command -Session $s -ScriptBlock 
{Get-FormatData -TypeName *SharePoint*
} | Export-FormatData -Path 
C:\scripts\SharePoint.Format.ps1xml 
Update-FormatData -PrependPath 
C:\scripts\SharePoint.Format.ps1xml

上面的代码段用于为所有的SharePoint cmdlet将格式化数据导入到本地,执行完此代码段,可以再次使用Invoke-Command通过远程线程调用Get-SPSite,效果如下图7所示:

从上图能看到在讲远程格式化数据导入到本地后,Get-SPSite的数据格式是和在本地执行时很相似的。需要强调的是通过执行上面的命令只能在当前线程中生效,如果关闭当前线程,重新打开PowerShell控制台,格式化数据将会丢失,用户可以在PowerShell的配置文件中添加Update-FormatData cmdlet,在启动PowerShell线程的同时获取格式化数据。

4 总结

为了能将从远程主机传输到本地的对象进行格式化输出,可以在传输对象之后将对象的格式化输出文件也同步到本地,对远程传输回本地的对象按照远程输出的样式。在本文中介绍了PowerShell远程管理的传输方式和输出形式,包括输出是如何从远程主机传输到本地,如何显示以及如何根据自己的需要格式化输出。

赛迪网地址:http://tech.ccidnet.com/art/302/20100706/2107021_1.html

作者: 付海军
出处:http://fuhj02.cnblogs.com
版权:本文版权归作者和博客园共有
转载:欢迎转载,为了保存作者的创作热情,请按要求【转载】,谢谢
要求:未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
个人网站: http://txj.shell.tor.hu/