59、PowerShell 事务与事件处理全解析

PowerShell 事务与事件处理全解析

1. PowerShell 事务处理

在 PowerShell 中,事务处理是一项强大的功能,它允许你将一系列操作组合在一起,要么全部成功执行,要么全部不执行,从而确保系统状态的一致性。目前,只有注册表提供程序支持事务。

1.1 安全地进行事务实验

如果你想尝试 PowerShell 的事务支持,但又不想以注册表提供程序为实验对象,可以使用 System.Management.Automation.TransactedString 对象和 Use-Transaction cmdlet 对字符串进行实验。

操作步骤如下:
1. 启动事务:

PS > Start-Transaction
  1. 创建 TransactedString 对象并追加内容:
PS > $transactedString = New-Object Microsoft.PowerShell.Commands.Management.TransactedString
PS > $transactedString.Append("Hello ")
  1. 使用 Use-Transaction 追加更多内容:
PS > Use-Transaction -UseTransaction { $transactedString.Append("World") }
  1. 查看当前字符串内容:
PS > $transactedString.ToString()
Hello
  1. 完成事务:
PS > Complete-Transaction
  1. 再次查看字符串内容:
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
  1. 尝试复制一个不存在的项:
HKCU:\ >Copy IDoNotExist Foo -UseTransaction
Copy-Item : Cannot find path 'HKCU:\IDoNotExist' because it does not exist.
  1. 尝试完成事务:
HKCU:\ >Complete-Transaction
Complete-Transaction : Cannot commit transaction. The transaction has been rolled back or has timed out.
  1. 启动一个新事务,并设置 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
  1. 注册事件:
PS > Register-ObjectEvent $timer Elapsed -SourceIdentifier Timer.Elapsed -Action { $GLOBAL:lastRandom = Get-Random }
  1. 启用定时器:
PS > $timer.Enabled = $true
  1. 查看随机数:
PS > $lastRandom
836077209
PS > $lastRandom
2030675971
PS > $lastRandom
1617766254
  1. 注销事件:
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" }
  1. 生成自定义事件:
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. 注册事件并设置最大触发次数为 1:
PS > $job = Register-ObjectEvent $timer Disposed -Action { [Console]::Beep(100,100) } -MaxTriggerCount 1
  1. 查看事件订阅者:
PS > Get-EventSubscriber
  1. 处置定时器:
PS > $timer.Dispose()
  1. 再次查看事件订阅者:
PS > Get-EventSubscriber
  1. 删除作业:
PS > Remove-Job $job
2.4 从远程计算机转发事件

如果你通过 PowerShell Remoting 连接到远程计算机,并且希望在该计算机上发生事件时得到通知,可以使用 PowerShell 的事件注册 cmdlets 订阅事件,并使用 -Forward 参数告诉 PowerShell 在事件到达时转发这些事件。

操作步骤如下:
1. 查看本地事件:

PS > Get-Event
  1. 创建远程会话:
PS > $session = New-PSSession leeholmes1c23
  1. 进入远程会话:
PS > Enter-PSSession $session
  1. 在远程会话中创建定时器对象并注册事件:
[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
  1. 退出远程会话:
[leeholmes1c23]: PS C:\> Exit-PSSession
  1. 查看本地事件:
PS > Get-Event

通过以上内容,你可以深入了解 PowerShell 的事务处理和事件处理功能,并根据实际需求进行操作。

PowerShell 事务与事件处理全解析(续)

2. PowerShell 事件处理(续)
2.4 从远程计算机转发事件(补充说明)

在从远程计算机转发事件的过程中,我们需要注意一些细节。当使用 -Forward 参数时,PowerShell 会将远程事件封装在 ForwardedEventArgs 对象中,这样我们可以在本地获取到这些事件信息。

下面是一个更详细的流程说明:
1. 本地环境准备 :在本地 PowerShell 环境中,首先查看当前的事件列表,确认没有相关事件。

PS > Get-Event
  1. 建立远程会话 :使用 New-PSSession 命令创建一个到远程计算机的会话,这里以 leeholmes1c23 为例。
PS > $session = New-PSSession leeholmes1c23
  1. 进入远程会话 :使用 Enter-PSSession 进入到远程计算机的 PowerShell 环境。
PS > Enter-PSSession $session
  1. 远程事件注册 :在远程会话中,创建一个定时器对象,并设置其属性,然后注册事件并使用 -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
  1. 退出远程会话 :完成事件注册后,使用 Exit-PSSession 退出远程会话。
[leeholmes1c23]: PS C:\> Exit-PSSession
  1. 查看本地事件 :回到本地环境后,再次查看事件列表,此时应该能看到从远程转发过来的事件。
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 进行系统管理和自动化操作,提高工作效率和系统的稳定性。

【2025年10月最新优化算法】混沌增强领导者黏菌算法(Matlab代码实现)内容概要:本文档介绍了2025年10月最新提出的混沌增强领导者黏菌算法(Matlab代码实现),属于智能优化算法领域的一项前沿研究。该算法结合混沌机制黏菌优化算法,通过引入领导者策略提升搜索效率和局寻优能力,适用于复杂工程优化问题的求解。文档不仅提供完整的Matlab实现代码,还涵盖了算法原理、性能验证及其他优化算法的对比分析,体现了较强的科研复现性和应用拓展性。此外,文中列举了大量相关科研方向和技术应用场景,展示其在微电网调度、路径规划、图像处理、信号分析、电力系统优化等多个领域的广泛应用潜力。; 适合人群:具备一定编程基础和优化理论知识,从事科研工作的研究生、博士生及高校教师,尤其是关注智能优化算法及其在工程领域应用的研发人员;熟悉Matlab编程环境者更佳。; 使用场景及目标:①用于解决复杂的连续空间优化问题,如函数优化、参数辨识、工程设计等;②作为新型元启发式算法的学习教学案例;③支持高水平论文复现算法改进创新,推动在微电网、无人机路径规划、电力系统等实际系统中的集成应用; 其他说明:资源包含完整Matlab代码和复现指导,建议结合具体应用场景进行调试拓展,鼓励在此基础上开展算法融合性能优化研究。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值