I am attempting to see what Office version is installed on network pcs so we can update only those that need our recent version per procedures. I really don’t want to walk up to 500+ pcs and check what Office is installed.
I understand that PSRemoting must be enabled on those machines.
I am trying to use Get-RemoteProgram.ps1
I want to get a list of PCs from a file (which is working), I want to get all listed versions of office (which is also working in my tests), and exclude anything that has “Update” in the program name (“Update” or “Security Update” things like that).
This code works, but gives me all the updates in my output which is not desired.
Get-Content -Path .\PClist.txt | ForEach-Object -Begin {. .\Get-RemoteProgram.ps1} -Process {Get-RemoteProgram -ComputerName $_} | Where-Object {$_.ProgramName -like '*Office*'} | Select-Object -Property ComputerName, ProgramName | Export-Csv -Append -Path .\InstalledPrograms.csv -NoTypeInformation
This code fails with a parsing error where
Where-Object {$_.ProgramName -like ‘Office’ -notmatch ‘Update’}
is located.
Get-Content -Path .\PClist.txt | ForEach-Object -Begin {. .\Get-RemoteProgram.ps1} -Process {Get-RemoteProgram -ComputerName $_} | Where-Object {$_.ProgramName -like '*Office*' -notmatch '*Update*'} | Select-Object -Property ComputerName, ProgramName | Export-Csv -Path .\InstalledPrograms.csv -NoTypeInformation
Here is the exact error
parsing “Update” - Quantifier {x,y} following nothing.
At line:1 char:146
- … ere-Object {$_.ProgramName -like ‘Office’ -notmatch ‘Update’} | S …
-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- CategoryInfo : OperationStopped: ( , ArgumentException
- FullyQualifiedErrorId : System.ArgumentException
I have also tried
{$_.ProgramName -like "*Office*" -notmatch "*Update*"'} |
and I have also tried
{$_.ProgramName -like "*Office*" -notlike "*Update*"'} |
Am I using the wrong selector(s) in the Where-Object?
Here is the Get-RemoteProgram.ps1
Function Get-RemoteProgram { [CmdletBinding(SupportsShouldProcess=$true)] param( [Parameter(ValueFromPipeline =$true, ValueFromPipelineByPropertyName=$true, Position=0 )] [string[]] $ComputerName = $env:COMPUTERNAME, [Parameter(Position=0)] [string[]] $Property, [switch] $ExcludeSimilar, [int] $SimilarWord ) begin { $RegistryLocation = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\', 'SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\' $HashProperty = @{} $SelectProperty = @('ProgramName','ComputerName') if ($Property) { $SelectProperty += $Property } } process { foreach ($Computer in $ComputerName) { $RegBase = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine,$Computer) $RegistryLocation | ForEach-Object { $CurrentReg = $_ if ($RegBase) { $CurrentRegKey = $RegBase.OpenSubKey($CurrentReg) if ($CurrentRegKey) { $CurrentRegKey.GetSubKeyNames() | ForEach-Object { if ($Property) { foreach ($CurrentProperty in $Property) { $HashProperty.$CurrentProperty = ($RegBase.OpenSubKey("$CurrentReg$_")).GetValue($CurrentProperty) } } $HashProperty.ComputerName = $Computer $HashProperty.ProgramName = ($DisplayName = ($RegBase.OpenSubKey("$CurrentReg$_")).GetValue('DisplayName')) if ($DisplayName) { New-Object -TypeName PSCustomObject -Property $HashProperty | Select-Object -Property $SelectProperty } } } } } | ForEach-Object -Begin { if ($SimilarWord) { $Regex = [regex]"(^(.+?\s){$SimilarWord}).*$|(.*)" } else { $Regex = [regex]"(^(.+?\s){3}).*$|(.*)" } [System.Collections.ArrayList]$Array = @() } -Process { if ($ExcludeSimilar) { $null = $Array.Add($_) } else { $_ } } -End { if ($ExcludeSimilar) { $Array | Select-Object -Property *,@{ name = 'GroupedName' expression = { ($_.ProgramName -split $Regex)[1] } } | Group-Object -Property 'GroupedName' | ForEach-Object { $_.Group[0] | Select-Object -Property * -ExcludeProperty GroupedName } } } } } }