diff --git a/src/AppInstallerSharedLib/Public/AppInstallerErrors.h b/src/AppInstallerSharedLib/Public/AppInstallerErrors.h index 43b2e7c095..b161598c9c 100644 --- a/src/AppInstallerSharedLib/Public/AppInstallerErrors.h +++ b/src/AppInstallerSharedLib/Public/AppInstallerErrors.h @@ -172,7 +172,7 @@ #define WINGET_CONFIG_ERROR_UNIT_INVOKE_GET ((HRESULT)0x8A15C104) #define WINGET_CONFIG_ERROR_UNIT_INVOKE_TEST ((HRESULT)0x8A15C105) #define WINGET_CONFIG_ERROR_UNIT_INVOKE_SET ((HRESULT)0x8A15C106) - +#define WINGET_CONFIG_ERROR_UNIT_MODULE_CONFLICT ((HRESULT)0x8A15C107) namespace AppInstaller { diff --git a/src/Microsoft.Management.Configuration.Processor/DscModules/DscModuleV2.cs b/src/Microsoft.Management.Configuration.Processor/DscModules/DscModuleV2.cs index a273fb95eb..3632686efd 100644 --- a/src/Microsoft.Management.Configuration.Processor/DscModules/DscModuleV2.cs +++ b/src/Microsoft.Management.Configuration.Processor/DscModules/DscModuleV2.cs @@ -11,10 +11,8 @@ namespace Microsoft.Management.Configuration.Processor.DscModule using System.Collections.ObjectModel; using System.Linq; using System.Management.Automation; - using System.Management.Automation.Runspaces; using Microsoft.Management.Configuration.Processor.DscResourcesInfo; using Microsoft.Management.Configuration.Processor.Exceptions; - using Microsoft.Management.Configuration.Processor.Extensions; using Microsoft.Management.Configuration.Processor.Helpers; using Microsoft.PowerShell.Commands; using Windows.Foundation.Collections; @@ -54,51 +52,26 @@ public DscModuleV2() public string InvokeDscResourceCmd { get; } = Commands.InvokeDscResource; /// - public IReadOnlyList GetAllDscResources(Runspace runspace) + public IReadOnlyList GetAllDscResources(PowerShell pwsh) { - var result = new List(); - - using PowerShell pwsh = PowerShell.Create(runspace); - var resources = pwsh.AddCommand(this.GetDscResourceCmd) - .InvokeAndStopOnError(); - - return this.ConvertToDscResourceInfoInternal(resources); + return this.GetDscResources(pwsh, null, null); } /// public IReadOnlyList GetDscResourcesInModule( - Runspace runspace, + PowerShell pwsh, ModuleSpecification moduleSpecification) { - var result = new List(); - - using PowerShell pwsh = PowerShell.Create(runspace); - - var resources = pwsh.AddCommand(this.GetDscResourceCmd) - .AddParameter(Parameters.Module, moduleSpecification) - .InvokeAndStopOnError(); - - return this.ConvertToDscResourceInfoInternal(resources); + return this.GetDscResources(pwsh, null, moduleSpecification); } /// public DscResourceInfoInternal? GetDscResource( - Runspace runspace, + PowerShell pwsh, string name, ModuleSpecification? moduleSpecification) { - using PowerShell pwsh = PowerShell.Create(runspace); - pwsh.AddCommand(this.GetDscResourceCmd) - .AddParameter(Parameters.Name, name); - - if (moduleSpecification is not null) - { - pwsh.AddParameter(Parameters.Module, moduleSpecification); - } - - var resources = pwsh.InvokeAndStopOnError(); - - var dscResourceInfos = this.ConvertToDscResourceInfoInternal(resources); + var dscResourceInfos = this.GetDscResources(pwsh, name, moduleSpecification); if (dscResourceInfos.Count == 0) { @@ -114,17 +87,15 @@ public IReadOnlyList GetDscResourcesInModule( /// public ValueSet InvokeGetResource( - Runspace runspace, + PowerShell pwsh, ValueSet settings, string name, ModuleSpecification? moduleSpecification) { - using PowerShell pwsh = PowerShell.Create(runspace); - var getResult = pwsh.AddCommand(this.InvokeDscResourceCmd) .AddParameters(PrepareInvokeParameters(name, settings, moduleSpecification)) .AddParameter(Parameters.Method, DscMethods.Get) - .InvokeAndStopOnError() + .Invoke() .FirstOrDefault(); if (getResult is null) @@ -151,19 +122,17 @@ public ValueSet InvokeGetResource( /// public bool InvokeTestResource( - Runspace runspace, + PowerShell pwsh, ValueSet settings, string name, ModuleSpecification? moduleSpecification) { - using PowerShell pwsh = PowerShell.Create(runspace); - // Returned type is InvokeDscResourceTestResult which is a PowerShell classed defined // in PSDesiredStateConfiguration.psm1. dynamic? testResult = pwsh.AddCommand(this.InvokeDscResourceCmd) .AddParameters(PrepareInvokeParameters(name, settings, moduleSpecification)) .AddParameter(Parameters.Method, DscMethods.Test) - .InvokeAndStopOnError() + .Invoke() .FirstOrDefault(); if (testResult is null || @@ -177,19 +146,17 @@ public bool InvokeTestResource( /// public bool InvokeSetResource( - Runspace runspace, + PowerShell pwsh, ValueSet settings, string name, ModuleSpecification? moduleSpecification) { - using PowerShell pwsh = PowerShell.Create(runspace); - // Returned type is InvokeDscResourceSetResult which is a PowerShell classed defined // in PSDesiredStateConfiguration.psm1. dynamic? setResult = pwsh.AddCommand(this.InvokeDscResourceCmd) .AddParameters(PrepareInvokeParameters(name, settings, moduleSpecification)) .AddParameter(Parameters.Method, DscMethods.Set) - .InvokeAndStopOnError() + .Invoke() .FirstOrDefault(); if (setResult is null || @@ -226,6 +193,40 @@ private static Dictionary PrepareInvokeParameters( return parameters; } + private IReadOnlyList GetDscResources( + PowerShell pwsh, + string? name, + ModuleSpecification? moduleSpecification) + { + pwsh.AddCommand(this.GetDscResourceCmd); + + if (name is not null) + { + pwsh.AddParameter(Parameters.Name, name); + } + + if (moduleSpecification is not null) + { + pwsh.AddParameter(Parameters.Module, moduleSpecification); + } + + try + { + var resources = pwsh.Invoke(); + return this.ConvertToDscResourceInfoInternal(resources); + } + catch (RuntimeException e) + { + // Detect easily this. + if (e.ErrorRecord.FullyQualifiedErrorId == "ExceptionWhenSetting,GetResourceFromKeyword") + { + throw new GetDscResourceModuleConflict(name, moduleSpecification, e); + } + + throw; + } + } + private List ConvertToDscResourceInfoInternal(Collection psObjects) { var result = new List(); diff --git a/src/Microsoft.Management.Configuration.Processor/DscModules/IDscModule.cs b/src/Microsoft.Management.Configuration.Processor/DscModules/IDscModule.cs index 2afc0a79cc..bd1fb6a428 100644 --- a/src/Microsoft.Management.Configuration.Processor/DscModules/IDscModule.cs +++ b/src/Microsoft.Management.Configuration.Processor/DscModules/IDscModule.cs @@ -7,7 +7,7 @@ namespace Microsoft.Management.Configuration.Processor.DscModule { using System.Collections.Generic; - using System.Management.Automation.Runspaces; + using System.Management.Automation; using Microsoft.Management.Configuration.Processor.DscResourcesInfo; using Microsoft.PowerShell.Commands; using Windows.Foundation.Collections; @@ -35,55 +35,55 @@ internal interface IDscModule /// /// Gets all DSC resource. /// - /// PowerShell Runspace. + /// PowerShell. /// A list with the DSC resource. - IReadOnlyList GetAllDscResources(Runspace runspace); + IReadOnlyList GetAllDscResources(PowerShell pwsh); /// /// Gets all resources in a module. /// - /// PowerShell Runspace. + /// PowerShell. /// Module specification. /// List of resources of that module and version. - IReadOnlyList GetDscResourcesInModule(Runspace runspace, ModuleSpecification moduleSpecification); + IReadOnlyList GetDscResourcesInModule(PowerShell pwsh, ModuleSpecification moduleSpecification); /// /// Gets a DSC Resource. /// - /// PowerShell Runspace. + /// PowerShell. /// Name. /// Module specification. /// DSC Resource from that module and version. - DscResourceInfoInternal? GetDscResource(Runspace runspace, string name, ModuleSpecification? moduleSpecification); + DscResourceInfoInternal? GetDscResource(PowerShell pwsh, string name, ModuleSpecification? moduleSpecification); /// /// Calls Invoke-DscResource -Method Get from this module. /// - /// PowerShell Runspace. + /// PowerShell. /// Settings. /// Name. /// Module specification. /// Properties of resource. - ValueSet InvokeGetResource(Runspace runspace, ValueSet settings, string name, ModuleSpecification? moduleSpecification); + ValueSet InvokeGetResource(PowerShell pwsh, ValueSet settings, string name, ModuleSpecification? moduleSpecification); /// /// Calls Invoke-DscResource -Method Test from this module. /// - /// PowerShell Runspace. + /// PowerShell. /// Settings. /// Name. /// Module specification. /// Is in desired state. - bool InvokeTestResource(Runspace runspace, ValueSet settings, string name, ModuleSpecification? moduleSpecification); + bool InvokeTestResource(PowerShell pwsh, ValueSet settings, string name, ModuleSpecification? moduleSpecification); /// /// Calls Invoke-DscResource -Method Set from this module. /// - /// PowerShell Runspace. + /// PowerShell. /// Settings. /// Name. /// Module specification. /// If a reboot is required. - bool InvokeSetResource(Runspace runspace, ValueSet settings, string name, ModuleSpecification? moduleSpecification); + bool InvokeSetResource(PowerShell pwsh, ValueSet settings, string name, ModuleSpecification? moduleSpecification); } } diff --git a/src/Microsoft.Management.Configuration.Processor/Exceptions/ErrorCodes.cs b/src/Microsoft.Management.Configuration.Processor/Exceptions/ErrorCodes.cs index 14a11bd4eb..5a8505ba9e 100644 --- a/src/Microsoft.Management.Configuration.Processor/Exceptions/ErrorCodes.cs +++ b/src/Microsoft.Management.Configuration.Processor/Exceptions/ErrorCodes.cs @@ -40,5 +40,10 @@ internal static class ErrorCodes /// Internal error calling Invoke-DscResource Set. /// internal const int WinGetConfigUnitInvokeSet = unchecked((int)0x8A15C106); + + /// + /// Internal error calling Get-DscResource. More than one module found with the same version. + /// + internal const int WinGetConfigUnitModuleConflict = unchecked((int)0x8A15C107); } } diff --git a/src/Microsoft.Management.Configuration.Processor/Exceptions/GetDscResourceModuleConflict.cs b/src/Microsoft.Management.Configuration.Processor/Exceptions/GetDscResourceModuleConflict.cs new file mode 100644 index 0000000000..dee4ba9a52 --- /dev/null +++ b/src/Microsoft.Management.Configuration.Processor/Exceptions/GetDscResourceModuleConflict.cs @@ -0,0 +1,43 @@ +// ----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT License. +// +// ----------------------------------------------------------------------------- + +namespace Microsoft.Management.Configuration.Processor.Exceptions +{ + using System; + using System.Management.Automation; + using Microsoft.PowerShell.Commands; + + /// + /// A call to Get-DscResource failed because at least two modules with the same version where found in the module path. + /// If you are getting this verify the module path. + /// + internal class GetDscResourceModuleConflict : Exception + { + /// + /// Initializes a new instance of the class. + /// + /// Resource name. + /// Optional module. + /// The original runtime exception thrown. + public GetDscResourceModuleConflict(string? resourceName, ModuleSpecification? module, RuntimeException inner) + : base($"Multiple modules with same version in module path: {resourceName?.ToString() ?? ""} [{module?.ToString() ?? ""}]", inner) + { + this.HResult = ErrorCodes.WinGetConfigUnitModuleConflict; + this.ResourceName = resourceName; + this.Module = module; + } + + /// + /// Gets the resource name. + /// + public string? ResourceName { get; } + + /// + /// Gets the module, if any. + /// + public ModuleSpecification? Module { get; } + } +} diff --git a/src/Microsoft.Management.Configuration.Processor/ProcessorEnvironments/HostedEnvironment.cs b/src/Microsoft.Management.Configuration.Processor/ProcessorEnvironments/HostedEnvironment.cs index e9a9593cc5..15b53891ed 100644 --- a/src/Microsoft.Management.Configuration.Processor/ProcessorEnvironments/HostedEnvironment.cs +++ b/src/Microsoft.Management.Configuration.Processor/ProcessorEnvironments/HostedEnvironment.cs @@ -15,8 +15,6 @@ namespace Microsoft.Management.Configuration.Processor.Runspaces using Microsoft.Management.Configuration.Processor.Constants; using Microsoft.Management.Configuration.Processor.DscModule; using Microsoft.Management.Configuration.Processor.DscResourcesInfo; - using Microsoft.Management.Configuration.Processor.Exceptions; - using Microsoft.Management.Configuration.Processor.Extensions; using Microsoft.Management.Configuration.Processor.Helpers; using Microsoft.Management.Configuration.Processor.ProcessorEnvironments; using Microsoft.PowerShell.Commands; @@ -51,7 +49,12 @@ public HostedEnvironment(Runspace runspace, ConfigurationProcessorType type, IDs /// /// Gets the DscModule. /// - protected IDscModule DscModule { get; } + internal IDscModule DscModule { get; } + + /// + /// Gets or initializes the set processor factory. + /// + internal ConfigurationSetProcessorFactory? SetProcessorFactory { get; init; } /// public void ValidateRunspace() @@ -84,28 +87,58 @@ public void ValidateRunspace() } /// - public IReadOnlyList GetAllDscResources() => - this.DscModule.GetAllDscResources(this.Runspace); + public IReadOnlyList GetAllDscResources() + { + using PowerShell pwsh = PowerShell.Create(this.Runspace); + var results = this.DscModule.GetAllDscResources(pwsh); + this.OnDiagnostics(DiagnosticLevel.Verbose, pwsh); + return results; + } /// - public IReadOnlyList GetDscResourcesInModule(ModuleSpecification moduleSpecification) => - this.DscModule.GetDscResourcesInModule(this.Runspace, moduleSpecification); + public IReadOnlyList GetDscResourcesInModule(ModuleSpecification moduleSpecification) + { + using PowerShell pwsh = PowerShell.Create(this.Runspace); + var results = this.DscModule.GetDscResourcesInModule(pwsh, moduleSpecification); + this.OnDiagnostics(DiagnosticLevel.Verbose, pwsh); + return results; + } /// - public DscResourceInfoInternal? GetDscResource(ConfigurationUnitInternal unitInternal) => - this.DscModule.GetDscResource(this.Runspace, unitInternal.Unit.UnitName, unitInternal.Module); + public DscResourceInfoInternal? GetDscResource(ConfigurationUnitInternal unitInternal) + { + using PowerShell pwsh = PowerShell.Create(this.Runspace); + var result = this.DscModule.GetDscResource(pwsh, unitInternal.Unit.UnitName, unitInternal.Module); + this.OnDiagnostics(DiagnosticLevel.Verbose, pwsh); + return result; + } /// - public ValueSet InvokeGetResource(ValueSet settings, string name, ModuleSpecification? moduleSpecification) => - this.DscModule.InvokeGetResource(this.Runspace, settings, name, moduleSpecification); + public ValueSet InvokeGetResource(ValueSet settings, string name, ModuleSpecification? moduleSpecification) + { + using PowerShell pwsh = PowerShell.Create(this.Runspace); + var result = this.DscModule.InvokeGetResource(pwsh, settings, name, moduleSpecification); + this.OnDiagnostics(DiagnosticLevel.Verbose, pwsh); + return result; + } /// - public bool InvokeTestResource(ValueSet settings, string name, ModuleSpecification? moduleSpecification) => - this.DscModule.InvokeTestResource(this.Runspace, settings, name, moduleSpecification); + public bool InvokeTestResource(ValueSet settings, string name, ModuleSpecification? moduleSpecification) + { + using PowerShell pwsh = PowerShell.Create(this.Runspace); + var result = this.DscModule.InvokeTestResource(pwsh, settings, name, moduleSpecification); + this.OnDiagnostics(DiagnosticLevel.Verbose, pwsh); + return result; + } /// - public bool InvokeSetResource(ValueSet settings, string name, ModuleSpecification? moduleSpecification) => - this.DscModule.InvokeSetResource(this.Runspace, settings, name, moduleSpecification); + public bool InvokeSetResource(ValueSet settings, string name, ModuleSpecification? moduleSpecification) + { + using PowerShell pwsh = PowerShell.Create(this.Runspace); + var result = this.DscModule.InvokeSetResource(pwsh, settings, name, moduleSpecification); + this.OnDiagnostics(DiagnosticLevel.Verbose, pwsh); + return result; + } /// public PSModuleInfo? GetImportedModule(ModuleSpecification moduleSpecification) @@ -117,6 +150,7 @@ public bool InvokeSetResource(ValueSet settings, string name, ModuleSpecificatio .Invoke() .FirstOrDefault(); + this.OnDiagnostics(DiagnosticLevel.Verbose, pwsh); return moduleInfo; } @@ -131,6 +165,7 @@ public bool InvokeSetResource(ValueSet settings, string name, ModuleSpecificatio .Invoke() .FirstOrDefault(); + this.OnDiagnostics(DiagnosticLevel.Verbose, pwsh); return moduleInfo; } @@ -145,6 +180,7 @@ public bool InvokeSetResource(ValueSet settings, string name, ModuleSpecificatio .Invoke() .FirstOrDefault(); + this.OnDiagnostics(DiagnosticLevel.Verbose, pwsh); return moduleInfo; } @@ -156,6 +192,8 @@ public void ImportModule(ModuleSpecification moduleSpecification) _ = pwsh.AddCommand(Commands.ImportModule) .AddParameter(Parameters.FullyQualifiedName, moduleSpecification) .Invoke(); + + this.OnDiagnostics(DiagnosticLevel.Verbose, pwsh); } /// @@ -188,6 +226,7 @@ public void ImportModule(ModuleSpecification moduleSpecification) .Invoke() .FirstOrDefault(); + this.OnDiagnostics(DiagnosticLevel.Verbose, pwsh); return result; } @@ -236,6 +275,7 @@ public void ImportModule(ModuleSpecification moduleSpecification) .Invoke() .FirstOrDefault(); + this.OnDiagnostics(DiagnosticLevel.Verbose, pwsh); return result; } @@ -247,7 +287,9 @@ public void SaveModule(PSObject inputObject, string location) _ = pwsh.AddCommand(Commands.SaveModule) .AddParameter(Parameters.Path, location) .AddParameter(Parameters.InputObject, inputObject) - .InvokeAndStopOnError(); + .Invoke(); + + this.OnDiagnostics(DiagnosticLevel.Verbose, pwsh); } /// @@ -265,7 +307,9 @@ public void InstallModule(PSObject inputObject) _ = pwsh.AddCommand(Commands.InstallModule) .AddParameter(Parameters.InputObject, inputObject) .AddParameter(Parameters.Force) - .InvokeAndStopOnError(); + .Invoke(); + + this.OnDiagnostics(DiagnosticLevel.Verbose, pwsh); } /// @@ -298,7 +342,9 @@ public void InstallModule(ModuleSpecification moduleSpecification) _ = pwsh.AddCommand(Commands.InstallModule) .AddParameters(parameters) .AddParameter(Parameters.Force) - .InvokeAndStopOnError(); + .Invoke(); + + this.OnDiagnostics(DiagnosticLevel.Verbose, pwsh); } } @@ -310,7 +356,7 @@ public List GetCertsOfValidSignedFiles(string[] paths) var signatures = pwsh.AddCommand(Commands.GetChildItem) .AddParameter(Parameters.Path, paths) .AddCommand(Commands.GetAuthenticodeSignature) - .InvokeAndStopOnError(); + .Invoke(); var thumbprint = new HashSet(); var certificates = new List(); @@ -326,6 +372,7 @@ public List GetCertsOfValidSignedFiles(string[] paths) } } + this.OnDiagnostics(DiagnosticLevel.Verbose, pwsh); return certificates; } @@ -408,5 +455,10 @@ private bool ValidateModule(ModuleSpecification moduleSpecification) return false; } + + private void OnDiagnostics(DiagnosticLevel level, PowerShell pwsh) + { + this.SetProcessorFactory?.OnDiagnostics(level, pwsh); + } } } diff --git a/src/Microsoft.Management.Configuration.Processor/ProcessorEnvironments/ProcessorEnvironmentFactory.cs b/src/Microsoft.Management.Configuration.Processor/ProcessorEnvironments/ProcessorEnvironmentFactory.cs index 703f356d8c..c55d20f415 100644 --- a/src/Microsoft.Management.Configuration.Processor/ProcessorEnvironments/ProcessorEnvironmentFactory.cs +++ b/src/Microsoft.Management.Configuration.Processor/ProcessorEnvironments/ProcessorEnvironmentFactory.cs @@ -33,13 +33,9 @@ public ProcessorEnvironmentFactory(ConfigurationProcessorType type) /// /// Create process environment. /// + /// Optional processor factory. /// IProcessorEnvironment. - public IProcessorEnvironment CreateEnvironment() - { - return this.CreateProcessorEnvironment(); - } - - private IProcessorEnvironment CreateProcessorEnvironment() + public IProcessorEnvironment CreateEnvironment(ConfigurationSetProcessorFactory? setProcessorFactory) { IDscModule dscModule = new DscModuleV2(); @@ -67,7 +63,10 @@ private IProcessorEnvironment CreateProcessorEnvironment() var runspace = RunspaceFactory.CreateRunspace(initialSessionState); runspace.Open(); - return new HostedEnvironment(runspace, this.type, dscModule); + return new HostedEnvironment(runspace, this.type, dscModule) + { + SetProcessorFactory = setProcessorFactory, + }; } throw new ArgumentException(this.type.ToString()); diff --git a/src/Microsoft.Management.Configuration.Processor/Public/ConfigurationSetProcessorFactory.cs b/src/Microsoft.Management.Configuration.Processor/Public/ConfigurationSetProcessorFactory.cs index 6d5cb14e84..bf904b60a4 100644 --- a/src/Microsoft.Management.Configuration.Processor/Public/ConfigurationSetProcessorFactory.cs +++ b/src/Microsoft.Management.Configuration.Processor/Public/ConfigurationSetProcessorFactory.cs @@ -7,6 +7,8 @@ namespace Microsoft.Management.Configuration.Processor { using System; + using System.Management.Automation; + using System.Text; using Microsoft.Management.Configuration; using Microsoft.Management.Configuration.Processor.ProcessorEnvironments; using Microsoft.Management.Configuration.Processor.Set; @@ -52,7 +54,7 @@ public IConfigurationSetProcessor CreateSetProcessor(ConfigurationSet set) this.OnDiagnostics(DiagnosticLevel.Verbose, $"Creating set processor for `{set.Name}`..."); var envFactory = new ProcessorEnvironmentFactory(this.type); - var processorEnvironment = envFactory.CreateEnvironment(); + var processorEnvironment = envFactory.CreateEnvironment(this); processorEnvironment.ValidateRunspace(); if (this.properties is not null) @@ -85,11 +87,57 @@ internal void OnDiagnostics(DiagnosticLevel level, string message) EventHandler? diagnostics = this.Diagnostics; if (diagnostics != null && level >= this.MinimumLevel) { - DiagnosticInformation information = new DiagnosticInformation(); - information.Level = level; - information.Message = message; - diagnostics.Invoke(this, information); + this.InvokeDiagnostics(diagnostics, level, message); } } + + /// + /// Sends diagnostic if appropriate for PowerShell streams. + /// + /// The level of this diagnostic message. + /// The PowerShell object. + internal void OnDiagnostics(DiagnosticLevel level, PowerShell pwsh) + { + EventHandler? diagnostics = this.Diagnostics; + if (diagnostics != null && level >= this.MinimumLevel && pwsh.HadErrors) + { + var builder = new StringBuilder(); + + // There are the last commands ran by that PowerShell obj, not all in our session. + builder.Append("PowerShellCommands: "); + foreach (var c in pwsh.Commands.Commands) + { + builder.Append($"['{c.CommandText}'"); + if (c.Parameters.Count > 0) + { + builder.Append(" Parameters: "); + foreach (var p in c.Parameters) + { + builder.Append($"{p.Name} = '{p.Value}' "); + } + builder.Append("]"); + } + + builder.AppendLine(); + } + + foreach (var error in pwsh.Streams.Error) + { + builder.AppendLine($"[WriteError] {error}"); + } + + this.InvokeDiagnostics(diagnostics, level, builder.ToString()); + } + } + + private void InvokeDiagnostics(EventHandler diagnostics, DiagnosticLevel level, string message) + { + DiagnosticInformation information = new () + { + Level = level, + Message = message, + }; + diagnostics.Invoke(this, information); + } } } \ No newline at end of file diff --git a/src/Microsoft.Management.Configuration.UnitTests/Fixtures/UnitTestFixture.cs b/src/Microsoft.Management.Configuration.UnitTests/Fixtures/UnitTestFixture.cs index b66d05df1c..65e5417f3a 100644 --- a/src/Microsoft.Management.Configuration.UnitTests/Fixtures/UnitTestFixture.cs +++ b/src/Microsoft.Management.Configuration.UnitTests/Fixtures/UnitTestFixture.cs @@ -57,7 +57,7 @@ public UnitTestFixture(IMessageSink messageSink) /// PowerShellRunspace. internal IProcessorEnvironment PrepareTestProcessorEnvironment(bool validate = false) { - var processorEnv = new ProcessorEnvironmentFactory(ConfigurationProcessorType.Hosted).CreateEnvironment(); + var processorEnv = new ProcessorEnvironmentFactory(ConfigurationProcessorType.Hosted).CreateEnvironment(null); processorEnv.PrependPSModulePath(this.TestModulesPath); if (validate) diff --git a/src/Microsoft.Management.Configuration.UnitTests/Helpers/TestConfigurationProcessorFactory.cs b/src/Microsoft.Management.Configuration.UnitTests/Helpers/TestConfigurationProcessorFactory.cs index 879df72f39..85d8c507d5 100644 --- a/src/Microsoft.Management.Configuration.UnitTests/Helpers/TestConfigurationProcessorFactory.cs +++ b/src/Microsoft.Management.Configuration.UnitTests/Helpers/TestConfigurationProcessorFactory.cs @@ -25,7 +25,9 @@ internal class TestConfigurationProcessorFactory : IConfigurationSetProcessorFac /// /// Diagnostics event; useful for logging and/or verbose output. /// +#pragma warning disable CS0067 // The event is never used public event EventHandler? Diagnostics; +#pragma warning restore CS0067 // The event is never used /// /// Gets or sets the minimum diagnostic level to send. diff --git a/src/Microsoft.Management.Configuration.UnitTests/Tests/DscModuleV2SimpleFileResourceTests.cs b/src/Microsoft.Management.Configuration.UnitTests/Tests/DscModuleV2SimpleFileResourceTests.cs index cb01e4e677..6bbf22d2a4 100644 --- a/src/Microsoft.Management.Configuration.UnitTests/Tests/DscModuleV2SimpleFileResourceTests.cs +++ b/src/Microsoft.Management.Configuration.UnitTests/Tests/DscModuleV2SimpleFileResourceTests.cs @@ -7,6 +7,7 @@ namespace Microsoft.Management.Configuration.UnitTests.Tests { using System.IO; + using System.Management.Automation; using Microsoft.Management.Configuration.Processor.DscModule; using Microsoft.Management.Configuration.Processor.Helpers; using Microsoft.Management.Configuration.UnitTests.Fixtures; @@ -58,10 +59,12 @@ public void SimpleFileResource_FileAbsent(string ensureValue, bool expectedResul }; var dscModule = new DscModuleV2(); + + using PowerShell pwsh = PowerShell.Create(processorEnv.Runspace); Assert.Equal( expectedResult, dscModule.InvokeTestResource( - processorEnv.Runspace, + pwsh, settings, TestModule.SimpleFileResourceName, PowerShellHelpers.CreateModuleSpecification( @@ -86,8 +89,9 @@ public void SimpleFileResource_FilePresent() }; var dscModule = new DscModuleV2(); + using PowerShell pwsh = PowerShell.Create(processorEnv.Runspace); Assert.True(dscModule.InvokeTestResource( - processorEnv.Runspace, + pwsh, settings, TestModule.SimpleFileResourceName, PowerShellHelpers.CreateModuleSpecification( @@ -112,8 +116,9 @@ public void SimpleFileResource_DifferentContent() }; var dscModule = new DscModuleV2(); + using PowerShell pwsh = PowerShell.Create(processorEnv.Runspace); Assert.False(dscModule.InvokeTestResource( - processorEnv.Runspace, + pwsh, settings, TestModule.SimpleFileResourceName, PowerShellHelpers.CreateModuleSpecification( @@ -139,8 +144,9 @@ public void SimpleFileResource_SameContent() }; var dscModule = new DscModuleV2(); + using PowerShell pwsh = PowerShell.Create(processorEnv.Runspace); Assert.True(dscModule.InvokeTestResource( - processorEnv.Runspace, + pwsh, settings, TestModule.SimpleFileResourceName, PowerShellHelpers.CreateModuleSpecification( @@ -181,8 +187,9 @@ public void SimpleFileResource_Set_Ensure(string ensureValue, bool preCondition, File.Exists(tmpFile.FullFileName)); var dscModule = new DscModuleV2(); + using PowerShell pwsh = PowerShell.Create(processorEnv.Runspace); dscModule.InvokeSetResource( - processorEnv.Runspace, + pwsh, settings, TestModule.SimpleFileResourceName, PowerShellHelpers.CreateModuleSpecification( @@ -221,8 +228,9 @@ public void SimpleFileResource_Set_Content(string? preSetContent, string postSet }; var dscModule = new DscModuleV2(); + using PowerShell pwsh = PowerShell.Create(processorEnv.Runspace); dscModule.InvokeSetResource( - processorEnv.Runspace, + pwsh, settings, TestModule.SimpleFileResourceName, PowerShellHelpers.CreateModuleSpecification( @@ -250,8 +258,9 @@ public void SimpleFileResource_Get() }; var dscModule = new DscModuleV2(); + using PowerShell pwsh = PowerShell.Create(processorEnv.Runspace); var properties = dscModule.InvokeGetResource( - processorEnv.Runspace, + pwsh, settings, TestModule.SimpleFileResourceName, PowerShellHelpers.CreateModuleSpecification( diff --git a/src/Microsoft.Management.Configuration.UnitTests/Tests/DscModuleV2Tests.cs b/src/Microsoft.Management.Configuration.UnitTests/Tests/DscModuleV2Tests.cs index 4ce2a57f5a..95e861a22a 100644 --- a/src/Microsoft.Management.Configuration.UnitTests/Tests/DscModuleV2Tests.cs +++ b/src/Microsoft.Management.Configuration.UnitTests/Tests/DscModuleV2Tests.cs @@ -6,10 +6,10 @@ namespace Microsoft.Management.Configuration.UnitTests.Tests { - using System; using System.IO; using System.Management.Automation; using Microsoft.Management.Configuration.Processor.DscModule; + using Microsoft.Management.Configuration.Processor.Exceptions; using Microsoft.Management.Configuration.Processor.Helpers; using Microsoft.Management.Configuration.UnitTests.Fixtures; using Microsoft.Management.Configuration.UnitTests.Helpers; @@ -48,7 +48,8 @@ public void GetAllDscResources_Test() var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); var dscModule = new DscModuleV2(); - var resources = dscModule.GetAllDscResources(testEnvironment.Runspace); + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); + var resources = dscModule.GetAllDscResources(pwsh); Assert.True(resources.Count > 0); Assert.Contains(resources, r => r.Name == TestModule.SimpleFileResourceName); @@ -67,8 +68,9 @@ public void GetDscResourcesInModule_Test(string module, int expectedResources) var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); var dscModule = new DscModuleV2(); + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); var resources = dscModule.GetDscResourcesInModule( - testEnvironment.Runspace, + pwsh, PowerShellHelpers.CreateModuleSpecification(module)); Assert.Equal(expectedResources, resources.Count); } @@ -102,27 +104,35 @@ public void GetDscResourcesInModule_VersionTest() //// testEnvironment.Runspace, //// PowerShellHelpers.CreateModuleSpecification(TestModule.SimpleTestResourceModuleName)); ////Assert.Equal(8, allResources.Count); - - var ogResources = dscModule.GetDscResourcesInModule( - testEnvironment.Runspace, + { + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); + var ogResources = dscModule.GetDscResourcesInModule( + pwsh, PowerShellHelpers.CreateModuleSpecification( TestModule.SimpleTestResourceModuleName, version: TestModule.SimpleTestResourceVersion)); - Assert.Equal(4, ogResources.Count); + Assert.Equal(4, ogResources.Count); + } - var newVersionResources = dscModule.GetDscResourcesInModule( - testEnvironment.Runspace, - PowerShellHelpers.CreateModuleSpecification( - TestModule.SimpleTestResourceModuleName, - version: newVersion)); - Assert.Equal(4, ogResources.Count); + { + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); + var newVersionResources = dscModule.GetDscResourcesInModule( + pwsh, + PowerShellHelpers.CreateModuleSpecification( + TestModule.SimpleTestResourceModuleName, + version: newVersion)); + Assert.Equal(4, newVersionResources.Count); + } - var badVersionResources = dscModule.GetDscResourcesInModule( - testEnvironment.Runspace, - PowerShellHelpers.CreateModuleSpecification( - TestModule.SimpleTestResourceModuleName, - version: "1.2.3.4")); - Assert.Equal(0, badVersionResources.Count); + { + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); + var badVersionResources = dscModule.GetDscResourcesInModule( + pwsh, + PowerShellHelpers.CreateModuleSpecification( + TestModule.SimpleTestResourceModuleName, + version: "1.2.3.4")); + Assert.Equal(0, badVersionResources.Count); + } } /// @@ -134,8 +144,9 @@ public void GetDscResource_ResourceExists() var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); var dscModule = new DscModuleV2(); + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); var resource = dscModule.GetDscResource( - testEnvironment.Runspace, + pwsh, TestModule.SimpleTestResourceName, PowerShellHelpers.CreateModuleSpecification(TestModule.SimpleTestResourceModuleName)); @@ -151,12 +162,13 @@ public void GetDscResource_ResourceDoesntExist() var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); var dscModule = new DscModuleV2(); - Assert.Throws( - () => dscModule.GetDscResource( - testEnvironment.Runspace, - "FakeResourceName", - PowerShellHelpers.CreateModuleSpecification( - TestModule.SimpleTestResourceModuleName))); + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); + var resource = dscModule.GetDscResource( + pwsh, + "FakeResourceName", + PowerShellHelpers.CreateModuleSpecification( + TestModule.SimpleTestResourceModuleName)); + Assert.Null(resource); } /// @@ -174,10 +186,10 @@ public void GetDscResource_Conflict() testEnvironment.AppendPSModulePath(tmpDir.FullDirectoryPath); var dscModule = new DscModuleV2(); - - Assert.Throws( + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); + Assert.Throws( () => dscModule.GetDscResource( - testEnvironment.Runspace, + pwsh, TestModule.SimpleTestResourceName, PowerShellHelpers.CreateModuleSpecification( TestModule.SimpleTestResourceModuleName))); @@ -208,24 +220,30 @@ public void GetDscResource_DiffVersions() var dscModule = new DscModuleV2(); // specific version. - var resource = dscModule.GetDscResource( - testEnvironment.Runspace, - TestModule.SimpleTestResourceName, - PowerShellHelpers.CreateModuleSpecification( - TestModule.SimpleTestResourceModuleName, - TestModule.SimpleTestResourceVersion)); - Assert.NotNull(resource); + { + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); + var resource = dscModule.GetDscResource( + pwsh, + TestModule.SimpleTestResourceName, + PowerShellHelpers.CreateModuleSpecification( + TestModule.SimpleTestResourceModuleName, + TestModule.SimpleTestResourceVersion)); + Assert.NotNull(resource); + } - var dsc = dscModule.GetDscResource( - testEnvironment.Runspace, - TestModule.SimpleTestResourceName, - PowerShellHelpers.CreateModuleSpecification( - TestModule.SimpleTestResourceModuleName, - version: newVersion)); + { + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); + var dsc = dscModule.GetDscResource( + pwsh, + TestModule.SimpleTestResourceName, + PowerShellHelpers.CreateModuleSpecification( + TestModule.SimpleTestResourceModuleName, + version: newVersion)); - Assert.NotNull(dsc); - Assert.NotNull(dsc.Version); - Assert.Equal(newVersion, dsc.Version.ToString()); + Assert.NotNull(dsc); + Assert.NotNull(dsc.Version); + Assert.Equal(newVersion, dsc.Version.ToString()); + } } /// @@ -237,9 +255,9 @@ public void InvokeGetResource_Test() var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); var dscModule = new DscModuleV2(); - + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); var getResult = dscModule.InvokeGetResource( - testEnvironment.Runspace, + pwsh, new ValueSet(), TestModule.SimpleTestResourceName, PowerShellHelpers.CreateModuleSpecification( @@ -260,9 +278,10 @@ public void InvokeGetResource_ResourceThrows() var dscModule = new DscModuleV2(); + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); var exception = Assert.Throws(() => dscModule.InvokeGetResource( - testEnvironment.Runspace, + pwsh, new ValueSet(), TestModule.SimpleTestResourceThrowsName, PowerShellHelpers.CreateModuleSpecification( @@ -280,10 +299,10 @@ public void InvokeGetResource_ResourceError() var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); var dscModule = new DscModuleV2(); - + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); Assert.Throws(() => dscModule.InvokeGetResource( - testEnvironment.Runspace, + pwsh, new ValueSet(), TestModule.SimpleTestResourceErrorName, PowerShellHelpers.CreateModuleSpecification( @@ -299,10 +318,10 @@ public void InvokeGetResource_ResourceDoesntExist() var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); var dscModule = new DscModuleV2(); - + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); var exception = Assert.Throws( () => dscModule.InvokeGetResource( - testEnvironment.Runspace, + pwsh, new ValueSet(), "FakeResourceName", PowerShellHelpers.CreateModuleSpecification( @@ -330,8 +349,9 @@ public void InvokeTestResource_Test(string value, bool expectedResult) { "secretCode", value }, }; + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); var testResult = dscModule.InvokeTestResource( - testEnvironment.Runspace, + pwsh, settings, TestModule.SimpleTestResourceName, PowerShellHelpers.CreateModuleSpecification( @@ -349,10 +369,10 @@ public void InvokeTestResource_Throws() var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); var dscModule = new DscModuleV2(); - + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); var exception = Assert.Throws(() => dscModule.InvokeTestResource( - testEnvironment.Runspace, + pwsh, new ValueSet(), TestModule.SimpleTestResourceThrowsName, PowerShellHelpers.CreateModuleSpecification( @@ -370,10 +390,10 @@ public void InvokeTestResource_ResourceError() var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); var dscModule = new DscModuleV2(); - + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); Assert.Throws(() => dscModule.InvokeTestResource( - testEnvironment.Runspace, + pwsh, new ValueSet(), TestModule.SimpleTestResourceErrorName, PowerShellHelpers.CreateModuleSpecification( @@ -389,10 +409,10 @@ public void InvokeTestResource_ResourceDoesntExist() var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); var dscModule = new DscModuleV2(); - + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); var exception = Assert.Throws(() => _ = dscModule.InvokeTestResource( - testEnvironment.Runspace, + pwsh, new ValueSet(), "FakeResourceName", PowerShellHelpers.CreateModuleSpecification( @@ -418,8 +438,9 @@ public void InvokeSetResource_Test() { "secretCode", "4815162342" }, }; + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); var testResult = dscModule.InvokeSetResource( - testEnvironment.Runspace, + pwsh, settings, TestModule.SimpleTestResourceName, PowerShellHelpers.CreateModuleSpecification( @@ -438,10 +459,10 @@ public void InvokeSetResource_Throws() var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); var dscModule = new DscModuleV2(); - + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); var exception = Assert.Throws(() => dscModule.InvokeSetResource( - testEnvironment.Runspace, + pwsh, new ValueSet(), TestModule.SimpleTestResourceThrowsName, PowerShellHelpers.CreateModuleSpecification( @@ -459,10 +480,10 @@ public void InvokeSetResource_ResourceError() var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); var dscModule = new DscModuleV2(); - + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); Assert.Throws(() => dscModule.InvokeSetResource( - testEnvironment.Runspace, + pwsh, new ValueSet(), TestModule.SimpleTestResourceErrorName, PowerShellHelpers.CreateModuleSpecification( @@ -478,10 +499,10 @@ public void InvokeSetResource_ResourceDoesntExist() var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); var dscModule = new DscModuleV2(); - + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); var exception = Assert.Throws(() => dscModule.InvokeSetResource( - testEnvironment.Runspace, + pwsh, new ValueSet(), "FakeResourceName", PowerShellHelpers.CreateModuleSpecification( @@ -513,22 +534,27 @@ public void InvokeResource_MultipleVersions() testEnvironment.AppendPSModulePath(tmpDir.FullDirectoryPath); var dscModule = new DscModuleV2(); + { + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); + dscModule.InvokeSetResource( + pwsh, + new ValueSet(), + TestModule.SimpleTestResourceName, + PowerShellHelpers.CreateModuleSpecification( + TestModule.SimpleTestResourceModuleName, + TestModule.SimpleTestResourceVersion)); + } - dscModule.InvokeSetResource( - testEnvironment.Runspace, - new ValueSet(), - TestModule.SimpleTestResourceName, - PowerShellHelpers.CreateModuleSpecification( - TestModule.SimpleTestResourceModuleName, - TestModule.SimpleTestResourceVersion)); - - dscModule.InvokeSetResource( - testEnvironment.Runspace, - new ValueSet(), - TestModule.SimpleTestResourceName, - PowerShellHelpers.CreateModuleSpecification( - TestModule.SimpleTestResourceModuleName, - version: newVersion)); + { + using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); + dscModule.InvokeSetResource( + pwsh, + new ValueSet(), + TestModule.SimpleTestResourceName, + PowerShellHelpers.CreateModuleSpecification( + TestModule.SimpleTestResourceModuleName, + version: newVersion)); + } } } }