
示例工程【免費下載鏈接】Windows-classic-samplesThis repo contains samples that demonstrate the API used in Windows classic desktop applications.項目地址https://gitcode.com/gh_mirrors/wi/Windows-classic-samples點擊查看免費下載本篇文章基于 Windows-classic-samples 倉庫中的 ActivityControllerExtensibility 樣例系統(tǒng)講解如何通過自定義PSActivityHostController擴展 Windows PowerShell Workflow 的活動控制器Activity Controller。該樣例以 RunspacePool 隊列化queuing的方式將工作流中的 PowerShell 活動調度到本地 WinRM 自定義工作流端點執(zhí)行并完整附帶端點搭建腳本。閱讀本文后你將掌握活動控制器的擴展點CreatePSActivityHostController、StartResumablePSCommand、ResumeBookmark等、自定義工作流端點的注冊方法以及該機制在真實代碼中的完整調用鏈。樣例概覽它要解決什么問題Windows PowerShell WorkflowWindows 8.1 / Windows Server 2012 R2 引入允許把 PowerShell 命令包裝為工作流中的活動Activity。默認情況下活動可以進程內直接執(zhí)行但對于某些活動宿主希望把執(zhí)行調度出去——例如放到另一臺機器、放到某個專用的 WinRM 端點或自行控制并發(fā)排隊策略。此時就需要擴展活動控制器。本樣例源碼位于 Samples/PowerShellWorkflow/ActivityControllerExtensibility/cs演示了兩件事如何擴展 Windows PowerShell Workflow 的活動控制器通過繼承PSResumableActivityHostController提供自定義執(zhí)行邏輯并把活動命令放入ConcurrentDictionary隊列由線程池線程在自定義 WinRM 工作流端點上執(zhí)行如何創(chuàng)建自定義工作流端點通過隨附的CustomWorkflowEndpointSetup.ps1腳本用Register-PSSessionConfiguration -SessionType Workflow注冊一個本地 WinRM 工作流端點。整體架構與執(zhí)行鏈路從源碼結構看整個樣例由 5 個文件構成一個閉環(huán)文件作用SampleConfigurationProvider.cs配置宿主運行時注入自定義活動控制器并聲明進程外活動清單SampleActivityController.cs核心擴展實現(xiàn)隊列化請求、在線程池執(zhí)行命令、恢復 BookmarkProgram.cs宿主程序加載 XAML 工作流、創(chuàng)建PSWorkflowJob、訂閱狀態(tài)事件并等待完成SampleWorkflow.xamlXAML 工作流定義含一個GetCommand活動CustomWorkflowEndpointSetup.ps1注冊自定義 WinRM 工作流端點的 PowerShell 腳本執(zhí)行鏈路可以概括為Program.cs 加載 XAML └─ new PSWorkflowRuntime(new SampleConfigurationProvider()) └─ CreatePSActivityHostController() 返回 SampleActivityController └─ JobManager.CreateJob(...) 創(chuàng)建 PSWorkflowJob 并 StartJob └─ 工作流運行到 GetCommand 活動 └─ StartResumablePSCommand() 將命令入隊 └─ ThreadPool 線程 ServiceRequests → PerformWork └─ 在自定義端點 RunspacePool 上 Invoke └─ job.ResumeBookmark(...) 恢復工作流 └─ Program 收到 Completed/Failed 事件下面依次剖析每一環(huán)的源碼實現(xiàn)。注入自定義控制器SampleConfigurationProviderSampleConfigurationProvider.cs 繼承自Microsoft.PowerShell.Workflow.PSWorkflowConfigurationProvider負責定義整個PSWorkflowRuntime的配置。它重寫了兩個關鍵成員public override Microsoft.PowerShell.Activities.PSActivityHostController CreatePSActivityHostController() { return new SampleActivityController(Runtime); }CreatePSActivityHostController()是擴展活動控制器的唯一入口運行時在此處決定使用默認控制器還是自定義控制器返回SampleActivityController實例構造函數(shù)接收PSWorkflowRuntime以便后續(xù)恢復 Job。public override IEnumerablestring OutOfProcessActivity { get { yield return GetProcess; } }OutOfProcessActivity屬性聲明了哪些活動屬于進程外活動。源碼注釋明確說明只有進程外活動才會觸發(fā)活動控制器調用進程內活動不需要活動控制器。這里將GetProcess列入進程外清單——這意味著任何名為GetProcess的活動都會經(jīng)由自定義控制器調度執(zhí)行本例中 XAML 工作流實際使用GetCommand活動但其輸出流與執(zhí)行機制同理。若要擴展更多活動只需繼續(xù)yield return其他活動名稱即可。核心擴展實現(xiàn)SampleActivityControllerSampleActivityController.cs 繼承PSResumableActivityHostController是整個樣例的精華所在。它實現(xiàn)了先入隊、后執(zhí)行、再恢復的異步調度模型。支持斷開式流SupportDisconnectedPSStreamspublic override bool SupportDisconnectedPSStreams { get { return true; } }該屬性通知工作流運行時關于流的使用方式如果不需要保持 Job 的實時流則應返回true當支持斷開式流時活動甚至可以在另一臺計算機上執(zhí)行Job 完成后數(shù)據(jù)再回傳到實時流。請求入隊StartResumablePSCommandpublic override void StartResumablePSCommand(Guid jobInstanceId, Bookmark bookmark, PowerShell command, PowerShellStreamsPSObject, PSObject streams, PSActivityEnvironment environment, PSActivity activityInstance)這是活動執(zhí)行時被回調的入口方法。注釋給出了重要的設計約束強烈建議不要在函數(shù)內阻塞式執(zhí)行活動應把全部信息記入隊列后立即返回讓工作流并行做其他事由獨立線程或另一臺機器從隊列取出數(shù)據(jù)執(zhí)行活動活動完成后恢復 Bookmark。實現(xiàn)方式是把調用參數(shù)打包成內部類ActivityActionData以jobInstanceId為鍵放入ConcurrentDictionaryGuid, ActivityActionData ActivityActionsQueue該類使用并發(fā)字典注釋指出字典嵌套字典可用于處理多個并行 Job隨后用ThreadPool.QueueUserWorkItem(ServiceRequests, jobInstanceId)安排一個線程池線程消費ActivityActionData data new ActivityActionData(); data.jobInstanceId jobInstanceId; data.bookmark bookmark; data.command command; data.streams streams; data.environment environment; ActivityActionsQueue.TryAdd(jobInstanceId, data); ThreadPool.QueueUserWorkItem(ServiceRequests, jobInstanceId);隊列消費與真實執(zhí)行ServiceRequests / PerformWork線程池線程執(zhí)行ServiceRequests從隊列中TryRemove出ActivityActionData然后調用PerformWork真正干活private void PerformWork(ActivityActionData data) { // 1) 把 PowerShell 命令的輸出流綁定到工作流提供的流 data.command.Streams.Debug data.streams.DebugStream; data.command.Streams.Error data.streams.ErrorStream; data.command.Streams.Progress data.streams.ProgressStream; data.command.Streams.Verbose data.streams.VerboseStream; data.command.Streams.Warning data.streams.WarningStream; // 2) 連接自定義 WinRM 工作流端點 WSManConnectionInfo connectionInfo new WSManConnectionInfo(); connectionInfo.ShellUri http://schemas.microsoft.com/powershell/CustomeWorkflowEndpoint; // 3) 在自定義端點上創(chuàng)建 RunspacePool 并執(zhí)行 using (RunspacePool r RunspaceFactory.CreateRunspacePool(1, 1, connectionInfo)) { r.Open(); data.command.RunspacePool r; data.command.Invoke(data.streams.InputStream, data.streams.OutputStream, new PSInvocationSettings()); r.Close(); r.Dispose(); } }幾個值得注意的細節(jié)流綁定Debug/Error/Progress/Verbose/Warning五類流被顯式重定向到工作流提供的流對象保證活動輸出能回流到 Job 的實時流中。端點尋址ShellUri必須與CustomWorkflowEndpointSetup.ps1注冊的端點名完全一致包括其中CustomeWorkflowEndpoint的拼寫——這是腳本與代碼約定好的端點名不可更改否則連接會失敗。RunspacePool 參數(shù)CreateRunspacePool(1, 1, connectionInfo)表示最小/最大運行空間數(shù)均為 1即單實例串行執(zhí)行這也是RunspacePool-based queuing的體現(xiàn)——隊列在此排隊等待唯一可用的運行空間?;謴蛨?zhí)行ResumeBookmark活動執(zhí)行完成后必須恢復工作流否則工作流會一直掛起。PerformWork的收尾邏輯是PSWorkflowJob job _runtime.JobManager.GetJob(data.jobInstanceId); if (failed) job.ResumeBookmark(data.bookmark, this.SupportDisconnectedPSStreams, data.streams, exception); else job.ResumeBookmark(data.bookmark, this.SupportDisconnectedPSStreams, data.streams);由于執(zhí)行發(fā)生在后臺線程任何異常都必須被捕獲并隨ResumeBookmark傳入讓工作流以失敗狀態(tài)恢復而不是讓異常逃逸出線程池。成功路徑則把bookmark、SupportDisconnectedPSStreams和streams回傳給運行時工作流從 Bookmark 處繼續(xù)執(zhí)行。停止命令StopAllResumablePSCommandspublic override void StopAllResumablePSCommands(Guid jobInstanceId) { this.StopExecution(jobInstanceId); }該方法是 Job 停止時清理執(zhí)行中命令的擴展點。樣例中的StopExecution僅為骨架注釋說明可通過持有ActivityActionData引用并調用 command 對象的Stop()來實現(xiàn)實際產(chǎn)品化時可在此補充強制終止邏輯。宿主程序Program.cs 的運行編排Program.cs 演示了宿主如何使用自定義配置運行工作流 Job流程如下// 1) 讀取 XAML 工作流定義 string xaml File.ReadAllText(SampleWorkflow.xaml); // 2) 以自定義配置提供器創(chuàng)建運行時 PSWorkflowRuntime runtime new PSWorkflowRuntime(new SampleConfigurationProvider()); // 3) 創(chuàng)建 Job工作流參數(shù)可放入字典 Dictionarystring, object parameters new Dictionarystring, object(); PSWorkflowJob job runtime.JobManager.CreateJob( Guid.NewGuid(), xaml, Get-CurrentProcess, SampleWorkflow, parameters); // 4) 啟動前訂閱狀態(tài)事件 AutoResetEvent wfEvent new AutoResetEvent(false); job.StateChanged delegate(object sender, JobStateEventArgs e) { switch (e.JobStateInfo.State) { case JobState.Failed: case JobState.Completed: wfEvent.Set(); break; } }; // 5) 啟動并等待 job.StartJob(); wfEvent.WaitOne(); if (job.JobStateInfo.State JobState.Completed) { Console.WriteLine(The job has completed successfully.); Console.WriteLine(Total Commands found: job.PSWorkflowInstance.Streams.OutputStream.Count); } else Console.WriteLine(The job has Failed.);要點說明CreateJob的參數(shù)依次為 Job 實例 ID、XAML 定義、Job 名稱Get-CurrentProcess、工作流名稱SampleWorkflow和參數(shù)字典。源碼注釋指出由于這里使用默認的基于文件的存儲file-based store因此必須顯式提供 XAML 工作流定義。StateChanged事件只關心Failed與Completed兩個終態(tài)用AutoResetEvent做同步等待避免主線程忙等。Job 完成后通過job.PSWorkflowInstance.Streams.OutputStream.Count讀取輸出流中累積的對象數(shù)量即工作流輸出的命令條目數(shù)這就是活動流被正確回傳的直接證據(jù)。工作流定義SampleWorkflow.xamlSampleWorkflow.xaml 是一個最小的 XAML 工作流Sequence中包含一個來自Microsoft.PowerShell.Core.Activities的GetCommand活動并為其Module參數(shù)指定了PSDiagnosticsSequence ... ns3:GetCommand DisplayNameGet-Command ... ns3:GetCommand.Module ns2:InArgument x:TypeArgumentss:String[] mpa:PowerShellValue x:TypeArgumentss:String[] ExpressionPSDiagnostics/ /ns2:InArgument /ns3:GetCommand.Module /ns3:GetCommand /Sequence在項目文件 ActivityControllerExtensibilitySample.csproj 中該 XAML 被聲明為XamlAppDef且CopyToOutputDirectoryAlways因此編譯后會隨 exe 一起出現(xiàn)在輸出目錄運行時File.ReadAllText(SampleWorkflow.xaml)才能正確加載。搭建自定義工作流端點CustomWorkflowEndpointSetup.ps1這是整個方案的基礎設施部分腳本完整內容位于 CustomWorkflowEndpointSetup.ps1只有 5 步卻環(huán)環(huán)相扣# 1) 確保 WinRM 已配置并啟動 winrm quickconfig -quiet restart-service winrm # 2) 創(chuàng)建工作流會話選項限制最大并發(fā)工作流數(shù)為 35 $wfExecuteOption New-PSWorkflowExecutionOption -MaxRunningWorkflows 35 # 3) 注冊自定義工作流端點 Register-PSSessionConfiguration -Name CustomeWorkflowEndpoint -SessionType Workflow -SessionTypeOption $wfExecuteOption -Force # 4) 驗證端點創(chuàng)建會話并運行一個測試工作流 $wfEP New-PSSession -ConfigurationName CustomeWorkflowEndpoint icm $wfEP {workflow TestWorkflow {get-process}} icm $wfEP {TestWorkflow} Remove-PSSession $wfEP對每一步的說明命令作用與參數(shù)說明winrm quickconfig -quiet快速完成 WinRM 服務與監(jiān)聽器配置-quiet表示不交互詢問restart-service winrm重啟 WinRM 服務使配置生效New-PSWorkflowExecutionOption -MaxRunningWorkflows 35創(chuàng)建工作流會話類型選項-MaxRunningWorkflows控制該端點上最多并發(fā)運行的工作流數(shù)量樣例設為 35可按實際負載調整Register-PSSessionConfiguration -Name CustomeWorkflowEndpoint -SessionType Workflow -SessionTypeOption $wfExecuteOption -Force注冊名為CustomeWorkflowEndpoint的會話配置-SessionType Workflow指明這是工作流類型端點非默認的DefaultRemoteShell-Force覆蓋可能存在的同名配置。注意端點名拼寫代碼中WSManConnectionInfo.ShellUri指向http://schemas.microsoft.com/powershell/CustomeWorkflowEndpoint二者必須嚴格一致New-PSSession -ConfigurationName CustomeWorkflowEndpoint用剛注冊的端點創(chuàng)建 PSSession用于連通性驗證icm $wfEP {workflow TestWorkflow {get-process}}在會話內定義并運行測試工作流確認端點可以承載工作流執(zhí)行該腳本必須以管理員權限運行注冊會話配置需要提升權限且需在運行樣例 exe之前完成否則RunspacePool.Open()將因找不到端點而失敗。構建與運行系統(tǒng)要求類別要求客戶端Windows 8.1服務器Windows Server 2012 R2運行時.NET Framework 4.0項目TargetFrameworkVersion為 v4.0、PowerShell 3.0 及以上工作流功能自 PowerShell 3.0 引入項目引用了Microsoft.PowerShell.Activities、Microsoft.PowerShell.Core.Activities、Microsoft.PowerShell.Management.Activities、Microsoft.PowerShell.Workflow.ServiceCore和System.Management.Automation版本均為 3.0.0.0等程序集這些組件隨 Windows 8.1 / Server 2012 R2 自帶無需額外安裝。構建步驟啟動 Visual Studio選擇File Open Project/Solution進入 Samples/PowerShellWorkflow/ActivityControllerExtensibility/cs 目錄雙擊ActivityControllerExtensibilitySample.sln打開解決方案解決方案支持 Debug/Release 兩種配置平臺為 Any CPU按F7或選擇Build Build Solution編譯。構建成功后ActivityControllerExtensibilitySample.exe以及隨輸出的SampleWorkflow.xaml會生成在bin\Debug目錄下。運行步驟以管理員身份啟動 Windows PowerShell切換到 CustomWorkflowEndpointSetup.ps1 所在目錄執(zhí)行該腳本注冊CustomeWorkflowEndpoint自定義工作流端點腳本末尾的測試命令會輸出get-process結果可據(jù)此確認端點可用切換到樣例二進制所在目錄bin\Debug執(zhí)行ActivityControllerExtensibilitySample.exe。程序運行時會加載SampleWorkflow.xaml創(chuàng)建 Job 并啟動工作流內的GetCommand活動請求經(jīng)SampleActivityController排隊后調度到自定義端點的 RunspacePool 上執(zhí)行完成后控制臺輸出The job has completed successfully. Total Commands found: 數(shù)量 Press Enter to continue...Total Commands found即工作流輸出流中累積的對象數(shù)驗證了活動在自定義端點上執(zhí)行、結果流回宿主的完整閉環(huán)。擴展設計的工程要點從本樣例的源碼注釋中可以提煉出擴展活動控制器的幾條關鍵設計原則回調函數(shù)絕不阻塞StartResumablePSCommand應只做入隊等輕量操作后立即返回讓工作流引擎繼續(xù)并行推進其他活動真實執(zhí)行放到獨立線程或獨立機器。隊列驅動解耦用并發(fā)隊列樣例為ConcurrentDictionaryGuid, ActivityActionData在活動請求與執(zhí)行者之間解耦鍵用jobInstanceId天然支持多 Job 并發(fā)注釋提示字典嵌套字典可擴展到同 Job 多活動并行。Bookmark 是恢復錨點活動完成后必須調用ResumeBookmark恢復工作流掛起點異常必須隨ResumeBookmark上報使 Job 進入失敗態(tài)而非懸掛。流必須顯式接線Debug/Error/Progress/Verbose/Warning流的接線決定活動輸出能否回傳SupportDisconnectedPSStreams返回true意味著 Job 可斷開、活動可異地執(zhí)行。端點與代碼強約定自定義端點名出現(xiàn)在腳本注冊命令與WSManConnectionInfo.ShellUri兩處任何一處改名都會導致運行失敗——這是把執(zhí)行調度到 WinRM 端點時必須牢記的一致性約束。小結ActivityControllerExtensibility 樣例用約 200 行 C# 代碼完整展示了 Windows PowerShell Workflow 活動控制器擴展的完整范式配置提供器注入自定義控制器、OutOfProcessActivity聲明進程外活動、控制器內入隊 → 線程池執(zhí)行 → ResumeBookmark 恢復的三段式調度以及用Register-PSSessionConfiguration -SessionType Workflow搭建自定義工作流端點。這套機制是實現(xiàn)工作流活動異地執(zhí)行、并發(fā)限流與自定義調度策略的參考藍本適合需要深度定制 PowerShell 工作流執(zhí)行引擎的開發(fā)者研讀。若需了解倉庫內更多工作流相關樣例可繼續(xù)查閱 Samples/PowerShellWorkflow 目錄下的其他子項目。贊分享示例工程【免費下載鏈接】Windows-classic-samplesThis repo contains samples that demonstrate the API used in Windows classic desktop applications.項目地址https://gitcode.com/gh_mirrors/wi/Windows-classic-samples點擊查看免費下載相關推薦使用 Windows PowerShell Activity Generation API 生成 Workflow 活動源碼并編譯為 DLLActivityGenerator 示例深度解析使用 Windows PowerShell Activity Generation API 生成 Workflow 活動源碼并編譯為 DLLActivityG示例工程Windows-classic-samples 實戰(zhàn)用 PowerShell Workflow 自定義活動Activity接收腳本塊參數(shù)——ContainerActivity 示例深度解析Windows classic samples 實戰(zhàn)用 PowerShell Workflow 自定義活動Activity接收腳本塊參數(shù)——Contain示例工程Windows PowerShell Debugger API 實戰(zhàn)基于 Windows-classic-samples 構建 Workflow 調試器示例Windows PowerShell Debugger API 實戰(zhàn)基于 Windows classic samples 構建 Workflow 調試器示例示例工程上一篇python-sdk 服務端資源Resources實戰(zhàn)指南從 URI 到模板與多類型返回下一篇Atlas OS中Xbox Game Pass登錄問題的深度解析與解決方案創(chuàng)作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考