PowerShell 学习_Part2_Building an inventory tool_1

来源:互联网 发布:python 主机 编辑:程序博客网 时间:2024/06/07 09:40

Tool design guidelines

其实也很简单,就一句话:Do one thing, and do it well

比如:1。Input tools

           2。Functional tools

           3。Output tools

还有要注意的事项:

■ What would be a good name for your tool?
■ What sort of information do you need for each tool? (These might be potential parameters.)
■ How do you think the tool would be run from a command prompt, or what type of data will it write to the pipeline?

Advanced functions, part 1

函数模版:

在这里要说一下Process块:

1. 如果函数只是通过接受参数,没有数据通过管道(pipeline),那么Process只执行一次。

2. 如果调用函数,用管道作为输入,那么Process会处理每一个在管道里的对象。

 

设计函数:

1. 我们最好要生成一格log文件,可以用来记录失败的情况,如果存在这种情况,可以重新处理失败的情况。

2. 我们要设计的函数功能如下:

     ■ ComputerName—The name of the computer
     ■ OSVersion—The Windows version
     ■ SPVersion—The service pack version
     ■ BIOSSerial—The BIOS serial number
     ■ Manufacturer—The computer’s manufacturer
     ■ Model—The computer’s model description

      第一个我们可以通过参数获得,接下来两个我们通过WMI’s Win32_OperatingSystem class获得;BIOSSerial通过Win32_BIOS;最后的通过Win32
_ComputerSystem class

3. 我们的函数要设计成可以接受多个computername参数,如:Get-SystemInfo –computer one,two,three –errorlog retries.txt

    当然,也可以通过管道,如:Get-Content computers.txt | Get-SystemInfo –errorlog retries.txt

 

声明参数:

function <name> {[CmdletBinding()]param([string[]]$ComputerName,[string]$ErrorLog)BEGIN {}PROCESS {}END {}}


测试参数:

function Get-SystemInfo {[CmdletBinding()]param([string[]]$ComputerName,[string]$ErrorLog)BEGIN {}PROCESS {Write-Output $ComputerNameWrite-Output $ErrorLog}END {}}Get-SystemInfo -computername one,two,three -errorlog x.txtGet-SystemInfo one x.txt


 

编写主要代码:

foreach语句在这里很重要:

function Get-SystemInfo {[CmdletBinding()]param([string[]]$ComputerName,[string]$ErrorLog)BEGIN {Write-Output "Log name is $errorlog"}PROCESS {foreach ($computer in $computername) {Write-Output "computer name is $computer"}}END {}}Get-SystemInfo -ComputerName one,two,three -ErrorLog x.txt


 

测试没问题,添加WMI命令:

function Get-SystemInfo {[CmdletBinding()]param([string[]]$ComputerName,[string]$ErrorLog)BEGIN {Write-Output "Log name is $errorlog"}PROCESS {foreach ($computer in $computername) {$os = Get-WmiObject -class Win32_OperatingSystem `-computerName $computer$comp = Get-WmiObject -class Win32_ComputerSystem `-computerName $computer$bios = Get-WmiObject -class Win32_BIOS `-computerName $computer}}END {}}


 

输出用户定义对象:

function Get-SystemInfo {[CmdletBinding()]param([string[]]$ComputerName,[string]$ErrorLog)BEGIN {Write-Output "Log name is $errorlog"}PROCESS {foreach ($computer in $computername) {$os = Get-WmiObject -class Win32_OperatingSystem `-computerName $computer$comp = Get-WmiObject -class Win32_ComputerSystem `-computerName $computer$bios = Get-WmiObject -class Win32_BIOS `-computerName $computer$props = @{'ComputerName'=$computer;'OSVersion'=$os.version;'SPVersion'=$os.servicepackmajorversion;'BIOSSerial'=$bios.serialnumber;'Manufacturer'=$comp.manufacturer;'Model'=$comp.model}$obj = New-Object -TypeName PSObject -Property $propsWrite-Output $obj}}END {}}Get-SystemInfo -ErrorLog x.txt -ComputerName localhost,localhost


 

说明:

1. 我们创建了一个hash table,并存储在了$Props里。

2. 然后我们用microsoft提供的特殊类型的对象创建了一个新对象,类型为PSObject,然后告诉它用hash table的属性产生新对象$obj

3. 然后用Write-Object输出对象到管道

运行结果:

我们可以把结果输出成我们想要的:

Get-SystemInfo –comp localhost –errorlog x.txt | Export-CSV
Get-SystemInfo –comp localhost –errorlog x.txt | ConvertTo-HTML
Get-SystemInfo –comp localhost –errorlog x.txt | Export-CliXML
Get-SystemInfo –comp localhost –errorlog x.txt | Sort OSVersion
Get-SystemInfo –comp localhost –errorlog x.txt | Format-Table

Advanced functions, part 2

Making parameters mandatory

如何设置参数为强制参数呢,很简单:

添加这个属性:[Parameter(Mandatory=$True)]

注意:

1. 如果同时为参数提供了默认值,那么默认值会被忽略。

2. 因为ComputerName为String[]类型,输入命令后会一直提示输入,两次回车就OK了。

 

Verbose output

记得我们在前面,因为Begin Block写一个String到pipeline, 所以违背了“一次只输出一个对象”的原则,下面提供一个专门的stream

function Get-SystemInfo {[CmdletBinding()]param([Parameter(Mandatory=$True)][string[]]$ComputerName,[string]$ErrorLog = 'c:\retry.txt')BEGIN {Write-Verbose "Error log will be $ErrorLog"}PROCESS {foreach ($computer in $computername) {Write-Verbose "Querying $computer"$os = Get-WmiObject -class Win32_OperatingSystem `-computerName $computer$comp = Get-WmiObject -class Win32_ComputerSystem `-computerName $computer$bios = Get-WmiObject -class Win32_BIOS `-computerName $computer$props = @{'ComputerName'=$computer;'OSVersion'=$os.version;'SPVersion'=$os.servicepackmajorversion;'BIOSSerial'=$bios.serialnumber;'Manufacturer'=$comp.manufacturer;'Model'=$comp.model}Write-Verbose "WMI queries complete"$obj = New-Object -TypeName PSObject -Property $propsWrite-Output $obj}}END {}}

 

注意

1. 里面的Write-Verbose语句

2. 默认情况下,Write_verbose是不输出的(您运行可能没有看到自己想要的结果),修改运行命令为:Get-SystemInfo -ComputerName localhost–verbose

 

Parameter aliases

为参数添加别名:在参数上添加属性:[Alias('hostname')],如此运行命令可以:Get-SystemInfo -Host localhost –verbose

 

Accepting pipeline input

记得在我们function设计的初衷,我们就有提到,-Computername可以从pipeLine接受string,下面我们就来实现,很简单:添加属性:

[Parameter(Mandatory=$True,ValueFromPipeline=$True)]

测试两种模式:

function Get-SystemInfo {[CmdletBinding()]param([Parameter(Mandatory=$True,ValueFromPipeline=$True)][Alias('hostname')][string[]]$ComputerName,[string]$ErrorLog = 'c:\retry.txt')BEGIN {Write-Verbose "Error log will be $ErrorLog"}PROCESS {Write-Verbose "Beginning PROCESS block"foreach ($computer in $computername) {Write-Verbose "Querying $computer"$os = Get-WmiObject -class Win32_OperatingSystem `-computerName $computer$comp = Get-WmiObject -class Win32_ComputerSystem `-computerName $computer$bios = Get-WmiObject -class Win32_BIOS `-computerName $computer$props = @{'ComputerName'=$computer;'OSVersion'=$os.version;'SPVersion'=$os.servicepackmajorversion;'BIOSSerial'=$bios.serialnumber;'Manufacturer'=$comp.manufacturer;'Model'=$comp.model}Write-Verbose "WMI queries complete"$obj = New-Object -TypeName PSObject -Property $propsWrite-Output $obj}}END {}}Write-Host "---- PIPELINE MODE ----"'localhost','localhost' | Get-SystemInfo -VerboseWrite-Host "---- PARAM MODE ----"Get-SystemInfo -ComputerName localhost,localhost -Verbose

从输出结果我们可以清楚地看到,pipeline的模式,我们的process运行了两次。

 

Parameter validation

我们现在的function存在潜在的缺点,我们要一次性查询每台电脑,可能需要很长的时间。所以我们最好加上参数验证,一次只能接受1到10个参数。

[Parameter(Mandatory=$True,ValueFromPipeline=$True)]
[ValidateCount(1,10)]

更新的function如下:

function Get-SystemInfo {[CmdletBinding()]param([Parameter(Mandatory=$True,ValueFromPipeline=$True)][ValidateCount(1,10)][Alias('hostname')][string[]]$ComputerName,[string]$ErrorLog = 'c:\retry.txt')BEGIN {Write-Verbose "Error log will be $ErrorLog"}PROCESS {Write-Verbose "Beginning PROCESS block"foreach ($computer in $computername) {Write-Verbose "Querying $computer"$os = Get-WmiObject -class Win32_OperatingSystem `-computerName $computer$comp = Get-WmiObject -class Win32_ComputerSystem `-computerName $computer$bios = Get-WmiObject -class Win32_BIOS `-computerName $computer$props = @{'ComputerName'=$computer;'OSVersion'=$os.version;'SPVersion'=$os.servicepackmajorversion;'BIOSSerial'=$bios.serialnumber;'Manufacturer'=$comp.manufacturer;'Model'=$comp.model}Write-Verbose "WMI queries complete"$obj = New-Object -TypeName PSObject -Property $propsWrite-Output $obj}}END {}}Get-SystemInfo -ComputerName one,two,three,four,five,six,seven,eight,nine,ten,eleven


 

执行,我们会看到:

“The number of supplied arguments (11) exceeds the maximum number of allowed arguments (10). Specify less than 10 arguments and then try the command again.”的错误信息。

 

Adding a switch parameter

还有,我们想把ErrorLog参数设置成可选参数:

param([Parameter(Mandatory=$True,ValueFromPipeline=$True)][ValidateCount(1,10)][Alias('hostname')][string[]]$ComputerName,[string]$ErrorLog = 'c:\retry.txt',[switch]$LogErrors)


 

添加参数提示信息:

param([Parameter(Mandatory=$True,ValueFromPipeline=$True,HelpMessage="Computer name or IP address")][ValidateCount(1,10)][Alias('hostname')][string[]]$ComputerName,[string]$ErrorLog = 'c:\retry.txt',[switch]$LogErrors)


 重要:

There are actually a bunch of other validation attributes that PowerShell understands: Runhelp about_functions_advanced_parameters in the shell to learn all about them.

 

Comment-based help

function Get-SystemInfo {<#.SYNOPSISRetrieves key system version and model informationfrom one to ten computers..DESCRIPTIONGet-SystemInfo uses Windows Management Instrumentation(WMI) to retrieve information from one or more computers.Specify computers by name or by IP address..PARAMETER ComputerNameOne or more computer names or IP addresses, up to a maximumof 10..PARAMETER LogErrorsSpecify this switch to create a text log file of computersthat could not be queried..PARAMETER ErrorLogWhen used with -LogErrors, specifies the file path and nameto which failed computer names will be written. Defaults toC:\Retry.txt..EXAMPLEGet-Content names.txt | Get-SystemInfo.EXAMPLEGet-SystemInfo -ComputerName SERVER1,SERVER2#>[CmdletBinding()]param([Parameter(Mandatory=$True,ValueFromPipeline=$True,HelpMessage="Computer name or IP address")][ValidateCount(1,10)][Alias('hostname')][string[]]$ComputerName,[string]$ErrorLog = 'c:\retry.txt',[switch]$LogErrors)BEGIN {Write-Verbose "Error log will be $ErrorLog"}PROCESS {Write-Verbose "Beginning PROCESS block"foreach ($computer in $computername) {Write-Verbose "Querying $computer"$os = Get-WmiObject -class Win32_OperatingSystem `-computerName $computer$comp = Get-WmiObject -class Win32_ComputerSystem `-computerName $computerListing 9.1 Adding comment-based help to our functionwww.it-ebooks.info82 CHAPTER 9 Writing help$bios = Get-WmiObject -class Win32_BIOS `-computerName $computer$props = @{'ComputerName'=$computer;'OSVersion'=$os.version;'SPVersion'=$os.servicepackmajorversion;'BIOSSerial'=$bios.serialnumber;'Manufacturer'=$comp.manufacturer;'Model'=$comp.model}Write-Verbose "WMI queries complete"$obj = New-Object -TypeName PSObject -Property $propsWrite-Output $obj}}END {}}help Get-SystemInfo -full

 

1 0