Powershell scripting Assistance *Windows Activation Status*

Experts Could use some scripting assistance

function Get-ActivationStatus {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [string]$DNSHostName = $Env:COMPUTERNAME
    )
    process {
        try {
            $wpa = Get-WmiObject SoftwareLicensingProduct -ComputerName $DNSHostName `
                -Filter "ApplicationID = '55c92734-d682-4d71-983e-d6ec3f16059f'" `
                -Property LicenseStatus -ErrorAction Stop
        }
        catch {
            $status = New-Object ComponentModel.Win32Exception ($_.Exception.ErrorCode)
            $wpa = $null    
        }
        $out = New-Object psobject -Property @{
            ComputerName = $DNSHostName;
            Status       = [string]::Empty;
        }
        if ($wpa) {
            :outer foreach ($item in $wpa) {
                switch ($item.LicenseStatus) {
                    0 {$out.Status = "Unlicensed"}
                    1 {$out.Status = "Licensed"; break outer}
                    2 {$out.Status = "Out-Of-Box Grace Period"; break outer}
                    3 {$out.Status = "Out-Of-Tolerance Grace Period"; break outer}
                    4 {$out.Status = "Non-Genuine Grace Period"; break outer}
                    5 {$out.Status = "Notification"; break outer}
                    6 {$out.Status = "Extended Grace"; break outer}
                    default {$out.Status = "Unknown value"}
                }
            }
        }
        else {$out.Status = $status.Message}
        $out
    }
}

#Get User Credentials
$cred = Get-Credential
<# $timer = (Get-Date -Format yyy-mm-dd-hhmm)

$HyperHostFileName = "c:\temp\" + $timer + "HyperVHostInfo.csv"
$HyperGuestFileName = "c:\temp\" + $timer + "HyperVGuestInfo.csv"
$HyperVFailoverFileName = "c:\temp\" + $timer + "HyperVFailoverInfo.csv" #>
$serverList = Get-ADComputer -Filter "Name -like '*K2*'" |Sort-Object -Property Name |Select-Object -ExpandProperty Name




#Get HyperV Guest Information
$HyperVGuestInfo = Invoke-Command -ComputerName $serverList -Credential $cred -ScriptBlock {
    $vMList = Get-VM |Select-Object Name -ExpandProperty Name
	Get-VM | Select-Object -Property `
		@{n='ComputerName';				e={$ENV:ComputerName}},
		VMName,
        State,
        @{n='License Status';				e={($vMList | Get-ActivationStatus)}}
      
} |
	Select-Object -Property * -ExcludeProperty PSComputerName, RunspaceId |
	Sort-Object -Property ComputerName, VMName
$HyperVGuestInfo | Out-GridView
<# write-host "Exported Hyper-V Guest Information to c:\Temp\"
$HyperVGuestInfo | Export-Csv -NoTypeInformation -Path $HyperGuestFileName #>

Open in new window


The License Status row is coming back completely blank, can someone please show me the error of my ways:

        @{n='License Status';                        e={($vMList | Get-ActivationStatus)}}
LVL 13
ITguy565Asked:
Who is Participating?
 
footechCommented:
This line needs to be changed.
@{n='License Status';e={($vMList | Get-ActivationStatus)}}
Instead of $vMList, we need to pass the name of the specific VM to the pipeline for Get-ActivationStatus to act on.  Get-ActivationStatus queries remote computers via RPC/DCOM to look at WMI information.  The function would have to be changed if we wanted to use PS Remoting instead.  At present, the firewall on each VM would need to allow the WMI traffic.

I'm not familiar with what the out from Get-VM is.  We just need to reference the correct property.  Something like below (which references the name property).
@{n='License Status';e={($_.Name | Get-ActivationStatus)}}

Open in new window

2
 
yo_beeDirector of Information TechnologyCommented:
Have you looked VAMT from MS?
https://docs.microsoft.com/en-us/windows/deployment/volume-activation/volume-activation-management-tool 
This is a GUI that will do what you are trying and it is much easier.
1
 
ITguy565Author Commented:
@Yo_bee

Thanks for the comment!

That is a very good suggestion, but I am really at this point looking to find out what was wrong with my script. A powershell script lets me query on a much more granular level than the VAMT GUI will allow. For instance, I am looking for only Virtual Machines on Specific HyperV Hosts.
0
Has Powershell sent you back into the Stone Age?

If managing Active Directory using Windows Powershell® is making you feel like you stepped back in time, you are not alone.  For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why.

 
ITguy565Author Commented:
There is something simple I am missing. If I test that function on machines that DO NOT sure powershell remoting then it works just fine..

For instance :

serverlist.txt
machine1
machine2
machine3
machine4

$serverlist = get-content c:\serverlist.txt

$serverlist | get-activationstatus

This will return the proper information for those workstations.

Once I add PSREMOTING into the equation and attempt to use the get-vm command everything falls apart.
0
 
Philip ElderTechnical Architect - HA/Compute/StorageCommented:
Line 42: <# $timer = (Get-Date -Format yyy-mm-dd-hhmm)

Shouldn't that be yyyy-mm-dd-hhmm) ?

This is what comes out for me:
PS C:\WINDOWS\system32> Get-ActivationStatus

ComputerName Status
------------ ------
MyPCName Licensed

PS C:\WINDOWS\system32>

Open in new window

0
 
Philip ElderTechnical Architect - HA/Compute/StorageCommented:
My search foo really sucks right now but, Invoke-Command on a remote machine requires a change in PowerShell Execution policy on the destination/remote system IIRC?
0
 
ITguy565Author Commented:
@phillip


There is more to that script than just the function get-activationstatus


If you copy the script and save it as test1.ps1
execute the script after changing the $serverlist variable to something that works on your network.

Then you should come out with something like this.

image.png
0
 
Philip ElderTechnical Architect - HA/Compute/StorageCommented:
PowerShell is a challenge for me at best but, maybe it's this?
Script Variables
Shouldn't those variables have different IDs?

EDIT: And, if I'm not being helpful, my apologies for the waste of time. :)
0
 
ITguy565Author Commented:
The ComputerName Column contains the name of the HyperVisor
The VMName is right below it

The other line you reference is just taking a list of computers and sending it to get-activationstatus
0
 
ITguy565Author Commented:
This command will pull the output I need in that column but I need it for all of my VM's

((get-vm).name[1] |get-activationstatus).status
0
 
footechCommented:
The problem with your original is that the function definition for Get-ActivationStatus is only run on the local machine.  When you run Invoke-Command to run the commands on the remote machines, they have no idea what Get-ActivationStatus is.  So you have to include the function in the scriptblock to be run remotely.

$scriptblock = {
    function Get-ActivationStatus {
        [CmdletBinding()]
        param(
            [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
            [string]$DNSHostName = $Env:COMPUTERNAME
        )
        process {
            try {
                $wpa = Get-WmiObject SoftwareLicensingProduct -ComputerName $DNSHostName `
                    -Filter "ApplicationID = '55c92734-d682-4d71-983e-d6ec3f16059f'" `
                    -Property LicenseStatus -ErrorAction Stop
            }
            catch {
                $status = New-Object ComponentModel.Win32Exception ($_.Exception.ErrorCode)
                $wpa = $null    
            }
            $out = New-Object psobject -Property @{
                ComputerName = $DNSHostName;
                Status       = [string]::Empty;
            }
            if ($wpa) {
                :outer foreach ($item in $wpa) {
                    switch ($item.LicenseStatus) {
                        0 {$out.Status = "Unlicensed"}
                        1 {$out.Status = "Licensed"; break outer}
                        2 {$out.Status = "Out-Of-Box Grace Period"; break outer}
                        3 {$out.Status = "Out-Of-Tolerance Grace Period"; break outer}
                        4 {$out.Status = "Non-Genuine Grace Period"; break outer}
                        5 {$out.Status = "Notification"; break outer}
                        6 {$out.Status = "Extended Grace"; break outer}
                        default {$out.Status = "Unknown value"}
                    }
                }
            }
            else {$out.Status = $status.Message}
            $out
        }
    }

    $vMList = Get-VM |Select-Object Name -ExpandProperty Name
	Get-VM | Select-Object -Property `
		@{n='ComputerName';				e={$ENV:ComputerName}},
		VMName,
        State,
        @{n='License Status';				e={($vMList | Get-ActivationStatus)}}
      
}

#Get HyperV Guest Information
$HyperVGuestInfo = Invoke-Command -ComputerName $serverList -Credential $cred -ScriptBlock $scriptblock |
	Select-Object -Property * -ExcludeProperty PSComputerName, RunspaceId |
	Sort-Object -Property ComputerName, VMName

Open in new window

0
 
David Johnson, CD, MVPOwnerCommented:
get-vm | select-object -expandproperty name | get-activationstatus

Open in new window

gave me a list of machines with their status
0
 
ITguy565Author Commented:
footech,

we are much closer

Currently this is what the output is showing from your code:

The License status information is still off as you can see:

The output should read
ComputerName |VMName |      License Status
HYPNA1                |Machine1 |     RPC Unavailable
HYPNA2                |Machine2 |    Licensed

 
output.png
0
 
ITguy565Author Commented:
@David

Rodger that sir.. The Get-ActivationStatus function isn't the issue. The issue at this point appears to be getting the array to display on this table correctly.
0
 
ITguy565Author Commented:
The lines of code that are still in question are the following :

vMList = Get-VM |Select-Object Name -ExpandProperty Name
	Get-VM | Select-Object -Property `
		@{n='ComputerName';				e={$ENV:ComputerName}},
		VMName,
        State,
        @{n='License Status';				e={($vMList | Get-ActivationStatus)}}

Open in new window


 @{n='License Status';                        e={($vMList | Get-ActivationStatus)}}
0
 
ITguy565Author Commented:
Want to thank everyone for their help so far.. We are much further ahead than where we started!!!
0
 
ITguy565Author Commented:
That was exactly where I needed to go.. You were EXTREMELY close on the syntax. The final Syntax was

 @{n='License Status';e={($_.Name | Get-ActivationStatus).Status}}

$scriptblock = {
    function Get-ActivationStatus {
        [CmdletBinding()]
        param(
            [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
            [string]$DNSHostName = $Env:COMPUTERNAME
        )
        process {
            try {
                $wpa = Get-WmiObject SoftwareLicensingProduct -ComputerName $DNSHostName `
                    -Filter "ApplicationID = '55c92734-d682-4d71-983e-d6ec3f16059f'" `
                    -Property LicenseStatus -ErrorAction Stop
            }
            catch {
                $status = New-Object ComponentModel.Win32Exception ($_.Exception.ErrorCode)
                $wpa = $null    
            }
            $out = New-Object psobject -Property @{
                ComputerName = $DNSHostName;
                Status       = [string]::Empty;
            }
            if ($wpa) {
                :outer foreach ($item in $wpa) {
                    switch ($item.LicenseStatus) {
                        0 {$out.Status = "Unlicensed"}
                        1 {$out.Status = "Licensed"; break outer}
                        2 {$out.Status = "Out-Of-Box Grace Period"; break outer}
                        3 {$out.Status = "Out-Of-Tolerance Grace Period"; break outer}
                        4 {$out.Status = "Non-Genuine Grace Period"; break outer}
                        5 {$out.Status = "Notification"; break outer}
                        6 {$out.Status = "Extended Grace"; break outer}
                        default {$out.Status = "Unknown value"}
                    }
                }
            }
            else {$out.Status = $status.Message}
            $out
        }
    }

    $vMList = (Get-VM |Select-Object Name -ExpandProperty Name | Get-ActivationStatus).Status
	Get-VM | Select-Object -Property `
		@{n='ComputerName';				e={$ENV:ComputerName}},
		VMName,
        State,
        @{n='License Status';e={($_.Name | Get-ActivationStatus).Status}}
        #@{n='License Status';				e={($vMList | Get-ActivationStatus).Status}}
       
}

#Get HyperV Guest Information
$cred = Get-Credential
$ServerList = Get-ADComputer -Filter "Name -like '*K2*'" |Sort-Object -Property Name |Select-Object -ExpandProperty Name

$HyperVGuestInfo = Invoke-Command -ComputerName $serverList -Credential $cred -ScriptBlock $scriptblock |
	Select-Object -Property * -ExcludeProperty PSComputerName, RunspaceId |
    Sort-Object -Property ComputerName, VMName
    $HyperVGuestInfo | Out-GridView

Open in new window

0
 
ITguy565Author Commented:
Thanks for the assistance on this!!!
0
 
footechCommented:
Glad to help!
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.