About the author

Author Name is someone.
E-mail me Send mail

Recent posts

Recent comments

Don't show

Authors

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2010

Getting through a proxy server with PowerShell

When we were looking at using the System.Net.WebClient class to retrieve web pages the question "how do you use this when you have to go through a proxy server and provide credentials?" came up.

A little bit of exploration with get-member and some digging in MSDN revealed that

  • the System.Net.WebClient class has a proxy property that can be set to an instance of the System.Net.WebProxyClass
  • the System.Net.WebProxyClass has a credentials property that can be set to an instance of any object that implements the ICredentials interface
  • The class System.Net.NetworkCredential implements ICredentials
  • the get-credential cmdlet returns a System.Management.Automation.PSCredential object
  • the PSCredential class has a method called GetNetworkCredential that returns a System.Net.NetworkCredential object - just what we need :-)

  Putting all of that together gives us this script which will ask for credentials and feed them to a proxy server.

[void][System.Reflection.Assembly]::LoadWithPartialName("System.Net")
#
# Create a proxy object
#
$proxy = new-object System.Net.WebProxy
#
# Grab some credentials and store them in the proxy object
#
$cred = get-credential
$proxy.credentials = $cred.GetNetworkCredential()
#
# Off to the web
#
$WebClient = new-object System.Net.WebClient
$WebClient.proxy = $proxy
$url = "http://www.microsoft.com"
$content = $WebClient.DownloadString($url)

It just goes to show how great the combination of PowerShell and the .Net framework is!

Currently rated 5.0 by 3 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by tb on Monday, January 07, 2008 3:53 AM
Permalink | Comments (0) | Post RSSRSS comment feed

A forms designer for PowerShell

I've just finished a great week teaching Mastering PowerShell for HBOS and a couple of interesting things came up.

When I teach the Windows.Forms module I usually show how easy it is to use one of the Visual Studio Express editions to build a form and then translate the designer generated code into PowerShell. This time however one of  the delegates pointed me at the Admin Script Editor which has a forms designer that generates native PowerShell script code :-)

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by tb on Monday, January 07, 2008 3:51 AM
Permalink | Comments (0) | Post RSSRSS comment feed

The PowerShell 2.0 CTP is here!

You can download it from here

There are a couple of new posts from the PowerShell team that give some more information about this preview release

The first thing that catches my eye is a new version of get-wmiobject that adds in some of the sorely missed functionality of the COM interface to WMI. Hopefully the WMI interface also has some bug fixes.

Congratulations to the PowerShell team.

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: PowerShell | CTP
Posted by tb on Monday, January 07, 2008 3:50 AM
Permalink | Comments (0) | Post RSSRSS comment feed

The PowerShell 2.0 CTP is nearly here!

Check out these messages from Jeffrey Snover

Start building your VMs :-)

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: PowerShell | CTP
Posted by tb on Monday, January 07, 2008 3:48 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Launching PowerShell Scripts in Response to WMI Events

This turns out to very straightforward, the key is to use the CommandLineEventConsumer class. It allows you to launch any program in response to a WMI event. In order to use it you only need to set two properties (although there are many more to explore)

  1. Name - a unique name for your class instance
  2. CommandLineTemplate - the command you want to run

As we want to launch a PowerShell script the command line would need to be something like

powershell.exe -command C:\temp\myscript.ps1

This would run the script myscript.ps1 and pass it any parameters that are added to the command line. Within the script you can access the parameters via the $args array.

A Working Example

Lets say that we wanted to stop people running Solitaire on their PCs - it's mean but hey, we're admins! The PowerShell cmdlet stop-process will kill a process if we supply the process ID so we'll pass that out from WMI to the script and pick it up via $args.

stop-process $args[0]

As before you need to create a filter and a consumer and join them together. So this code creates a filter that looks for instances of Solitaire starting up

$EFClass = [wmiclass]"\root\subscription:__EventFilter"
$ef = $EFClass.CreateInstance()
$ef.Name = "NewProcessFilter"
$ef.Querylanguage = "WQL"
$ef.Query = "select * from __InstanceCreationEvent within 5 where targetinstance isa 'Win32_Process' and targetinstance.name = 'Solitaire.exe'"
$ef.EventNamespace = "root\cimv2"
$ef.put()

Next we create a consumer, using the CommandLineEventConsumer class. %TargetInstance.Handle% picks up the process ID from the win32_process object that triggered the event and adds it onto the end of the PowerShell command line.

$CLECClass = [wmiclass]"\root\subscription:CommandLineEventConsumer"
$clec = $CLECClass.CreateInstance()
$clec.Name = "RunPowerShell"
$clec.CommandLineTemplate = "powershell.exe -command C:\temp\myscript.ps1 %TargetInstance.Handle%"
$clec.put()

and finally join them together with an instance of the __FilterToConsumerBinding class

$FCBClass = [wmiclass]"\root\subscription:__FilterToConsumerBinding"
$fcb = $FCBClass.createinstance()
$fcb.Consumer = $clec.__Path
$fcb.Filter = $ef.__Path
$fcb.put()

Now every time you start Solitaire the PowerShell script myscript.ps1 will run and Solitaire will be terminated :-)

Note

You might get the same errors that I noted in an earlier post when you invoke the put method. This is a known bug in PowerShell 1.0 and will be fixed in v2.0. The workaround for now is to keep invoking put until it works.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: events | PowerShell | WMI
Posted by tb on Monday, January 07, 2008 3:41 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Make it stop, make it stop!

The easiest way to stop event processing is to delete the binding between a filter and a consumer. In WMI terms the '__FilterToConsumerBinding' class is known as an association class, all it does is link together two other classes. Association classes are a pain to connect to directly so it's simpler to use another type of WQL query that returns the association class connected to your filter or consumer. The code below does exactly that and once you have the associator you can invoke its delete method to break the link. Do bear in mind that a filter or consumer may be associated with more than one other filter or consumer so you might get an array of results rather than just one.


$AssociatorInstance = gwmi -query "REFERENCES OF {__EventFilter='NewProcessFilter'}" -namespace "root\subscription"
$AssociatorInstance.delete()

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by tb on Monday, January 07, 2008 3:39 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Configuring WMI Event Handling with PowerShell

PowerShell provides a helpful type accelerator '[WMICLASS]' that makes using these WMI classes extremely easy.

Lets say that we wanted to log to a file every process that was created on a machine.

First we need to create our filter. To do this we connect to the '__EventFilter' class, create a new instance, set it's properties and save it into WMI. Note - you need admin rights to write into the WMI store so you will need to run PowerShell as administrator for these scripts to work. There is no way to provide alternative credentials when you are using the type accelerator. Get-WmiObject does support a credential parameter but it doesn't work on local connections and there's no way to use the credential when you invoke 'Put' on the new class instance.

The code below creates a filter that will check the '\root\cimv2' namespace every 5 seconds for new instances of the 'Win32_Process' class'

$EFClass = [wmiclass]"\root\subscription:__EventFilter"
$ef = $EFClass.CreateInstance()
$ef.Name = "NewProcessFilter"
$ef.Querylanguage = "WQL"
$ef.Query = "select * from __InstanceCreationEvent within 5 where targetinstance isa 'Win32_Process'"
$ef.EventNamespace = "root\cimv2"
$ef.put()

Now we create the event consumer - in this case we're going to use the LogFileEventConsumer. As before we attach to the appropriate class, create an instance, set its properties and store the new instance. Note the use of a string template in the text property. This allows us to pull out properties from the object that caused the event - in this case an instance of Win32_Process.

$ECClass = [wmiclass]"\root\subscription:LogFileEventConsumer"
$lfc = $ECCLass.createinstance()
$lfc.Name = "MyLogFileConsumer"
$lfc.FileName = "c:\temp\Win32Process.log"
$lfc.Text = "Process %TargetInstance.Name% was created on %TargetInstance.CreationDate%"
$lfc.put()

And then to start everything off we connect the filter and consumer using an instance of the '__FilterToConsumerBinding' class. This class requires that you give it the unique identifiers of the filter and consumer that you want to connect. You can always get this from a WMI object by referencing its '__Path' property.

$FCBClass = [wmiclass]"\root\subscription:__FilterToConsumerBinding"
$fcb = $FCBClass.createinstance()
$fcb.Consumer = $lfc.__Path
$fcb.Filter = $ef.__Path
$fcb.put()

And that's it! WMI will now record every process that starts on your machine until you delete the binding.

But it doesn't work!

You may find that when you try to invoke the 'put' method on a WMI object you get an error like this

WMIError

If that happens just invoke 'Put' again (and again and again) and it will work - eventually!

 WMIWorking

You might also find that when you try to store the paths of your filter and consumer into the binding object you get nulls rather than  valid paths. Retrying a few times will fix this. I've seen this behaviour on XP and Vista. There's definitely something odd going on here but I haven't tracked it down yet.

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by tb on Monday, January 07, 2008 3:34 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Event Handling Classes in WMI

Finally, some clear time to write another post!

In order to get WMI to to do something with the stream of events that flows through a system you need to use three classes in combination

  1. The event filter class.
  2. The event consumer class.
  3. The filter to consumer binding class.
Event filters

Event filters are used to specify the particular events that you want WMI to look out for. They are specified in WQL, a SQL like language. There is a good discussion of WQL and event filters here in MSDN.

The WMI class that represents an event filter is '__EventFilter'.

A word about namespaces

Internally the WMI store is partitioned into a number of namespaces. Microsoft recommend that you register all of your event classes in the '\root\subscription' name space. As the events that you will be interested in won't be occurring in this namespace it is important to set the 'EventNamespace' property on any filter that you create so that WMI knows where to look for candidate events. If you forget to do this you will get errors in the Application event log when you try to use your filter.

Event consumers

Event consumers are the bits of code that receive notification of the events that you have registered an interest in. WMI comes with 5 preinstalled consumers on Vista/XP and Server 2003. On Windows 2000 you need to install the providers yourself by compiling their MOF files.

ActiveScriptEventConsumer
This allows you to run an arbitrary script in response to an event.
LogFileEventConsumer
This allows you to write to a text file in response to events.
NTEventLogEventConsumer
Theis allows you to write to the Windows event logs in response to events.
SMTPEventConsumer
This allows you to send e-mail in response to events.
CommandLineEventConsumer
This allows you to run any command in response to events

You can find much more information about these consumers here in MSDN.

Additionally if you have installed the WMI Tools you will get an extra consumer - the 'WMI Event Viewer Consumer'. This is a simple GUI tool that displays the events captured by a filter as they happen. It's great for testing your filters before you go into production with one of the other consumers.

 If you are using CIM Studio from the WMI Tools then have a look in the 'ROOT\subscription namespace' and navigate to '__SystemClass\__IndicationRelated\__EventConsumer' to see a list of the event consumers installed on your machine.

Filter to consumer bindings

These are the essential bits of plumbing that connect filters to consumers. The WMI class for this is '__FilterToConsumerBinding' and you can read more about it here. Once you have set this up WMI will keep routing the events captured by a filter to your chosen consumer until you reconfigure things - even across reboots.

 

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by tb on Monday, January 07, 2008 3:31 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Power GUI

Check out PowerGUI a cool new free extensible GUI host for PowerShell from Quest. See it in action here.

Imagine an MMC like interface where each leaf node in the tree on the left hand pane is a PowerShell script or cmdlet and the right hand pane shows the results in tabuar form with the ability to filter and export. It comes bundled with extensions for managing Exchange 2007, Operations Manager 2007, local systems and Active Directory computers.

It's a little bit buggy at the moment but it has just made the job of building your own PowerShell based management tools so much easier :-)

But isn't there something slightly odd about hiding the command prompt behind a GUI...

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: PowerShell | PowerGUI
Posted by tb on Monday, January 07, 2008 3:29 AM
Permalink | Comments (0) | Post RSSRSS comment feed

A first look at WMI events

Event notification is built into WMI and if you open up CIM Studio (one of the tools in the WMI Toolkit) and navigate to '__SystemClass\__IndicationRelated' you will find all of the classes related to event handling. There are two types of event that you can use -

Intrinsic Events

These are generated by WMI in response to changes in the CIM repository and further breakdown into events related to namespaces, classes, instances and timers. You can see these by navigating to '__SystemClass\__IndicationRelated\__Event' where you will find

  • __NamespaceOperationEvent and its children
  • __ClassOperationEvent and its children
  • __InstanceOperationEvent and its children
  • __TimerEvent

If you poke around under these classes you'll see that there are various events that fire when something interesting happens in the CIM repository. The timer event is different as this lets you set up an event that fires on a regular basis or at a scheduled time.

Extrinsic Events

Providers

Extrinsic events are fired into WMI by providers. Providers allow third parties to plug in to WMI and make their management information available. You'll probably have a whole bunch of these registered on your systems. They are often created as DLLs with an accompanying MOF file. You can find some provider related files in '%windir%\system32\wbem'. Look for any files with 'prov' in their names. Alternatively running these commands will give you an exhaustive list of the providers installed in the 'root\CIMv2' namespace from WMIs perspective.


get-wmiobject -class "__InstanceProviderRegistration" | select-object -property Provider
get-wmiobject -class "__ClassProviderRegistration" | select-object -property Provider
get-wmiobject -class "__EventProviderRegistration" | select-object -property Provider
get-wmiobject -class "__MethodProviderRegistration" | select-object -property Provider
get-wmiobject -class "__PropertyProviderRegistration" | select-object -property Provider
get-wmiobject -class "__EventConsumerProviderRegistration" | select-object -property Provider
and Events

In order to list all of the extrinsic events available on a system you need to recurse through all of the namespaces in WMI listing out all of the '__ExtrinsicEvent' classes that you find. This next piece of code does exactly that. It uses a couple of functions -

Get-ExtrinsicEvents
runs a query against all of the classes in a particular namespace and lists only the '__ExtrinsicEvent' classes. Specifying 'meta-class' causes Get-WmiObject to retrieve class rather than instance objects from the repository.
ExamineNamespace
recurses through a namespace hierarchy calling Get-ExtrinsicEvents

function Get-ExtrinsicEvents( [string]$ns )
{
Get-WmiObject -class meta_class
-namespace $ns
-filter "__this isa '__ExtrinsicEvent'" |
select-object Name | Format-Table -HideTableHeaders
}

function ExamineNamespace( [string]$ns )
{
write-host "==================" $ns
Get-ExtrinsicEvents $ns

foreach ($n in (Get-WmiObject -Class "__NAMESPACE" -namespace $ns))
{
ExamineNamespace ($n.__NAMESPACE + "\" + $n.Name)
}
}

ExamineNamespace "ROOT"

In my next post I'll look at how you register you interest in specific WMI events and how you can launch PowerShell scripts in response to WMI events.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: events | PowerShell | WMI
Posted by tb on Monday, January 07, 2008 2:32 AM
Permalink | Comments (0) | Post RSSRSS comment feed