diff --git a/Localization/Resources/de-DE/Resources.de-DE.resx b/Localization/Resources/de-DE/Resources.de-DE.resx
index 71517b84..eecde663 100644
--- a/Localization/Resources/de-DE/Resources.de-DE.resx
+++ b/Localization/Resources/de-DE/Resources.de-DE.resx
@@ -1441,9 +1441,6 @@ Warnung: Die Verwendung dieses Arguments kann dazu führen, dass das Token proto
Es wurde kein Vorgang angegeben. Verwenden Sie „--help“, um verfügbare Vorgänge anzuzeigen.
-
- Der Vorgang der DSC-Ressource ist fehlgeschlagen
-
Gibt an, ob sich eine Instanz im gewünschten Zustand befindet
diff --git a/Localization/Resources/es-ES/Resources.es-ES.resx b/Localization/Resources/es-ES/Resources.es-ES.resx
index 414179ed..a13dee7c 100644
--- a/Localization/Resources/es-ES/Resources.es-ES.resx
+++ b/Localization/Resources/es-ES/Resources.es-ES.resx
@@ -1441,9 +1441,6 @@ Advertencia: El uso de este argumento puede resultar en que se registre el token
No se especificó ninguna operación. Utilice --help para ver las operaciones disponibles.
-
- La operación del recurso DSC ha fallado
-
Indica si una instancia se encuentra en el estado deseado
diff --git a/Localization/Resources/fr-FR/Resources.fr-FR.resx b/Localization/Resources/fr-FR/Resources.fr-FR.resx
index 411cb7a5..5b22d7d8 100644
--- a/Localization/Resources/fr-FR/Resources.fr-FR.resx
+++ b/Localization/Resources/fr-FR/Resources.fr-FR.resx
@@ -1441,9 +1441,6 @@ Avertissement : l’utilisation de cet argument peut entraîner la journalisati
Aucune opération n’est spécifiée. Utilisez --help pour voir les opérations disponibles.
-
- Nous n’avons pas pu effectuer l’opération de la ressource DSC
-
Indique si un instance est dans l’état souhaité
diff --git a/Localization/Resources/it-IT/Resources.it-IT.resx b/Localization/Resources/it-IT/Resources.it-IT.resx
index 1c8f9379..97b6afc3 100644
--- a/Localization/Resources/it-IT/Resources.it-IT.resx
+++ b/Localization/Resources/it-IT/Resources.it-IT.resx
@@ -1441,9 +1441,6 @@ Avviso: l'uso di questo argomento può comportare la registrazione del token. Va
Nessuna operazione specificata. Usa --help per visualizzare le operazioni disponibili.
-
- Operazione sulla risorsa DSC non riuscita
-
Indica se un'istanza si trova nello stato desiderato
diff --git a/Localization/Resources/ja-JP/Resources.ja-JP.resx b/Localization/Resources/ja-JP/Resources.ja-JP.resx
index 4a9421c5..14bb81d1 100644
--- a/Localization/Resources/ja-JP/Resources.ja-JP.resx
+++ b/Localization/Resources/ja-JP/Resources.ja-JP.resx
@@ -1441,9 +1441,6 @@
エラー: 操作が指定されていません。--help を使用して、使用可能な操作を確認してください。
-
- DSC リソース操作に失敗しました
-
インスタンスが目的の状態であるかどうかを示します
diff --git a/Localization/Resources/ko-KR/Resources.ko-KR.resx b/Localization/Resources/ko-KR/Resources.ko-KR.resx
index 335ada25..33802483 100644
--- a/Localization/Resources/ko-KR/Resources.ko-KR.resx
+++ b/Localization/Resources/ko-KR/Resources.ko-KR.resx
@@ -1441,9 +1441,6 @@
지정된 작업이 없습니다. --help를 사용하여 사용 가능한 작업을 확인하세요.
-
- DSC 리소스 작업이 실패했습니다.
-
인스턴스가 원하는 상태인지 여부를 나타냅니다.
diff --git a/Localization/Resources/pt-BR/Resources.pt-BR.resx b/Localization/Resources/pt-BR/Resources.pt-BR.resx
index 397df8e3..274ee180 100644
--- a/Localization/Resources/pt-BR/Resources.pt-BR.resx
+++ b/Localization/Resources/pt-BR/Resources.pt-BR.resx
@@ -1441,9 +1441,6 @@ Aviso: o uso desse argumento pode fazer com que o token seja registrado. Consid
Nenhuma operação especificada. Use --help para ver as operações disponíveis.
-
- Falha na operação do recurso DSC
-
Indica se uma instância está no estado desejado
diff --git a/Localization/Resources/ru-RU/Resources.ru-RU.resx b/Localization/Resources/ru-RU/Resources.ru-RU.resx
index c2819724..c5c30b6e 100644
--- a/Localization/Resources/ru-RU/Resources.ru-RU.resx
+++ b/Localization/Resources/ru-RU/Resources.ru-RU.resx
@@ -1441,9 +1441,6 @@
Операция не указана. Используйте параметр --help для просмотра доступных операций.
-
- Сбой операции с ресурсом DSC
-
Указывает, находится ли экземпляр в желаемом состоянии
diff --git a/Localization/Resources/zh-CN/Resources.zh-CN.resx b/Localization/Resources/zh-CN/Resources.zh-CN.resx
index e09d7fe8..214b87ef 100644
--- a/Localization/Resources/zh-CN/Resources.zh-CN.resx
+++ b/Localization/Resources/zh-CN/Resources.zh-CN.resx
@@ -1441,9 +1441,6 @@
未指定任何操作。使用 --help 查看可用操作。
-
- DSC 资源操作失败
-
指示实例是否处于所需状态
diff --git a/Localization/Resources/zh-TW/Resources.zh-TW.resx b/Localization/Resources/zh-TW/Resources.zh-TW.resx
index 258271be..6d9fec26 100644
--- a/Localization/Resources/zh-TW/Resources.zh-TW.resx
+++ b/Localization/Resources/zh-TW/Resources.zh-TW.resx
@@ -1441,9 +1441,6 @@
未指定任何作業。使用 --help 查看可用的作業。
-
- DSC 資源作業失敗
-
指出實例是否處於預期狀態
diff --git a/src/WingetCreateCLI/Commands/DscCommand.cs b/src/WingetCreateCLI/Commands/DscCommand.cs
index c703acd3..9d14f103 100644
--- a/src/WingetCreateCLI/Commands/DscCommand.cs
+++ b/src/WingetCreateCLI/Commands/DscCommand.cs
@@ -96,13 +96,7 @@ public override async Task Execute()
{
if (methodFlag)
{
- if (!methodAction())
- {
- Logger.ErrorLocalized(nameof(Resources.DscResourceOperationFailed_Message));
- return false;
- }
-
- return true;
+ return methodAction();
}
}
diff --git a/src/WingetCreateCLI/Commands/DscCommands/BaseDscCommand.cs b/src/WingetCreateCLI/Commands/DscCommands/BaseDscCommand.cs
index 5f25db86..aa3387c7 100644
--- a/src/WingetCreateCLI/Commands/DscCommands/BaseDscCommand.cs
+++ b/src/WingetCreateCLI/Commands/DscCommands/BaseDscCommand.cs
@@ -85,10 +85,34 @@ public static List GetAvailableCommands()
/// True if the command was successful; otherwise, false.
public abstract bool Schema();
+ ///
+ /// Writes a JSON output line to the console.
+ ///
+ /// The JSON token to be written.
+ protected static void WriteJsonOutputLine(JToken token)
+ {
+ Console.WriteLine(token.ToString(Formatting.None));
+ }
+
+ ///
+ /// Writes a JSON output line to the error stream.
+ ///
+ /// The message level.
+ /// The message to be written.
+ protected static void WriteMessageOutputLine(DscMessageLevel level, string message)
+ {
+ var token = new JObject
+ {
+ [GetMessageLevel(level)] = message,
+ };
+ Console.Error.WriteLine(token.ToString(Formatting.None));
+ }
+
///
/// Creates a Json schema for a DSC resource object.
///
/// The type of the resource object.
+ /// The name of the command for which the schema is being created.
/// A Json object representing the schema.
protected JObject CreateSchema(string commandName)
where T : BaseResourceObject, new()
@@ -106,11 +130,21 @@ protected JObject CreateSchema(string commandName)
}
///
- /// Writes a JSON output line to the console.
+ /// Gets the message level as a string based on the provided DscMessageLevel enum value.
///
- /// The JSON token to be written.
- protected void WriteJsonOutputLine(JToken token)
+ /// The DscMessageLevel enum value.
+ /// A string representation of the message level.
+ /// Thrown when the provided message level is not recognized.
+ private static string GetMessageLevel(DscMessageLevel level)
{
- Console.WriteLine(token.ToString(Formatting.None));
+ return level switch
+ {
+ DscMessageLevel.Error => "error",
+ DscMessageLevel.Warning => "warn",
+ DscMessageLevel.Info => "info",
+ DscMessageLevel.Debug => "debug",
+ DscMessageLevel.Trace => "trace",
+ _ => throw new ArgumentOutOfRangeException(nameof(level), level, null),
+ };
}
}
diff --git a/src/WingetCreateCLI/Commands/DscCommands/DscSettingsCommand.cs b/src/WingetCreateCLI/Commands/DscCommands/DscSettingsCommand.cs
index fd6538da..06844760 100644
--- a/src/WingetCreateCLI/Commands/DscCommands/DscSettingsCommand.cs
+++ b/src/WingetCreateCLI/Commands/DscCommands/DscSettingsCommand.cs
@@ -3,7 +3,6 @@
namespace Microsoft.WingetCreateCLI.Commands.DscCommands;
-using Microsoft.WingetCreateCLI.Logging;
using Microsoft.WingetCreateCLI.Models.DscModels;
using Microsoft.WingetCreateCLI.Properties;
using Newtonsoft.Json.Linq;
@@ -29,7 +28,7 @@ public override bool Set(JToken input)
{
if (input == null)
{
- Logger.ErrorLocalized(nameof(Resources.DscInputRequired_Message), nameof(this.Set));
+ WriteMessageOutputLine(DscMessageLevel.Error, string.Format(Resources.DscInputRequired_Message, nameof(this.Set)));
return false;
}
@@ -45,8 +44,8 @@ public override bool Set(JToken input)
data.Set();
}
- this.WriteJsonOutputLine(data.Output.ToJson());
- this.WriteJsonOutputLine(diff);
+ WriteJsonOutputLine(data.Output.ToJson());
+ WriteJsonOutputLine(diff);
return true;
}
@@ -55,7 +54,7 @@ public override bool Test(JToken input)
{
if (input == null)
{
- Logger.ErrorLocalized(nameof(Resources.DscInputRequired_Message), nameof(this.Test));
+ WriteMessageOutputLine(DscMessageLevel.Error, string.Format(Resources.DscInputRequired_Message, nameof(this.Test)));
return false;
}
@@ -64,8 +63,8 @@ public override bool Test(JToken input)
data.Get();
data.Output.InDesiredState = data.Test();
- this.WriteJsonOutputLine(data.Output.ToJson());
- this.WriteJsonOutputLine(data.DiffJson());
+ WriteJsonOutputLine(data.Output.ToJson());
+ WriteJsonOutputLine(data.DiffJson());
return true;
}
@@ -74,14 +73,14 @@ public override bool Export(JToken input)
{
var data = new SettingsFunctionData();
data.Get();
- this.WriteJsonOutputLine(data.Output.ToJson());
+ WriteJsonOutputLine(data.Output.ToJson());
return true;
}
///
public override bool Schema()
{
- this.WriteJsonOutputLine(this.CreateSchema(CommandName));
+ WriteJsonOutputLine(this.CreateSchema(CommandName));
return true;
}
}
diff --git a/src/WingetCreateCLI/Models/DscModels/DscMessageLevel.cs b/src/WingetCreateCLI/Models/DscModels/DscMessageLevel.cs
new file mode 100644
index 00000000..f98bc75b
--- /dev/null
+++ b/src/WingetCreateCLI/Models/DscModels/DscMessageLevel.cs
@@ -0,0 +1,35 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license.
+
+namespace Microsoft.WingetCreateCLI.Models.DscModels;
+
+///
+/// Specifies the severity level of a message.
+///
+public enum DscMessageLevel
+{
+ ///
+ /// Represents an error message.
+ ///
+ Error,
+
+ ///
+ /// Represents a warning message.
+ ///
+ Warning,
+
+ ///
+ /// Represents an informational message.
+ ///
+ Info,
+
+ ///
+ /// Represents a debug message.
+ ///
+ Debug,
+
+ ///
+ /// Represents a trace message.
+ ///
+ Trace,
+}
diff --git a/src/WingetCreateCLI/Properties/Resources.Designer.cs b/src/WingetCreateCLI/Properties/Resources.Designer.cs
index d2b0f9e0..67cecdbf 100644
--- a/src/WingetCreateCLI/Properties/Resources.Designer.cs
+++ b/src/WingetCreateCLI/Properties/Resources.Designer.cs
@@ -843,15 +843,6 @@ public static string DscResourceNameNotFound_Message {
}
}
- ///
- /// Looks up a localized string similar to DSC resource operation failed.
- ///
- public static string DscResourceOperationFailed_Message {
- get {
- return ResourceManager.GetString("DscResourceOperationFailed_Message", resourceCulture);
- }
- }
-
///
/// Looks up a localized string similar to No operation specified. Use --help to see available operations..
///
diff --git a/src/WingetCreateCLI/Properties/Resources.resx b/src/WingetCreateCLI/Properties/Resources.resx
index e5791b33..ac75be2c 100644
--- a/src/WingetCreateCLI/Properties/Resources.resx
+++ b/src/WingetCreateCLI/Properties/Resources.resx
@@ -1441,9 +1441,6 @@ Warning: Using this argument may result in the token being logged. Consider an a
No operation specified. Use --help to see available operations.
-
- DSC resource operation failed
-
Indicates whether an instance is in the desired state
diff --git a/src/WingetCreateCLI/WingetCreateCLI.csproj b/src/WingetCreateCLI/WingetCreateCLI.csproj
index c43df76f..b29439bf 100644
--- a/src/WingetCreateCLI/WingetCreateCLI.csproj
+++ b/src/WingetCreateCLI/WingetCreateCLI.csproj
@@ -98,10 +98,6 @@
-
-
-
-
diff --git a/src/WingetCreateTests/WingetCreateTests/Models/DscExecuteResult.cs b/src/WingetCreateTests/WingetCreateTests/Models/DscExecuteResult.cs
index 5c4fb083..a9c11410 100644
--- a/src/WingetCreateTests/WingetCreateTests/Models/DscExecuteResult.cs
+++ b/src/WingetCreateTests/WingetCreateTests/Models/DscExecuteResult.cs
@@ -6,6 +6,7 @@ namespace Microsoft.WingetCreateUnitTests.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Linq;
using Microsoft.WingetCreateCLI.Models.DscModels;
using Newtonsoft.Json;
@@ -18,11 +19,13 @@ public class DscExecuteResult
/// Initializes a new instance of the class.
///
/// Value indicating whether the command execution was successful.
- /// Output of the command execution.
- public DscExecuteResult(bool success, string output)
+ /// Output stream content.
+ /// Error stream content.
+ public DscExecuteResult(bool success, string output, string error)
{
this.Success = success;
this.Output = output;
+ this.Error = error;
}
///
@@ -31,10 +34,29 @@ public DscExecuteResult(bool success, string output)
public bool Success { get; }
///
- /// Gets the output result of the operation.
+ /// Gets the output stream content of the operation.
///
public string Output { get; }
+ ///
+ /// Gets the error stream content of the operation.
+ ///
+ public string Error { get; }
+
+ ///
+ /// Gets the messages from the error stream.
+ ///
+ /// List of messages with their levels.
+ public List<(DscMessageLevel Level, string Message)> Messages()
+ {
+ var lines = this.Error.Split([Environment.NewLine], StringSplitOptions.RemoveEmptyEntries);
+ return lines.SelectMany(line =>
+ {
+ var map = JsonConvert.DeserializeObject>(line);
+ return map.Select(kvp => (this.GetMessageLevel(kvp.Key), kvp.Value)).ToList();
+ }).ToList();
+ }
+
///
/// Gets the output as settings state.
///
@@ -58,4 +80,23 @@ public SettingsResourceObject OutputState()
var diff = JsonConvert.DeserializeObject>(lines[1]);
return (settingsObject, diff);
}
+
+ ///
+ /// Gets the message level from a string representation.
+ ///
+ /// The string representation of the message level.
+ /// The level as .
+ /// Thrown when the level is unknown.
+ private DscMessageLevel GetMessageLevel(string level)
+ {
+ return level switch
+ {
+ "error" => DscMessageLevel.Error,
+ "warn" => DscMessageLevel.Warning,
+ "info" => DscMessageLevel.Info,
+ "debug" => DscMessageLevel.Debug,
+ "trace" => DscMessageLevel.Trace,
+ _ => throw new ArgumentOutOfRangeException(nameof(level), level, "Unknown message level"),
+ };
+ }
}
diff --git a/src/WingetCreateTests/WingetCreateTests/TestUtils.cs b/src/WingetCreateTests/WingetCreateTests/TestUtils.cs
index 99f5e916..9058ab5c 100644
--- a/src/WingetCreateTests/WingetCreateTests/TestUtils.cs
+++ b/src/WingetCreateTests/WingetCreateTests/TestUtils.cs
@@ -224,11 +224,14 @@ public static void DeleteCachedFiles(List testFileNames)
/// Result of executing the DSC command.
public static async Task ExecuteDscCommandAsync(params string[] args)
{
- var sw = new StringWriter();
- Console.SetOut(sw);
+ var outSw = new StringWriter();
+ var errSw = new StringWriter();
+ Console.SetOut(outSw);
+ Console.SetError(errSw);
var executeResult = await Parser.Default.ParseArguments(args).Value.Execute();
- var output = sw.ToString();
- return new(executeResult, output);
+ var output = outSw.ToString();
+ var errorOutput = errSw.ToString();
+ return new(executeResult, output, errorOutput);
}
}
}
diff --git a/src/WingetCreateTests/WingetCreateTests/UnitTests/DscCommandTests.cs b/src/WingetCreateTests/WingetCreateTests/UnitTests/DscCommandTests.cs
index 46783c86..079567e9 100644
--- a/src/WingetCreateTests/WingetCreateTests/UnitTests/DscCommandTests.cs
+++ b/src/WingetCreateTests/WingetCreateTests/UnitTests/DscCommandTests.cs
@@ -86,6 +86,5 @@ public async Task DscSettingsResourceFailedOperation_ErrorMessage()
// Assert
Assert.That(result.Success, Is.False);
- Assert.That(result.Output, Does.Contain(Resources.DscResourceOperationFailed_Message));
}
}
diff --git a/src/WingetCreateTests/WingetCreateTests/UnitTests/DscSettingsCommandTests.cs b/src/WingetCreateTests/WingetCreateTests/UnitTests/DscSettingsCommandTests.cs
index b9d170c8..ee19ba32 100644
--- a/src/WingetCreateTests/WingetCreateTests/UnitTests/DscSettingsCommandTests.cs
+++ b/src/WingetCreateTests/WingetCreateTests/UnitTests/DscSettingsCommandTests.cs
@@ -112,10 +112,13 @@ public async Task DscSettingsResource_SetEmpty_Fail()
{
// Act
var result = await TestUtils.ExecuteDscCommandAsync(DscSettingsCommand.CommandName, "--set", string.Empty);
+ var messages = result.Messages();
// Assert
Assert.That(result.Success, Is.False);
- Assert.That(result.Output, Does.Contain(string.Format(Resources.DscInputRequired_Message, nameof(DscSettingsCommand.Set))));
+ Assert.That(messages.Count, Is.EqualTo(1));
+ Assert.That(messages[0].Level, Is.EqualTo(DscMessageLevel.Error));
+ Assert.That(messages[0].Message, Is.EqualTo(string.Format(Resources.DscInputRequired_Message, nameof(DscSettingsCommand.Set))));
}
///
@@ -127,10 +130,13 @@ public async Task DscSettingsResource_TestEmpty_Fail()
{
// Act
var result = await TestUtils.ExecuteDscCommandAsync(DscSettingsCommand.CommandName, "--test", string.Empty);
+ var messages = result.Messages();
// Assert
Assert.That(result.Success, Is.False);
- Assert.That(result.Output, Does.Contain(string.Format(Resources.DscInputRequired_Message, nameof(DscSettingsCommand.Test))));
+ Assert.That(messages.Count, Is.EqualTo(1));
+ Assert.That(messages[0].Level, Is.EqualTo(DscMessageLevel.Error));
+ Assert.That(messages[0].Message, Is.EqualTo(string.Format(Resources.DscInputRequired_Message, nameof(DscSettingsCommand.Test))));
}
///