power shell 脚本需要在多个系统上运行,但不能循环遍历给定的计算机列表

power shell 脚本需要在多个系统上运行,但不能循环遍历给定的计算机列表
PS C:\Windows\system32> $compute = Get-Content D:\www\Comp.txt
Get-Content $compute | Foreach-Object {Get-RemoteProgram  -Property Publisher,InstallDate,DisplayVersion,InstallSource,IsMinorUpgrade,ReleaseType,ParentDisplayName,SystemComponent  | Where-Object {[string]$_.SystemComponent -ne 1 -and ![string]$_.IsMinorUpgrade -and ![string]$_.ReleaseType -and ![string]$_.ParentDisplayName} | Format-Table -auto -wrap | Out-File  -FilePath "D:\www\g4.txt"  -Append }
Get-Content : Cannot bind argument to parameter 'Path' because it is an empty string.
At line:2 char:13
+ Get-Content $compute | Foreach-Object {Get-RemoteProgram  -Property Publisher,In ...
+             ~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Get-Content], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.GetContentCommand

答案1

塞斯也说了同样的话...

话虽如此,你的帖子给人的印象是你刚刚开始掌握 PowerShell,这很好,因为我们都必须从某个地方开始。然而,你的代码中确实有一些非常基本的 PowerShell 错误。

您正在使用此功能读取文件内容...

$compute = Get-Content D:\www\Comp.txt

...这很好,但是你没有显示该文件中的内容,那么,有了这个...

Get-Content $compute | 
Foreach-Object {
Get-RemoteProgram  -Property Publisher,InstallDate,DisplayVersion,InstallSource,IsMinorUpgrade,ReleaseType,ParentDisplayName,SystemComponent  | 
Wher e-Object {
    [string]$_.SystemComponent -ne 1 -and ![string]$_.IsMinorUpgrade -and ![string]$_.ReleaseType -and ![string]$_.ParentDisplayName} | 
    Format-Table -auto -wrap | 
    Out-File  -FilePath "D:\www\g4.txt"  -Append
}

... 您正在尝试读取变量内容,但实际上您无需这样做,因为您已经存储了这些内容。因此,通过执行此操作来简化...

Get-Content -Path 'D:\www\Comp.txt' | 
ForEach-Object {}

我也不确定为什么你觉得有必要将它们转换为字符串,而默认情况下,你无论如何都会从属性返回值中获取它们。所以,就这样...

    $_.SystemComponent -ne 1 -and !$_.IsMinorUpgrade -and !$_.ReleaseType -and !$_.ParentDisplayName

此外,尽量避免在脚本中使用简写,这会让那些关注你的人或你可能将其传递给的人难以应对。有几篇文章讨论了这种非简写的事情,所以这不是个人观点。但它们非常适合快速互动的东西。

基本 PowerShell:避免在共享 PowerShell 脚本中使用简写

在 PowerShell 中没有名为 Get-RemoteProgram 的命令,这意味着您要么自己执行了此命令/函数,要么从其他地方获取了它。快速访问 MS Powershellgallery,会显示一个名称相似的脚本。因此,我假设您就是从那里获取的。

Find-Module -Name '*RemoteProgram*' | Ft -a
Find-Command -Name '*RemoteProgram*' | Ft -a
Find-Script -Name '*RemoteProgram*' | Ft -a

Version Name              Repository Description                                                                                                     
------- ----              ---------- -----------                                                                                                     
1.2.1   [Get-RemoteProgram PSGallery][2]  This function generates a list by querying the registry and returning the installed programs of a local or re...


# Load the script
. .\Get-RemoteProgram.ps1

# get function / cmdlet details
(Get-Command -Name Get-RemoteProgram).Parameters.Keys
Get-help -Name Get-RemoteProgram -Full
Get-help -Name Get-RemoteProgram -Online
Get-help -Name Get-RemoteProgram -Examples

Get-RemoteProgram
Get-RemoteProgram -ComputerName server01,server02
Get-RemoteProgram -ComputerName Server01 -Property DisplayVersion,VersionMajor
'server01','server02' | Get-RemoteProgram -Property Uninstallstring
'server01','server02' | Get-RemoteProgram -Property Uninstallstring -ExcludeSimilar -SimilarWord 4
Get-RemoteProgram -Property installdate,uninstallstring,installlocation -LastAccessTime | Where-Object {$_.installlocation}
Get-RemoteProgram -Property installdate -IncludeProgram *office*
Get-RemoteProgram -Property installdate -IncludeProgram 'Microsoft Office Access','Microsoft SQL Server 2014'
Get-RemoteProgram -IncludeProgram ^Office -ProgramRegExMatch

因此,看看作者所说的目标是什么以及你对它的使用。你真的只需要一些下面的链接。利用 PowerShell 自然换行符使其更易读,嗯,有些人会这么说。这是一个选择。如果您要将输出发送到文件,请不要使用格式,因为该格式适用于屏幕,当您在文件中执行此操作时它会被截断,除非您为其编写代码。

Get-Content -Path 'D:\www\Comp.txt' | 
ForEach-Object {
    Get-RemoteProgram -ComputerName $PSItem -Property Publisher, InstallDate, DisplayVersion,
    InstallSource, IsMinorUpgrade, ReleaseType, ParentDisplayName, SystemComponent  | 
    Where-Object {
        $PSItem.SystemComponent -ne 1 -and 
        -Not $PSItem.IsMinorUpgrade -and 
        -Not $PSItem.ReleaseType -and 
        -Not $PSItem.ParentDisplayName} | 
        Out-File -FilePath 'D:\www\g4.txt' -Append
}

notepad 'D:\www\g4.txt'

# Results


ComputerName      : WS01
ProgramName       : 7-Zip 18.01 (x64)
Publisher         : Igor Pavlov
InstallDate       : 
DisplayVersion    : 18.01
InstallSource     : 
IsMinorUpgrade    : 
ReleaseType       : 
ParentDisplayName : 
SystemComponent   : 

ComputerName      : WS01
ProgramName       : SAPIEN Document Explorer 2019
Publisher         : SAPIEN Technologies, Inc.
InstallDate       : 
DisplayVersion    : 3.1.88.0
InstallSource     : 
IsMinorUpgrade    : 
ReleaseType       : 
ParentDisplayName : 
SystemComponent   : 

ComputerName      : WS01
ProgramName       : Git version 2.21.0
Publisher         : The Git Development Community
InstallDate       : 20190227
DisplayVersion    : 2.21.0
InstallSource     : 
IsMinorUpgrade    : 
ReleaseType       : 
ParentDisplayName : 
SystemComponent   : 

...

因此,花一些时间在 YouTube 和 MSDN Channel9 上查看和学习那里的初级、中级、高级等视频。这样,在您前进的过程中,这将帮助您减少错误、困惑、坏习惯等。

OP 更新

至于:

我如何将其导出为 csv

只需改变这个...

Out-File -FilePath 'D:\www\g4.txt' -Append

... 至此...

Export-Csv -Path 'D:\www\g4.txt-Append -NoTypeInformation

OP 更新

您应该获得以下内容,而不是长度。

. .\Get-RemoteProgram.ps1
$env:COMPUTERNAME | 
ForEach-Object {
    Get-RemoteProgram -ComputerName $PSItem -Property Publisher, InstallDate, DisplayVersion,
    InstallSource, IsMinorUpgrade, ReleaseType, ParentDisplayName, SystemComponent  | 
    Where-Object {
        $PSItem.SystemComponent -ne 1 -and 
        -Not $PSItem.IsMinorUpgrade -and 
        -Not $PSItem.ReleaseType -and 
        -Not $PSItem.ParentDisplayName} | 
        Export-Csv -Path 'F:\temp\g4.txt' -Append -NoTypeInformation
}



Get-Content -Path 'F:\temp\g4.txt'

# Results


"ComputerName","ProgramName","Publisher","InstallDate","DisplayVersion","InstallSource","IsMinorUpgrade","ReleaseType","ParentDisplayName","SystemComponent"
"WS01","7-Zip 18.01 (x64)","Igor Pavlov",,"18.01",,,,,
"WS01","SAPIEN Document Explorer 2019","SAPIEN Technologies, Inc.",,"3.1.88.0",,,,,
...




Import-Csv -Path 'F:\temp\g4.txt' | 
Format-Table


# Results

ComputerName ProgramName                                                          Publisher                                                    InstallDate Disp
                                                                                                                                                           layV
                                                                                                                                                           ersi
                                                                                                                                                           on  
------------ -----------                                                          ---------                                                    ----------- ----
WS01         7-Zip 18.01 (x64)                                                    Igor Pavlov                                                              1...
WS01         SAPIEN Document Explorer 2019                                        SAPIEN Technologies, Inc.                                                3...
WS01         Git version 2.21.0                                                   The Git Development Community                                20190227    2...

答案2

这是不正确的:

$compute = Get-Content D:\www\Comp.txt
Get-Content $compute 

您正在从 D:\ww\Comp.txt 读取文件。然后,您尝试将该文件中的内容作为另一个路径读取。如果 D:\ww\Comp.txt 包含“MyPC”,那么您将尝试在“MyPC”上获取内容

尝试这样做:

$computers = Get-Content D:\Computers.txt
$Computers | ForEach {
    #DO STUFF
}

您还没有告诉 PowerShell 脚本在脚本中使用远程计算机:

Get-RemoteProgram  -Property Publisher,InstallDate,DisplayVersion,InstallSource,IsMinorUpgrade,ReleaseType,ParentDisplayName,SystemComponent

(在这种情况下 - 您可能处于循环内,但并未告知该命令针对远程计算机执行)

因为您的 PowerShell 脚本不是标准 cmdlet - 我假设您正在使用这个:https://gallery.technet.microsoft.com/scriptcenter/Get-RemoteProgram-Get-list-de9fd2b4

该脚本需要-ComputerName切换-因此您应该尝试类似以下操作:

Get-RemoteProgram  -ComputerName $_ -Property Publisher,InstallDate,DisplayVersion,InstallSource,IsMinorUpgrade,ReleaseType,ParentDisplayName,SystemComponent

脚本中还有其他一些部分需要注意,例如FT通过管道传输到Out-File。如果您想要文件中的网格 - 请尝试Export-csv

把它们放在一起 - 我认为你正在寻找类似的东西(编辑,这个脚本已经更新以反映评论中请求的额外帮助):

$ComputerList = Get-Content D:\Computers.txt

$ComputerList | ForEach {
    if (Test-Connection -ComputerName $_ -Quiet -Count 1) {
        Get-RemoteProgram -ComputerName $_ -Property Publisher,InstallDate,DisplayVersion,InstallSource,IsMinorUpgrade,ReleaseType,ParentDisplayName,SystemComponent | Where {
            [string]$_.SystemComponent -ne 1 -and ![string]$_.IsMinorUpgrade -and ![string]$_.ReleaseType -and ![string]$_.ParentDisplayName
        } | Export-Csv -Append -NoTypeInformation -Path D:\Results.csv
    } else {
        $_ | Out-File D:\UncontactableMachines.txt -Append
    }
}

附注:大多数(如果不是全部)操作都可以通过Get-WMIObjectGet-CIMInstance不通过引入外部Get-RemoteProgramcmdlet/函数来完成

希望这可以帮助。

相关内容