Get-WmiObject : Invalid class "SoftwareLicensingProduct" - powershell

I'm new to powershell and am trying to write a program that will get the product key of numerous servers.
I am looping through the server names and trying to do the following code but am getting the error in the title
$LicenseInfo = Get-WmiObject -Class SoftwareLicensingProduct -ComputerName $target -Credential $cred | `
Where-Object { $_.PartialProductKey -and $_.ApplicationID -eq "55c92734-d682-4d71-983e-d6ec3f16059f" } | Select-Object PartialProductKey, Description, ProductKeyChannel, #{ N = "LicenseStatus"; E = { $lstat["$($_.LicenseStatus)"] } }
Any help would be appreciated

That error is very specific. Are you targeting machines that do not have this class available? As per learn.microsoft.com for SoftwareLicensingProduct:
Minimum supported client: Windows 7
Minimum supported server: Windows Server 2008 R2

Related

Powershell variable not being populated

Here's the simple script:
$groups = Get-WMIObject -Class Win32_GroupUser -ComputerName $server | Select-object #{N="Group";E={($_.PartComponent -split "Name=")[1].Replace('"','')}}
$groups
However, $groups is null!
I've checked the interwebs and cannot find a solution.
I'm sure there's a simple answer...
Query is syntactically correct. Check if you are storing the correct value in the $server parameter and that your WMI service is running.
Nothing wrong with what you have here, as it pulls the data when I test this.
Note I am using my localhost, not a remote system here.
(
$groups = Get-WMIObject -Class Win32_GroupUser -ComputerName $env:COMPUTERNAME `
| Select-object #{N="Group";E={($_.PartComponent -split "Name=")[1].Replace('"','')}}
)
Group
-----
postanote
...
IUSR
...
SYSTEM
...
INTERACTIVE
Authenticated Users
...
DefaultAccount
Guest
Administrator
...
SYSTEM
...
$groups.Count
27
And fine on a remote system.
(
$groups = Get-WMIObject -Class Win32_GroupUser -ComputerName 'ws01' `
| Select-object #{N="Group";E={($_.PartComponent -split "Name=")[1].Replace('"','')}}
)
Group
-----
Administrator
Domain Admins
...
Guest
SYSTEM
...
INTERACTIVE
Authenticated Users
Domain Users
SYSTEM
$groups.Count
18
So, something environmental in your environment, is the catch 22 for you.
Run this on your localhost host and see if you can get anything back from your targets.
Test-WSMan -ComputerName ws01
wsmid : http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd
ProtocolVersion : http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd
ProductVendor : Microsoft Corporation
ProductVersion : OS: 0.0.0 SP: 0.0 Stack: 3.0

Functions tabular output changing on some remote computers

I have this function I'm using a foreach statement block to run against a number of machines:
function Get-InstalledApps ($appStr) {
$appWC = "*$appStr*"
if ([IntPtr]::Size -eq 4) {
$regpath = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*'
}
else {
$regpath = #(
'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*'
'HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
)
}
$getapps = Get-ItemProperty $regpath | .{process{if($_.DisplayName -and $_.UninstallString) { $_ } }}
Foreach ($app in $getapps | where {$_.DisplayName -like $appWC}) {
[pscustomobject]#{Computer = ($env:COMPUTERNAME + "." + $env:USERDNSDOMAIN)
AppName = ($app.displayname)
Publisher = ($app.Publisher)
DisplayVersion = ($app.DisplayVersion)
InstallDate = ($app.InstallDate)
UninstallString = ($App.UninstallString)}
}
}
Locally, it looks like this:
PS C:\windows\system32> Get-InstalledApps ibm | ft
Computer AppName Publisher DisplayVersion InstallDate UninstallString
-------- ------- --------- -------------- ----------- ---------------
Computer.domain.COM IBM Tivoli Storage Manager Client IBM 06.04.0001 20140807 MsiExec.exe /I{FF99015E-71B4-41AB-8985-67D99383A72A}
But when run remotely on some computers
(i.e:)
Invoke-Command -ComputerName $computer -ScriptBlock
${function:Get-InstalledApps} -ArgumentList $appStr
I get the above, however on others I get this:
Name Value
---- -----
UninstallString MsiExec.exe /I{68C09095-AC00-4541-B46B-0835F2BDB0CE}
Computer comp1.domain.com
Publisher IBM
InstallDate 20150122
DisplayVersion 07.01.0000
AppName IBM Tivoli Storage Manager Client
UninstallString MsiExec.exe /X{1316AC9A-7A5D-4866-B41F-4B3CF03CE52A}
Computer comp2.domain.com
Publisher IBM Corp.
InstallDate 20170226
DisplayVersion 9.2.7.53
AppName IBM BigFix Client
Without having a chance to verify PowerShell versions of some of the computers yet, I'm guessing the 2nd set of results may be as a result of being run against computers running < version 3.0.
Any way to force the output to display as a table (1st example output) on all computers?
I'm guessing the 2nd set of results may be as a result of being run against computers running < version 3.0.
If you are running that on systems that are not at least version 3 then your [pscustomobject] cast would fail since that was introduced in v3. I would have expected that to just trigger an error but instead it appears to be returning the hashtable. A compatible solution would be to use new-object instead.
New-Object -TypeName PSCustomObject -Property #{
Computer = ($env:COMPUTERNAME + "." + $env:USERDNSDOMAIN)
AppName = ($app.displayname)
Publisher = ($app.Publisher)
DisplayVersion = ($app.DisplayVersion)
InstallDate = ($app.InstallDate)
UninstallString = ($App.UninstallString)
}
Thanks Matt.
That worked, which is my preferred method.
if the app wasn't installed or the host was offline, a couple of variations of IF statements didn't seem to pick up the output at another point in the script (only displayed if it was installed) and returned as a blank line, however this seemed to be picked up by the statement blocks:
function Get-InstalledApps ($appStr) {
$appWC = "*$appStr*"
if ([IntPtr]::Size -eq 4) {
$regpath = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*'
}
else {
$regpath = #(
'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*'
'HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
)
}
$getapps = Get-ItemProperty $regpath | .{process{if($_.DisplayName -and $_.UninstallString) { $_ } }}
$getapps | where {$_.DisplayName -like $appWC} | Select #{n='Computer';e={$env:COMPUTERNAME + "." + $env:USERDNSDOMAIN}},Displayname,Publisher,DisplayVersion,InstallDate,UninstallString
}

Remove Symantec Endpoint Protection in an Enterprise Environment

I have many servers I need to remove Symantec Endpoint Protection from. I contacted Symantec and received the code below:
(Get-WmiObject -Class Win32_Product -Filter "Name='Symantec Endpoint Protection'" -ComputerName xxxxxx).Uninstall()
I have used it and it worked on 10 servers no problem at all. I tried it again today and am getting the error:
You cannot call a method on a null-valued expression.
At line:1 char:1
+ (Get-WmiObject -Class Win32_Product -Filter "Name='Symantec Endpoint Protection' ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull
Nothing has changed from when I started and am trying to figure out what the above error means. Also if I can get this to work does anyone see a way to add many servers to a foreach command or something.
Two things from my side:
1) you should not use win32_product cause it is broken to a certain level.
It is very slow alsso because it scans the entire thing.
2) In your case, "Name='Symantec Endpoint Protection'" reports Null for you which means that the value is not there. Please check the proper name.
For better performance and as part of enhancement , you should use the registry to fetch the details.
Function Get-RemoteSoftware{
<#
.SYNOPSIS
Displays all software listed in the registry on a given computer.
.DESCRIPTION
Uses the SOFTWARE registry keys (both 32 and 64bit) to list the name, version, vendor, and uninstall string for each software entry on a given computer.
.EXAMPLE
C:\PS> Get-RemoteSoftware -ComputerName SERVER1
This shows the software installed on SERVER1.
#>
param (
[Parameter(mandatory=$true,ValueFromPipelineByPropertyName=$true)][string[]]
# Specifies the computer name to connect to
$ComputerName
)
Process {
foreach ($Computer in $ComputerName)
{
#Open Remote Base
$reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine',$Computer)
#Check if it's got 64bit regkeys
$keyRootSoftware = $reg.OpenSubKey("SOFTWARE")
[bool]$is64 = ($keyRootSoftware.GetSubKeyNames() | ? {$_ -eq 'WOW6432Node'} | Measure-Object).Count
$keyRootSoftware.Close()
#Get all of they keys into a list
$softwareKeys = #()
if ($is64){
$pathUninstall64 = "SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
$keyUninstall64 = $reg.OpenSubKey($pathUninstall64)
$keyUninstall64.GetSubKeyNames() | % {
$softwareKeys += $pathUninstall64 + "\\" + $_
}
$keyUninstall64.Close()
}
$pathUninstall32 = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
$keyUninstall32 = $reg.OpenSubKey($pathUninstall32)
$keyUninstall32.GetSubKeyNames() | % {
$softwareKeys += $pathUninstall32 + "\\" + $_
}
$keyUninstall32.Close()
#Get information from all the keys
$softwareKeys | % {
$subkey=$reg.OpenSubKey($_)
if ($subkey.GetValue("DisplayName")){
$installDate = $null
if ($subkey.GetValue("InstallDate") -match "/"){
$installDate = Get-Date $subkey.GetValue("InstallDate")
}
elseif ($subkey.GetValue("InstallDate").length -eq 8){
$installDate = Get-Date $subkey.GetValue("InstallDate").Insert(6,".").Insert(4,".")
}
New-Object PSObject -Property #{
ComputerName = $Computer
Name = $subkey.GetValue("DisplayName")
Version = $subKey.GetValue("DisplayVersion")
Vendor = $subkey.GetValue("Publisher")
UninstallString = $subkey.GetValue("UninstallString")
InstallDate = $installDate
}
}
$subkey.Close()
}
$reg.Close()
}
}
}
Note: Use the function or the query inside the function to get the result.
Hope it helps.

How to verify whether a windows server has mountpoint or not using WMI

I am generating a report where I need to find which servers has mountpoints configured on it..
can you help how to get that infor using WMI or powershell.
I mean I need to identify the servers, if mountpoints exists in it.. and also their names....
Get a list of all servers from textfile, AD, etc. and run a foreach loop with something like this:
Get-Wmiobject -query “select name,driveletter,freespace from win32_volume where drivetype=3 AND driveletter=NULL” -computer servername
A quick google search for "windows mount point wmi" would return THIS (source).
Then export the results to CSV, HTML or whatever you need. Your question is lacking a lot of details and any sign of effort from your part, so I can't/won't go any further.
UPDATE: Does this help? It lists mount points(folder paths, not driveletters).
$servers = #("server1","server2","server3","server4","server5")
$servers | % {
$mountpoints = #(Get-WmiObject Win32_MountPoint -ComputerName $_ | Select-Object -ExpandProperty Directory | ? { $_ -match 'Win32_Directory.Name="(\w:\\\\.+)"' }) | % { [regex]::Match($_,'Win32_Directory.Name="(\w:\\\\.+)"').Groups[1].Value -replace '\\\\', '\' }
if($mountpoints.Count -gt 0) {
New-Object psobject -Property #{
Server = $_
MountPoints = $mountpoints
}
}
}
Server MountPoints
------ -----------
{server1} {D:\SSD, C:\Test}

How to find IpAddress of a virtual machine programmatically from hypervisor?

I am using HyperV WMI provider to to update virtual machine's configuration/settings (like hard ware, disks etc..)
How can I get IpAddress of a VM from HyperV?
How to do the same thing in VMWare?
Regards,
Dreamer!
This article describes how to get the IP address of a virtual
machine from Hyper-V (Windows 2008 R2 Hyper-V) using Powershell.
Using the PowerCli: (get-vm <name of your vm>).guest.ipaddress
For Hyper-V, this is how I usually pull an IP from a host box.
$vm = Get-WmiObject -computerName "." -NameSpace "Root\Virtualization" -query "SELECT * FROM Msvm_KvpExchangeComponent" #pulls VM WMI object ExchangeComponents
$vmitems = $vm.GuestIntrinsicExchangeItems
$ipitem = $vmitems[-4]#yay! a hack that relies on XML schemas!
$xmlip = [xml]$ipitem #convert string format to XML
$ipaddr = $xmlip.INSTANCE.PROPERTY[1].VALUE #playing with XML schemas again hopefully reliably
It's not the neatest/cleanest/nicest code, but it is a way to get that information.
Here's an alternate variation that I cooked up to demonstrate a more robust approach at finding the value for a given name. This doesn't rely on a specific relative ordering inside the schema of Caption, Data, Description, ElementName, Name or Source
$vmParams = #{
NameSpace = 'Root\Virtualization';
Query = 'SELECT * FROM Msvm_KvpExchangeComponent' #pulls VM WMI object ExchangeComponents
}
Get-WmiObject #vmParams |
% {
$xml = [Xml]"<properties>$($_.GuestIntrinsicExchangeItems)</properties>"
$xml.properties.INSTANCE.Property |
% {
$value = ($_.ParentNode.Property | ? { $_.Name -eq 'Data' }).VALUE
if ($_.Value -eq 'FullyQualifiedDomainName')
{
Write-Host "Host: $($value)"
}
if ($_.Value -eq 'RDPAddressIPv4')
{
Write-Host "RDP Address: $($value)"
}
}
}