Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Helper for retrieving installed applications list #396

Open
justdanpo opened this issue Aug 23, 2015 · 6 comments · May be fixed by #441
Open

Helper for retrieving installed applications list #396

justdanpo opened this issue Aug 23, 2015 · 6 comments · May be fixed by #441

Comments

@justdanpo
Copy link

About 60 packages use "Get-WmiObject -Class Win32_Product" to check if a package is already installed https://www.google.com/search?q=Win32_Product%20site%3Achocolatey.org

"Win32_Product" class has serious performance issues https://www.google.com/search?q=win32_product%20issues
It forces Windows Installer to reconfigure every application installed through MSI (see Windows event log).
Depending on installed applications it may take more than 30 minutes to execute a request.
It may be replaced by direct registry access and a required code is large enough to create a suitable helper.

Here is an example of such helper:

## Get-Installed
##############################################################################################################
## Returns a list of installed applications.
## Registry based replacement for "Get-WmiObject -Class Win32_Product".
##############################################################################################################

function Get-Installed {
param(
  [string] $NonMSIOption = 'HideNonMSI' # You may use 'ShowNonMSI' option
)

  if(($NonMSIOption -ine 'HideNonMSI') -and ($NonMSIOption -ine 'ShowNonMSI')) {
    throw "Unsupported argument: $NonMSIOption"
  }


  $items = @()

  if(Test-Path "HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall") {
    $items += Get-ChildItem "HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
  }
  if(Test-Path "HKLM:SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall") {
    $items += Get-ChildItem "HKLM:SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
  }

  $Win32_Product = @()

  foreach ($app in $items)
  {
    $propitems = $app | Foreach-Object {Get-ItemProperty $_.PsPath}
    $w32item = New-Object System.Object
    $w32item | Add-Member -type NoteProperty -Name "IdentifyingNumber" -Value $app.PsChildname
    $w32item | Add-Member -type NoteProperty -Name "Name"    -Value $propitems.DisplayName
    $w32item | Add-Member -type NoteProperty -Name "Version" -Value $propitems.DisplayVersion
    $w32item | Add-Member -type NoteProperty -Name "Vendor"  -Value $propitems.Publisher
    $w32item | Add-Member -type NoteProperty -Name "Caption" -Value $propitems.DisplayName

    if($w32item.Name) {
      if(($NonMSIOption -ieq 'ShowNonMSI') -or ($propitems.WindowsInstaller -eq "1")) {
        $Win32_Product += $w32item
      }
    }
  }

  return $Win32_Product
}

"Get-WmiObject -Class Win32_Product" or "gwmi win32_product" may be directly replaced with "Get-Installed" call.
Also this implementation can return applications installed through non-MSI installer systems ("Get-Installed ShowNonMSI").

@justdanpo
Copy link
Author

As I can't wait until every package maintainers will update their scripts (it will take a long time I guess) I've also patched chocolateyScriptRunner.ps1 to automatically fix scripts. I've added these lines:

## Replace 'Get-WmiObject -Class Win32_Product' with 'Get-Installed'
$re = '(Get-WmiObject|gwmi)\s*(-class)?\s*Win32_Product'
$scriptContent = Get-Content $packageScript
if( @($scriptContent | Where-Object { $_ -imatch $re }).Count ) {
  ($scriptContent) | Foreach-Object {$_ -ireplace $re, 'Get-Installed'} | Set-Content $packageScript
  Write-Warning "`'$packageScript`' uses Win32_Product class which is bad. Replaced with `'Get-Installed`'. If you are the maintainer, please update your package file."
}

before these:

Write-Debug "Running `'$packageScript`'";
& "$packageScript"

@ferventcoder
Copy link
Member

I've been saying it is bad since before we turned on moderation. With moderation on we are able to inspect and suggest using registry searches instead. Thanks for the suggestion.

@justdanpo
Copy link
Author

jre8
Last updated: Wednesday, September 2, 2015
Status: approved

flashplayeractivex & flashplayerplugin
Last updated: Monday, September 21, 2015
Status: approved

They still use Win32_Product class. And I'm still unable to install/update them without patching install scripts. Does moderation work?

My current patch code (modified for install scripts which import something from another scripts):

## Replace 'Get-WmiObject -Class Win32_Product' with 'Get-Installed'
$location = (Get-ChildItem $packageScript).Directory.FullName
$re = '(Get-WmiObject|gwmi)\s*(-class)?\s*Win32_Product'
Get-ChildItem $location -Filter *.ps1 | `
Foreach-Object{
  $packageScript2 =  $_.FullName
  $scriptContent = Get-Content $packageScript2
  if( @($scriptContent | Where-Object { $_ -imatch $re }).Count ) {
    ($scriptContent) | Foreach-Object {$_ -ireplace $re, 'Get-Installed'} | Set-Content $packageScript2
    Write-Warning "`'$packageScript2`' uses Win32_Product class which is bad. Replaced with `'Get-Installed`'. If you are the maintainer, please update your package file."
  }
}

@ferventcoder
Copy link
Member

They still use Win32_Product class. And I'm still unable to install/update them without patching install scripts. Does moderation work?

Some of these items fall under trusted packages. We have not yet added this to the list of a requirement not to use. It's still considered a guideline and usually something we catch to ask folks not to use.

My current patch code

You know you could stop patching each package and instead build an extension that would fix those automatically in the interim.

@justdanpo
Copy link
Author

The code does it automatically (it's placed in chocolateyScriptRunner.ps1)

@ferventcoder
Copy link
Member

Perfect. Do you want to follow up with a PR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants