880
CHAPTER 20
R
ESPONDING
IN
REAL
TIME
WITH
EVENTING
And you’re done. Now whenever an entry is added to the Application event log on the 
remote computer, you’ll see the entry message displayed on your console. Of course, if 
you’re impatient, you can trigger an event yourself. Use the .
NET
FailFast()
API
to 
cause a “Watson” event to be generated by crashing a PowerShell process:
PS (4) > powershell "[System.Environment]::FailFast('An event')" 
PS (5) >
After a short time, you’ll see something like the following displayed on the console:
PS (6) > Got an event:
Well, this sort of worked: the event did trigger the event handler and you got the part 
of the event you wrote. Unfortunately, the most interesting piece—the message in the 
event itself—is mysteriously absent. You’ll see what happened in the next section.
20.9.2
Serialization issues with remote events
The serialization mechanism used by remoting can sometimes cause problems when 
using remote events. Because the event is being sent over the remoting channel, it has 
to be serialized by the PowerShell serializer. By default, the serialization depth is only 
one. This means you get the top-level properties but not the second-level properties. 
So to preserve the message content in 
$event.Entry.Message
, you need to change 
the serialization depth for this type of object to 2. Back in section 11.7.3, we covered 
the types.ps1xml files and how they can be used to add metadata to a type. In section
12.6.5, we also talked about how those files can be used to change the serialization 
depth for a type. So you need an 
XML
document that you can pass to 
Update-Type-
Data
to change the serialization depth for 
System.Diagnostics.Entry-
WrittenEventArgs
to 2. Save this 
XML
in a variable as a string for now:
PS (7) > $typeSpec = @' 
>>     <Types> 
>>        <Type> 
>>            <Name>System.Diagnostics.EntryWrittenEventArgs</Name> 
>>             <Members> 
>>                 <MemberSet> 
>>                     <Name>PSStandardMembers</Name> 
>>                     <Members> 
>>                         <NoteProperty> 
>>                             <Name>SerializationDepth</Name> 
>>                             <Value>2</Value> 
>>                         </NoteProperty> 
>>                     </Members> 
>>                 </MemberSet> 
>>             </Members> 
>>        </Type> 
>>     </Types> 
>> '@ 
>>
Pdf reverse page order - re-order PDF pages in C#.net, ASP.NET, MVC, Ajax, WinForms, WPF
Support Customizing Page Order of PDF Document in C# Project
move pages in pdf; rearrange pdf pages reader
Pdf reverse page order - VB.NET PDF Page Move Library: re-order PDF pages in vb.net, ASP.NET, MVC, Ajax, WinForms, WPF
Sort PDF Document Pages Using VB.NET Demo Code
reorder pages in pdf document; pdf rearrange pages online
R
EMOTING
AND
EVENT
FORWARDING
881
Now before you use this to set up new events, you should remove the existing event 
registrations on both the local and remote ends of the connection:
PS (8) > Invoke-Command $s { Unregister-Event EventWatcher1 } 
PS (9) > Unregister-Event EventWatcher1
You have the 
XML
in a local variable but you need to update the type metadata on the 
remote end. You need to get the content of the 
$typeSpec
variable over to the 
remote machine, which you’ll do by passing it as an argument to the 
Invoke-Com-
mand
scriptblock:
PS (10) > Invoke-Command -ArgumentList $typeSpec -Session $s { 
>>     param ($typeSpec) 
>> 
>>     $tempFile = [System.IO.Path]::GetTempFileName() 
>>     $tempFile = $tempFile -replace '\.tmp$', '.ps1xml' 
>>     $typeSpec > $tempFile 
>>     try 
>>     { 
>>         Update-TypeData $tempFile 
>>     } 
>>     finally 
>>     { 
>>         Remove-Item $tempFile 
>>     } 
>> } 
>>
Let’s go over what’s happening in this scriptblock. First you’re using the .
NET
Get-
TempFileName()
method to get a temporary filename to use to store the data. Because 
the default extension on the filename that’s returned is .tmp and you need it to be 
.ps1xml, you used the 
-replace
operator to change the extension. Then you write 
$typeSpec
to the file in 
$tempFile
using redirection, call 
Update-TypeData
to load 
the file, and finally clean up by removing the temp file. You’re using the 
try/finally 
statement to make sure that the file gets cleaned up even if there’s a problem updating.
With the type metadata updated, you can set up the remote event registration, 
just like before:
PS (11) > Invoke-Command $s { 
>>     $myLog = New-Object System.Diagnostics.EventLog application 
>>     Register-ObjectEvent ` 
>>         -InputObject $myLog ` 
>>         -SourceIdentifier EventWatcher1 ` 
>>         -EventName EntryWritten ` 
>>         -Forward 
>> 
>>     $myLog.EnableRaisingEvents = $true 
>> } 
>>
C# Word: How to Use C# Code to Print Word Document for .NET
document pages in original or reverse order within entire C# Class Code to Print Certain Page(s) of powerful & profession imaging controls, PDF document, image
rearrange pages in pdf; move pages in pdf online
882
CHAPTER 20
R
ESPONDING
IN
REAL
TIME
WITH
EVENTING
Then the local event subscription:
PS (12) > Register-EngineEvent -SourceIdentifier EventWatcher1 -Action
>>    param($sender, $event) 
>> 
>>    Write-Host "Got an event: $($event.entry.message)" 
>> } 
>>
Id              Name            State      HasMoreData     Location 
--              ----            -----      -----------     --------
              EventWatcher1   NotStarted False
And finally, you’re ready to try your event trigger again:
PS (13) > powershell "[System.Environment]::FailFast('An event')"
PS (14) >
PS (15) > Got an event: .NET Runtime version 2.0.50727.4200 - An event 
PS (16) >
This time, when you see the event message, it includes the text from the call to 
Fail-
Fast()
as written into the event log on the remote system.
Congratulations! We’ve pretty much reached the end of our eventing discussion 
and you’re still with us. Event processing is an advanced topic, even for full-time pro-
grammers. Trying to understand how multiple actions are going to interoperate can 
be mind-boggling. PowerShell’s approach to eventing is designed to make this as sim-
ple as possible, but understanding how it works under the hood can go a long way to 
helping you figure things out. Let’s take a peek.
20.10 H
OW
EVENTING
WORKS
The eventing infrastructure relies on two other components of PowerShell introduced 
in PowerShell v2: modules (for isolation, as discussed earlier) and jobs (for managing 
subscriptions). When you registered an event subscription, you saw that an object 
was returned. This object is in fact a job object, with the same base class as the object 
you get back from 
Start-Job
or the 
-AsJob
parameter on 
Invoke-Command
. Once 
an event subscription is created, it will show up in the 
Job
table, which means that 
you can use the 
Get-Job
cmdlet as another way to find this subscription. Let’s go 
back to our timer event subscription (see 20.4.1) and see what this looks like:
PS (6) > Get-Job | Format-List
Module        : __DynamicModule_3fd88733-cbcb-4c0b-b489-1e1305782970 
StatusMessage : 
HasMoreData   : False 
Location      : 
Command       :  Write-Host "<TIMER>"
JobStateInfo  : NotStarted 
Finished      : System.Threading.ManualResetEvent 
InstanceId    : d3f41e39-776d-4fe8-9bd2-db82a7e1311c
H
OW
EVENTING
WORKS
883
Id            : 1
Name          : fca4b869-8d5a-4f11-8d45-e84af30845f1 
ChildJobs     : {}
Output        : {}
Error         : {}
Progress      : {}
Verbose       : {}
Debug         : {}
Warning       : {}
State         : NotStarted
Let’s start the timer running again, setting the interval to something large so you can 
still type:
PS (21) > $timer.Interval = 60000
PS (22) > $timer.Start()
Now when you run 
Get-Job
PS (29) > Get-Job | Format-Table State,Command -AutoSize
State Command
----- -------
Running  Write-Host "<TIMER>"
you see that the job state has been changed to 
Running
. The other thing you should 
be able to do if it’s a 
Job
is to stop it by calling 
Stop-Job
. Let’s try it:
PS (33) > Stop-Job
PS (33) > Get-Job | Format-Table State,Command -AutoSize
State Command
----- -------
Stopped  Write-Host "<TIMER>"
It works. But this code has done more than just stop the job—it’s also removed the 
event subscription:
PS (35) > Get-EventSubscriber
PS (36) >
Because event handlers are effectively running in the background, it seems logical to 
manage an active subscription as a 
Job
. You should note that, although the executing 
event handler is represented as a 
Job
, it wasn’t started using 
Start-Job
and, unlike 
PowerShell jobs, still runs in process with the session that set up the subscription.
At the beginning of our discussion on events, we talked about the issues involved 
in dealing with asynchronous events. Because these events can occur in any order, 
great care is required to make sure that the integrity of shared data structures is main-
tained. To maintain this integrity, you have to make sure that programs synchronize 
access to the shared objects, and doing so turns out to be difficult. In fact, this is one 
of the most common reasons that a program stops responding and appears to be 
hung. If two actions are trying to update a synchronized object at the same time, they
884
CHAPTER 20
R
ESPONDING
IN
REAL
TIME
WITH
EVENTING
can end up blocking each other, each trying to get exclusive access to the resource. 
This type of contention is called a deadlock.
PowerShell deals with this  problem by imposing a strict order on the actions 
instead of on individual data objects. When an asynchronous event occurs, the event-
ing subsystem adds that event object to the event queue. Then, at various points in 
the PowerShell runtime, the engine checks to see if there are any events posted to the 
event queue. If there are, the engine suspends the mainline activity, pulls an event off 
the queue, switches to the module context for that event handler, and then executes 
the event scriptblock. Going back to the lecture analogy I used at the beginning of 
the chapter, this operates like an online “Live Meeting” where the participants use 
instant messaging to submit their questions. These questions get added to the queue 
without interrupting the speaker. The audience can message at any time, but the 
speaker will only address a question when it’s a suitable time to do so. This queuing 
mechanism is illustrated in figure 20.8.
Events are added to the queue as they arrive and then are pulled off the queue by 
the engine and processed when a convenient spot is reached.
To make sure events get processed in a timely manner, the engine needs to check 
the queue fairly often. On the other hand, if it checks too often, it would substan-
tially slow down the interpreter. As implemented in PowerShell v2, the engine checks 
for events in all calls that write objects, including between each stage in a pipeline. It 
also checks between each statement in a script and anywhere the engine might loop
Events fire asynchronously and are added to queue
4
Mainline script execution
3
2
1
Process
event
When in a stable state,
check for events on queue 
Resume mainline processing
Event queue
Pull event off queue if
available
Figure 20.8 How asynchronous event processing is handled in PowerShell. As 
events occur, they are added to the queue asynchronously. At various stable points, 
the engine checks the queue and pulls events off to execute. Once the event execu-
tion is complete, normal processing resumes.
S
UMMARY
885
for a long time. This provides a good tradeoff between event latency and overall per-
formance. In the case where there are multiple events pending on the queue at the 
time of the check, the engine will use a throttling policy to decide how many of the 
pending events will be processed before returning to the mainline so that the fore-
ground activity isn’t “starved.” (As an aside, the places where  the  event queue is 
checked are the same places that the engine checks to see if it has been requested to 
stop executing, such as when the user presses 
C
trl-
C
.)
If the event has an action block associated with it, that scriptblock executes until 
it’s completed. Once the event action is finished, the mainline activity is resumed. 
Because the engine only processes events when it knows that the system state is stable, 
problems related to inconsistent system state don’t arise and all activity is effectively 
synchronous.
NOTE
An event action runs until it’s complete. As long as it’s run-
ning, no other events are processed and the mainline activity is sus-
pended.  This  means  that  event  handlers  shouldn’t  be  written  to 
execute for a long time. The same consideration exists when writing 
GUI
s. If a control’s event handler runs on the UI thread for a long 
time, the UI will be blocked, unable to respond to events, causing it to 
appear to hang. 
This  architecture  isn’t  as efficient as the more fine-grained  techniques so  it’s not 
appropriate for programs that are very performance sensitive. It is however simple, 
effective, and completely sufficient for PowerShell scripting. It makes asynchronous 
event handling in PowerShell a reasonable, if somewhat advanced, proposition.
This completes our coverage of eventing. We started with the basic synchronous 
event handling mechanisms carried over from PowerShell v1. Then we moved on to 
asynchronous processing, introducing the eventing cmdlets. We looked at a couple of 
different event sources and how you can use them. You saw how eventing and remot-
ing work together and explored how the eventing infrastructure works.
20.11 S
UMMARY
In this chapter, we introduced an advanced but useful topic: eventing. This feature 
allows you to write scripts that can respond to real-world events in a timely manner. 
The chapter began by introducing key concepts used in eventing and described 
how event-driven scripts operate with the “don’t-call-me-I’ll-call-you” principle. We 
explored  the  idea  that  there  are  two  fundamental  event  types:  synchronous  and 
asynchronous.
In synchronous events, all activities are synchronized so that no activity is ever 
interrupted. This model has been used all along in PowerShell for things like the 
ForEach-Object
and 
Where-Object
cmdlets and in the kind of 
GUI
scripting you 
saw in section 17.3. Digging  further into synchronous events, we looked at how
886
CHAPTER 20
R
ESPONDING
IN
REAL
TIME
WITH
EVENTING
.
NET
represents events using the 
System.Delegate
type. We also looked at a sub-
class of 
System.Delegate
: the 
System.EventHandler
type. In PowerShell v1, only 
the 
System.EventHandler
type was directly supported by PowerShell.
In section 20.3, we introduced asynchronous events, which execute in a nondeter-
ministic  order. To  deal  with  these  asynchronous  events,  PowerShell includes  an 
eventing subsystem that takes care of synchronizing all operations. The core model for 
eventing in PowerShell is built around the idea of event subscriptions. There are three 
cmdlets  for creating  these  subscriptions: 
Get-ObjectEvent
Get-WmiEvent
, and 
Get-EngineEvent
for .
NET
WMI
, and PowerShell engine events respectively. 
As part of the event subscription, an action scriptblock may be specified that will be 
executed when the event is triggered. Context information for the event is made 
available to  the scriptblock through the 
$Event
automatic variable. Some of the 
properties on the object in 
$Event
are also directly available through additional auto-
matic variables (see table 20.2). 
Events may also be processed by calling 
Wait-Event
to block for an event and 
then process them as they arrive. Event subscripts can be listed with 
Get-Event-
Subscription
and unregistered using 
Unregister-Event
.
Handling events that come from .
NET
objects involves setting up an event sub-
scription on the event member of the class or object of interest. For 
WMI
events, a 
small number of events may be subscribed to by using specific 
WMI
classes, but creat-
ing arbitrary event subscriptions requires the use of the eventing extensions to the 
WMI
Query Language. As opposed to normal instance queries (section 19.2.2), event 
queries require the use of the 
WITHIN
keyword to specify the polling interval for the 
event being monitored. Queries are written using the intrinsic event classes (such as 
__InstanceModified
 to specify the event to subscribe to. Because the intrinsic 
events apply to a large number of classes, the 
WHERE
clause should be used to select a 
specific target class by doing something like:
Where TargetInstance Isa 'Win32_Service'
Additional instance filter criteria can also be specified in the 
WHERE
clause if needed. 
To aggregate or group together related sets of 
WMI
events, the 
GROUP
keyword can 
be added to the query. By grouping events, you reduce the network and processing 
overhead on the client that would be incurred if each event was sent individually. 
This can be important when writing a scalable application.
The final event source was engine events. These are PowerShell-specific events 
that are subscribed to by name using the 
Register-EngineEvent
cmdlet with the 
-SourceIdentifier
parameter. Engine events may be generated by the PowerShell 
engine itself (though only one event is currently defined: 
Engine.Exiting
). Scripts 
can also generate their own engine events with the 
New-Event
cmdlet. Finally, event 
forwarding allows remote event subscriptions to act  as a  source  of engine  events. 
When using PowerShell remoting, an event subscription can be created on a remote 
computer, which, instead of executing a taking local action, forwards the events over
S
UMMARY
887
the remoting connection to the client for processing. The source identifier defined 
for the event on the remote computer becomes a subscribable engine event on the 
client side.
Wrapping things up, in this chapter we introduced some advanced features that 
have  traditionally  only  been  used  by  programmers.  The  PowerShell  eventing 
subsystem makes these powerful techniques accessible to the nonprogrammer and 
IT 
professional as well. Mastering these features gives you the ability to create more 
responsive, efficient, and reliable scripts.
And now, in the last chapter of this book, we’re going to shift from doing things 
to not doing things, or more specifically, to keeping unauthorized users from doing 
things to our systems. Chapter 21 looks at security, the role PowerShell plays in 
securing a computing environment, and the security features included in PowerShell. 
With an environment as powerful as PowerShell, a good understanding of the secu-
rity topics involving PowerShell is critical. Remember: security is only boring until 
you’ve been hacked.
888
C
H
A
P T E R   2 1
Security, security, security
21.1  Introduction to security  889
21.2  Security modeling   891
21.3  Securing the PowerShell 
environment 897
21.4  Signing scripts  904
21.5  Writing secure scripts  916
21.6  Using the SecureString class  916
21.7  Summary  926
Oh brave new world, that has such people in it!
—Miranda in William Shakespeare’s The Tempest
In this chapter, we’ll explore the topics of security and secure programming to see 
how they impact PowerShell. In contrast to the previous chapters where our focus has 
been on what people can do with PowerShell, with security our focus is on how to 
prevent people (or at least the wrong people) from doing things. This switch is radical 
but it’s the essence of security. 
We’ll begin the chapter by introducing security-modeling concepts, and then look 
at the security features in PowerShell. We’ll also show you how to write secure scripts 
in PowerShell. Boring, you say. Do you need to know this stuff? Yes, you do. In a 
connected world, security is incredibly important. A small mistake can have huge 
consequences. People will talk about a “zone of influence”—the idea that something 
that happens far away can’t impact you. This idea is meaningless in a connected 
world. Anyone, anywhere can attack your system just as if they were next door. You 
also have to consider cascading consequences: a useful script that someone posts on 
her blog may get copied thousands of times. If there’s a security flaw in that script, it 
will propagate along with the script, get copied into new scripts, and so on. A small
I
NTRODUCTION
TO
SECURITY
889
flaw in the original script may be replicated around the world. Now that we’re all 
appropriately terrified, let us proceed. 
When discussing security and PowerShell, there’s only one thing you should keep 
in mind: PowerShell executes code. That’s what it does—that’s all it does. As a conse-
quence, you need to consider how having PowerShell on your system might introduce 
security risks. Of course, this isn’t specific to PowerShell. It’s true of anything that runs 
code—Perl,  Python,  even 
cmd.exe
 Making  sure that a  system with PowerShell 
installed is secure is the topic of the first part of this chapter. Once you have PowerShell 
installed, you’re going to want to write, deploy, and execute scripts. The latter portion 
of the chapter covers some approaches to writing secure PowerShell scripts.
21.1
I
NTRODUCTION
TO
SECURITY
We’ll begin our security discussion with some basic definitions. In this section, we’ll 
look at what security is and what that means. We’ll also talk about what it isn’t, which 
can be just as important.
21.1.1
What security is and what it isn’t
Computer security is the field devoted to the creation of techniques and technologies 
that allow computers to be used in a secure manner. Obvious perhaps, but there are 
two parts to the story. Secure means that the computer is protected against external 
danger or loss of valuables (financial, personal, or otherwise). The flip side is that the 
system has to remain useful. (There’s a joke in the security industry that the only way 
to make a computer completely secure is to turn it off, disconnect all the cables, seal it 
in concrete, and dump it into the middle of the ocean. This makes for a very secure 
computer, but it’s not a very useful one.) 
In approaching security, you must balance security requirements with utility. If 
the techniques needed to secure a system are too hard to use, users won’t use them, 
and the system will be unsecured. If they interfere with the basic tasks that need to be 
performed, they’ll be disabled or bypassed and the system will be unsecured. Are you 
getting the picture? 
Now let’s look at what security isn’t. Security isn’t just cryptography. This fact is 
oddly surprising to many people. Security uses cryptography—it’s one of the main 
tools used to secure an environment. They are, however, separate fields. The corollary 
is that unless you’re a cryptographer, you shouldn’t write your own cryptography 
code. It’s very hard. And even the experts don’t always get it right. Even if it’s right 
today, it may be wrong tomorrow.
NOTE
An example of this is the 
MD
 hash  algorithm, which had 
been considered the gold standard for secure hashes for a long time 
before it was found to be vulnerable.
The PowerShell environment, through .NET and the Windows platform, has access 
to a variety of cryptographic tools for building secure systems. You should use these
Documents you may be interested
Documents you may be interested