Initialversion

This commit is contained in:
2026-08-09 13:27:53 +02:00
commit eec4f52b5a
25 changed files with 2123 additions and 0 deletions
+160
View File
@@ -0,0 +1,160 @@
using System.Diagnostics;
namespace Plandent.MstscScriptHook.Configurator;
internal static class ScriptTestLauncher
{
public static Process Start(HookConfig config)
{
string scriptPath = Environment.ExpandEnvironmentVariables(config.ScriptPath ?? string.Empty);
if (string.IsNullOrWhiteSpace(scriptPath) || !File.Exists(scriptPath))
{
throw new FileNotFoundException("Das ausgewählte Script wurde nicht gefunden.", scriptPath);
}
string extension = Path.GetExtension(scriptPath).ToLowerInvariant();
string workingDirectory = string.IsNullOrWhiteSpace(config.WorkingDirectory)
? Path.GetDirectoryName(scriptPath) ?? Environment.CurrentDirectory
: Environment.ExpandEnvironmentVariables(config.WorkingDirectory);
var startInfo = new ProcessStartInfo
{
UseShellExecute = false,
CreateNoWindow = config.Hidden,
WindowStyle = config.Hidden ? ProcessWindowStyle.Hidden : ProcessWindowStyle.Normal,
WorkingDirectory = workingDirectory
};
switch (extension)
{
case ".bat":
case ".cmd":
startInfo.FileName = Environment.GetEnvironmentVariable("ComSpec")
?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "cmd.exe");
startInfo.ArgumentList.Add("/D");
startInfo.ArgumentList.Add("/S");
startInfo.ArgumentList.Add("/C");
startInfo.ArgumentList.Add(BuildCmdCommand(scriptPath, config.Arguments));
break;
case ".ps1":
startInfo.FileName = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.System),
"WindowsPowerShell",
"v1.0",
"powershell.exe");
startInfo.ArgumentList.Add("-NoLogo");
startInfo.ArgumentList.Add("-NoProfile");
startInfo.ArgumentList.Add("-NonInteractive");
startInfo.ArgumentList.Add("-ExecutionPolicy");
startInfo.ArgumentList.Add("Bypass");
startInfo.ArgumentList.Add("-File");
startInfo.ArgumentList.Add(scriptPath);
AddRawArguments(startInfo, config.Arguments);
break;
case ".exe":
startInfo.FileName = scriptPath;
AddRawArguments(startInfo, config.Arguments);
break;
default:
throw new NotSupportedException("Unterstützt werden .bat, .cmd, .ps1 und .exe.");
}
return Process.Start(startInfo)
?? throw new InvalidOperationException("Der Testprozess konnte nicht gestartet werden.");
}
private static string BuildCmdCommand(string scriptPath, string? arguments)
{
string command = QuoteForCmd(scriptPath);
if (!string.IsNullOrWhiteSpace(arguments))
{
command += " " + arguments;
}
return command;
}
private static string QuoteForCmd(string value)
{
return "\"" + value.Replace("\"", "\\\"") + "\"";
}
// Die GUI behandelt das Argumentfeld bewusst als Kommandozeilen-Argumentstring.
// Für den Test wird eine einfache Windows-Argumentzerlegung verwendet. Das Plugin selbst
// übergibt den String unverändert an cmd.exe/PowerShell bzw. an die EXE-Kommandozeile.
private static void AddRawArguments(ProcessStartInfo startInfo, string? raw)
{
if (string.IsNullOrWhiteSpace(raw))
{
return;
}
foreach (string argument in CommandLineSplitter.Split(raw))
{
startInfo.ArgumentList.Add(argument);
}
}
}
internal static class CommandLineSplitter
{
public static IReadOnlyList<string> Split(string commandLine)
{
var result = new List<string>();
var current = new System.Text.StringBuilder();
bool inQuotes = false;
int backslashes = 0;
for (int i = 0; i < commandLine.Length; i++)
{
char ch = commandLine[i];
if (ch == '\\')
{
backslashes++;
continue;
}
if (ch == '"')
{
current.Append('\\', backslashes / 2);
if (backslashes % 2 == 0)
{
inQuotes = !inQuotes;
}
else
{
current.Append('"');
}
backslashes = 0;
continue;
}
current.Append('\\', backslashes);
backslashes = 0;
if (char.IsWhiteSpace(ch) && !inQuotes)
{
if (current.Length > 0)
{
result.Add(current.ToString());
current.Clear();
}
}
else
{
current.Append(ch);
}
}
current.Append('\\', backslashes);
if (current.Length > 0)
{
result.Add(current.ToString());
}
return result;
}
}