Powershell 管道与参数参数输入?

Powershell 管道与参数参数输入?,powershell,powershell-5.1,Powershell,Powershell 5.1,对于通过管道或参数输入接受值时的区别,我有一个疑问 我这样问是因为: 在我的脚本中,通过管道接受值是有效的 使用诸如“-ComputerName”之类的参数参数接受值是可行的 我这样说是因为,它确实从同一个变量获取我的输入,直到有一个变量无法连接,然后停止脚本。这有什么原因吗 以下是我给好奇的人的剧本: Function Set-DWRCVersion { <# NAME Set-DWRCVersion SYNTAX Set-DWRCVersion [[-Co

对于通过管道或参数输入接受值时的区别,我有一个疑问

我这样问是因为:

  • 在我的脚本中,通过管道接受值是有效的
  • 使用诸如“
    -ComputerName
    ”之类的参数参数接受值是可行的
我这样说是因为,它确实从同一个变量获取我的输入,直到有一个变量无法连接,然后停止脚本。这有什么原因吗

以下是我给好奇的人的剧本:

Function Set-DWRCVersion {
<#
NAME
    Set-DWRCVersion
    
SYNTAX
    Set-DWRCVersion [[-ComputerName] <string[]>]  [<CommonParameters>]

EXAMPLES
    Set-DWRCVersion -ComputerName LocalHost,ComputerOne
    'LocalHost','ComputerOne' | Set-DWRCVersion
    $CritNames | Set-DWRCVersion
    
    $CritNames | Set-DWRCVersion |Export-Csv "$($env:USERPROFILE.Substring(0,20))\Desktop\NewCrit.CSV" -Force -NoTypeInformation 
#>

[cmdletbinding()]
    Param(
        [Parameter(Mandatory=$true,
                   ValueFromPipeline=$true,
                   ValueFromPipeLineByPropertyName=$true)]
                   [ValidateLength(1,15)]
                   [Alias('Comp','CN','name')]
                   [string[]]$ComputerName)
                   
Process{
        try{
        [string]$Path = "C:\Users\Abraham\Desktop\dwrcs"  #Dameware File Path (current)
            foreach($Computer in $ComputerName){
                $PSSession = New-PSSession -ComputerName $Computer -ErrorAction Stop
                $TestPath  = Invoke-Command -Session $PSSession -ScriptBlock { Test-Path -Path "C:\Windows\dwrcs" }
                    if($TestPath -eq $false){
                        Copy-Item -Path $Path -Destination "\\$Computer\C$\Windows" -Recurse -Force }
                        #Start-Sleep -Seconds 1

                $EXEVersion = Invoke-Command -Session $PSSession -ScriptBlock { [System.Diagnostics.FileVersionInfo]::GetVersionInfo("C:\Windows\dwrcs\DWRCS.EXE").FileVersion }
                $DLLVersion = Invoke-Command -Session $PSSession -ScriptBlock { [System.Diagnostics.FileVersionInfo]::GetVersionInfo("C:\Windows\dwrcs\DWRCRSS.dll").FileVersion }
                    if($EXEVersion -notmatch '12.1.2.584'){
                        [PSCustomObject] @{
                                "Computer Name"  = $Computer
                                "Status"         = "Online"
                                "DWRC Version"   = $EXEVersion
                                "DWRCRSS DLL"    = $DLLVersion
                                "DWRC Check"     = "Not up to date" }
                                ""
                        Write-Output -InputObject "Version not current"
                        Write-Output -InputObject "Stopping Service. . ."
                        Invoke-Command -Session $PSSession -ScriptBlock { 
                            Stop-Service -Name dwmrcs;
                            Get-Item -Path C:\windows\dwrcs | Rename-Item -NewName "dwrcs.old" }
                            Remove-Item -Path "\\$Computer\c$\Windows\dwrcs.old" -Recurse -Force -ErrorAction SilentlyContinue
                            #Start-Sleep 1

                        Write-Output -InputObject "Copying new files over. . ."
                        Copy-Item -Path $Path -Destination "\\$Computer\C$\Windows" -Recurse -Force

                        Write-Output -InputObject "Starting Service. . ."
                        Invoke-Command -Session $PSSession -ScriptBlock { Start-Service -Name dwmrcs }
                              } 
                    elseif($EXEVersion -match '12.1.2.584') {
                        [PSCustomObject] @{
                                "Computer Name"  = $Computer
                                "Status"         = "Online"
                                "DWRC Version"   = $EXEVersion
                                "DWRCRSS DLL"    = $DLLVersion
                                "Version Check"  = "Up to Date" }
                              }
                    else { Write-Output -InputObject "Error Occured"
                           Throw "$($Error[0].Exception.Message)"  }
                    }
            } Catch {
                        [PSCustomObject] @{
                                "Computer Name"  = $Computer
                                "Status"         = "Offline"
                                "DWRC Version"   = $null
                                "DWRCRSS DLL"    = $null
                                "Version Check"  = $null }
            } Finally {
                if ($PSSession) {
                Get-PSSession | Remove-PSSession }
        }
    }
}
函数集DWRCVersion{
[cmdletbinding()]
Param(
[参数(必需=$true,
ValueFromPipeline=$true,
ValueFromPipeLineByPropertyName=$true)]
[验证长度(1,15)]
[别名('Comp','CN','name')]
[字符串[]]$ComputerName)
过程{
试一试{
[string]$Path=“C:\Users\Abraham\Desktop\dwrcs”#数据软件文件路径(当前)
foreach($ComputerName中的计算机){
$PSSession=新PSSession-ComputerName$Computer-ErrorAction停止
$TestPath=Invoke命令-Session$PSSession-ScriptBlock{TestPath-Path“C:\Windows\dwrcs”}
if($TestPath-eq$false){
复制项目-Path$Path-Destination“\\$Computer\C$\Windows”-Recurse-Force}
#开始睡眠-秒1
$execversion=Invoke命令-Session$PSSession-ScriptBlock{[System.Diagnostics.FileVersionInfo]::GetVersionInfo(“C:\Windows\dwrcs\dwrcs.EXE”).FileVersion}
$DLLVersion=Invoke命令-Session$PSSession-ScriptBlock{[System.Diagnostics.FileVersionInfo]::GetVersionInfo(“C:\Windows\dwrcs\DWRCRSS.dll”).FileVersion}
如果($exevision-不匹配'12.1.2.584'){
[PSCustomObject]@{
“计算机名”=$Computer
“状态”=“联机”
“DWRC版本”=$EXEVersion
“DWRCRSS DLL”=$DLLVersion
“DWRC检查”=“非最新”}
""
写入输出-InputObject“版本非当前”
写入输出-InputObject“正在停止服务…”
调用命令-Session$PSSession-ScriptBlock{
停止服务-名称dwmrcs;
获取项目-路径C:\windows\dwrcs |重命名项目-NewName“dwrcs.old”}
删除项-路径“\\$Computer\c$\Windows\dwrcs.old”-递归-强制-错误操作SilentlyContinue
#开始睡眠1
写入输出-InputObject“通过…复制新文件”
复制项目-路径$Path-目标“\\$Computer\C$\Windows”-递归-强制
写入输出-输入对象“正在启动服务…”
调用命令-Session$PSSession-ScriptBlock{Start Service-Name dwmrcs}
} 
elseif($exevision-匹配'12.1.2.584'){
[PSCustomObject]@{
“计算机名”=$Computer
“状态”=“联机”
“DWRC版本”=$EXEVersion
“DWRCRSS DLL”=$DLLVersion
“版本检查”=“最新”}
}
else{写入输出-InputObject“发生错误”
抛出“$($错误[0]。异常。消息)”}
}
}抓住{
[PSCustomObject]@{
“计算机名”=$Computer
“状态”=“脱机”
“DWRC版本”=$null
“DWRCRSS DLL”=$null
“版本检查”=$null}
}最后{
如果($PSSession){
获取PSSession |删除PSSession}
}
}
}
总的来说,这是一个非常简单的脚本,它将为我获得一些远程文件版本。我只是不确定为什么接受管道中的值不会停止脚本,但使用常规参数输入值会停止脚本

Im从csv导入以使用以下内容获取名称:

$Crit = Import-Csv -Path "$($env:USERPROFILE.Substring(0,20))\Desktop\med.csv"
$CritNames = $Crit.'NetBios Name' -replace "AREA51\\","" 

<# Names return like so:
COmputerOne
COmputerTwo
COmputerThr
Etc.. #>
$Crit=Import Csv-Path“$($env:USERPROFILE.Substring(0,20))\Desktop\med.Csv”
$CritNames=$Crit.NetBios Name'-替换为“AREA51\\”
当使用管道输入运行它时:
$CritNames | Set DWRCVersion
有效,但是,
Set DWRCVersion-ComputerName$CritNames
无效;直到它碰到离线计算机,然后停止脚本


我有什么遗漏吗?比我聪明得多的人能教我吗?(:

你可以通过移动
foreach
循环中的
try
/
catch
/
finally
语句来解决这个问题:

process {
  foreach($Computer in $ComputerName){
    try {
      # ...
    }
    catch {
      # ...
    }
    finally {
      # ...
    }
  }
}

为什么这会有不同

当通过
-ComputerName
显式绑定一个值时,
进程
块只调用一次,但当您通过管道提供输入时,
进程
块会对每个输入项调用一次

您可以使用以下简单的测试函数来观察此行为:

function Test-ProcessInvocation {
  param(
    [Parameter(Mandatory,ValueFromPipeline)]
    [string[]]$ComputerName
  )

  process {
    "Running process block with $($ComputerName.Length) input arguments: [$ComputerName]"
  }
}
在两种输入模式下运行此操作将使此行为清晰可见:

PS~>testprocessinvocation-ComputerName 1,2,3
正在使用3个输入参数运行进程块:[1 2 3]
PS~>1,2,3 |测试过程调用
正在使用1个输入参数运行进程块:[1]
正在使用1个输入参数运行进程块:[2]
使用1个输入参数运行进程块
# Single invocation of `process` block with $ComputerName = all input values at once
try {
  foreach($Computer in 'Computer1','Computer2'){

  }
}
catch {}
finally {}
# `process` block repeats per input item
try {
  foreach($Computer in 'Computer1'){

  }
}
catch {}
finally {}

try {
  foreach($Computer in 'Computer2'){

  }
}
catch {}
finally {}