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

Popular posts from this blog

Edit Group Policy

Hyper-V VM not reaching OS 'Logon' screen

DNS question...