上一篇說過, 使用 wmic qfe
方式可以取得Windows裝了哪些的Patch的資訊。通常需要盤點電腦上裝了哪些patch的時候,也通常還想知道這電腦上的其他軟體有沒有更新到安全的版本,例如Office、Java、Adobe、或最近才傳出災情的7-zip。
很明顯的,在 wmic qfe
中,都不會顯示這些資訊。土法是,打開 控制台→程式集→程式和功能觀看目前安裝的軟體及其版本;然後可以再加碼進必已安裝的更新看到安裝過的更新。這個做法,如果台數一多就是個令人吐血的苦工(例如筆者要管破百的台數,就不適合);再上網Google一下,發現微軟公司有一個叫MBSA的工具,看起來也不錯,可是,他似乎也不能產出這電腦上的所有安裝資訊。
於是,我的目標轉往PowerShell,畢竟他可是Windows自己的Shell語言呢,這種資訊要是撈不出來,就很跌股了。
在Google打入 "powershell get office hotfix" 找出一大堆。下面是我試出一個可以用的。
貼Script的方式是這樣的:
Param([String[]]$Computers)
If (!$Computers) {$Computers = $ENV:ComputerName}
$Base = New-Object PSObject;
$Base | Add-Member Noteproperty ComputerName -Value $Null;
$Base | Add-Member Noteproperty Name -Value $Null;
$Base | Add-Member Noteproperty Publisher -Value $Null;
$Base | Add-Member Noteproperty InstallDate -Value $Null;
$Base | Add-Member Noteproperty EstimatedSize -Value $Null;
$Base | Add-Member Noteproperty Version -Value $Null;
$Base | Add-Member Noteproperty Wow6432Node -Value $Null;
$Results = New-Object System.Collections.Generic.List[System.Object];
ForEach ($ComputerName in $Computers){
$Registry = $Null;
Try{$Registry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine,$ComputerName);}
Catch{Write-Host -ForegroundColor Red "$($_.Exception.Message)";}
If ($Registry){
$UninstallKeys = $Null;
$SubKey = $Null;
$UninstallKeys = $Registry.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Uninstall",$False);
$UninstallKeys.GetSubKeyNames()|%{
$SubKey = $UninstallKeys.OpenSubKey($_,$False);
$DisplayName = $SubKey.GetValue("DisplayName");
If ($DisplayName.Length -gt 0){
$Entry = $Base | Select-Object *
$Entry.ComputerName = $ComputerName;
$Entry.Name = $DisplayName.Trim();
$Entry.Publisher = $SubKey.GetValue("Publisher");
[ref]$ParsedInstallDate = Get-Date
If ([DateTime]::TryParseExact($SubKey.GetValue("InstallDate"),"yyyyMMdd",$Null,[System.Globalization.DateTimeStyles]::None,$ParsedInstallDate)){
$Entry.InstallDate = $ParsedInstallDate.Value
}
$Entry.EstimatedSize = [Math]::Round($SubKey.GetValue("EstimatedSize")/1KB,1);
$Entry.Version = $SubKey.GetValue("DisplayVersion");
[Void]$Results.Add($Entry);
}
}
If ([IntPtr]::Size -eq 8){
$UninstallKeysWow6432Node = $Null;
$SubKeyWow6432Node = $Null;
$UninstallKeysWow6432Node = $Registry.OpenSubKey("Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall",$False);
If ($UninstallKeysWow6432Node) {
$UninstallKeysWow6432Node.GetSubKeyNames()|%{
$SubKeyWow6432Node = $UninstallKeysWow6432Node.OpenSubKey($_,$False);
$DisplayName = $SubKeyWow6432Node.GetValue("DisplayName");
If ($DisplayName.Length -gt 0){
$Entry = $Base | Select-Object *
$Entry.ComputerName = $ComputerName;
$Entry.Name = $DisplayName.Trim();
$Entry.Publisher = $SubKeyWow6432Node.GetValue("Publisher");
[ref]$ParsedInstallDate = Get-Date
If ([DateTime]::TryParseExact($SubKeyWow6432Node.GetValue("InstallDate"),"yyyyMMdd",$Null,[System.Globalization.DateTimeStyles]::None,$ParsedInstallDate)){
$Entry.InstallDate = $ParsedInstallDate.Value
}
$Entry.EstimatedSize = [Math]::Round($SubKeyWow6432Node.GetValue("EstimatedSize")/1KB,1);
$Entry.Version = $SubKeyWow6432Node.GetValue("DisplayVersion");
$Entry.Wow6432Node = $True;
[Void]$Results.Add($Entry);
}
}
}
}
}
}
$Results
}```
---
呼叫Script定義好的 **Function "Get-InstalledSoftware"** 是這樣的
- 進入 **PS C:\Users\user name>**
- 輸入以下
```Get-InstalledSoftware | Sort-Object @{Expression={$_.ComputerName};Ascending=$True},@{Expression={$_.Name};Ascending=$True} | Export-CSV -NoTypeInformation ".\InstalledSoftware.csv"```
產生的檔案就會在username的folder下。