01_你倒底想干嘛?

缘起

要说起这次自我挑战,起因还是今年行政院拍板了新板的「资通安全管理法子法」。身为网管,IT中的挨踢,这下皮可要蹦紧了。

挨踢狗自己盘算了一下,手上管的上百部员工用电脑,会是过去没查过,未来的主要稽查目标之一。
https://ithelp.ithome.com.tw/upload/images/20181017/20111755pGbsT3kb7w.jpg
<来源> https://www.nccst.nat.gov.tw/HandoutDetail?lang=zh&seq=1276
而,要通过稽查,有以下的关卡必需突破:

  1. 即时查询电脑硬体资讯,包含 {电脑名称,电脑型号,使用IP,网卡硬体位址等}
  2. 即时查询电脑软体资讯,包含 {电脑的OS,安装的软体及版本,最近一次更新纪录等}
  3. 即时查询登入人的资讯,包含 {现在登入帐号是谁,是否具本机管理员权限,是否开启USB权限等}

在查访了商用套装软体、开源软体等,有天注意到PowerShell这工具,在2009 iT 邦帮忙铁人赛,有高手引导在前。于是,挨踢狗满怀希望的展开这次计划,希望铁人赛期间,日有进境的完成这些关卡的突破。

查询你的Windows上, OFFICE等装了哪些的Patch?

上一篇说过, 使用 wmic qfe 方式可以取得Windows装了哪些的Patch的资讯。通常需要盘点电脑上装了哪些patch的时候,也通常还想知道这电脑上的其他软体有没有更新到安全的版本,例如Office、Java、Adobe、或最近才传出灾情的7-zip

很明显的,在 wmic qfe 中,都不会显示这些资讯。土法是,打开 控制台程序集程序和功能观看目前安装的软体及其版本;然后可以再加码进必已安装的更新看到安装过的更新。这个做法,如果台数一多就是个令人吐血的苦工(例如笔者要管破百的台数,就不适合);再上网Google一下,发现微软公司有一个叫MBSA的工具,看起来也不错,可是,他似乎也不能产出这电脑上的所有安装资讯。

于是,我的目标转往PowerShell,毕竟他可是Windows自己的Shell语言呢,这种资讯要是捞不出来,就很跌股了。
在Google打入 “powershell get office hotfix” 找出一大堆。下面是我试出一个可以用的。

要操作这组script前,要进入PowerShell,PowerShell有2个模式:cmdlet (发音如 “command-let”,就是命令列模式) 和ISE模式(视窗模式)。我使用的是cmdlet模式。先将Script贴上,然后呼叫Script定义好的 Function “Get-InstalledSoftware”

贴Script的方式是这样的:

  • 进入 PS C:\Users\user name>
  • 输入以下
    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下。