How to find License Status of Windows Servers with Powershell - Part 2

Today i would like to announce the new version of my previous script Identify Windows Licenses Status.

Powershell can automate lot of things and for this reason i try to learn as more as i can BUT with the right way.

Because I am not an expert in Powershell someone with experience in Powershell will understand that the first version of this script has a lot of errors in structure of the code.

For this reason i read very careful the script from the beginning and i did lot of changes in the structure.

But except the structure of the code my updates include a GUI with WPF that to be honest i found it very interesting.

So let's do a recap with the updates in the new version

  • Add Powershell GUI with WPF.
  • Replace arraylist with a variable while get-adcomputers from ActiveDirectory.
  • Check the connection status with Test-Connection before try to retrieve License Status.
  • Add Computer Status (online/offline) field to recognize which computers are offline.
  • Add Operating System Field .
  • Include the option to export in Csv file the Report.

Of course a similar feature like the Windows License Status you can find it in the VirtualMetric  which is an advanced monitoring tool crafted with care to facilitate your work instead to right on your own.

You can find a Review of this tool for more details. 

 

Let's write again the Prerequisites before run the Script.

 

Prerequisites

Before you run the script in your environment you must keep some specs.

The reason is because the Powersell script retrieve all the Computer names from your Active Directory 

Run the following command to install Active Directory Powershell  Module

Install-WindowsFeature RSAT-AD-PowerShell

 

How the Powershell Script Run

It's easier to give the Script without any explanation but i believe it will give more value if explain how the script works line by line to help you expanded or change it base on your requirements.

You can download the Script from here

Before start to explain how the code works let's explain how can run the Script.

The script Included from 2 Buttons and 1 DataGrid.

The buttons are:

Get License Status which create the Report in the DatagrdView

Export to excel which export all the Results in the Excel after retrieve the results in Datagridview

Let's see in a printscreen how looks like the script after run it.

 

In the license status you will see a number. The number has a description which is the status of the license.

Find the table here from Microsoft Site

Value Description
0 Unlicensed
1 Licensed
2 OOBGrace
3 OOTGrace
4 NonGenuineGrace
5 Notification
6 ExtendedGrace

 

 

Before start to use WPF you must first add the Assembly into the current script with the Add-Type

Add-Type -AssemblyName PresentationFramework
 

After load the Assembly you can start to create the GUI with WPF.

I will not explain how WPF works because it's not the scope of the article but you can find lot of details of how can start from Damien Van Robaeys in his blog articles

Just to note that in this area we design the GUI environment with all the controls like buttons,Datagrid,Textbox that we need.

#Build the GUI
[xml]$xaml = @"
<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Name="Window" Title="Windows Servers License Status Report" WindowStartupLocation = "CenterScreen" 
    Width = "1000" Height = "400" ShowInTaskbar = "True">
<StackPanel>
  <Button Name="getlsstatus" Content="Get License Status" Width="100" HorizontalAlignment="Left" Margin="10"/>
  <Button Name="exportexcel" Content="Export to Excel" Width="100" HorizontalAlignment="Left" Margin="10"/>
<ListView Name="datagrid" Grid.Column="4" Grid.Row="0" Margin="30,30,30,30" Height="600" ScrollViewer.VerticalScrollBarVisibility="Visible"  >
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="OS" Width="210" DisplayMemberBinding="{Binding os}" />
                    <GridViewColumn Header="License" Width="210" DisplayMemberBinding="{Binding license}" />
                    <GridViewColumn Header="Computer Name" Width="150" DisplayMemberBinding="{Binding Computername}"/>
                     <GridViewColumn Header="License Status" Width="150" DisplayMemberBinding="{Binding licensestatus}" />
                    <GridViewColumn Header="Computer Status" Width="200" DisplayMemberBinding="{Binding status}"/>
                </GridView>
            </ListView.View>
        </ListView>
</StackPanel>
</Window>
"@ 

 

After the XAML Code we must load in Powershell script with the following 2 lines

$reader=(New-Object System.Xml.XmlNodeReader $xaml)
$Window=[Windows.Markup.XamlReader]::Load( $reader )

 

Now to declare the controls we use the following lines

$getlsstatus = $Window.FindName("getlsstatus")
$datagrid = $Window.FindName("datagrid")
$exportexcel = $Window.FindName("exportexcel")

 

Create a variable to ask for credentials 

$cred = Get-Credential domain\user

 

Create the event for the button when click on it

$getlsstatus.Add_Click({

 

Store in variable all the computernames of the Servers from ActiveDirectory

$servernames = Get-ADComputer -Filter 'OperatingSystem -like "Windows Server*"'

 

Create an array that will use it in the loop to determine the status of the Computer name

$srvstatus=@()

 

Run a loop in all Computer Names to identify which are online and offline.

Save the results in objects and included in the array $srvstatus that i create above
 

ForEach($name in $servernames){
$servernames=$name.Name
if (Test-Connection -ComputerName $servernames  -Count 1 -Quiet )
  {
        $o = new-object  psobject
        $o | add-member -membertype noteproperty -name computername -value (Get-CIMInstance Win32_Computersystem -computername $servernames).Caption | Out-Null
        $o | add-member -membertype noteproperty -name status -value "Online"| Out-Null
  }
else
  {
        $o = new-object  psobject
        $o | add-member -membertype noteproperty -name computername -value  $servernames | Out-Null
        $o | add-member -membertype noteproperty -name status -value "Offline"| Out-Null
  }
    $srvstatus+=$o
}

 

Create another one array that will use it to include results of the License Status

$lsstatus=@()

 

Run a loop base on the list with status of the computers and use Invoke-Command with Get-CimInstance to retrieve the License Status and more details if the Computer status is online or get Not Available if the Computer Status is offline.

ForEach($servers in $srvstatus){
$status=$servers.status

$names=$servers.computername
        $ScriptBlock={
            $licenses=@{
             os=(Get-CIMInstance Win32_Operatingsystem ).Caption
             license= ( Get-CimInstance -ClassName SoftwareLicensingProduct | where {$_.productkeyid} ).Description
             Computername=$env:Computername
             licensestatus= ( Get-CimInstance -ClassName SoftwareLicensingProduct | where {$_.productkeyid} ).LicenseStatus
             status=$status
            }
            $localresult=New-Object psobject -Property $licenses
            $localresult
            }
  
if ($status -eq "Online"){
   $lsstatus+= Invoke-Command -cn $names -Credential $cred -ScriptBlock $Scriptblock -ArgumentList $names,$status
    }
if ($status -eq "Offline"){
            $licenses=@{
            os="Not Available"
            license= "Not Available"
            Computername=$names
            licensestatus= "Not Available"
            status=$status
            }
            $r=New-Object psobject -Property $licenses
            $r
}
$lsstatus+=$r
}
$lsstatus| Select-Object -property os,license,Computername,licensestatus,status

 

Bind the results in the Datagrid

$datagrid=$Window.FindName("datagrid").ItemsSource = $lsstatus

 

Create an event of another Button to export the Report from Datagrid in Csv and save it whenever you want.

$exportexcel.Add_Click({
$OpenFileDialog = New-Object System.Windows.Forms.SaveFileDialog
    $OpenFileDialog.filter = "CSV (*.csv)| *.csv"
    $OpenFileDialog.ShowDialog() | Out-Null

$datagrid.ItemsSource| Select-Object -property os,license,Computername,licensestatus,status |export-csv $OpenFileDialog.FileName -NoType   
})

 

I hope to give you understand how the code works in case that you would like to do changes base on your requirements.

I invite you to follow me on Twitter or Facebook. If you have any questions, send email at info@askme4tech.com

Have a nice Holidays!!

Tags