From 99d32fdefd77696913a2bc53b0100b22b6ba4ff1 Mon Sep 17 00:00:00 2001 From: JohnMcPMS Date: Fri, 1 May 2026 16:56:01 -0700 Subject: [PATCH 1/4] Stream dsc.exe output to diagnostics via time-based batching ProcessExecution already fired OutputLineReceived/ErrorLineReceived events per line as data arrived from the async stream readers, but RunSynchronously() never subscribed to them -- instead dumping all buffered output in one diagnostic message only after the process exited. If dsc.exe hangs, nothing appears in the log until (or unless) the process terminates. Add ProcessOutputBatcher, a thread-safe helper that: - Subscribes to ProcessExecution's stream events - Accumulates [out]/[err]-prefixed lines in a StringBuilder under a lock - Flushes the buffer to IDiagnosticsSink as a single batched message on a 500ms timer, so output appears promptly without one IPC call per line - Exposes Flush() to drain remaining lines after WaitForExit() Wire it into RunSynchronously(): the post-exit diagnostic now logs only the exit code (content has already been streamed). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../DSCv3/Helpers/ProcessOutputBatcher.cs | 117 ++++++++++++++++++ .../DSCv3/Schema_2024_04/DSCv3.cs | 11 +- 2 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 src/Microsoft.Management.Configuration.Processor/DSCv3/Helpers/ProcessOutputBatcher.cs diff --git a/src/Microsoft.Management.Configuration.Processor/DSCv3/Helpers/ProcessOutputBatcher.cs b/src/Microsoft.Management.Configuration.Processor/DSCv3/Helpers/ProcessOutputBatcher.cs new file mode 100644 index 0000000000..f99a685a52 --- /dev/null +++ b/src/Microsoft.Management.Configuration.Processor/DSCv3/Helpers/ProcessOutputBatcher.cs @@ -0,0 +1,117 @@ +// ----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT License. +// +// ----------------------------------------------------------------------------- + +namespace Microsoft.Management.Configuration.Processor.DSCv3.Helpers +{ + using System; + using System.Text; + using System.Threading; + + /// + /// Subscribes to a 's output and error events, + /// accumulates lines in a thread-safe buffer, and forwards them to an + /// as a single batched message on a fixed interval. + /// This avoids one cross-process IPC call per output line while still delivering + /// output promptly even if the process never exits. + /// + internal sealed class ProcessOutputBatcher : IDisposable + { + private const string OutputPrefix = "[out] "; + private const string ErrorPrefix = "[err] "; + private const string BatchHeader = "--- Process Output ---"; + + private readonly IDiagnosticsSink? sink; + private readonly Timer flushTimer; + private readonly object bufferLock = new object(); + private StringBuilder buffer = new StringBuilder(); + private bool disposed = false; + + /// + /// Initializes a new instance of the class. + /// + /// The diagnostics sink to forward batched output to. May be null. + /// How often to flush accumulated output to the sink. + public ProcessOutputBatcher(IDiagnosticsSink? sink, TimeSpan flushInterval) + { + this.sink = sink; + this.flushTimer = new Timer(this.OnTimerTick, null, flushInterval, flushInterval); + } + + /// + /// Subscribes to the given 's output and error events. + /// Must be called before . + /// + /// The process execution to monitor. + public void Subscribe(ProcessExecution processExecution) + { + processExecution.OutputLineReceived += this.OnOutputLineReceived; + processExecution.ErrorLineReceived += this.OnErrorLineReceived; + } + + /// + /// Stops the timer, flushes any remaining buffered lines to the sink, and disposes resources. + /// Call this after returns to ensure all output is delivered. + /// + public void Flush() + { + this.flushTimer.Change(Timeout.Infinite, Timeout.Infinite); + this.EmitBuffer(); + } + + /// + public void Dispose() + { + if (!this.disposed) + { + this.disposed = true; + this.flushTimer.Dispose(); + } + } + + private void OnOutputLineReceived(object? sender, string line) + { + lock (this.bufferLock) + { + this.buffer.AppendLine(OutputPrefix + line); + } + } + + private void OnErrorLineReceived(object? sender, string line) + { + lock (this.bufferLock) + { + this.buffer.AppendLine(ErrorPrefix + line); + } + } + + private void OnTimerTick(object? state) + { + this.EmitBuffer(); + } + + private void EmitBuffer() + { + if (this.sink == null) + { + return; + } + + StringBuilder toEmit; + lock (this.bufferLock) + { + if (this.buffer.Length == 0) + { + return; + } + + toEmit = this.buffer; + this.buffer = new StringBuilder(); + } + + this.sink.OnDiagnostics(DiagnosticLevel.Verbose, BatchHeader + "\n" + toEmit); + } + } +} diff --git a/src/Microsoft.Management.Configuration.Processor/DSCv3/Schema_2024_04/DSCv3.cs b/src/Microsoft.Management.Configuration.Processor/DSCv3/Schema_2024_04/DSCv3.cs index ddd634f426..89d8435ef6 100644 --- a/src/Microsoft.Management.Configuration.Processor/DSCv3/Schema_2024_04/DSCv3.cs +++ b/src/Microsoft.Management.Configuration.Processor/DSCv3/Schema_2024_04/DSCv3.cs @@ -275,9 +275,16 @@ private bool RunSynchronously(ProcessExecution processExecution) { this.processorSettings.DiagnosticsSink?.OnDiagnostics(DiagnosticLevel.Verbose, $"Starting process: {processExecution.CommandLine}{(processExecution.Input == null ? string.Empty : $"\n--- Input Stream ---\n{processExecution.Input}")}"); - processExecution.Start().WaitForExit(); + using (var batcher = new ProcessOutputBatcher(this.processorSettings.DiagnosticsSink, TimeSpan.FromMilliseconds(500))) + { + batcher.Subscribe(processExecution); + + processExecution.Start().WaitForExit(); + + batcher.Flush(); + } - this.processorSettings.DiagnosticsSink?.OnDiagnostics(DiagnosticLevel.Verbose, $"Process exited with code: {processExecution.ExitCode}\n--- Output Stream ---\n{processExecution.GetAllOutputLines()}\n--- Error Stream ---\n{processExecution.GetAllErrorLines()}"); + this.processorSettings.DiagnosticsSink?.OnDiagnostics(DiagnosticLevel.Verbose, $"Process exited with code: {processExecution.ExitCode}"); return processExecution.ExitCode != 0; } From 8e8fc94821117a4a64465ca813f8c624ecd86946 Mon Sep 17 00:00:00 2001 From: JohnMcPMS Date: Fri, 1 May 2026 22:25:32 -0700 Subject: [PATCH 2/4] fixes --- .../DSCv3/Helpers/ProcessExecution.cs | 10 +++++++++- .../DSCv3/Helpers/ProcessOutputBatcher.cs | 17 ++++++++++------- .../DSCv3/Schema_2024_04/DSCv3.cs | 16 ++++++++++------ 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/Microsoft.Management.Configuration.Processor/DSCv3/Helpers/ProcessExecution.cs b/src/Microsoft.Management.Configuration.Processor/DSCv3/Helpers/ProcessExecution.cs index 0ff810f98e..44fec9aaa3 100644 --- a/src/Microsoft.Management.Configuration.Processor/DSCv3/Helpers/ProcessExecution.cs +++ b/src/Microsoft.Management.Configuration.Processor/DSCv3/Helpers/ProcessExecution.cs @@ -18,6 +18,8 @@ namespace Microsoft.Management.Configuration.Processor.DSCv3.Helpers /// internal class ProcessExecution { + private static int nextExecutionNumber = 0; + private List outputLines = new List(); private List errorLines = new List(); @@ -26,6 +28,7 @@ internal class ProcessExecution /// public ProcessExecution() { + this.ExecutionNumber = Interlocked.Increment(ref nextExecutionNumber); } /// @@ -38,6 +41,11 @@ public ProcessExecution() /// public event EventHandler? ErrorLineReceived; + /// + /// Gets the monotonically increasing number assigned to this process execution. + /// + public int ExecutionNumber { get; } + /// /// Gets the executable path. /// @@ -264,7 +272,7 @@ private static string GetAllLines(List lines) foreach (string line in lines) { - stringBuilder.AppendLine(line); + stringBuilder.Append(line).Append('\n'); } return stringBuilder.ToString(); diff --git a/src/Microsoft.Management.Configuration.Processor/DSCv3/Helpers/ProcessOutputBatcher.cs b/src/Microsoft.Management.Configuration.Processor/DSCv3/Helpers/ProcessOutputBatcher.cs index f99a685a52..ecefc47f98 100644 --- a/src/Microsoft.Management.Configuration.Processor/DSCv3/Helpers/ProcessOutputBatcher.cs +++ b/src/Microsoft.Management.Configuration.Processor/DSCv3/Helpers/ProcessOutputBatcher.cs @@ -19,14 +19,13 @@ namespace Microsoft.Management.Configuration.Processor.DSCv3.Helpers /// internal sealed class ProcessOutputBatcher : IDisposable { - private const string OutputPrefix = "[out] "; - private const string ErrorPrefix = "[err] "; - private const string BatchHeader = "--- Process Output ---"; - private readonly IDiagnosticsSink? sink; private readonly Timer flushTimer; private readonly object bufferLock = new object(); private StringBuilder buffer = new StringBuilder(); + private string batchHeader = "--- Process Output ---"; + private string outputPrefix = "[out] "; + private string errorPrefix = "[err] "; private bool disposed = false; /// @@ -47,6 +46,10 @@ public ProcessOutputBatcher(IDiagnosticsSink? sink, TimeSpan flushInterval) /// The process execution to monitor. public void Subscribe(ProcessExecution processExecution) { + int number = processExecution.ExecutionNumber; + this.batchHeader = $"--- [{number}] Process Output ---"; + this.outputPrefix = $"[{number}:out] "; + this.errorPrefix = $"[{number}:err] "; processExecution.OutputLineReceived += this.OnOutputLineReceived; processExecution.ErrorLineReceived += this.OnErrorLineReceived; } @@ -75,7 +78,7 @@ private void OnOutputLineReceived(object? sender, string line) { lock (this.bufferLock) { - this.buffer.AppendLine(OutputPrefix + line); + this.buffer.Append('\n').Append(this.outputPrefix).Append(line); } } @@ -83,7 +86,7 @@ private void OnErrorLineReceived(object? sender, string line) { lock (this.bufferLock) { - this.buffer.AppendLine(ErrorPrefix + line); + this.buffer.Append('\n').Append(this.errorPrefix).Append(line); } } @@ -111,7 +114,7 @@ private void EmitBuffer() this.buffer = new StringBuilder(); } - this.sink.OnDiagnostics(DiagnosticLevel.Verbose, BatchHeader + "\n" + toEmit); + this.sink.OnDiagnostics(DiagnosticLevel.Verbose, this.batchHeader + toEmit); } } } diff --git a/src/Microsoft.Management.Configuration.Processor/DSCv3/Schema_2024_04/DSCv3.cs b/src/Microsoft.Management.Configuration.Processor/DSCv3/Schema_2024_04/DSCv3.cs index 89d8435ef6..cf546b9072 100644 --- a/src/Microsoft.Management.Configuration.Processor/DSCv3/Schema_2024_04/DSCv3.cs +++ b/src/Microsoft.Management.Configuration.Processor/DSCv3/Schema_2024_04/DSCv3.cs @@ -273,15 +273,19 @@ private static List CreateEnvironmentVariab /// True if the exit code was not 0. private bool RunSynchronously(ProcessExecution processExecution) { - this.processorSettings.DiagnosticsSink?.OnDiagnostics(DiagnosticLevel.Verbose, $"Starting process: {processExecution.CommandLine}{(processExecution.Input == null ? string.Empty : $"\n--- Input Stream ---\n{processExecution.Input}")}"); + this.processorSettings.DiagnosticsSink?.OnDiagnostics(DiagnosticLevel.Verbose, $"[{processExecution.ExecutionNumber}] Starting process: {processExecution.CommandLine}{(processExecution.Input == null ? string.Empty : $"\n--- Input Stream ---\n{processExecution.Input}")}"); using (var batcher = new ProcessOutputBatcher(this.processorSettings.DiagnosticsSink, TimeSpan.FromMilliseconds(500))) { - batcher.Subscribe(processExecution); - - processExecution.Start().WaitForExit(); - - batcher.Flush(); + try + { + batcher.Subscribe(processExecution); + processExecution.Start().WaitForExit(); + } + finally + { + batcher.Flush(); + } } this.processorSettings.DiagnosticsSink?.OnDiagnostics(DiagnosticLevel.Verbose, $"Process exited with code: {processExecution.ExitCode}"); From bed8bb880fea0dbf0f116d90667a82c9a946f9e8 Mon Sep 17 00:00:00 2001 From: JohnMcPMS Date: Wed, 6 May 2026 10:50:40 -0700 Subject: [PATCH 3/4] Add export debug command for testing, exporter resource type, and the fix for the hang: default to redirecting input --- .../Commands/DebugCommand.cpp | 188 ++++++++++++++++++ .../Commands/DebugCommand.h | 14 ++ .../DSCv3/Helpers/ProcessExecution.cs | 2 +- .../DSCv3/Model/ResourceKind.cs | 5 + .../Definitions/ResourceKind.cs | 5 + .../Outputs/ResourceListItem.cs | 1 + 6 files changed, 214 insertions(+), 1 deletion(-) diff --git a/src/AppInstallerCLICore/Commands/DebugCommand.cpp b/src/AppInstallerCLICore/Commands/DebugCommand.cpp index 0df85d0f2a..7b17d72893 100644 --- a/src/AppInstallerCLICore/Commands/DebugCommand.cpp +++ b/src/AppInstallerCLICore/Commands/DebugCommand.cpp @@ -4,6 +4,8 @@ #if _DEBUG #include "DebugCommand.h" +#include "Public/ConfigurationSetProcessorFactoryRemoting.h" +#include #include #include #include "AppInstallerDownloader.h" @@ -62,6 +64,7 @@ namespace AppInstaller::CLI std::make_unique(FullName()), std::make_unique(FullName()), std::make_unique(FullName()), + std::make_unique(FullName()), }); } @@ -365,6 +368,191 @@ namespace AppInstaller::CLI context.Reporter.Info() << context.Args.GetArg(WINGET_DEBUG_PROGRESS_POST) << std::endl; } } + +#define WINGET_DEBUG_DSC_RESOURCE_RESOURCE Args::Type::SourceName +#define WINGET_DEBUG_DSC_RESOURCE_EXPORT Args::Type::AllVersions + + std::vector DebugDscResourceCommand::GetArguments() const + { + return { + Argument{ "resource", 'r', WINGET_DEBUG_DSC_RESOURCE_RESOURCE, Resource::String::SourceListUpdatedNever, ArgumentType::Positional }, + Argument{ "export", 'e', WINGET_DEBUG_DSC_RESOURCE_EXPORT, Resource::String::SourceListUpdatedNever, ArgumentType::Flag }, + Argument::ForType(Args::Type::ConfigurationProcessorPath), + }; + } + + Resource::LocString DebugDscResourceCommand::ShortDescription() const + { + return Utility::LocIndString("Run DSCv3 resource actions"sv); + } + + Resource::LocString DebugDscResourceCommand::LongDescription() const + { + return Utility::LocIndString("Directly invokes DSCv3 resource functions through WinGet's infrastructure, without requiring a full configuration document."sv); + } + + void DebugDscResourceCommand::ExecuteInternal(Execution::Context& context) const + { + using namespace winrt::Microsoft::Management::Configuration; + using namespace winrt::Windows::Foundation::Collections; + + if (!context.Args.Contains(WINGET_DEBUG_DSC_RESOURCE_EXPORT)) + { + OutputHelp(context.Reporter); + return; + } + + std::string resourceName{ context.Args.GetArg(WINGET_DEBUG_DSC_RESOURCE_RESOURCE) }; + + context.Reporter.Info() << "Creating OOP DSCv3 processor factory..." << std::endl; + + IConfigurationSetProcessorFactory factory; + if (Runtime::IsRunningWithLimitedToken()) + { + factory = ConfigurationRemoting::CreateDynamicRuntimeFactory(ConfigurationRemoting::ProcessorEngine::DSCv3); + } + else + { + factory = ConfigurationRemoting::CreateOutOfProcessFactory(ConfigurationRemoting::ProcessorEngine::DSCv3); + } + + auto factoryMap = factory.as>(); + + if (context.Args.Contains(Args::Type::ConfigurationProcessorPath)) + { + factoryMap.Insert(ConfigurationRemoting::ToHString(ConfigurationRemoting::PropertyName::DscExecutablePath), Utility::ConvertToUTF16(context.Args.GetArg(Args::Type::ConfigurationProcessorPath))); + } + else + { + // Run the state machine to locate dsc.exe. + for (;;) + { + winrt::hstring nextTransition = factoryMap.Lookup(ConfigurationRemoting::ToHString(ConfigurationRemoting::PropertyName::FindDscStateMachine)); + AICLI_LOG(CLI, Info, << "FindDscStateMachine: " << Utility::ConvertToUTF8(nextTransition)); + + if (nextTransition == L"Found") + { + break; + } + else if (nextTransition == L"NotFound") + { + context.Reporter.Error() << Resource::String::ConfigurationInstallDscPackageFailed << std::endl; + AICLI_TERMINATE_CONTEXT(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); + } + else + { + // InstallStable/InstallPreview etc. are not supported in debug mode; install DSCv3 manually. + context.Reporter.Error() << "DSCv3 unavailable (" << Utility::ConvertToUTF8(nextTransition) << "); use --processor-path or install DSCv3." << std::endl; + AICLI_TERMINATE_CONTEXT(E_NOTIMPL); + } + } + } + + if (Logging::Log().IsEnabled(Logging::Channel::Config, Logging::Level::Verbose)) + { + factoryMap.Insert(ConfigurationRemoting::ToHString(ConfigurationRemoting::PropertyName::DiagnosticTraceEnabled), L"True"); + } + + // Build and configure the processor. + ConfigurationProcessor processor{ factory }; + processor.Caller(L"winget-debug"); + + if (Logging::Log().IsEnabled(Logging::Channel::Config, Logging::Level::Verbose)) + { + processor.MinimumLevel(DiagnosticLevel::Verbose); + } + + processor.Diagnostics([&context](const winrt::Windows::Foundation::IInspectable&, const IDiagnosticInformation& diag) + { + Logging::Level level = Logging::Level::Info; + switch (diag.Level()) + { + case DiagnosticLevel::Verbose: level = Logging::Level::Verbose; break; + case DiagnosticLevel::Informational: level = Logging::Level::Info; break; + case DiagnosticLevel::Warning: level = Logging::Level::Warning; break; + case DiagnosticLevel::Error: level = Logging::Level::Error; break; + case DiagnosticLevel::Critical: level = Logging::Level::Crit; break; + } + context.GetThreadGlobals().GetDiagnosticLogger().Write(Logging::Channel::Config, level, Utility::ConvertToUTF8(diag.Message())); + }); + + // Construct a minimal ConfigurationUnit for the named resource. + ConfigurationUnit unit; + unit.Type(Utility::ConvertToUTF16(resourceName)); + unit.Identifier(L"debug-item"); + unit.Intent(ConfigurationUnitIntent::Inform); + + context.Reporter.Info() << "Exporting resource: " << resourceName << std::endl; + + auto progressScope = context.Reporter.BeginAsyncProgress(true); + progressScope->Callback().SetProgressMessage(Resource::String::ConfigurationExportingUnit()); + + GetAllConfigurationUnitsResult exportResult = nullptr; + { + auto exportAction = processor.GetAllUnitsAsync(unit); + auto cancellationScope = progressScope->Callback().SetCancellationFunction([&]() { exportAction.Cancel(); }); + exportResult = exportAction.get(); + } + + progressScope.reset(); + + HRESULT hr = exportResult.ResultInformation().ResultCode(); + if (FAILED(hr)) + { + auto description = exportResult.ResultInformation().Description(); + context.Reporter.Error() << "Export failed (0x" << Logging::SetHRFormat << hr << "): "; + if (!description.empty()) + { + context.Reporter.Error() << Utility::ConvertToUTF8(description); + } + context.Reporter.Error() << std::endl; + AICLI_TERMINATE_CONTEXT(hr); + } + + auto units = exportResult.Units(); + context.Reporter.Info() << "Exported " << units.Size() << " instance(s):" << std::endl; + + for (const auto& resultUnit : units) + { + context.Reporter.Info() << " Type: " << Utility::ConvertToUTF8(resultUnit.Type()) << std::endl; + context.Reporter.Info() << " Identifier: " << Utility::ConvertToUTF8(resultUnit.Identifier()) << std::endl; + + auto settings = resultUnit.Settings(); + if (settings && settings.Size() > 0) + { + context.Reporter.Info() << " Settings:" << std::endl; + for (const auto& [key, value] : settings) + { + auto prop = value.try_as(); + if (prop) + { + std::string valueStr; + switch (prop.Type()) + { + case winrt::Windows::Foundation::PropertyType::String: + valueStr = Utility::ConvertToUTF8(prop.GetString()); + break; + case winrt::Windows::Foundation::PropertyType::Boolean: + valueStr = prop.GetBoolean() ? "true" : "false"; + break; + case winrt::Windows::Foundation::PropertyType::Int32: + valueStr = std::to_string(prop.GetInt32()); + break; + case winrt::Windows::Foundation::PropertyType::Int64: + valueStr = std::to_string(prop.GetInt64()); + break; + default: + valueStr = "(unsupported type)"; + break; + } + context.Reporter.Info() << " " << Utility::ConvertToUTF8(key) << ": " << valueStr << std::endl; + } + } + } + + context.Reporter.Info() << std::endl; + } + } } #endif diff --git a/src/AppInstallerCLICore/Commands/DebugCommand.h b/src/AppInstallerCLICore/Commands/DebugCommand.h index 5e37520b2d..6b34a91aec 100644 --- a/src/AppInstallerCLICore/Commands/DebugCommand.h +++ b/src/AppInstallerCLICore/Commands/DebugCommand.h @@ -85,6 +85,20 @@ namespace AppInstaller::CLI protected: void ExecuteInternal(Execution::Context& context) const override; }; + + // Directly invokes a DSCv3 resource function through WinGet's infrastructure. + struct DebugDscResourceCommand final : public Command + { + DebugDscResourceCommand(std::string_view parent) : Command("dsc-resource", {}, parent) {} + + std::vector GetArguments() const override; + + Resource::LocString ShortDescription() const override; + Resource::LocString LongDescription() const override; + + protected: + void ExecuteInternal(Execution::Context& context) const override; + }; } #endif diff --git a/src/Microsoft.Management.Configuration.Processor/DSCv3/Helpers/ProcessExecution.cs b/src/Microsoft.Management.Configuration.Processor/DSCv3/Helpers/ProcessExecution.cs index 44fec9aaa3..e3762281a9 100644 --- a/src/Microsoft.Management.Configuration.Processor/DSCv3/Helpers/ProcessExecution.cs +++ b/src/Microsoft.Management.Configuration.Processor/DSCv3/Helpers/ProcessExecution.cs @@ -60,7 +60,7 @@ public ProcessExecution() /// /// Gets the data to write to standard input of the process. /// - public string? Input { get; init; } = null; + public string? Input { get; init; } = string.Empty; /// /// Gets the list of custom environment variables to use for the process. diff --git a/src/Microsoft.Management.Configuration.Processor/DSCv3/Model/ResourceKind.cs b/src/Microsoft.Management.Configuration.Processor/DSCv3/Model/ResourceKind.cs index 1815d476fd..5799441c3a 100644 --- a/src/Microsoft.Management.Configuration.Processor/DSCv3/Model/ResourceKind.cs +++ b/src/Microsoft.Management.Configuration.Processor/DSCv3/Model/ResourceKind.cs @@ -36,5 +36,10 @@ internal enum ResourceKind /// An importer resource. /// Importer, + + /// + /// An exporter resource. + /// + Exporter, } } diff --git a/src/Microsoft.Management.Configuration.Processor/DSCv3/Schema_2024_04/Definitions/ResourceKind.cs b/src/Microsoft.Management.Configuration.Processor/DSCv3/Schema_2024_04/Definitions/ResourceKind.cs index b9176036c1..a845264751 100644 --- a/src/Microsoft.Management.Configuration.Processor/DSCv3/Schema_2024_04/Definitions/ResourceKind.cs +++ b/src/Microsoft.Management.Configuration.Processor/DSCv3/Schema_2024_04/Definitions/ResourceKind.cs @@ -43,5 +43,10 @@ internal enum ResourceKind /// The name used by the code. /// Importer = Import, + + /// + /// An exporter resource. + /// + Exporter, } } diff --git a/src/Microsoft.Management.Configuration.Processor/DSCv3/Schema_2024_04/Outputs/ResourceListItem.cs b/src/Microsoft.Management.Configuration.Processor/DSCv3/Schema_2024_04/Outputs/ResourceListItem.cs index 6c6d4c0d01..03eee84c3f 100644 --- a/src/Microsoft.Management.Configuration.Processor/DSCv3/Schema_2024_04/Outputs/ResourceListItem.cs +++ b/src/Microsoft.Management.Configuration.Processor/DSCv3/Schema_2024_04/Outputs/ResourceListItem.cs @@ -36,6 +36,7 @@ internal class ResourceListItem : IResourceListItem Definitions.ResourceKind.Adapter => Model.ResourceKind.Adapter, Definitions.ResourceKind.Group => Model.ResourceKind.Group, Definitions.ResourceKind.Import => Model.ResourceKind.Importer, + Definitions.ResourceKind.Exporter => Model.ResourceKind.Exporter, _ => throw new System.IO.InvalidDataException($"Unknown ResourceKind: {this.Kind}") }; From 73ab6d9be09c8a0b073f69cc29b0e9dd07f05ac4 Mon Sep 17 00:00:00 2001 From: JohnMcPMS Date: Wed, 6 May 2026 13:54:53 -0700 Subject: [PATCH 4/4] Disable test for a bit --- src/AppInstallerCLIE2ETests/ConfigureExportCommand.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/AppInstallerCLIE2ETests/ConfigureExportCommand.cs b/src/AppInstallerCLIE2ETests/ConfigureExportCommand.cs index cfc30554b8..d9046b64bf 100644 --- a/src/AppInstallerCLIE2ETests/ConfigureExportCommand.cs +++ b/src/AppInstallerCLIE2ETests/ConfigureExportCommand.cs @@ -144,6 +144,7 @@ public void ExportTestPackageWithVersion() /// Export all. /// [Test] + [Ignore("DSC 3.2 design changes ", Until = "2026-05-10")] public void ExportAll() { var exportDir = TestCommon.GetRandomTestDir();