2017-08-08 71 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

相關問題