As promised, this posting is the first of hopefully several that will talk about PSH 2.0 features. Hmmm... in fact, maybe I will turn this into an ongoing series named "Stupid PowerShell Tricks".
Anyhow, Eventing was one of the things that kind of thwarted me with the CTP2 build. For some reason, I just could not get Eventing to work correctly (well actually not at all). That being said, thanks to a brain dump from the product team, me realizing that my logic was flawed, and the CTP3 version, I can not only get Eventing work (well kinda). But, I felt that I might be able to help other people as well. So... the following is a step-by-step which hopefully shows how to use Eventing with a custom assembly.
BTW - CTP3 was just released. Click here for more!
Step One
Load up your custom assembly, create an object, and see if the object supports Events. For example the following shows how you might do this using some pseudo code:
Add-Type -Path "C:\tools\SuperCool.dll"
$MyObject = New-Object cool.scp "host1", "myuser", "mypassword"
$MyObject | Get-Member
In my case, the resulting formatted table had the following events:
Cool, considering I was transferring files between systems.
Step Two
Once you have figured out which types of events are available to you, using those events is the next challenge. To figure that out, use the Register-ObjectEvent cmdlet to register an event subscription into your PowerShell session. For example:
Register-ObjectEvent -InputObject $MyObject -EventName OnTransferProgress -SourceIdentifier Scp.OnTransferProgress `
-Action {$Global:MCDPtotalBytes = $args[3]; $Global:MCDPtransferredBytes = $args[2]}
Register-ObjectEvent -InputObject $MyObject -EventName OnTransferEnd `
-SourceIdentifier Scp.OnTransferEnd -Action {$Global:MCDPGetDone = $True}
So... what exactly is going on here... First off, you are using the InputObject parameter to pass in your object to the cmdlet. You are doing this because the cmdlet needs the object from which it will create the event subscription. For the EventName name parameter, you provide the name of the event(s) you discovered in step one. For the SourceIdentifier parameter, you just need to provide a unique name. I tend to use something that is related to the object from which my events will be coming from. Lastly, the Action parameter is optional. In my case, I needed the event to do something.
At this point, you might be asking, "Just how is Tyson using these events?"
Well, at first, I just needed the script to wait until a command that was issued was done moving a file using SCP. Basically, without the script waiting, it kept going once a Get or Put command was issued. If I was interactively issuing these commands, that would have been fine. But, because the script was getting, comparing, and then copying files all from the remote source. I was running into timing issues were the script was trying to compare files that had yet not finishing copying.
To make the script wait, I had two options. First, I could use the Wait-Event cmdlet, which will cause the script to wait for a particular event to occur. Unfortunately when I used this cmdlet, I kept running into strange issues were the script execution sometimes didn't "Wait" or just kept "Waiting". It turned out the waiting issue was related to stuff like network drops, which resulted in the event never being fired. While the other issue remains a mystery.
At any rate, the second option was put together a loop that just kept checking for something to be True. For this we first start with the scriptblock that was defined for one of the action parameters I listed previous:
-Action {$Global:MCDPGetDone = $True}
Note to the wise, the scriptblock defined for the action parameter executes within its own scope. Hence, why I define the MCDPGetDone variable as Global!
Next, we define the following loop:
do {Write-Progress -Activity "Getting - $($_.Name)" -Status "Copying" -PercentComplete (($MCDPtransferredBytes/$MCDPtotalBytes)*100)} while ($MCDPGetDone -eq $Null)
Super cool... not only does my now script wait for a file to be transferred! But, thanks to the OnTransferProgress event handler I also get a progress bar. :>)
Hopefully this was helpful!
Normal 0 false false false EN-US JA X-NONE MicrosoftInternetExplorer4
/* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-qformat:yes; mso-style-parent:""; mso-padding-alt:0in 5.4pt 0in 5.4pt; mso-para-margin:0in; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Calibri","sans-serif";}
If you like this, check out some other posts from Tyson:
Or if you want, you can also check out some of Tyson's latest publications:
Lastly, visit the Microsoft Subnet for more news, blogs, and opinions from around the Internet. Or, sign up for the bi-weekly Microsoft newsletter. (Click on News/Microsoft News Alert)
With more than ten years of experience in IT, Tyson Kopczynski has become a specialist in Active Directory, Information Assurance, Windows automation, PKI, and IT security practices. Tyson is also the founding author of the Windows PowerShell Unleashed series and has been a contributing author for such books as Microsoft Internet Security and Acceleration (ISA) Server 2006 Unleashed and Microsoft Windows Server 2008 R2 Unleashed. He has also written many detailed technical papers and guides covering various technologies. As a consultant at Convergent Computing, Tyson works with and provides feedback for next generation Microsoft technologies since their inception and has also played a key role in expanding the automation and security practices at CCO. Tyson also holds such certifications as the Certified Information Systems Security Professional (CISSP), the SANS Security Essentials Certification (GSEC) and SANS Certified Incident Handler (GCIH), and the MCTS (Application Platform, Active Directory, and Network Infrastructure).
Certifications:
Publications:
Other Stuff: