PowerShell 事务与事件处理全解析
1. PowerShell 事务处理
在 PowerShell 中,事务处理是一项强大的功能,它允许你将一系列操作组合在一起,要么全部成功执行,要么全部不执行,从而确保系统状态的一致性。目前,只有注册表提供程序支持事务。
1.1 安全地进行事务实验
如果你想尝试 PowerShell 的事务支持,但又不想以注册表提供程序为实验对象,可以使用
System.Management.Automation.TransactedString
对象和
Use-Transaction
cmdlet 对字符串进行实验。
操作步骤如下:
1. 启动事务:
PS > Start-Transaction
-
创建
TransactedString对象并追加内容:
PS > $transactedString = New-Object Microsoft.PowerShell.Commands.Management.TransactedString
PS > $transactedString.Append("Hello ")
-
使用
Use-Transaction追加更多内容:
PS > Use-Transaction -UseTransaction { $transactedString.Append("World") }
- 查看当前字符串内容:
PS > $transactedString.ToString()
Hello
- 完成事务:
PS > Complete-Transaction
- 再次查看字符串内容:
PS > $transactedString.ToString()
Hello World
PowerShell 的事务支持基于四个核心 cmdlet:
Start-Transaction
、
Use-Transaction
、
Complete-Transaction
和
Undo-Transaction
。
-
Start-Transaction
:开始一个事务,创建一个上下文,在该上下文中,事务内的命令可以看到更改,但外部看不到。
-
Use-Transaction
:用于对支持事务的 .NET 对象进行脚本编写。
-
Complete-Transaction
:使事务生效。
-
Undo-Transaction
:放弃事务中的更改。
以下是一个使用
Undo-Transaction
的示例:
PS > Start-Transaction
PS > $transactedString = New-Object Microsoft.PowerShell.Commands.Management.TransactedString
PS > $transactedString.Append("Hello ")
PS > Use-Transaction -UseTransaction { $transactedString.Append("World") }
PS > $transactedString.ToString()
Hello
PS > Undo-Transaction
PS > $transactedString.ToString()
Hello
1.2 更改事务中的错误恢复行为
你可以使用
Start-Transaction
cmdlet 的
-RollbackPreference
参数来控制哪种类型的错误会导致 PowerShell 自动撤销你的事务。
操作步骤如下:
1. 启动事务并创建一个新项:
HKCU:\ >Start-Transaction
HKCU:\ >New-Item Foo -UseTransaction
- 尝试复制一个不存在的项:
HKCU:\ >Copy IDoNotExist Foo -UseTransaction
Copy-Item : Cannot find path 'HKCU:\IDoNotExist' because it does not exist.
- 尝试完成事务:
HKCU:\ >Complete-Transaction
Complete-Transaction : Cannot commit transaction. The transaction has been rolled back or has timed out.
-
启动一个新事务,并设置
RollbackPreference为TerminatingError:
HKCU:\ >Start-Transaction -RollbackPreference TerminatingError
HKCU:\ >Copy IDoNotExist Foo -UseTransaction
Copy-Item : Cannot find path 'HKCU:\IDoNotExist' because it does not exist.
HKCU:\ >Complete-Transaction
HKCU:\ >Get-Item Foo
-RollbackPreference
参数有以下三个可选值:
| 值 | 说明 |
| ---- | ---- |
| Error | 任何错误发生时,PowerShell 都会回滚你的事务。 |
| TerminatingError | 只有当发生终止错误时,PowerShell 才会回滚你的事务。 |
| Never | PowerShell 永远不会自动回滚你的事务以响应错误。 |
2. PowerShell 事件处理
系统管理的很多工作是反应式的,例如在系统服务关闭、文件创建或删除、Windows 注册表更改时采取行动。PowerShell 提供了一组一致的事件相关 cmdlet,让你可以处理各种不同的事件源。
2.1 响应自动生成的事件
你可以使用
Register-ObjectEvent
、
Register-CimIndicationEvent
和
Register-EngineEvent
cmdlets 的
-Action
参数,在事件到达时得到通知,并让 PowerShell 调用你提供的脚本块。
操作步骤如下:
1. 创建一个定时器对象:
PS > $timer = New-Object Timers.Timer
PS > $timer.Interval = 1000
- 注册事件:
PS > Register-ObjectEvent $timer Elapsed -SourceIdentifier Timer.Elapsed -Action { $GLOBAL:lastRandom = Get-Random }
- 启用定时器:
PS > $timer.Enabled = $true
- 查看随机数:
PS > $lastRandom
836077209
PS > $lastRandom
2030675971
PS > $lastRandom
1617766254
- 注销事件:
PS > Unregister-Event Timer.Elapsed
在
-Action
脚本块中,PowerShell 提供了五个自动变量:
-
eventSubscriber
:生成此事件的订阅者(事件注册)。
-
event
:事件本身的详细信息,如
MessageData
、
TimeGenerated
等。
-
args
:事件处理程序的参数。
-
sender
:触发事件的对象(如果有)。
-
eventArgs
:事件定义的自定义事件信息(如果有)。
你还可以在事件注册时使用
-MessageData
参数提供任何对象,PowerShell 会将此数据与该事件注册生成的任何事件通知关联起来。
为了防止脚本块意外破坏它中断的脚本的状态,PowerShell 将其置于一个非常隔离的环境中。你可以使用
Receive-Job
cmdlet 检索事件操作生成的任何输出。
graph TD;
A[创建定时器对象] --> B[注册事件];
B --> C[启用定时器];
C --> D[查看随机数];
D --> E[注销事件];
2.2 创建和响应自定义事件
你可以使用
New-Event
cmdlet 创建自定义事件,并使用
Register-EngineEvent
cmdlet 的
-Action
参数自动响应这些事件。
操作步骤如下:
1. 注册事件:
PS > Register-EngineEvent -SourceIdentifier Custom.Event -Action { Write-Host "Received Event" }
- 生成自定义事件:
PS > $null = New-Event Custom.Event
Received Event
New-Event
cmdlet 的一个主要用途是适应通过通用 WMI 和 .NET 事件 cmdlet 公开的复杂事件。你可以使用
Register-ObjectEvent
或
Register-CimIndicationEvent
cmdlets 注册事件,并在
-Action
脚本块中使用
New-Event
cmdlet 生成更专业的事件。
以下是一个示例,用于在新进程启动时通知你:
## Enable process creation events
function Enable-ProcessCreationEvent
{
$identifier = "WMI.ProcessCreated"
$query = "SELECT * FROM __instancecreationevent " +
"WITHIN 5 " +
"WHERE targetinstance isa 'win32_process'"
Register-CimIndicationEvent -Query $query -SourceIdentifier $identifier `
-SupportEvent -Action {
[void] (New-Event "PowerShell.ProcessCreated" `
-Sender $sender `
-EventArguments $EventArgs.NewEvent.TargetInstance)
}
}
## Disable process creation events
function Disable-ProcessCreationEvent
{
Unregister-Event -Force -SourceIdentifier "WMI.ProcessCreated"
}
使用示例:
PS > Enable-ProcessCreationEvent
PS > calc
PS > Get-Event
PS > Disable-ProcessCreationEvent
2.3 创建临时事件订阅
你可以使用事件注册命令的
-MaxTriggerCount
参数将 PowerShell 限制为事件的一次发生。
操作步骤如下:
1. 创建定时器对象:
PS > $timer = New-Object Timers.Timer
- 注册事件并设置最大触发次数为 1:
PS > $job = Register-ObjectEvent $timer Disposed -Action { [Console]::Beep(100,100) } -MaxTriggerCount 1
- 查看事件订阅者:
PS > Get-EventSubscriber
- 处置定时器:
PS > $timer.Dispose()
- 再次查看事件订阅者:
PS > Get-EventSubscriber
- 删除作业:
PS > Remove-Job $job
2.4 从远程计算机转发事件
如果你通过 PowerShell Remoting 连接到远程计算机,并且希望在该计算机上发生事件时得到通知,可以使用 PowerShell 的事件注册 cmdlets 订阅事件,并使用
-Forward
参数告诉 PowerShell 在事件到达时转发这些事件。
操作步骤如下:
1. 查看本地事件:
PS > Get-Event
- 创建远程会话:
PS > $session = New-PSSession leeholmes1c23
- 进入远程会话:
PS > Enter-PSSession $session
- 在远程会话中创建定时器对象并注册事件:
[leeholmes1c23]: PS C:\> $timer = New-Object Timers.Timer
[leeholmes1c23]: PS C:\> $timer.Interval = 1000
[leeholmes1c23]: PS C:\> $timer.AutoReset = $false
[leeholmes1c23]: PS C:\> Register-ObjectEvent $timer Elapsed -SourceIdentifier Timer.Elapsed -Forward
[leeholmes1c23]: PS C:\> $timer.Enabled = $true
- 退出远程会话:
[leeholmes1c23]: PS C:\> Exit-PSSession
- 查看本地事件:
PS > Get-Event
通过以上内容,你可以深入了解 PowerShell 的事务处理和事件处理功能,并根据实际需求进行操作。
PowerShell 事务与事件处理全解析(续)
2. PowerShell 事件处理(续)
2.4 从远程计算机转发事件(补充说明)
在从远程计算机转发事件的过程中,我们需要注意一些细节。当使用
-Forward
参数时,PowerShell 会将远程事件封装在
ForwardedEventArgs
对象中,这样我们可以在本地获取到这些事件信息。
下面是一个更详细的流程说明:
1.
本地环境准备
:在本地 PowerShell 环境中,首先查看当前的事件列表,确认没有相关事件。
PS > Get-Event
-
建立远程会话
:使用
New-PSSession命令创建一个到远程计算机的会话,这里以leeholmes1c23为例。
PS > $session = New-PSSession leeholmes1c23
-
进入远程会话
:使用
Enter-PSSession进入到远程计算机的 PowerShell 环境。
PS > Enter-PSSession $session
-
远程事件注册
:在远程会话中,创建一个定时器对象,并设置其属性,然后注册事件并使用
-Forward参数。
[leeholmes1c23]: PS C:\> $timer = New-Object Timers.Timer
[leeholmes1c23]: PS C:\> $timer.Interval = 1000
[leeholmes1c23]: PS C:\> $timer.AutoReset = $false
[leeholmes1c23]: PS C:\> Register-ObjectEvent $timer Elapsed -SourceIdentifier Timer.Elapsed -Forward
[leeholmes1c23]: PS C:\> $timer.Enabled = $true
-
退出远程会话
:完成事件注册后,使用
Exit-PSSession退出远程会话。
[leeholmes1c23]: PS C:\> Exit-PSSession
- 查看本地事件 :回到本地环境后,再次查看事件列表,此时应该能看到从远程转发过来的事件。
PS > Get-Event
这个过程可以用以下 mermaid 流程图表示:
graph LR;
A[本地查看事件] --> B[创建远程会话];
B --> C[进入远程会话];
C --> D[远程创建定时器并注册事件];
D --> E[退出远程会话];
E --> F[本地查看事件];
2.5 事件处理的综合应用
在实际的系统管理中,我们可能会综合运用上述的事件处理方法来实现复杂的功能。例如,我们可以结合自定义事件和远程事件转发,实现一个分布式系统中的事件监控和响应机制。
以下是一个简单的示例,假设我们有多个远程服务器,我们希望在其中任何一个服务器上有新进程启动时,在本地进行相应的处理。
首先,在每个远程服务器上定义一个函数来启用进程创建事件的监控:
## Enable process creation events
function Enable-ProcessCreationEvent
{
$identifier = "WMI.ProcessCreated"
$query = "SELECT * FROM __instancecreationevent " +
"WITHIN 5 " +
"WHERE targetinstance isa 'win32_process'"
Register-CimIndicationEvent -Query $query -SourceIdentifier $identifier `
-SupportEvent -Action {
[void] (New-Event "PowerShell.ProcessCreated" `
-Sender $sender `
-EventArguments $EventArgs.NewEvent.TargetInstance)
}
}
然后,在本地创建到多个远程服务器的会话,并在每个会话中启用进程创建事件监控,同时使用
-Forward
参数将事件转发到本地:
# 定义远程服务器列表
$servers = @("server1", "server2", "server3")
foreach ($server in $servers) {
$session = New-PSSession $server
Invoke-Command -Session $session -ScriptBlock {
Enable-ProcessCreationEvent
$timer = New-Object Timers.Timer
$timer.Interval = 1000
$timer.AutoReset = $false
Register-ObjectEvent $timer Elapsed -SourceIdentifier Timer.Elapsed -Forward
$timer.Enabled = $true
}
}
最后,在本地注册一个事件处理脚本块,当接收到远程转发过来的进程创建事件时,进行相应的处理:
Register-EngineEvent -SourceIdentifier PowerShell.ProcessCreated -Action {
Write-Host "New process created on remote server: $($EventArgs.NewEvent.TargetInstance.Name)"
}
通过这种方式,我们可以实现一个分布式系统中的事件监控和响应机制,提高系统管理的效率和自动化程度。
3. 总结
PowerShell 的事务处理和事件处理功能为系统管理提供了强大的支持。事务处理可以确保一系列操作的原子性,避免因部分操作失败而导致系统状态不一致。而事件处理则可以让我们实时响应系统中的各种变化,实现自动化的系统管理。
在事务处理方面,我们可以通过
Start-Transaction
、
Use-Transaction
、
Complete-Transaction
和
Undo-Transaction
等 cmdlet 来管理事务,同时可以使用
-RollbackPreference
参数来控制事务的错误恢复行为。
在事件处理方面,我们可以使用
Register-ObjectEvent
、
Register-CimIndicationEvent
和
Register-EngineEvent
等 cmdlets 来注册事件,并使用
-Action
参数来自动响应事件。此外,还可以使用
New-Event
来创建自定义事件,以及通过
-MaxTriggerCount
参数创建临时事件订阅,使用
-Forward
参数从远程计算机转发事件。
以下是一个总结表格:
| 功能 | 主要 cmdlet | 关键参数 | 用途 |
| ---- | ---- | ---- | ---- |
| 事务处理 | Start-Transaction、Use-Transaction、Complete-Transaction、Undo-Transaction | -RollbackPreference | 确保操作的原子性,控制错误恢复行为 |
| 事件处理 | Register-ObjectEvent、Register-CimIndicationEvent、Register-EngineEvent | -Action、-MessageData、-MaxTriggerCount、-Forward | 响应自动生成的事件、创建自定义事件、创建临时事件订阅、转发远程事件 |
通过深入学习和掌握这些功能,我们可以更好地利用 PowerShell 进行系统管理和自动化操作,提高工作效率和系统的稳定性。
超级会员免费看
56

被折叠的 条评论
为什么被折叠?



