Automation

 View Only
  • 1.  PowerCLI script to gather Virtual Machine installed software

    Posted Nov 02, 2016 01:25 PM

    All,

    We have a requirement to gather the installed software on 17,000 Virtual Machines in our enterprise. In searching I've not been able to locate any PowerCLI script that gets inside the VM itself to pull the info. We have a PowerShell script but this requires logging into each and every VM. Is there a way to gather the data with PowerCLI? Is so how would we get SQL, McAfee, etc?

    Mark



  • 2.  RE: PowerCLI script to gather Virtual Machine installed software

    Posted Nov 02, 2016 01:31 PM

    There is the Invoke-VMScript cmdlet that allows you to run a script inside the guest OS.

    This requires a credential for th guest OS, and also that VMware Tools are installed on the VMs.

    Another alternative is to query the guest OS remotely (for example with WMI calls from a PowerShell script).

    But this requires a connection to the guest OS over the network, and it requires that the remote session feature is enabled in the guest OS.

    Would you mind sharing the SW inventory script you are using?



  • 3.  RE: PowerCLI script to gather Virtual Machine installed software

    Posted Nov 03, 2016 04:07 PM

    #---------------------------------------------------------------------------------

     

    Function Get-OSCInstalledApplication

       [CmdletBinding(DefaultParameterSetName='SinglePoint')]

       Param

       [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, ParameterSetName="SinglePoint")]

       [Alias('CName')][String[]]$ComputerName,

       [Parameter(Mandatory=$true, Position=0, ParameterSetName="MultiplePoint")]

       [Alias('CNPath')][String]$ComputerFilePath

       If($ComputerName)

     

       Foreach($CN in $ComputerName)

     

       #test compter connectivity

       $PingResult = Test-Connection -ComputerName $CN -Count 1 -Quiet

       If($PingResult)

     

       FindInstalledApplicationInfo -ComputerName $CN

       Else

       Write-Warning "Failed to connect to computer '$ComputerName'."

     

       If($ComputerFilePath)

     

       $ComputerName = (Import-Csv -Path $ComputerFilePath).ComputerName

     

       Foreach($CN in $ComputerName)

     

       FindInstalledApplicationInfo -ComputerName $CN

     

    Function FindInstalledApplicationInfo($ComputerName)

     

       $Objs = @()

       $RegKey = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*"

       $InstalledAppsInfos = Get-ItemProperty -Path $RegKey

       Foreach($InstalledAppsInfo in $InstalledAppsInfos)

     

       $Obj = [PSCustomObject]@{Computer=$ComputerName;

      DisplayName = $InstalledAppsInfo.DisplayName;

      DisplayVersion = $InstalledAppsInfo.DisplayVersion;

      Publisher = $InstalledAppsInfo.Publisher}

       $Objs += $Obj

       $Objs | Where-Object { $_.DisplayName }



  • 4.  RE: PowerCLI script to gather Virtual Machine installed software

    Posted Nov 03, 2016 08:06 PM

    That function seems to rely on network connectivity to the stations.

    Are you using the script that way?



  • 5.  RE: PowerCLI script to gather Virtual Machine installed software

    Posted Nov 04, 2016 01:49 PM

    Currently we are connecting directly to the VM and running the script to gather the data. Cumbersome and extremely time consuming to say the least. Is there a way to gather this with PowerCLI connected to the respective Datacenter? I have PowerCLI scripts that I have set as Templates to use the Task Scheduler, Cashed Administrator Creds, and send the output to me via e-mail. All I need it the meat and potatoes of the script to plug in the middle :smileyhappy:



  • 6.  RE: PowerCLI script to gather Virtual Machine installed software

    Posted Nov 04, 2016 03:07 PM

    Coming back to my first answer on this thread, is the Invoke-VMScript an option?

    In other words, do you have the VMware Tools installed on each of these VM?

    And do you have an common account with the required permissions to run the script on each of the guest OS of these VM?



  • 7.  RE: PowerCLI script to gather Virtual Machine installed software

    Posted Nov 07, 2016 03:55 PM

    Luc

    We have a shared account but different Passwords for the respective Customer VM's.

    Mark



  • 8.  RE: PowerCLI script to gather Virtual Machine installed software

    Posted Nov 07, 2016 06:47 PM

    Do you have system/method to correlate the VMs with the credentials?

    A kind of lookup table, or a function you can call?



  • 9.  RE: PowerCLI script to gather Virtual Machine installed software

    Posted Sep 03, 2024 03:20 AM

    For Windows:

    https://grzegorzkulikowski.info/2020/06/25/get-installed-software-inside-vm-windows-using-invoke-vmscript/

    $script = @'
    function get-software{
    [String]$ComputerName = $env:COMPUTERNAME
    $keys = @('Software\Microsoft\Windows\CurrentVersion\Uninstall','Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall')
            $baseKeys = [System.Collections.Generic.List[Microsoft.Win32.RegistryKey]]::new()
            $baseKeys.Add([Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $ComputerName, 'Registry64'))
            $baseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('Users', $ComputerName, 'Registry64')
                    foreach ($name in $baseKey.GetSubKeyNames()) {
                        if (-not $name.EndsWith('_Classes')) {
                            try {
                                $baseKeys.Add($baseKey.OpenSubKey($name, $false))
                            } catch {}
                        }
                    }
           foreach ($baseKey in $baseKeys) {
                if ($basekey.Name -eq 'HKEY_LOCAL_MACHINE') {
                    $username = 'LocalMachine'
                } else {
                    # Attempt to resolve a SID
                    try {
                        [System.Security.Principal.SecurityIdentifier]$sid = Split-Path $baseKey.Name -Leaf
                        $username = $sid.Translate([System.Security.Principal.NTAccount]).Value
                    } catch {
                        $username = Split-Path $baseKey.Name -Leaf
                    }
                }
                foreach ($key in $keys) {
                    try {
                        $uninstallKey = $baseKey.OpenSubKey($key, $false)
    
                        if ($uninstallKey) {
                          
                            foreach ($name in $uninstallKey.GetSubKeyNames()) {
                                $packageKey = $uninstallKey.OpenSubKey($name)
                                $installDate = Get-Date
                                $dateString = $packageKey.GetValue('InstallDate')
                                if (-not $dateString -or -not [DateTime]::TryParseExact($dateString, 'yyyyMMdd', (Get-Culture), 'None', [Ref]$installDate)) {
                                    $installDate = $null
                                }
                                ''|select-object @{n='name';e={$name}}, @{n='ComputerName';e={$ComputerName}}, @{n='DisplayName';e={$packageKey.GetValue('DisplayName')}},@{n='DisplayVersion';e={$packageKey.GetValue('DisplayVersion')}}, @{n='Uninstallstring';e={$packageKey.GetValue('UninstallString')}}, @{n='publisher';e={$packageKey.GetValue('Publisher')}}, @{n='InstallDate';e={$installDate}}, @{n='InstallLocation';e={$packageKey.GetValue('InstallLocation')}},@{n='HelpLink';e={$packageKey.GetValue('HelpLink')}},@{n='username';e={$username}},@{n='hive';e={$baseKey.Name}},@{n='path';e={Join-Path -Path $key -ChildPath $name}} 
                            }
                        }
                    } catch {}
                }
            }
        } 
    get-software |convertto-json
    '@
    

    Connect to Vcenter via Connect-VIServer

    Than:

    Use some account that has read-only rights on those VM's

    $guestcredential = Get-Credential

    Now gather all VM's where GuestOS is Windows:

    $gvm = (Get-VM).where{$_.GuestId -like '*Windows*'}.Name
    $o = Invoke-VMScript -VM $gvm -ScriptText $script -GuestCredential $guestcredential -ScriptType Powershell

    Now turn the scriptoutput (which is JSON) into another Object:

    $a = $o.ScriptOutput | ConvertFrom-Json

    Now filter on for instance VMware Tools:

    $a.Where{$_.DisplayName -like '*vmware*'} | Select-Object ComputerName, DisplayName, DisplayVersion