diff --git a/doc/windows/package-manager/winget/returnCodes.md b/doc/windows/package-manager/winget/returnCodes.md
index 6f01c97940..51c2375884 100644
--- a/doc/windows/package-manager/winget/returnCodes.md
+++ b/doc/windows/package-manager/winget/returnCodes.md
@@ -192,4 +192,6 @@ Installation failed. Restart your PC then try again. |
| 0x8A15C106 | -1978285818 | WINGET_CONFIG_ERROR_UNIT_INVOKE_SET | The configuration unit failed while attempting to apply the desired state. |
| 0x8A15C107 | -1978285817 | WINGET_CONFIG_ERROR_UNIT_MODULE_CONFLICT | The module for the configuration unit is available in multiple locations with the same version. |
| 0x8A15C108 | -1978285816 | WINGET_CONFIG_ERROR_UNIT_IMPORT_MODULE | Loading the module for the configuration unit failed. |
-| 0x8A15C109 | -1978285815 | WINGET_CONFIG_ERROR_UNIT_INVOKE_INVALID_RESULT | The configuration unit returned an unexpected result during execution. |
\ No newline at end of file
+| 0x8A15C109 | -1978285815 | WINGET_CONFIG_ERROR_UNIT_INVOKE_INVALID_RESULT | The configuration unit returned an unexpected result during execution. |
+| 0x8A15C110 | -1978285814 | WINGET_CONFIG_ERROR_UNIT_SETTING_CONFIG_ROOT | A unit contains a setting that requires the config root. |
+| 0x8A15C111 | -1978285813 | WINGET_CONFIG_ERROR_UNIT_IMPORT_MODULE_ADMIN | Loading the module for the configuration unit failed because it requires administrator privileges to run. |
\ No newline at end of file
diff --git a/src/AppInstallerCLICore/Resources.h b/src/AppInstallerCLICore/Resources.h
index e00683ec22..1822c2a995 100644
--- a/src/AppInstallerCLICore/Resources.h
+++ b/src/AppInstallerCLICore/Resources.h
@@ -104,6 +104,7 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationUnitFailedUnitProcessing);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationUnitHasDuplicateIdentifier);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationUnitHasMissingDependency);
+ WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationUnitImportModuleAdmin);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationUnitIsPartOfDependencyCycle);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationUnitManuallySkipped);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationUnitModuleConflict);
@@ -118,6 +119,7 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationUnitNotRunDueToDependency);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationUnitNotRunDueToFailedAssert);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationUnitReturnedInvalidResult);
+ WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationUnitSettingConfigRoot);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationUnitSkipped);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationValidationFoundNoIssues);
WINGET_DEFINE_RESOURCE_STRINGID(ConfigurationWaitingOnAnother);
diff --git a/src/AppInstallerCLICore/Workflows/ConfigurationFlow.cpp b/src/AppInstallerCLICore/Workflows/ConfigurationFlow.cpp
index d693e86bd2..39704041f8 100644
--- a/src/AppInstallerCLICore/Workflows/ConfigurationFlow.cpp
+++ b/src/AppInstallerCLICore/Workflows/ConfigurationFlow.cpp
@@ -407,8 +407,10 @@ namespace AppInstaller::CLI::Workflow
case WINGET_CONFIG_ERROR_UNIT_INVOKE_TEST: return { Resource::String::ConfigurationUnitFailedDuringTest(), true };
case WINGET_CONFIG_ERROR_UNIT_INVOKE_SET: return { Resource::String::ConfigurationUnitFailedDuringSet(), true };
case WINGET_CONFIG_ERROR_UNIT_MODULE_CONFLICT: return { Resource::String::ConfigurationUnitModuleConflict(), false };
- case WINGET_CONFIG_ERROR_UNIT_IMPORT_MODULE: return { Resource::String::ConfigurationUnitModuleImportFailed(), true };
+ case WINGET_CONFIG_ERROR_UNIT_IMPORT_MODULE: return { Resource::String::ConfigurationUnitModuleImportFailed(), false };
case WINGET_CONFIG_ERROR_UNIT_INVOKE_INVALID_RESULT: return { Resource::String::ConfigurationUnitReturnedInvalidResult(), false };
+ case WINGET_CONFIG_ERROR_UNIT_SETTING_CONFIG_ROOT: return { Resource::String::ConfigurationUnitSettingConfigRoot(), false };
+ case WINGET_CONFIG_ERROR_UNIT_IMPORT_MODULE_ADMIN: return { Resource::String::ConfigurationUnitImportModuleAdmin(), false };
}
switch (resultInformation.ResultSource())
diff --git a/src/AppInstallerCLIE2ETests/Constants.cs b/src/AppInstallerCLIE2ETests/Constants.cs
index 5c5e793278..ae7ac3f6a2 100644
--- a/src/AppInstallerCLIE2ETests/Constants.cs
+++ b/src/AppInstallerCLIE2ETests/Constants.cs
@@ -317,6 +317,7 @@ public class ErrorCode
public const int CONFIG_ERROR_UNIT_IMPORT_MODULE = unchecked((int)0x8A15C108);
public const int CONFIG_ERROR_UNIT_INVOKE_INVALID_RESULT = unchecked((int)0x8A15C109);
public const int CONFIG_ERROR_UNIT_SETTING_CONFIG_ROOT = unchecked((int)0x8A15C110);
+ public const int CONFIG_ERROR_UNIT_IMPORT_MODULE_ADMIN = unchecked((int)0x8A15C111);
}
#pragma warning restore SA1310 // Field names should not contain underscore
diff --git a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw
index cef16113e7..b2b6f7a8c6 100644
--- a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw
+++ b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw
@@ -2587,6 +2587,15 @@ Please specify one of them using the --source option to proceed.
Successfully enabled Windows Features dependencies
+
+ Loading the module for the configuration unit failed because it requires administrator privileges to run.
+
+
+ A unit contains a setting that requires the config root.
+
+
+ Loading the module for the configuration unit failed because it requires administrator privileges to run.
+
Resumes execution of a previously saved command by passing in the unique identifier of the saved command. This is used to resume an executed command that may have been terminated due to a reboot.
diff --git a/src/AppInstallerSharedLib/Errors.cpp b/src/AppInstallerSharedLib/Errors.cpp
index 082985cab3..e3a8ac743c 100644
--- a/src/AppInstallerSharedLib/Errors.cpp
+++ b/src/AppInstallerSharedLib/Errors.cpp
@@ -261,7 +261,8 @@ namespace AppInstaller
WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_UNIT_IMPORT_MODULE, "Loading the module for the configuration unit failed."),
WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_UNIT_INVOKE_INVALID_RESULT, "The configuration unit returned an unexpected result during execution."),
WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_UNIT_SETTING_CONFIG_ROOT, "A unit contains a setting that requires the config root."),
-
+ WINGET_HRESULT_INFO(WINGET_CONFIG_ERROR_UNIT_IMPORT_MODULE_ADMIN, "Loading the module for the configuration unit failed because it requires administrator privileges to run."),
+
// Errors without the error bit set
WINGET_HRESULT_INFO(WINGET_INSTALLED_STATUS_INSTALL_LOCATION_NOT_APPLICABLE, "The install location is not applicable."),
WINGET_HRESULT_INFO(WINGET_INSTALLED_STATUS_FILE_FOUND_WITHOUT_HASH_CHECK, "The file was found but the hash was not checked."),
diff --git a/src/AppInstallerSharedLib/Public/AppInstallerErrors.h b/src/AppInstallerSharedLib/Public/AppInstallerErrors.h
index 6702ab5227..7b27c311b9 100644
--- a/src/AppInstallerSharedLib/Public/AppInstallerErrors.h
+++ b/src/AppInstallerSharedLib/Public/AppInstallerErrors.h
@@ -194,6 +194,7 @@
#define WINGET_CONFIG_ERROR_UNIT_IMPORT_MODULE ((HRESULT)0x8A15C108)
#define WINGET_CONFIG_ERROR_UNIT_INVOKE_INVALID_RESULT ((HRESULT)0x8A15C109)
#define WINGET_CONFIG_ERROR_UNIT_SETTING_CONFIG_ROOT ((HRESULT)0x8A15C110)
+#define WINGET_CONFIG_ERROR_UNIT_IMPORT_MODULE_ADMIN ((HRESULT)0x8A15C111)
namespace AppInstaller
{
diff --git a/src/Microsoft.Management.Configuration.Processor/Exceptions/ErrorCodes.cs b/src/Microsoft.Management.Configuration.Processor/Exceptions/ErrorCodes.cs
index 89b32996c8..40ee9560cd 100644
--- a/src/Microsoft.Management.Configuration.Processor/Exceptions/ErrorCodes.cs
+++ b/src/Microsoft.Management.Configuration.Processor/Exceptions/ErrorCodes.cs
@@ -65,5 +65,10 @@ internal static class ErrorCodes
/// The unit contains a setting that requires config root.
///
internal const int WinGetConfigUnitSettingConfigRoot = unchecked((int)0x8A15C110);
+
+ ///
+ /// The module where the DSC resource is implemented requires admin.
+ ///
+ internal const int WinGetConfigUnitImportModuleAdmin = unchecked((int)0x8A15C111);
}
}
diff --git a/src/Microsoft.Management.Configuration.Processor/Exceptions/ImportModuleException.cs b/src/Microsoft.Management.Configuration.Processor/Exceptions/ImportModuleException.cs
index 05c8f541a0..22e771555d 100644
--- a/src/Microsoft.Management.Configuration.Processor/Exceptions/ImportModuleException.cs
+++ b/src/Microsoft.Management.Configuration.Processor/Exceptions/ImportModuleException.cs
@@ -7,6 +7,7 @@
namespace Microsoft.Management.Configuration.Processor.Exceptions
{
using System;
+ using System.Management.Automation;
///
/// Import-Module threw an exception.
@@ -17,11 +18,11 @@ internal class ImportModuleException : Exception
/// Initializes a new instance of the class.
///
/// Module name.
- /// Inner exception.
- public ImportModuleException(string? moduleName, Exception inner)
- : base($"Could not import module: {moduleName?.ToString() ?? ""}", inner)
+ /// Inner exception.
+ public ImportModuleException(string? moduleName, Exception pwshEx)
+ : base($"Could not import module: {moduleName?.ToString() ?? ""}", pwshEx)
{
- this.HResult = ErrorCodes.WinGetConfigUnitImportModule;
+ this.HResult = this.GetHResult(pwshEx);
this.ModuleName = moduleName;
}
@@ -29,5 +30,22 @@ public ImportModuleException(string? moduleName, Exception inner)
/// Gets the module name.
///
public string? ModuleName { get; }
+
+ private int GetHResult(Exception pwshEx)
+ {
+ if (pwshEx.InnerException is not null)
+ {
+ var scriptEx = pwshEx.InnerException as ScriptRequiresException;
+ if (scriptEx is not null)
+ {
+ if (scriptEx.ErrorRecord.CategoryInfo.Category == ErrorCategory.PermissionDenied)
+ {
+ return ErrorCodes.WinGetConfigUnitImportModuleAdmin;
+ }
+ }
+ }
+
+ return ErrorCodes.WinGetConfigUnitImportModule;
+ }
}
}
diff --git a/src/Microsoft.Management.Configuration.UnitTests/Microsoft.Management.Configuration.UnitTests.csproj b/src/Microsoft.Management.Configuration.UnitTests/Microsoft.Management.Configuration.UnitTests.csproj
index 679ba79949..797abac6dc 100644
--- a/src/Microsoft.Management.Configuration.UnitTests/Microsoft.Management.Configuration.UnitTests.csproj
+++ b/src/Microsoft.Management.Configuration.UnitTests/Microsoft.Management.Configuration.UnitTests.csproj
@@ -35,7 +35,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
@@ -53,7 +53,7 @@
-
+
@@ -63,6 +63,12 @@
+
+ PreserveNewest
+
+
+ PreserveNewest
+
PreserveNewest
diff --git a/src/Microsoft.Management.Configuration.UnitTests/TestCollateral/PowerShellModules/xAdminTestResource/xAdminTestResource.psd1 b/src/Microsoft.Management.Configuration.UnitTests/TestCollateral/PowerShellModules/xAdminTestResource/xAdminTestResource.psd1
new file mode 100644
index 0000000000..014cc57c30
--- /dev/null
+++ b/src/Microsoft.Management.Configuration.UnitTests/TestCollateral/PowerShellModules/xAdminTestResource/xAdminTestResource.psd1
@@ -0,0 +1,37 @@
+#
+# Module manifest for module 'xAdminTestResource'
+#
+# Generated by: Luffytaro
+#
+# Generated on: 10/11/2023
+#
+
+@{
+
+RootModule = 'xAdminTestResource.psm1'
+ModuleVersion = '0.0.0.1'
+GUID = 'a0be43e8-ac22-4244-8efc-7263dfa58b8c'
+CompatiblePSEditions = 'Core'
+Author = 'Luffytaro'
+CompanyName = 'Microsoft Corporation'
+Copyright = '(c) Microsoft Corporation. All rights reserved.'
+Description = 'PowerShell module with DSC resources for unit tests that requires admin'
+PowerShellVersion = '7.2'
+FunctionsToExport = @()
+CmdletsToExport = @()
+DscResourcesToExport = @(
+ 'AdminResource'
+)
+HelpInfoURI = 'https://www.contoso.com/help'
+
+# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
+PrivateData = @{
+
+ PSData = @{
+ ProjectUri = 'https://github.com/microsoft/winget-cli'
+ IconUri = 'https://www.contoso.com/icons/icon.png'
+ }
+
+}
+
+}
diff --git a/src/Microsoft.Management.Configuration.UnitTests/TestCollateral/PowerShellModules/xAdminTestResource/xAdminTestResource.psm1 b/src/Microsoft.Management.Configuration.UnitTests/TestCollateral/PowerShellModules/xAdminTestResource/xAdminTestResource.psm1
new file mode 100644
index 0000000000..7e8b9b2aca
--- /dev/null
+++ b/src/Microsoft.Management.Configuration.UnitTests/TestCollateral/PowerShellModules/xAdminTestResource/xAdminTestResource.psm1
@@ -0,0 +1,29 @@
+# Simple module that requires admin.
+#Requires -RunAsAdministrator
+enum Ensure
+{
+ Absent
+ Present
+}
+
+[DscResource()]
+class AdminResource
+{
+ [DscProperty(Key)]
+ [string] $key
+
+ [AdminResource] Get()
+ {
+ return $this
+ }
+
+ [bool] Test()
+ {
+ return $false
+ }
+
+ [void] Set()
+ {
+ }
+}
+
diff --git a/src/Microsoft.Management.Configuration.UnitTests/Tests/ConfigurationSetProcessorTests.cs b/src/Microsoft.Management.Configuration.UnitTests/Tests/ConfigurationSetProcessorTests.cs
index c2f62d4192..ee3c7860b1 100644
--- a/src/Microsoft.Management.Configuration.UnitTests/Tests/ConfigurationSetProcessorTests.cs
+++ b/src/Microsoft.Management.Configuration.UnitTests/Tests/ConfigurationSetProcessorTests.cs
@@ -791,6 +791,30 @@ public void CreateUnitProcessor_TestTypes()
unitProcessor.TestSettings();
}
+ ///
+ /// Tests a module that requires admin is loaded from non admin.
+ ///
+ [FactSkipIfCI]
+ public void CreateUnitProcessor_ModuleRequiresAdmin()
+ {
+ var processorEnv = this.fixture.PrepareTestProcessorEnvironment();
+
+ var setProcessor = new ConfigurationSetProcessor(processorEnv, new ConfigurationSet());
+
+ var unit = new ConfigurationUnit
+ {
+ Type = "AdminResource",
+ Intent = ConfigurationUnitIntent.Assert,
+ };
+ unit.Metadata.Add("module", "xAdminTestResource");
+ unit.Metadata.Add("version", "0.0.0.1");
+
+ unit.Settings.Add("key", "key");
+
+ var importModuleException = Assert.Throws(() => setProcessor.CreateUnitProcessor(unit));
+ Assert.Equal(ErrorCodes.WinGetConfigUnitImportModuleAdmin, importModuleException.HResult);
+ }
+
private ConfigurationUnit CreateConfigurationUnit()
{
var unit = new ConfigurationUnit();
diff --git a/src/Microsoft.Management.Configuration/ConfigurationUnitResultInformation.cpp b/src/Microsoft.Management.Configuration/ConfigurationUnitResultInformation.cpp
index 7a303aa018..97cb9040b1 100644
--- a/src/Microsoft.Management.Configuration/ConfigurationUnitResultInformation.cpp
+++ b/src/Microsoft.Management.Configuration/ConfigurationUnitResultInformation.cpp
@@ -16,6 +16,8 @@ namespace winrt::Microsoft::Management::Configuration::implementation
case WINGET_CONFIG_ERROR_UNIT_NOT_FOUND_REPOSITORY:
case WINGET_CONFIG_ERROR_UNIT_MULTIPLE_MATCHES:
case WINGET_CONFIG_ERROR_UNIT_IMPORT_MODULE:
+ case WINGET_CONFIG_ERROR_UNIT_SETTING_CONFIG_ROOT:
+ case WINGET_CONFIG_ERROR_UNIT_IMPORT_MODULE_ADMIN:
return ConfigurationUnitResultSource::ConfigurationSet;
case WINGET_CONFIG_ERROR_UNIT_MODULE_CONFLICT:
return ConfigurationUnitResultSource::SystemState;
diff --git a/src/PowerShell/Microsoft.WinGet.Configuration.Engine/Exceptions/ErrorCodes.cs b/src/PowerShell/Microsoft.WinGet.Configuration.Engine/Exceptions/ErrorCodes.cs
index 14b010c6fe..9b6d9abf72 100644
--- a/src/PowerShell/Microsoft.WinGet.Configuration.Engine/Exceptions/ErrorCodes.cs
+++ b/src/PowerShell/Microsoft.WinGet.Configuration.Engine/Exceptions/ErrorCodes.cs
@@ -39,6 +39,8 @@ internal static class ErrorCodes
internal const int WinGetConfigUnitModuleConflict = unchecked((int)0x8A15C107);
internal const int WinGetConfigUnitImportModule = unchecked((int)0x8A15C108);
internal const int WinGetConfigUnitInvokeInvalidResult = unchecked((int)0x8A15C109);
+ internal const int WinGetConfigUnitSettingConfigRoot = unchecked((int)0x8A15C110);
+ internal const int WinGetConfigUnitImportModuleAdmin = unchecked((int)0x8A15C111);
#pragma warning restore SA1310 // Field names should not contain underscore
#pragma warning restore SA1600 // ElementsMustBeDocumented
}
diff --git a/src/PowerShell/Microsoft.WinGet.Configuration.Engine/PSObjects/PSUnitResult.cs b/src/PowerShell/Microsoft.WinGet.Configuration.Engine/PSObjects/PSUnitResult.cs
index ec22ebc304..8e78eb118a 100644
--- a/src/PowerShell/Microsoft.WinGet.Configuration.Engine/PSObjects/PSUnitResult.cs
+++ b/src/PowerShell/Microsoft.WinGet.Configuration.Engine/PSObjects/PSUnitResult.cs
@@ -101,6 +101,10 @@ private string GetUnitMessage(ConfigurationUnit unit, IConfigurationUnitResultIn
return Resources.ConfigurationUnitManuallySkipped;
case ErrorCodes.WingetConfigErrorDependencyUnsatisfied:
return Resources.ConfigurationUnitNotRunDueToDependency;
+ case ErrorCodes.WinGetConfigUnitSettingConfigRoot:
+ return Resources.WinGetConfigUnitSettingConfigRoot;
+ case ErrorCodes.WinGetConfigUnitImportModuleAdmin:
+ return Resources.WinGetConfigUnitImportModuleAdmin;
}
switch (resultInfo.ResultSource)
diff --git a/src/PowerShell/Microsoft.WinGet.Configuration.Engine/Resources/Resources.Designer.cs b/src/PowerShell/Microsoft.WinGet.Configuration.Engine/Resources/Resources.Designer.cs
index 804e43e4ec..1b0d7b7892 100644
--- a/src/PowerShell/Microsoft.WinGet.Configuration.Engine/Resources/Resources.Designer.cs
+++ b/src/PowerShell/Microsoft.WinGet.Configuration.Engine/Resources/Resources.Designer.cs
@@ -554,5 +554,23 @@ internal static string SeeLineAndColumn {
return ResourceManager.GetString("SeeLineAndColumn", resourceCulture);
}
}
+
+ ///
+ /// Looks up a localized string similar to Loading the module for the configuration unit failed because it requires administrator privileges to run..
+ ///
+ internal static string WinGetConfigUnitImportModuleAdmin {
+ get {
+ return ResourceManager.GetString("WinGetConfigUnitImportModuleAdmin", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to A unit contains a setting that requires the config root..
+ ///
+ internal static string WinGetConfigUnitSettingConfigRoot {
+ get {
+ return ResourceManager.GetString("WinGetConfigUnitSettingConfigRoot", resourceCulture);
+ }
+ }
}
}
diff --git a/src/PowerShell/Microsoft.WinGet.Configuration.Engine/Resources/Resources.resx b/src/PowerShell/Microsoft.WinGet.Configuration.Engine/Resources/Resources.resx
index ba6966f185..56a39d0835 100644
--- a/src/PowerShell/Microsoft.WinGet.Configuration.Engine/Resources/Resources.resx
+++ b/src/PowerShell/Microsoft.WinGet.Configuration.Engine/Resources/Resources.resx
@@ -309,4 +309,10 @@
Have you reviewed the configuration and would you like to proceed verifying it against the system?
+
+ Loading the module for the configuration unit failed because it requires administrator privileges to run.
+
+
+ A unit contains a setting that requires the config root.
+
\ No newline at end of file