4
\$\begingroup\$

Hoping someone can help me out with the two aspects of my script that I think is causing the most performance hindrance. Recreating the Array $Result and using the Get-ItemProperty on each and every key to get the required information. Is there a better way to accomplish this task?

Function Get-SoftwareList {
 <#
 #>
 Param()
 New-Variable -Force -ErrorAction SilentlyContinue -Name Result -Value @()
 New-Variable -Force -ErrorAction SilentlyContinue -Name Function -Value @{}
 $Function.Exclusions = (
 "Security Update for Windows",
 "Security Update for Microsoft",
 "Update for Windows",
 "Update for Microsoft",
 "Hotfix for Windows",
 "Update for Skype",
 "Security Update for Skype"
 )
 If([IntPtr]::Size -eq 8){ 
 $Function.OSArch='64-bit' 
 } Else{ 
 $Function.OSArch='32-bit' 
 }
 $Function.Registry = Get-Childitem -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall"
 IF ($Function.OSArch -EQ "64-bit") {
 $Function.Registry += Get-ChildItem -Path "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
 }
 ForEach ($Key in $Function.Registry) {
 $Key = Get-ItemProperty -Path Registry::$Key
 IF ($Key.DisplayName.length -NE 0) {
 ForEach ($Exclusion in $Function.Exclusions) {
 If ($Key.DisplayName.StartsWith($Exclusion) -EQ $True) { 
 $Skip = $True
 Break
 } Else {
 $Skip = $False
 }
 }
 IF ($Skip -EQ $False) {
 $Result += New-Object PSObject -Property @{ 
 DisplayName = $Key.DisplayName
 Version = $Key.DisplayVersion 
 UninstallString = $Key.UninstallString
 Publisher = $Key.Publisher
 #ModifyPath = $Key.ModifyPath
 InstallDate = $Key.InstallDate
 }
 }
 }
 }
 Return $Result
}
200_success
145k22 gold badges190 silver badges478 bronze badges
asked Mar 31, 2018 at 12:32
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Finding a very quick/reliable solution was actually significantly harder than I was expecting but this is the best I can come up with. It lists about ~130 applications in about 22ms on my computer.

 Function Get-InstalledSoftware {
 Param (
 [Array]$Properties = @('DisplayName','DisplayVersion')
 )
 $Keys = "Software\Microsoft\Windows\CurrentVersion\Uninstall","SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
 $Result = New-Object -TypeName 'System.Collections.ArrayList'
 $BaseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine,$ENV:ComputerName)
 ForEach($Key in $Keys) {
 $RegKey = $BaseKey.OpenSubkey($key)
 If($RegKey -ne $null) {
 ForEach($subName in $RegKey.getsubkeynames()) {
 foreach($sub in $RegKey.opensubkey($subName)) {
 [string]$Name = $sub.getvalue("displayname")
 If ($Name.trim().Length -gt 0) {
 $HashProperty = @{}
 ForEach ($CurrentProperty in $Properties) {
 $HashProperty.$CurrentProperty = $sub.GetValue($CurrentProperty)
 }#End-ForEach
 $Result.add([psCustomObject]$HashProperty)
 }#End-IF
 }#End-ForEach
 }#End-Foreach
 }#End-IF
 }#End-ForEach
 $Result
}

The new script is not only significantly more flexible, but also significantly faster than previous solutions.

Measure-Command {
 for($i = 0; $i -lt 100; $i++) {
 Get-InstalledSoftware99 -Properties DisplayName,UninstallString,DisplayVersion
 }
}
Measure-Command {
 for($i = 0; $i -lt 100; $i++) {
 Get-SoftwareList
 }
}
Days : 0
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 925
Ticks : 9259570
TotalDays : 1.07170949074074E-05
TotalHours : 0.000257210277777778
TotalMinutes : 0.0154326166666667
TotalSeconds : 0.925957
TotalMilliseconds : 925.957
Days : 0
Hours : 0
Minutes : 0
Seconds : 14
Milliseconds : 695
Ticks : 146959970
TotalDays : 0.00017009255787037
TotalHours : 0.00408222138888889
TotalMinutes : 0.244933283333333
TotalSeconds : 14.695997
TotalMilliseconds : 14695.997
answered Mar 31, 2018 at 15:54
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.