Presentation Materials from the September 2013 Mississippi PowerShell User Group Meeting on ‘WSUS and PowerShell’

For those of you who were unable to attend my talk or for those who want check out my scripts on WSUS and PowerShell that I gave at the Mississippi PowerShell User Group last night, I have my slide deck and demo scripts available for download at the link below.

This was a great time and I had a blast getting to do my first speaking event with the group and to talk PowerShell and WSUS! The session was recorded and it is anticipated that the video will be available next Tuesday. When it has been posted, I will be sure to write a blog post here to let everyone know.

PowerShell and WSUS Demos and Slides

Posted in powershell, WSUS | Tagged , , , , | 3 Comments

Make a Window Flash in Taskbar using PowerShell and PInvoke

While working on a different project, I came across the need to do some sort of notification when something happened during a script. I didn’t need popup or some loud noise to alert me, but something a little subtle to look over and see when an action had occurred.

After some thinking, I decided on making the icon in the taskbar flash when something happened. The trick is that this isn’t something easily done just by itself with PowerShell. I had to go deeper down the rabbit hole into the realm of pinvoke to make something like this happen.

Looking at pinvoke.net, I came across 2 possible solutions to my dilemma:

In the end, I chose FlashWindowEx and the reason for this is that while FlashWindow has the easiest approach to setup and use…

image

…it doesn’t allow the capability to control the flash rate and set number of flashes that can occur before showing a solid pane of the flashing color (usually orange).

With FlashWindowEx, there are more pieces to put together before it will function properly.

image

We have a Struct and some defined constants that handle how the flashing will occur with the window. Before I get started, you can take a look at some of my previous articles that talk about using pinvoke with PowerShell so you can see what has been done in the past.

As I have done in the past, I put the signature into a here-string that will be used with Add-Type to compile the code and make it available to my current session.

Add-Type -TypeDefinition @"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

public class Window
{
    [StructLayout(LayoutKind.Sequential)]
    public struct FLASHWINFO
    {
        public UInt32 cbSize;
        public IntPtr hwnd;
        public UInt32 dwFlags;
        public UInt32 uCount;
        public UInt32 dwTimeout;
    }

    //Stop flashing. The system restores the window to its original state. 
    const UInt32 FLASHW_STOP = 0;
    //Flash the window caption. 
    const UInt32 FLASHW_CAPTION = 1;
    //Flash the taskbar button. 
    const UInt32 FLASHW_TRAY = 2;
    //Flash both the window caption and taskbar button.
    //This is equivalent to setting the FLASHW_CAPTION | FLASHW_TRAY flags. 
    const UInt32 FLASHW_ALL = 3;
    //Flash continuously, until the FLASHW_STOP flag is set. 
    const UInt32 FLASHW_TIMER = 4;
    //Flash continuously until the window comes to the foreground. 
    const UInt32 FLASHW_TIMERNOFG = 12; 


    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool FlashWindowEx(ref FLASHWINFO pwfi);

    public static bool FlashWindow(IntPtr handle, UInt32 timeout, UInt32 count)
    {
        IntPtr hWnd = handle;
        FLASHWINFO fInfo = new FLASHWINFO();

        fInfo.cbSize = Convert.ToUInt32(Marshal.SizeOf(fInfo));
        fInfo.hwnd = hWnd;
        fInfo.dwFlags = FLASHW_ALL | FLASHW_TIMERNOFG;
        fInfo.uCount = count;
        fInfo.dwTimeout = timeout;

        return FlashWindowEx(ref fInfo);
    }
}
"@

Now I have my compiled code ready to use!

image

The next step is to get the MainWindowHandle of a window that is either minimized or not currently active. In this case, I will use something like notepad as the example.

$handle = (Get-Process -Name Notepad).MainWindowHandle
$handle

image

Now to make the window flash. In this case, I am going to make it flash every 150 milliseconds and only flash 10 times.

[window]::FlashWindow($handle,150,10)

image

Now I have a flashing window!

image

Note:This will only work if the window is not currently in focus! It must either be minimized or the focus shifted to some other window.

All I have to do now is to click on the taskbar icon and bring the window up to the front and it will stop flashing or go back to its original state.

Sounds like a good candidate for a function, right? Well, you are right! I went ahead and put a function together called Invoke-FlashWindow which makes the process of having a window flash easier.

image

The following parameters are being used.

  1. MainWindowHandle
    1. Handle of the window that will be set to flash
  2. FlashRate
    1. The rate at which the window is to be flashed, in milliseconds. Default value is: 0 (Default cursor blink rate)
  3. FlashCount
    1. The number of times to flash the window. Default value is: 2147483647

One example is by using the current PowerShell console and put the console to sleep for a few seconds (enough time to either minimize or shift the focus to something else) and then make the window flash. The use of semicolon is by design.

Start-Sleep -Seconds 5; Get-Process -Id $PID | Invoke-FlashWindow

image

 

Hopefully you will find some other uses for this script in your environment. You can download the script from the link below.

Download

Technet Script Repository

Posted in powershell, scripts | Tagged , , , , | 2 Comments

Speaking at the Mississippi PowerShell Users Group on WSUS in September

I have the honor of being a speaker at the Mississippi PowerShell Users Group (MSPUG) on September 10th. A big thank you to Mike Robbins (Twitter | Blog) for extending the invitation to talk about one of my chapters from the PowerShell Deep Dives book. In this case, I will be talking about Windows Server Update Services (WSUS) and using the API (and maybe talk a little on the UpdateServices module). Hope to see you there!

Posted in Deep Dive, News, powershell, WSUS | Tagged , , , | Leave a comment

Introducing PoshEventUI: A UI Way to Create Permanent WMI Events

Something that I have been working on the past couple of months (in between other things) was a UI approach to creating permanent WMI events vs. a command line approach.

I really had only a few requirements that I wanted to achieve with this:

  • Have a main window showing the current WMI events
  • Have Add/Remove buttons for each instance (Filter,Consumer and Binding)
  • Use separate windows for each instance
    • The Consumer window will have one window but will change based on the type of Consumer being created

So without further ado, here is my latest project: PoshEventUI

image

The main UI window is based on Trevor Sullivan’s wmieventhelper.exe available from http:s//powerevents.codeplex.com.

The download for this is at https://posheventui.codeplex.com/

Once you download it, unblock the file so PowerShell will not complain about it and prompt for each script being run (Unblock-File works great!)

image

Navigate through the unzipped folder and run .\wmieventutility.ps1

image

Once the window has been opened, you can choose to to create a New instance or to Remove and instance.

image

Let’s work through each of these just to get an idea on what you can do.

First off is the Filter.

image

Here you can specify a Name and a WQL Query that will be used to monitor for a specific event in WMI. You can look at my articles on Temporary Events and Permanent Events for ideas or look at some searches on your favorite search engine. Also available is some great information in the PowerEvents documentation that shows more on working with WQL queries and also provides some great examples.

image

Once completed, click Create and it will now be added to the WMI repository.

image

Next up is the Consumer creation. There are 5 possible consumers to choose from and you can have multiple consumers setup with a filter via the Binding, so use whatever you wish to accomplish your requirement.

Lets look at all of the possible Consumer choices. You can pick whichever consumer you prefer from the drop down menu in the upper left hand corner labeled Select Consumer Type.

image

ActiveScriptEventConsumer

image

CommandLineEventConsumer

image

LogFileEventConsumer

image

NTEventLogEventConsumer

image

SMTPEventConsumer

image

In this case I am going with an SMTP consumer.

image

Note that with the From field blank, it will default to WMI@<computername>.com for the address.

Once you have the picked out your consumer and entered the necessary information, click Create and you will be taken back to the main window with the new consumer listed.

image

You can event filter the Consumers based on the type using the drop-down menu.

image

Last on the list is to bind these together using the Binding.

image

Not really a lot to it. You pick the Filter and Consumer and click Create. This will create the binding and enable the WMI event subscription.

image

That is really all there is to it! The trick is really knowing the WQL query for the Filter and then determining what kind of consumer fits this best.

Almost forgot… You can even connect to remote systems to add and remove event subscriptions! Just click on the File menu and select Connect to Another Computer.

image

Enter a computername and click OK and away you go.

image

image

Please keep this mind that it is in Beta, so there will most likely be bugs crawling around. Just stop by the Issues page and let me know what they are and I will work to get rid of them. I do have plans for a Template feature which will have pre-determined Filters as well as the option to save custom filters as templates for use later. This may also move over to the Consumers as well at a later date.

Hope everyone enjoys this!

Posted in GUI, powershell, WPF | Tagged , , , , | 4 Comments

PowerShell and Events: Permanent WMI Event Subscriptions

Wrapping up my series on PowerShell and Events, I will be talking about Permanent WMI Event Subscriptions and creating these using PowerShell.

Mentioned in my previous article on temporary events, WMI events are a very powerful and useful way to monitor for a wide variety of things with the only downside of those events being stopped when a console session is closed, a system is restarted or some other issue occurs that affects WMI. Enter the permanent WMI events. Unlike the temporary event, the permanent event is persistent object that will last through a reboot and continue to operate until it has been removed from the WMI repository.

There are multiple ways of setting up the WMI events and I will be covering 3 of those ways (as they deal with PowerShell) in this article. But before we dive into building out the event subscriptions, we first need to look at the basics behind building the events.

You need to be running as an Administrator on the system in order to create the event instances.

There are 3 pieces to the puzzle that have to be put together in order to have a fully functioning event subscription.  They are the Filter, Consumer and Binding.

Filter

The filter is a WQL query which says what you are looking for. Think back to my previous article on temporary events and how you setup a query that would be used to fire the action block. This is the exact same thing! You define the query and create the Filter WMI object.

Consumer

This would be your “Action” block that is in Register-WMIEvent with the exception of there being 5 possible Consumer classes to use with the Filter. Depending on your objective, you will use 1 of these ( or multiple that are binding by the same Filter) to perform an action of some sort. What are these 5 Consumer classes? Let’s take a look and see!

Consumer

Description

ActiveScriptEventConsumer

Executes a predefined script in an arbitrary scripting language when an event is delivered to it. This consumer is available on Windows 2000 and above.

CommandLineEventConsumer

Launches an arbitrary process in the local system context when an event is delivered to it. This consumer is available on Windows XP and above.

LogFileEventConsumer

Writes customized strings to a text log file when events are delivered to it. This consumer is available on Windows XP and above.

NTEventLogEventConsumer

Logs a specific message to the Windows NT event log when an event is delivered to it. This consumer is available on Windows XP and above.

SMTPEventConsumer

Sends an email message using SMTP every time that an event is delivered to it. This consumer is available on Windows 2000 and above.

Binding

The Binding is literally the glue that holds the Filter and Consumer together. Once you bind both of these together, you are enabling the WMI event subscriber to work right off the bat. To disable an existing WMI subscription, all you have to do is delete the binding instance and you will no longer have the subscription enabled.

 

Finding the WMI Instances

First off, lets see what I already have for Filters, Consumers and Bindings. We can use Get-WMIObject with the –Class parameter consisting of root\Subscription and then specifying the appropriate class that we wish to view.

#List Event Filters
Get-WMIObject -Namespace root\Subscription -Class __EventFilter

image

You can tell what kind of query is being used by the Query property of the Filter instance.

#List Event Consumers
Get-WMIObject -Namespace root\Subscription -Class __EventConsumer

image

#List Event Bindings
Get-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding

Here you can see that the NTLogEventConsumer is being used by the __CLASS property and what exactly is being used in the other properties.

image

You can see from the __PATH property which Filter and Consumer is being used for a WMI event.

Option #1: Using [wmiclass]

The first method of creating the WMI event subscription is by taking advantage of the wmiclass type accelerator and using the CreateInstance() method. First I will start off by creating the instance of the Filter.

#Creating a new event filter
$instanceFilter = ([wmiclass]"\\.\root\subscription:__EventFilter").CreateInstance()

What I have available is an object that I can modify based on my requirements.

image

There really isn’t a lot to the Filter instance and all I really need to and  add is the Query, QueryLanguage, EventNamespace and a name that makes sense.

$instanceFilter.QueryLanguage = "WQL"
$instanceFilter.Query = "select * from __instanceModificationEvent within 5 where targetInstance isa 'win32_Service'"
$instanceFilter.Name = "ServiceFilter"
$instanceFilter.EventNamespace = 'root\cimv2'

I am confident that this is all I need to put in for the Filter instance and need to actually save this instance into the WMI repository. I do this by using the Put() method. Note that you cannot actually see this member by using Get-Member by itself. You have to use the –View property and specify All in order to see the Put method as well as others.

$instancefilter | Get-Member -View All

image

As I was saying, I will use the Put method to save this instance. When I save this, it will output an object that I will need to hold onto so I can use it’s Path property later on for the Binding.

$result = $instanceFilter.Put()
$newFilter = $result.Path

image

Up next is the Consumer. I am going to take the same approach as the Filter and first create the instance.

#Creating a new event consumer
$instanceConsumer = ([wmiclass]"\\.\root\subscription:LogFileEventConsumer").CreateInstance()

Next, I configure the object to create a log file whenever the Filter has fired.

$instanceConsumer.Name = 'ServiceConsumer'
$instanceConsumer.Filename = "C:\Scripts\Log.log"
$instanceConsumer.Text = 'A change has occurred on the service: %TargetInstance.DisplayName%'

Make sure that you have a valid path for the logfile, otherwise this will not work out so well. The %TargetInstance.Name% represents the name of the service that is changing, whether it is the state or something else.

Lastly, we need to save the object into the WMI repository.

$result = $instanceConsumer.Put()
$newConsumer = $result.Path

Same as what I did with the Filter, I am saving the path so it can be used with the binding.

Speaking of binding, that is up next to create.

#Bind filter and consumer
$instanceBinding = ([wmiclass]"\\.\root\subscription:__FilterToConsumerBinding").CreateInstance()

Now we bind the Filter and the Consumer together and save the instance.

$instanceBinding.Filter = $newFilter
$instanceBinding.Consumer = $newConsumer
$result = $instanceBinding.Put()
$newBinding = $result.Path

You may have noticed that I saved the Binding path. This will be used to remove the binding instance later on.

I will now stop a service and check the Scripts folder for a logfile.

Stop-Service wuauserv -Verbose

image

image

Ok, now I need to remove these before the next example. The following is 1 of the 2 examples that I will show in this article and really benefits from Option 1 more than any other.

##Removing WMI Subscriptions using [wmi] and Delete() Method
([wmi]$newFilter).Delete()
([wmi]$newConsumer).Delete()
([wmi]$newBinding).Delete()

By giving the path of the instance, the [wmi] type accelerator will cast it out to the proper type. This also means that you have access to the Delete() method and can easily remove all of the subscription instances without any issues.

Option #2: Using Set-WMIInstance

Up next is the second approach to creating permanent WMI using the Set-WMIInstance cmdlet. This method makes use of the –Arguments parameter which accepts a hashtable that will be used to define each instance and its properties. This method also lends itself very nicely to “splatting”.

I plan re-creating the same type of Filter and Consumer as Option 1 to keep everything simple and show the same results.

First off I am going to create the hash table that will be used with my splatting and these are also the common parameters which will not be changed with each WMI instance.

#Set up some hash tables for splatting
$wmiParams = @{
    Computername = $env:COMPUTERNAME
    ErrorAction = 'Stop'
    NameSpace = 'root\subscription'
}

Next up is the Filter creation.

#Creating a new event filter
$wmiParams.Class = '__EventFilter'
$wmiParams.Arguments = @{
    Name = 'ServiceFilter'
    EventNamespace = 'root\CIMV2'
    QueryLanguage = 'WQL'
    Query = "select * from __instanceModificationEvent within 5 where targetInstance isa 'win32_Service'"
}
$filterResult = Set-WmiInstance @wmiParams

Instead of saving a path, I am going to save the actual object which will be used for the Binding at the end of this section. You will also notice that I have a hash table within my splatting hash table to handle all of the arguments that will be applied to the creation of the instance.

Moving on to the Consumer creation:

$wmiParams.Class = 'LogFileEventConsumer'
$wmiParams.Arguments = @{
    Name = 'ServiceConsumer'
    Text = 'A change has occurred on the service: %TargetInstance.DisplayName%'
    FileName = "C:\Scripts\Log.log"
}
$consumerResult = Set-WmiInstance @wmiParams

The only things that really changed with my WMI hash table is the Class and Arguments which is easily overwritten by adding new things.

Last is the Binding creation to enable this event subscription.

$wmiParams.Class = '__FilterToConsumerBinding'
$wmiParams.Arguments = @{
    Filter = $filterResult
    Consumer = $consumerResult
}
$bindingResult = Set-WmiInstance @wmiParams

Using the Filter and Consumer object this time, I can create the Binding with no issue at all. You can run the same test as Option 1 and you will see the log file being written to.

The other removal option that I will show is using Remove-WMIObject. Using Get-WMIObject to locate the instance and piping into Remove-WMIObject, you can easily remove one or all of the created WMI instances.  Depending on your objective, you can either Filter for each instance using –Filter or just go crazy and remove everything!

##Removing WMI Subscriptions using Remove-WMIObject
#Filter
Get-WMIObject -Namespace root\Subscription -Class __EventFilter -Filter "Name='ServiceFilter'" | 
    Remove-WmiObject -Verbose
 
#Consumer
Get-WMIObject -Namespace root\Subscription -Class LogFileEventConsumer -Filter "Name='ServiceConsumer'" | 
    Remove-WmiObject -Verbose
 
#Binding
Get-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding -Filter "__Path LIKE '%ServiceFilter%'"  | 
    Remove-WmiObject -Verbose

 

image

My previously created instances are now no longer!

Option #3 Using the PowerEvents Module

Wrapping up this article, I wanted to throw out an excellent module called PowerEvents (https://powerevents.codeplex.com/) that Trevor Sullivan (Twitter | Blog) has created. Not only does it come with some great examples, but it is incredibly easy to use! Let’s repeat the same type of event subscription that we have done before in the previous options. If you have the option to download and use this, I would recommend it!

First off, since this is a Module (and assuming you are on V2), it will need to be imported first.

#Import the module, if not running PowerShell V3 or above
Import-Module PowerEvents

image

We only have 3 commands to work with, but that is all we need to get this done.

image

First I set up some hash tables to splat against the New-WMIEventFilter and New-WMIEventConsumer functions.

#Set up a hash table for parameters
$filterParams = @{
    Computername = $env:COMPUTERNAME
    QueryLanguage = 'WQL'
    Query = "select * from __instanceModificationEvent within 5 where targetInstance isa 'win32_Service'"
    EventNamespace = 'root\CIMV2'
    Namespace = 'root\subscription'
    Name = 'ServiceFilter'
}
$consumerParams = @{
    Computername = $env:COMPUTERNAME
    ConsumerType = 'LogFile'
    Namespace = 'root\subscription'
    FileName = "C:\Scripts\Log.log"
    Name = 'ServiceConsumer'
    Text = 'A change has occurred on the service: %TargetInstance.DisplayName%'
}

Now we can create the Filter and Consumer, keeping in mind that we need to save the output object so it can be used with New-WMIFilterToConsumerBinding function.

#Create the Filter and Consumer
$filterResult = New-WmiEventFilter @filterParams
$consumerResult = New-WmiEventConsumer @consumerParams

Last on this is to bind the Filter and Consumer together.

$bindingParams = @{
    Computername = $env:COMPUTERNAME
    Filter = $filterResult
    Consumer = $consumerResult
}
 
#Create the binding
$bindingResult = New-WmiFilterToConsumerBinding @bindingParams

Deciding whether or not to save the output of the binding creation is up to you. You could just as easily save it to $Null or even let the object be displayed. Now we have an enabled event subscription in which you will see updates to the logfile as mentioned previously. How to remove these instances is up to you. You can use either of my methods listed in Options 1 and 2 or you can go about it another way.

While I repeated the same type of monitoring with each example, this should at least get you started in the right direction in creating your own types of permanent WMI events!

With that, this wraps up my series on PowerShell and Events with Permanent WMI Events.  Hopefully this has shown some various approaches to monitoring using PowerShell.

Posted in powershell | Tagged , , , , , | 10 Comments