2017-08-08 70 views
0

我已经编写了一个基本的PS脚本,以便卸载在文本文件($ servers)中定义的所有服务器上的文本文件($ appname)中定义的任何程序。PowerShell脚本从服务器列表中卸载多个程序

手动运行此命令,但没有变量,它可以正常工作,但是通过Jenkins或PS命令行运行脚本时,它只是挂起,所以我甚至无法调试,任何人有任何想法?

[array]$servers= Get-Content "D:\Jenkins\BuildUtilities\Citrix\CitrixServerList.txt" 
[array]$appname= Get-Content "D:\Jenkins\BuildUtilities\Citrix\ProgramsList.txt" 

ForEach($server in $servers) { 

$prod=gwmi -ComputerName $server Win32_product | ?{$_.name -eq $appname} 
$prod.uninstall() 

} 

澄清:通过运行手动我的意思是运行以下: gwmi -ComputerName CTX-12的Win32_Product | ?{_。Name -eq“Microsoft Word”}

Microsoft Word是一个示例。

+0

编辑您的问题,以澄清到底什么“工作正常” - 你是什么运行“手动没有变量”?你是从你的工作站上运行的吗? Jenkins和您的工作站上的PS命令行,还是他们在不同的机器上? –

+0

嗨迈克,请道歉请参阅我的编辑@ MikeSherrill'CatRecall' – jto

+0

好吧,您可以开始添加线路,告诉您当前正在卸载哪个产品以查看它挂在哪个服务器和产品上,以查看是否存在趋势。 '$ appname'是一个数组。 '-eq'不是这种方式的数组运算符。你需要使用'-contains'或'-in'。此外,我不知道你是否可以一次调用'.Uninstall()'所有数组项目/一个好主意。 '$ appname -contains $ _。name'或'$ appname'只有一行吗? – Matt

回答

0

它应该是很容易跟随马茨暗示

[array]$servers= Get-Content "D:\Jenkins\BuildUtilities\Citrix\CitrixServerList.txt" 
[array]$appname= Get-Content "D:\Jenkins\BuildUtilities\Citrix\ProgramsList.txt" 

ForEach($server in $servers) { 
    $prod=gwmi -ComputerName $server Win32_product | ?{ $appname -contains $_.name} 
    $prod.uninstall() 
} 
+0

嗨,我遵循Matts提示,它仍然不工作,我害怕。 – jto

+0

但是现在出现以下错误消息:您无法在空值表达式上调用方法。 在D:\ Jenkins \ BuildUtilities \ Citrix \ UninstallPrograms.ps1:6 char:5 + $ prod.uninstall() + ~~~~~~~~~~~~~~~~~ + CategoryInfo: InvalidOperation:(:) [],RuntimeException + FullyQualifiedErrorId:InvokeMethodOnNull – jto

0

你正在做两个数组的比较,你想要做的是检查督促阵列中的匹配应用的每一个实例你从取服务器,所以使用管道如何拥有它并不理想。

[array]$servers= Get-Content "D:\Jenkins\BuildUtilities\Citrix\CitrixServerList.txt" 
[array]$appname= Get-Content "D:\Jenkins\BuildUtilities\Citrix\ProgramsList.txt" 
$DebugPreference= 'Continue' 

foreach($server in $servers) 
{ 
    Write-Debug "Getting all installed applications on server $server" 
    $prod= Invoke-Command -ComputerName $server -Scriptblock {gwmi Win32_product} 
    Write-Debug "Installed applications collected, there are $($prod.Count) items in the array." 

    foreach($p in $prod) 
    { 
     Write-Debug "Searching apps array for the name $($p.Name)." 
     if($appname -contains $p.Name) 
     { 
      Write-Verbose -Message "$($p.Name) found on server $server, uninstalling." 
      $p.uninstall() 
     } 
     else 
     { 
      Write-Verbose -Message "$($p.Name) was not found on server $server." 
     } 
    } 
} 

编辑:由于您提出了速度问题,使用Win32_product是非常缓慢的。所以更快的方法是从注册表项HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall获取已安装应用程序的列表(详细说明如何做到这一点是here)。构建一系列需要卸载的应用程序,然后调用Win32_product。只要知道这只会加速脚本的一部分,如果找到任何应​​用程序,速度仍然会降低。当你找到一台没有任何卸载应用程序的服务器时,主要的速度收益将来自于此。编辑2:做了一些尝试,使用简单的Invoke-Command大大加快了Get-WMIObject命令的速度。我在服务上做了它,单独使用命令花费了9秒,使用Invoke-Command花了1秒。测试:

$firstStart = Get-Date 
$service1 = Get-WmiObject win32_service -ComputerName $ServerName 
$firstEnd = Get-Date 
$firstTime = New-TimeSpan -Start $firstStart -End $firstEnd 
Write-Host "The first collection completed in $($firstTime.TotalSeconds) seconds." -ForegroundColor Green 

$secondStart = Get-Date 
$service2 = Invoke-Command -ComputerName $ServerName -ScriptBlock {Get-WmiObject win32_service} 
$secondEnd = Get-Date 
$secondTime = New-TimeSpan -Start $secondStart -End $secondEnd 
Write-Host "The second collection completed in $($secondTime.TotalSeconds) seconds." -ForegroundColor Green 
+1

您可以使用'write-debug'来代替devmode。你也有拼写错误'Verbonse' =>'verbose' – Matt

+0

@Matt谢谢,这是一个奇妙的想法。 – Paolis

+0

Hi @Paolis感谢您花时间回答。我目前正在Jenkins试用你的脚本,但是它已经运行了10分钟,仍然没有完成服务器上所有已安装的应用程序,是否有更高效的方法来执行此操作?也许只是寻找$ appname中列出的应用程序? – jto

相关问题