Issues with foreach for a function , need help.
hi folks, writing kind of function/script find apps installed multiple machine input file of computer name looks reading data local computer only.
here code, see missing here.
$computers = get-content -path .\computers.txt
function get-installedapps
{
[cmdletbinding()]
param
(
[parameter(mandatory=$true)][string[]]$computers
)
foreach ($computername in $computers)
{
$proc =$env:processor_architecture
$regkey = "hklm:\software\microsoft\windows\currentversion\uninstall\*"
$regkey32 = "hklm:\software\wow6432node\microsoft\windows\currentversion\uninstall\*"
$installedapps = get-itemproperty -path $regkey
$installedapps32 = get-itemproperty -path $regkey32
if ($proc -eq 'amd64')
{
#process variable data
write-verbose -message 'starting exporting 64bit application installed csv' -verbose
$installedapps | where-object {($_.displayname -notlike "security update for*") -and ($_.displayname -notlike "update for*")} `
| select @{n='computername';e={$computername}}, displayname, publisher, displayversion -unique | export-csv -path .\apssinstalled.csv -notypeinformation
write-verbose -message '64bit application exported csv file' -verbose
write-verbose -message 'starting exporting 32bit application installed csv' -verbose
$installedapps32 | where-object {($_.displayname -notlike "security update for*") -and ($_.displayname -notlike "update for*")}`
| select @{n='computername';e={$computername}}, displayname, publisher, displayversion -unique | sort-object -property publisher -descending | export-csv -path .\apssinstalled.csv -notypeinformation -append
write-verbose -message '32bit application exported csv file' -verbose
}
else
{
write-verbose -message 'starting exporting 32bit application installed csv' -verbose
$installedapps | where-object {($_.displayname -notlike "security update for*") -and ($_.displayname -notlike "update for*")} `
| select @{n='computername';e={$computername}}, displayname, publisher, displayversion -unique | sort-object -property publisher -descending | export-csv -path .\apssinstalled.csv -notypeinformation
write-verbose -message '64bit application exported csv file' -verbose
}
}
}
thanks
roushan
hi roushan,
you cannot access remote registries registry provider in powershell (it's local use only). may loop through computers specified, never use the computername anywhere.
fortunately you, christmas coming, either put in lot of work or stole lot (which fine) , wrote function years ago:
function get-installedapplication { <# .synopsis reads registry of multiple computers installed applications. .description reads registry of multiple computers installed applications. it reads uninstall paths both x86 , x64 applications. this means applications proper installer detected. .parameter computername the computers scanned. various input types accepted. accepts pipeline input .parameter appid only applications id matches parameter (if set @ all) returned. the comparison uses -like operator , accepts wildcards .parameter appname only applications name matches parameter (if set @ all) returned. the comparison uses -like operator , accepts wildcards .parameter publisher only applications publisher matches parameter (if set @ all) returned. the comparison uses -like operator , accepts wildcards .parameter version only applications version matches parameter (if set @ all) returned. the comparison uses -like operator , accepts wildcards .parameter architecture only applications architecure matches parameter (if set @ all) returned. accepts strings "32-bit" , "64-bit" the comparison uses -like operator , accepts wildcards .parameter matchall if switch set false, first hit each computer returned. .parameter nores internal use .example ps c:\> get-installedapplications -computername "pc1234567" retrieve applications installed on pc1234567. #> [cmdletbinding()] param ( [parameter(position = 0, valuefrompipeline = $true)] [string[]] $computername = $env:computername, [string] $appid, [string] $appname, [string] $publisher, [string] $version, [string] [validateset("32-bit", "64-bit", "x86", "x64", "32-bit", "64-bit", "32bit", "64bit", "32bit", "64bit")] $architecture, [switch] $matchall = $true, [switch] $nores ) begin { write-debug "[start] [scanning installed applications]" # set registry paths $hklm = [uint32] "0x80000002" $uninstall_key = "software\microsoft\windows\currentversion\uninstall" $uninstall_key_wow = "software\wow6432node\microsoft\windows\currentversion\uninstall" # create hash table containing requested application properties. $propertylist = @{ } if ($appid -ne "") { $propertylist.appid = $appid } if ($appname -ne "") { $propertylist.appname = $appname } if ($publisher -ne "") { $propertylist.publisher = $publisher } if ($version -ne "") { $propertylist.version = $version } if ($architecture -ne "") { switch ($architecture) { "x86" { $architecture = "32-bit" } "x64" { $architecture = "64-bit" } "32-bit" { $architecture = "32-bit" } "64-bit" { $architecture = "64-bit" } "32bit" { $architecture = "32-bit" } "64bit" { $architecture = "64-bit" } "32bit" { $architecture = "32-bit" } "64bit" { $architecture = "64-bit" } } $propertylist.architecture = $architecture } # results $results = @() #region helper function function compare-leafequality { <# .synopsis compares 2 lists of paths, comparing leafs .description compares 2 lists of paths, comparing leafs .parameter list1 first list of paths .parameter list2 second list of paths #> [cmdletbinding()] param ( [parameter(position = 0)] $list1, [parameter(position = 1)] $list2 ) # create arraylists hold leaf items , build both lists. $leaflist1 = new-object system.collections.arraylist $list1 | foreach-object { [void]$leaflist1.add((split-path $_ -leaf)) } $leaflist2 = new-object system.collections.arraylist $list2 | foreach-object { [void]$leaflist2.add((split-path $_ -leaf)) } # if compare-object has no output, lists matched. $test = (compare-object $leaflist1 $leaflist2 | measure-object).count -eq 0 return $test } #endregion helper function } process { foreach ($computer in $computername) { write-verbose ("getting installed applications " + $computer) #region start scanning computer try { $result = @() $regprov = [wmiclass] "\\$($computer)\root\default:stdregprov" # enumerate hklm\software\microsoft\windows\currentversion\uninstall # note request redirected wow6432node if running 32-bit # powershell on 64-bit windows. $keylist = new-object system.collections.arraylist $keys = $regprov.enumkey($hklm, $uninstall_key) foreach ($key in $keys.snames) { [void]$keylist.add((join-path $uninstall_key $key)) } # enumerate hklm\software\wow6432node\microsoft\windows\currentversion\uninstall $keylistwow64 = new-object system.collections.arraylist $keys = $regprov.enumkey($hklm, $uninstall_key_wow) if ($keys.returnvalue -eq 0) { foreach ($key in $keys.snames) { [void]$keylistwow64.add((join-path $uninstall_key_wow $key)) } } # default 32-bit. if there items in $keylistwow64, compare # leaf items in both lists of subkeys. if leaf items in both lists match, we're # seeing wow6432node redirection in effect , can ignore $keylistwow64. # otherwise, we're 64-bit , append $keylistwow64 $keylist enumerate both. $is64bit = $false if ($keylistwow64.count -gt 0) { if (-not (compare-leafequality $keylist $keylistwow64)) { $is64bit = $true [void]$keylist.addrange($keylistwow64) } } # enumerate subkeys. foreach ($subkey in $keylist) { $name = $regprov.getstringvalue($hklm, $subkey, "displayname").svalue if ($name -eq $null) { continue } # skip entry if empty display name $output = new-object psobject -property @{ computername = ""; appid = ""; appname = ""; publisher = ""; version = ""; architecture = ""; installpath = "" } $output.computername = $computer $output.appid = (split-path $subkey -leaf) $output.appname = $name $output.publisher = $regprov.getstringvalue($hklm, $subkey, "publisher").svalue $output.version = $regprov.getstringvalue($hklm, $subkey, "displayversion").svalue $output.installpath = $regprov.getstringvalue($hklm, $subkey, "installlocation").svalue # if subkey's name in wow6432node, application 32-bit. otherwise, # $is64bit determines whether application 32-bit or 64-bit. if ($subkey -like "software\wow6432node\*") { $apparchitecture = "32-bit" } else { if ($is64bit) { $apparchitecture = "64-bit" } else { $apparchitecture = "32-bit" } } $output.architecture = $apparchitecture # if no properties defined on command line, output object. if ($propertylist.keys.count -eq 0) { $result += $output } # otherwise, iterate requested properties , count number of matches. else { $matches = 0 foreach ($key in $propertylist.keys) { if ($output.$key -like $propertylist.$key) { $matches += 1 } } # if properties matched, output object. if ($matches -eq $propertylist.keys.count) { $result += $output # if -matchall missing, don't enumerate further. if (-not $matchall) { break } } } } # [endofloop] each entry $results += $result $result } #endregion start scanning computer #region manage errors catch { $exception = $_.exception $object = new-object psobject -property @{ computername = ""; appid = ""; appname = ""; publisher = ""; version = ""; architecture = ""; installpath = "" } if ($exception.message -like "*hresult: 0x800706ba*") { $object.computername = $computer $object.appid = "error" $object.appname = "rpc-server not available" $object.publisher = $exception.gettype().name $object.version = "hresult: 0x800706ba" $object.architecture = $exception.message } elseif (($exception.message -like "*zugriff verweigert*") -or ($exception.message -like "*access denied*")) { $object.computername = $computer $object.appid = "error" $object.appname = "access denied" $object.publisher = $exception.gettype().name $object.version = "access denied" $object.architecture = $exception.message } else { $object.computername = $computer $object.appid = "error" $object.appname = "unidentified error" $object.publisher = $exception.gettype().name $object.version = "unidentified error" $object.architecture = $exception.message } $results += $object $object } #endregion manage errors } } end { if ($nores -ne $true) { $script:result = $results } # write closing line write-debug "[end] [scanning installed applications]" } }
not finest work, should job :)
cheers,
fred
there's no place 127.0.0.1
Windows Server > Windows PowerShell
Comments
Post a Comment