Link to home
Start Free TrialLog in
Avatar of ITguy565
ITguy565Flag for United States of America

asked on

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)}}
Avatar of yo_bee
yo_bee
Flag of United States of America image

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.
Avatar of ITguy565

ASKER

@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.
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.
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

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?
@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.

User generated image
PowerShell is a challenge for me at best but, maybe it's this?
User generated image
Shouldn't those variables have different IDs?

EDIT: And, if I'm not being helpful, my apologies for the waste of time. :)
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
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
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

get-vm | select-object -expandproperty name | get-activationstatus

Open in new window

gave me a list of machines with their status
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

 
User generated image
@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.
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)}}
Want to thank everyone for their help so far.. We are much further ahead than where we started!!!
ASKER CERTIFIED SOLUTION
Avatar of footech
footech
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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

Thanks for the assistance on this!!!
Glad to help!