161 lines
5.2 KiB
C#
161 lines
5.2 KiB
C#
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;
|
|
}
|
|
}
|