Powershell Modules and BigFix

Problem: Trying to find out what powershell modules are installed and their versions.

Is there an analysis for this that I am missing?

I tried creating a task that outputs to a flat file for an analysis but it seems to have a problem running as local system. PS Action Script below.

 Set-Content -Path C:\windows\temp\PSMod.txt -Value (Get-InstalledModule | select-object -Property name, version | foreach { $_.name + " " + $_.version })

In a perfect world, there would be an easy way to run PS one-liners with a task… So that way I can hand it over to our MSP that is really PS dependent.

What does your Actionscript look like? Are you using the ‘PowerShell’ script type or trying to run this in native Actionscript, and if native Actionscript, did you escape the open-curlybrackets as {{ ?

Using the PowerShell script type.
My action is literally just this below. Simple, right? :wink:

Set-Content -Path C:\windows\temp\PSMod.txt -Value (Get-InstalledModule | select-object -Property name, version | foreach { $_.name + " " + $_.version })

Also, tried with and without curly bracket escape. Although I was under the impression that I didn’t need to as a powershell script type

Does that PowerShell give you results when you run it locally? On my test machines, it doesn’t, but I’ve not explicitly installed modules using the Install-Module cmdlet. As described at https://docs.microsoft.com/en-us/powershell/module/powershellget/get-installedmodule?view=powershell-7.2 , the “Get-InstalledModule” doesn’t list any default modules or those that are loaded by just adding them to the PS paths, it only lists the ones explicitly installed via Install-Module.

Install-Module can install to machine scope or just to the current user scope. I would expect Get-InstalledModule, when running as LocalSystem, should only show what’s installed to the Machine scope.

To list the default modules or the ones loaded by copy to the PS paths, I think Get-Module -ListAvailable may be more fitting, and it does give me results when I send that one through BigFix.

1 Like

It does work locally once I installed one…

Here is why I am not sure that Get-Module -ListAvailable will work

PS C:\Users\user> Get-InstalledModule | select-object -Property name, version | foreach { $_.name + " " + $_.version }

PackageManagement 1.4.7
PowerShellGet 2.2.5

PS C:\Users\user> Get-Module -ListAvailable | select-object -Property name, version | foreach { $_.name + " " + $_.version }

Microsoft.PowerShell.Operation.Validation 1.0.1
PackageManagement 1.4.7
PackageManagement 1.0.0.1
etc…

So as you can see the Get-Module -ListAvailable shows two versions of the same module.

I would think that the security context that the PS script runs in would be a factor in getting results. The Local System account doesn’t have visibility into other users’ security contexts.

This article on installing PowerShell Modules may provide other pathways to the information you’re looking for:

1 Like

Thanks for that. I am going to go with Jason’s original suggestion and let the script kidd… I mean the “PowerShell Experts” deal with it. :wink:

1 Like

Important note here. Since BigFix runs a 32bit bit, it only has access to PowerShell 32bit, which is missing many modules and inability to import modules like vmware. This has created limitations for us when running scripts natively. I think there are workarounds, but this is something you will run into.

I put in a BF Idea you may want to vote on: https://bigfix-ideas.hcltechsw.com/ideas/BFP-I-264

1 Like

Voted! sigh always a catch.

BTW, here is what i ended up with and then just created a simple analysis to pull the lines of the file daily.

 Set-Content -Path <your path>\PSMod.txt -Value (Get-Module -ListAvailable | select-object -Property name, version | foreach { $_.name + " " + $_.version })

I am hoping this is now patched in 10.0.6, and that we’ll be able to use cmdlets like “Get-NetConnectionProfile” on x64, but I haven’t been able to verify yet.

I think this is covered in 10.0.6 under the change note:
Issue BFP-24172 - DA KB0096760 - Running fixlet as powershell action fails

1 Like

@Viking Here is a variation of your one-liner to provide some additional context.

Get-Module -ListAvailable | Group-Object -Property Name | Sort-Object Name | ForEach-Object { if ($_.Count -eq 1) { "$($_.Name) - $($_.Group.Version)" } else { $_.Group | Sort-Object Version, Path -Descending | ForEach-Object { "$($_.Name) - $($_.Version) ($(Split-Path -Parent $_.Path | ForEach-Object { if([Version]::TryParse((Split-Path $_ -Leaf), [ref]$null)) { Split-Path -Parent $_} else {$_} } | Split-Path -Parent))" } } }

This will produce output lines matching one of two patterns:

  • Module-Name - Version
  • Module-Name - Version (Path)

When only a single version/instance of a module is present, the first output will be generated. If a module is installed in multiple locations or there are multiple versions of that module installed, the second output will be generated. In the event you only want the second pattern for all modules, you can use this instead:

Get-Module -ListAvailable | Group-Object -Property Name | Sort-Object Name | ForEach-Object { $_.Group | Sort-Object Version, Path -Descending | ForEach-Object { "$($_.Name) - $($_.Version) ($(Split-Path -Parent $_.Path | ForEach-Object { if([Version]::TryParse((Split-Path $_ -Leaf), [ref]$null)) { Split-Path -Parent $_} else {$_} } | Split-Path -Parent))" } }

Get-Module is a core PowerShell cmdlet that is fully cross-platform supported and uses the same internal code that performs the actual module loading for PowerShell to generate it’s output. This cmdlet will enumerate all the module paths that the current session knows about (via the environmental variable PSModulePath) regardless of architecture (32/64-bit) so running thru BigFix under the 32-bit context will produce valid results.

Get-InstalledModule on the other hand is a cmdlet out of the PowerShellGet module that will list only modules that have been installed via the PowerShellGet Install-Module cmdlets.

Hope this helps.

3 Likes

@Mike Very Helpful. Thanks!