On Windows PowerShell and other admin-related topics

Use Windows PowerShell to get antivirus product information

Windows Security Center has been available in Windows client operating systems since Windows XP SP2. This is a useful feature for monitoring the overall for security status for the system, including antivirus, antimalware and firewall protection. In situations no monitoring software like System Center Operations Manager is in place to monitor the security health on client computers, one option is to use Windows Management Instrumentation. There is a WMI namespace called root\SecurityCenter2 which exposes information from the Windows Security Center, like what antivirus product is installed on the system.

I`ve created PowerShell function to query computers for information on what antivirus is installed as well as the current status for antivirus definitions and real-time protection:

function Get-AntiVirusProduct {
param (
[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)

$AntiVirusProduct = Get-WmiObject -Namespace root\SecurityCenter2 -Class AntiVirusProduct  -ComputerName $computername

#Switch to determine the status of antivirus definitions and real-time protection.
#The values in this switch-statement are retrieved from the following website:

switch ($AntiVirusProduct.productState) {
"262144" {$defstatus = "Up to date" ;$rtstatus = "Disabled"
"262160" {$defstatus = "Out of date" ;$rtstatus = "Disabled"
"266240" {$defstatus = "Up to date" ;$rtstatus = "Enabled"
"266256" {$defstatus = "Out of date" ;$rtstatus = "Enabled"
"393216" {$defstatus = "Up to date" ;$rtstatus = "Disabled"
"393232" {$defstatus = "Out of date" ;$rtstatus = "Disabled"
"393488" {$defstatus = "Out of date" ;$rtstatus = "Disabled"
"397312" {$defstatus = "Up to date" ;$rtstatus = "Enabled"
"397328" {$defstatus = "Out of date" ;$rtstatus = "Enabled"
"397584" {$defstatus = "Out of date" ;$rtstatus = "Enabled"}
default {$defstatus = "Unknown" ;$rtstatus = "Unknown"

#Create hash-table for each computer
$ht = @{}
$ht.Computername = 
.Name = $AntiVirusProduct.displayName
$ht.ProductExecutable = $AntiVirusProduct.pathToSignedProductExe
$ht.‘Definition Status’ = 
.‘Real-time Protection Status’ = $rtstatus

#Create a new object for each computer
New-Object -TypeName PSObject -Property $ht



Sample output:


The root\SecurityCenter2 namespace isn`t documented on MSDN, so it`s hard to find information on the properties and methods we find in the different classes in the namespace.

The productstate property of the AntiVirusProduct class is exposed as a integer value, which needs to be converted to a hexadecimal value. Then the different bytes in the value contains information in regards to definition updates and real-time protection. More information on this is available here. I haven`t found a complete reference to all possible values, the best I could find is available here.

The above function outputs Windows PowerShell objects, so it`s possible to filter the output i.e. based on the “Definition Status” property.  The computername parameter also supports value from pipeline to make it easy to get the computers to query from i.e. Active Directory without using a foreach construct. A few examples:

#Get antivirus product information for all computers in the specified OU/container
Import-Module ActiveDirectory
Get-ADComputer -SearchBase "CN=Computers,DC=contoso,DC=local" -Filter * | Select-Object -ExpandProperty name | Get-AntiVirusProduct

#Filter using Where-Object to get all computers where the Definition State is not "Up to date"
Get-AntiVirusProduct -computer (Get-Content computers.txt) | Where-Object {$_.‘Definition Status’ -notlike ‘Up to date’}


The root\SecurityCenter2 namespace is available on Windows Vista SP1 and above. Windows Security Center is not available on server operatingsystems, meaning that the root\SecurityCenter2 namespace also isn`t available. In Windows XP SP2 the namespace is called root\SecurityCenter, but the properties are not the same as in root\SecurityCenter2. It`s possible to get the function work on Windows XP, but you would need to customize it to match the properties available in the root\SecurityCenter namespace.

I would encourage you to add error handling before using this function in a production environment, i.e. adding a test to check if the remote computer is available and allowing RPC-communication. If you would like to explore the other classes in the root\SecurityCenter2 namespace for working with firewall and antispyware products, you can start by exploring the available classes like this: Get-WmiObject -Namespace root\SecurityCenter2 -List

June 12, 2011 Posted by | Desktop management, Scripting, Windows 7, Windows PowerShell, Windows Vista | , | Leave a comment

Export and import WLAN profiles

Network Shell (Netsh) is a command-line utility that makes it possible to work with various server roles and operating system components in Windows, and have been available since Windows 2000. It`s commonly used to change network interface information such as IP-addresses, as well as for resetting the TCP/IP stack. For a complete overview of the capabilities of netsh, have a look at the Netsh Command Reference on Microsoft TechNet.

Starting with Windows Vista/Windows Server 2008, netsh provides commands for Wireless Local Area Networks (WLAN). This makes it possible to import and export WLAN profiles, which can be useful when re-installing your computer or maybe when deploying corporate computers where WPA Enterprise is not used.

In combination with Windows PowerShell it`s easy to import and export WLAN profiles using netsh. I`ve provided a script containing two PowerShell functions:

  • Export-WLAN
  • Import-WLAN

Click on the thumbnails to see help info for the functions:

image image

The script is available here.

Note that Windows Vista/7 has a concept of all-user and per-user WLAN profiles:


All-user profiles is the default, and the functions are not customized to work with per-user functions.

January 23, 2011 Posted by | Desktop management, Windows 7, Windows PowerShell, Windows Vista | | Leave a comment

Generate an installation-report for specific hotfixes using Windows PowerShell

Windows PowerShell 2.0 contains a cmdlet called Get-HotFix, which retrieves installed hotfixes from the local computer or specified remote computers.

This is quite useful when you need to check if a particular hotfix is installed prior to installing new software that requires a specific set of hotfixes, or when a critical security hotfix is released and you want to make sure the hotfix is installed.

The Get-HotFix cmdlet retrieves all hotfixes installed by Component-Based Servicing. If you would like to know more about CBS, I would recommend the article Understanding Component-Based Servicing on the Windows Server Performance Team`s blog.

When you need to check several computers, and maybe also check for several hotfixes, it might be a time consuming process to run Get-HotFix against each computer and also keep track of the status for each computer/hotfix. To ease this scenario, I`ve written a script named Get-HotFixReport.ps1.


Get-HotFixReport.ps1 overview

  • Retrieves the computers to run Get-HotFix against using the Get-ADComputer cmdlet, which is available in Microsoft`s PowerShell-module for Active Directory
  • Loops through each computer and creates a custom object for every hotfix, containing information about the installation of the current hotfix for the current computer. Any error that occurs is also stored in the custom object. Get-HotFix are only run if the current computer responds to a ping request.
  • Every custom object are added to an array, which at last are exported to a csv-file.

The following three variables must be customized before running the script:

   1: $Computers = Get-ADComputer -Filter * -Properties Name,Operatingsystem | Where-Object {$_.Operatingsystem -like "*server*"} | Select-Object Name

   2: $HotFix = "KB979744,KB979744,KB983440,KB979099,KB982867,KB977020"

   3: $CsvFilePath = "C:\temp\$hotfix.csv"

The example above retrieves all computer objects in Active Directory running a Windows Server operating system. You may specify only one computer, or a secific Organizational Unit, if required.

In the HotFix-variable you need to specify one or more hotfixes to check for. If more than one are specified, they must be separated with a comma. The hotfix-variable in the example above contains all hotfixes that are the prerequisites to install Exchange Server 2010 SP1 on Windows Server 2008 R2.

The csv-file may be opened in Microsoft Office Excel where it`s possible to apply filters to sort on e.g. “true” in the HotfixInstalled-column:



Note that the Get-HotFix cmdlet actually leverages the Win32_QuickFixEngineering WMI-class, and thus, it would be possible to run the script under Windows PowerShell 1.0 if you replace Get-HotFix with Get-WmiObject -Class Win32_QuickFixEngineering.

Of course you might also choose other ways to retrieve the computer-list, e.g. a csv-file, a txt-file or by using Quest`s PowerShell commands for Active Directory.

October 31, 2010 Posted by | Desktop management, Remote Management, Scripting, Server management, Windows PowerShell, Windows Update | , , | Leave a comment

Pin and unpin applications from the taskbar and Start-menu using Windows PowerShell

I`ve created a PowerShell module for working with pinned applications in Windows 7 and Windows Server 2008 R2. The module are created based on a script created by Ragnar Harper and Kristian Svantorp.

The module are available here, on the TechNet Script Center Gallery.

Installation and usage

Modules in Windows PowerShell can be “installed” in two ways:

1) Save the module as a psm1-file, and store it in a folder with the same name as the psm1-file. Copy this folder, using i.e. xcopy or Copy-Item, to a desired PowerShell module-folder (see available module paths using $env:PSModulePath)

2) Import the module by calling the psm1-file directly.

The first option are preferred for production use.

Next, import the module using Import-Module:

(Option 1)

(Option 2)

The module consist of one function as shown here:


The help text are available with Get-Help:


For example usage, add –Examples to the Get-Help cmdlet:


Basic error checking for valid parameters are included:


The Set-PinnedApplication function supports the en-us and nb-no locales as-is, but you can easily add support for more locales.

Feel free to let me know in the comment section below if you got any feedback.

Update, 06.08.2010: A new version of the module are now published at the original link on the TechNet Script Center Gallery. In the new version, there are full MUI support, after an update by Johan Akerstrom.

February 26, 2010 Posted by | Desktop management, Windows 7, Windows PowerShell, Windows Server 2008 R2 | | 18 Comments