This post is about using Invoke-VMScript, in order to get software list inside windows virtual machine guest . I am using Chris Dent’s script to obtain all the software from Windows and some tiny tricks we will make it happen. His script :
Implementation with Invoke-VMScript
We will be using invoke-VMScript to call the script from inside the VM. What is also worth noticing is that we will be sending ourselves the json format as an output. The returned object contains property ScriptOutput, which be default is just text.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
$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 '@ #invoking the script inside VM $output = Invoke-VMScript -VM $gvm -ScriptText $script -GuestCredential $guestcredential -ScriptType Powershell |
When the script is about to finish it converts the output to Json format so we can transform it easily from Json later on in our powershell session.
1 |
$o = Invoke-VMScript -VM $gvm -ScriptText $script -GuestCredential $guestcredential -ScriptType Powershell |
You will see inside the $o/$output ScriptOutput property showing what was on the screen.
At this moment this is Json string. Now we are converting it.
At this moment we can now filter , modify, select etc anything we want there.
What is worth mentioning is that in order to run Invoke-VMScript you need to have the credentials to local account with administrator rights. You also might hit a problem where you need to adjust your InvalidCertificateAction using Set-PowerCLIConfiguration.
Mystery
Since i am already here writing about Invoke-VMScript, today i finally understood, why i could not find most of the times cmdlets in VMware {code} documentation portal. Have a look at this 😉
It’s because of the text is case sensitive i believe. As you can see it is all case sensitive, one must have great memory in order to remember the exact words. invoke-vmscript is not correct, but Invoke-VMScript is. If i do not know exactly what i am looking for, then why would one assume that i know how to type it correctly. Well, another mystery i guess. I have submitted my feedback already, maybe this will get fixed. Maybe its just me, doing the search not in compatible way. No idea to be honest.
Summary
Yesterday i wrote about about the trick with ConvertTo-Json and Invoke-VMScript, if you are interested about about this have a look there. Chris did a really great job with the pulling software script, i just modified it a bit to have it working with Invoke-VMScript. Information like this can be really useful with CMDB systems, or ticketing, helpdesk software.