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
- You must install the Active Directory Powershell Module in your Server/Workstation that you will run the script.
- You must enable the Wsman and allow it in your Firewall for your Servers that will scan the License Status.
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!!