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