【问题标题】:PowerShell Invoke-Command Speed (win32_product)PowerShell 调用命令速度 (win32_product)
【发布时间】:2021-01-19 14:04:26
【问题描述】:

我编写了一个简短的脚本来卸载多台计算机上的程序(来自主机名的文本文档)。该脚本按预期工作,但每个主机大约需要 2-3 分钟。有没有办法在所有机器上同时执行此操作?

这是我的脚本。

$computers = Get-Content C:\Computernames.txt
foreach($Computer in $computers){
    Invoke-Command -ComputerName $Computer -ScriptBlock{
    
    $application = Get-WmiObject -Class Win32_Product -Filter "Name LIKE '%Appname%'"

    #uninstall the app if it exists
    if($application){
        $application.Uninstall()
        Write-Output "Application uninstalled successfully.."
    }

    else{
        Write-Output "Application not found.."
    }
    } 
}

我可以在Invoke-Command -ComputerName $Computers 上同时做所有机器以避免循环吗?

【问题讨论】:

  • -ComputerName 参数支持计算机阵列。所以$Computers 应该可以工作,只要它包含计算机名称。
  • “我可以……” - 你……试过了吗? :-) 这里没有人会阻止你
  • 我试过了,但我或多或少不确定如何在不手动检查的情况下验证脚本是否真的在每台机器上运行。我添加了一个`Write-Output $env:COMPUTERNAME` 去掉了循环,并使用了Invoke-Command -ComputerName $Computer -ScriptBlock{ ...,它打印了每个主机名,所以我相信它有效。

标签: powershell powershell-2.0 powershell-3.0 powershell-4.0


【解决方案1】:

按照建议,使用$Computers 成功。我能够摆脱循环并极大地加快脚本速度。

这是更新后的脚本 - 感谢您让我知道它支持数组。

#list of computers
$computers = Get-Content C:\Computernames.txt


Invoke-Command -ComputerName $computers -ScriptBlock{
    

$application = Get-WmiObject -Class Win32_Product -Filter "Name LIKE '%appname%'"


if($application){
    $application.Uninstall()
    Write-Output "Successful uninstall on $env:COMPUTERNAME "
    }

else{
    Write-Output "Application not found on $env:COMPUTERNAME"
    }
}

【讨论】:

  • 不想等待完成也可以使用-asjob
  • @AbrahamZinala 你能解释一下你的意思吗?这是否意味着窗口将在运行时关闭?
【解决方案2】:

众所周知,win32_product 类的速度很慢,因为它会在使用每个 msi 时对其进行验证。我假设 appname 被替换为特定名称。您可以在 powershell 5.1 中使用鲜为人知的 get-package 和 uninstall-package,但只能使用 msi 提供程序:

get-package appname | uninstall-package

【讨论】:

  • 你的假设是正确的。感谢您的建议 - 我下次会尝试。
猜你喜欢
  • 2015-04-22
  • 1970-01-01
  • 1970-01-01
  • 2021-12-24
  • 2016-12-12
  • 1970-01-01
  • 1970-01-01
  • 2022-12-10
  • 1970-01-01
相关资源
最近更新 更多