diff --git a/DellMonitorControl/DellMonitorControl.csproj b/DellMonitorControl/DellMonitorControl.csproj
index 33bc968..5233e95 100644
--- a/DellMonitorControl/DellMonitorControl.csproj
+++ b/DellMonitorControl/DellMonitorControl.csproj
@@ -15,9 +15,9 @@
- 1.1.0
- 1.1.0.0
- 1.1.0.0
+ 1.1.1
+ 1.1.1.0
+ 1.1.1.0
diff --git a/Library/Helpers/ConsoleHelper.cs b/Library/Helpers/ConsoleHelper.cs
index e490303..dbf215c 100644
--- a/Library/Helpers/ConsoleHelper.cs
+++ b/Library/Helpers/ConsoleHelper.cs
@@ -41,6 +41,46 @@ internal class ConsoleHelper
return await readTask;
}
+ ///
+ /// Execute an exe directly with arguments (no cmd.exe or batch file wrapper)
+ ///
+ public static async Task<(string Output, int ExitCode)> ExecuteExeAsync(string exePath, string arguments, int timeoutMs = 5000)
+ {
+ var p = new Process
+ {
+ StartInfo = new ProcessStartInfo
+ {
+ FileName = exePath,
+ Arguments = arguments,
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true
+ }
+ };
+
+ p.Start();
+
+ var readTask = Task.Run(async () =>
+ {
+ var output = await p.StandardOutput.ReadToEndAsync();
+ await p.WaitForExitAsync();
+ return (output, p.ExitCode);
+ });
+
+ var completedTask = await Task.WhenAny(readTask, Task.Delay(timeoutMs));
+
+ if (completedTask != readTask)
+ {
+ try { p.Kill(true); } catch { }
+ return (string.Empty, -1);
+ }
+
+ var result = await readTask;
+ p.Close();
+ return result;
+ }
+
public static async Task CmdCommandAsync(params string[] cmds) =>
await CommandAsync(cmdFileName, cmds);
diff --git a/Library/Method/CMMCommand.cs b/Library/Method/CMMCommand.cs
index 87f6df3..fc950af 100644
--- a/Library/Method/CMMCommand.cs
+++ b/Library/Method/CMMCommand.cs
@@ -17,37 +17,36 @@ public static class CMMCommand
public static async Task ScanMonitor()
{
await BytesToFileAsync(new(CMMexe));
- await ConsoleHelper.CmdCommandAsync($"{CMMexe} /smonitors {CMMsMonitors}");
+ await ConsoleHelper.ExecuteExeAsync(CMMexe, $"/smonitors {CMMsMonitors}");
}
- public static Task PowerOn(string monitorSN)
- {
- return ConsoleHelper.CmdCommandAsync($"{CMMexe} /SetValue {monitorSN} D6 1");
- }
-
- public static Task Sleep(string monitorSN)
+ public static async Task PowerOn(string monitorSN)
{
- return ConsoleHelper.CmdCommandAsync($"{CMMexe} /SetValue {monitorSN} D6 4");
+ await ConsoleHelper.ExecuteExeAsync(CMMexe, $"/SetValue {monitorSN} D6 1");
+ }
+
+ public static async Task Sleep(string monitorSN)
+ {
+ await ConsoleHelper.ExecuteExeAsync(CMMexe, $"/SetValue {monitorSN} D6 4");
}
private static async Task GetMonitorValue(string monitorSN, string vcpCode = "D6", int maxRetries = 2)
{
for (int attempt = 0; attempt <= maxRetries; attempt++)
{
- var cmdFileName = Path.Combine(CMMTmpFolder, $"{Guid.NewGuid()}.bat");
- var cmd = $"{CMMexe} /GetValue {monitorSN} {vcpCode}\r\n" +
- $"echo %errorlevel%";
- File.WriteAllText(cmdFileName, cmd);
- var values = await ConsoleHelper.ExecuteCommand(cmdFileName);
- try { File.Delete(cmdFileName); } catch { }
+ // Execute directly without batch file wrapper
+ var (output, exitCode) = await ConsoleHelper.ExecuteExeAsync(
+ CMMexe,
+ $"/GetValue {monitorSN} {vcpCode}");
// Empty result means timeout - don't retry, monitor is unresponsive
- if (string.IsNullOrEmpty(values))
+ if (string.IsNullOrEmpty(output) && exitCode == -1)
return string.Empty;
- var value = values.Split("\r\n", StringSplitOptions.RemoveEmptyEntries).LastOrDefault();
+ // Parse output - ControlMyMonitor outputs the value directly
+ var value = output?.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).LastOrDefault()?.Trim();
- if (!string.IsNullOrEmpty(value) && value != "0")
+ if (!string.IsNullOrEmpty(value) && exitCode == 0)
return value;
// Only retry on non-timeout failures
@@ -60,9 +59,9 @@ public static class CMMCommand
#region Brightness (VCP Code 10)
- public static Task SetBrightness(string monitorSN, int value)
+ public static async Task SetBrightness(string monitorSN, int value)
{
- return ConsoleHelper.CmdCommandAsync($"{CMMexe} /SetValue {monitorSN} 10 {value}");
+ await ConsoleHelper.ExecuteExeAsync(CMMexe, $"/SetValue {monitorSN} 10 {value}");
}
public static async Task GetBrightness(string monitorSN)
@@ -75,9 +74,9 @@ public static class CMMCommand
#region Contrast (VCP Code 12)
- public static Task SetContrast(string monitorSN, int value)
+ public static async Task SetContrast(string monitorSN, int value)
{
- return ConsoleHelper.CmdCommandAsync($"{CMMexe} /SetValue {monitorSN} 12 {value}");
+ await ConsoleHelper.ExecuteExeAsync(CMMexe, $"/SetValue {monitorSN} 12 {value}");
}
public static async Task GetContrast(string monitorSN)
@@ -90,9 +89,9 @@ public static class CMMCommand
#region Input Source (VCP Code 60)
- public static Task SetInputSource(string monitorSN, int value)
+ public static async Task SetInputSource(string monitorSN, int value)
{
- return ConsoleHelper.CmdCommandAsync($"{CMMexe} /SetValue {monitorSN} 60 {value}");
+ await ConsoleHelper.ExecuteExeAsync(CMMexe, $"/SetValue {monitorSN} 60 {value}");
}
public static async Task GetInputSource(string monitorSN)
@@ -106,7 +105,7 @@ public static class CMMCommand
var options = new List();
var savePath = Path.Combine(CMMTmpFolder, $"{monitorSN}_vcp.tmp");
- await ConsoleHelper.CmdCommandAsync($"{CMMexe} /sjson {savePath} {monitorSN}");
+ await ConsoleHelper.ExecuteExeAsync(CMMexe, $"/sjson {savePath} {monitorSN}");
if (!File.Exists(savePath)) return options;
@@ -183,7 +182,7 @@ public static class CMMCommand
static async Task ScanMonitorStatus(string savePath, XMonitor mon)
{
- await ConsoleHelper.CmdCommandAsync($"{CMMexe} /sjson {savePath} {mon.MonitorID}");
+ await ConsoleHelper.ExecuteExeAsync(CMMexe, $"/sjson {savePath} {mon.MonitorID}");
var monitorModel = JsonHelper.JsonFormFile>(savePath);
var status = monitorModel.ReadMonitorStatus();