Menu

Virtual Geek

Tales from real IT system administrators world and non-production environment

Microsoft PowerShell: Check Windows license activation status

September 23, 2017 02:11PM

This is my version of fetching Microsoft windows license status, for stream lining environment and make compliant as per audit standards, This is old wine in new bottle. I have improvised it to get more information and made it dynamic to get information remotely using CIM(winrm) as well as or WMI(dcom) protocol, it will collect OS and Microsoft softwares ie: Office license activation status. Here made available optional choice to type user & password credentials, incase credentials are different for remote machine. Status is collected from SoftwareLicensingProduct class. This class exposes the product-specific properties and methods of the Software Licensing service. 

You can copy paste the script content in ps1 file to execute it or copy from Github, make sure you are executing it on at least powershell version 4. For more information check my earlier blogs for help if you are facing any issues.
Different ways to bypass Powershell execution policy :.ps1 cannot be loaded because running scripts is disabled
Installing, importing and using any module in powershell

Below are the Parameters to be used to get licensing information.
ComputerName: Multiple computernames or IPs with comma separated can be used, It can be used with protocol and credential.
TextFile: ComputerName and TextFile can not be used with each other and can be combined with optional parameters
Protocol: This is optional parameter and if didn't mentioned uses wmi (dcom) as default to connect remote server or computer. For ps remoting use wsman argument and if you have issue connecting follow article POWERSHELL PS REMOTING BETWEEN STANDALONE WORKGROUP COMPUTERS 
Credential: This is another optional parameter if you want to use different username and password to connect remote server.

In below example computer name information is gathered from text file using different username and password with PS remoting protocol.
.\Get-WindowsLicenseDetails.ps1 -TextFile C:\Temp\ComputerList.txt -Credential -Protocol Wsman

Microsoft Windows Powershell Get-Windows LicenseDetails, ps1, licenseStatus, get-ciminstance, get-wmiobject SoftwareLicensingProduct class

In this another example I am using computername parameter, and information is exported to CSV file, which can be opened using excel software.
.\Get-WindowsLicenseDetails.ps1 -ComputerName Member01,Member02 | Export-Csv info.csv

Microsoft Windows Powershell Get-Windows LicenseDetails, ps1, licenseStatus, get-ciminstance, get-wmiobject SoftwareLicensingProduct class, Export-csv, computername try

Find this code on Github.

  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
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#
#requires -version 4
<#
.SYNOPSIS
    Get windows office and OS licensing information.
.DESCRIPTION
    The Get-WindowsLicenseDetails list Windows licening activation details as well as Microsoft software such as office activation details.
.PARAMETER ComputerName
    Prompts for Computername or IP address. CN and Name can be used as an alias, If no information is provided, this will take local computer hostname as argument. 
.PARAMETER TextFile
    This syntax asks for valid text file name and it is mandatory parameter. Text file must contain computername or IP address in list.
.PARAMETER Protocol
    There are two protocols can be used while connecting to remote computer, This is optional parameter, first is DCOM which is default and need not to mention, Default will work in all scenario. Another protocol is WSman require PS remoting need to be enabled. 
.PARAMETER Credential
    This is optional parameter, Popups for active directory username password, supply domain admin user account to connect remote server.
.INPUTS
    [System.String]
.OUTPUTS
    [System.Object]
.NOTES
    Version:        1.0
    Author:         Kunal Udapi
    Creation Date:  20 September 2017
    Purpose/Change: Get windows office and OS licensing information.
    Useful URLs: http://vcloud-lab.com, https://msdn.microsoft.com/en-us/library/cc534596(v=vs.85).aspx
.EXAMPLE
    PS C:\>.\Get-WindowsLicenseDetails -ComputerName Server01,Server02,Server03 

    This list windows license details from provided computernames, and use wmi (DCom) protocol. This used currently logged in user account.
.EXAMPLE
    PS C:\>.\Get-WindowsLicenseDetails -ComputerName Server01 -Protocol Wsman -Crdential

    This list windows license details from provided computernames, and use wsman (winrm) protocol is used to connect remote computers, by providing credential parameter it will ask for username and password to connect remote computer.
.EXAMPLE
    PS C:\>.\Get-WindowsLicenseDetails -TextFile C:\Temp\list.txt

    Text file has computer name list, information is collected using wmi (DCom) protocol, this will try to connect remote computers with currently logged in user account.
.EXAMPLE
    PS C:\>.\Get-WindowsLicenseDetails -TextFile C:\Temp\list.txt -Protocol Wsman -Crdential

    Text file has computer name list, information is collected using wsman (winrm) protocol, It will pop ups for username password.

#>
[CmdletBinding(SupportsShouldProcess=$True,
    ConfirmImpact='Medium',
    HelpURI='http://vcloud-lab.com',
    DefaultParameterSetName='CN')]
Param
(
    [parameter(Position=0, Mandatory=$True, ParameterSetName='File', ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true, HelpMessage='Type valid text file pathname')]
    [ValidateScript({
        If(Test-Path $_){$true}else{throw "Invalid path given: $_"}
    })]
    [alias('File')]
    [string]$TextFile,
    
    [parameter(Position=0, Mandatory=$false, ParameterSetName='CN', ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true, HelpMessage='Type valid text file pathname')]
    [alias('CN', 'Name')]
    [String[]]$ComputerName = $env:COMPUTERNAME,

    [parameter(ParameterSetName = 'File', Position=1, Mandatory=$false, HelpMessage='Type valid text file pathname')]
    [parameter(ParameterSetName = 'CN', Position=0, Mandatory=$false)]
    [ValidateSet('Dcom','Default','Wsman')]
    [String]$Protocol = 'Dcom',

    [parameter(ParameterSetName = 'File', Position=2, Mandatory=$false)]
    [parameter(ParameterSetName = 'CN', Position=2, Mandatory=$false)]    
    [Switch]$Credential
)
Begin {
    #[String[]]$ComputerName = $env:COMPUTERNAME
    if ($Credential.IsPresent -eq $True) {
        $Cred = Get-Credential -Message 'Type domain credentials to connect remote Server' -UserName (WhoAmI)
    }
    $CimSessionOptions = New-CimSessionOption -Protocol $Protocol
    $Query = "Select * from  SoftwareLicensingProduct Where PartialProductKey LIKE '%'"
}
Process {
    switch ($PsCmdlet.ParameterSetName) {
        'CN' {
            Break
        }
        'File' {
            $ComputerName = Get-Content $TextFile
            Break
        }
    }
    foreach ($Computer in $ComputerName) {
        if (-not(Test-Connection -ComputerName $Computer -Count 2 -Quiet)) {
            Write-Host -BackgroundColor DarkYellow ([char]8734) -NoNewline
            Write-Host " $Computer is not reachable, ICMP may be disabled...."
            #Break
        }
        else {
            Write-Host -BackgroundColor DarkGreen ([char]8730) -NoNewline
            Write-Host " $Computer is reachable connecting...."
        }
        try {
            if ($Credential.IsPresent -eq $True) {
                $Cimsession = New-CimSession -Name $Computer -ComputerName $Computer -SessionOption $CimSessionOptions -Credential $Cred -ErrorAction Stop
            }
            else {
                $Cimsession = New-CimSession -Name $Computer -ComputerName $Computer -SessionOption $CimSessionOptions  -ErrorAction Stop
            }
            $LicenseInfo = Get-CimInstance -Query $Query -CimSession $Cimsession -ErrorAction Stop 
            Switch ($LicenseInfo.LicenseStatus) {
                0 {$LicenseStatus = 'Unlicensed'; Break}
                1 {$LicenseStatus = 'Licensed'; Break}
                2 {$LicenseStatus = 'OOBGrace'; Break}
                3 {$LicenseStatus = 'OOTGrace'; Break}
                4 {$LicenseStatus = 'NonGenuineGrace'; Break}
                5 {$LicenseStatus = 'Notification'; Break}
                6 {$LicenseStatus = 'ExtendedGrace'; Break}
            } 
            $LicenseInfo | Select-Object PSComputerName, Name, @{N = 'LicenseStatus'; E={$LicenseStatus}},AutomaticVMActivationLastActivationTime, Description, GenuineStatus, GracePeriodRemaining, LicenseFamily, PartialProductKey, RemainingSkuReArmCount, IsKeyManagementServiceMachine #, ApplicationID
            }
        catch {
            Write-Host -BackgroundColor DarkRed ([char]215) -NoNewline
            Write-Host " Cannot fetch information from $Computer" 
        }
    }
}

Useful Articles
Powershell Active Directory: List complete hierarchy of upstream nested groups recursively of User
POWERSHELL: USE PARAMETERS AND CONFIGURATION FROM INI FILE, USE AS SPLATTING

Go Back

Comment