mirror of
https://github.com/tribufu/ServerManagers
synced 2026-05-06 15:17:34 +00:00
122 lines
4.2 KiB
C#
122 lines
4.2 KiB
C#
using NLog;
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Text;
|
|
|
|
namespace ServerManagerTool.Common.Utils
|
|
{
|
|
public static class ScriptUtils
|
|
{
|
|
public static Logger _logger = LogManager.GetCurrentClassLogger();
|
|
|
|
static int NextScriptId = 0;
|
|
|
|
public static bool RunElevatedShellScript(string scriptName, string script)
|
|
{
|
|
return RunShellScript(scriptName, script, withElevation: true);
|
|
}
|
|
|
|
public static bool RunShellScript(string scriptName, string script, bool withElevation = false, bool waitForExit = true, bool deleteOnExit = true, bool includePID = false)
|
|
{
|
|
var scriptNameBase = includePID ? $"{scriptName}_{Process.GetCurrentProcess().Id}" : scriptName;
|
|
|
|
string baseScriptPath = Path.Combine(Path.GetTempPath(), $"{scriptNameBase}.cmd");
|
|
string scriptWrapperPath = Path.Combine(Path.GetTempPath(), $"{scriptNameBase}_wrapper.cmd");
|
|
|
|
string scriptLogPath = null;
|
|
scriptLogPath = Path.ChangeExtension(baseScriptPath, ".out");
|
|
|
|
_logger.Debug($"Running Script (Elevation {withElevation}) : {script}");
|
|
|
|
var scriptId = NextScriptId++;
|
|
try
|
|
{
|
|
WriteCommandScript(baseScriptPath, script);
|
|
|
|
//
|
|
// Wrap to capture logging (necessary for running administrator scripts from non-admin contexts)
|
|
//
|
|
WriteCommandScript(scriptWrapperPath, $"CMD /C {baseScriptPath.AsQuoted()} > {scriptLogPath.AsQuoted()} 2>&1");
|
|
|
|
//
|
|
// Launch the process
|
|
//
|
|
ProcessStartInfo psInfo = new ProcessStartInfo()
|
|
{
|
|
FileName = $"{scriptWrapperPath.AsQuoted()}",
|
|
Verb = withElevation ? "runas" : String.Empty,
|
|
UseShellExecute = true,
|
|
CreateNoWindow = true,
|
|
//WindowStyle = ProcessWindowStyle.Hidden,
|
|
};
|
|
|
|
var process = new Process
|
|
{
|
|
EnableRaisingEvents = true,
|
|
StartInfo = psInfo,
|
|
};
|
|
|
|
process.Start();
|
|
|
|
//
|
|
// If we wait, copy the log files when the process is done.
|
|
//
|
|
if (waitForExit)
|
|
{
|
|
process.WaitForExit();
|
|
|
|
try
|
|
{
|
|
_logger.Debug($"SCRIPT {scriptId} OUTPUT: {File.ReadAllText(scriptLogPath)}");
|
|
}
|
|
catch { }
|
|
|
|
return process.ExitCode == 0;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.Error($"{nameof(RunShellScript)} - Failed to run elevated script. {ex.Message}\r\n{ex.StackTrace}");
|
|
Debug.WriteLine("Failed to run elevated script: {0}", ex.Message);
|
|
Debugger.Break();
|
|
return false;
|
|
}
|
|
finally
|
|
{
|
|
//
|
|
// If we aren't waiting, we can't delete because we will kill the scripts before cmd.exe gets a chance to run them.
|
|
//
|
|
if (waitForExit && deleteOnExit)
|
|
{
|
|
File.Delete(baseScriptPath);
|
|
File.Delete(scriptWrapperPath);
|
|
File.Delete(scriptLogPath);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void WriteCommandScript(string destinationPath, string script)
|
|
{
|
|
var builder = new StringBuilder();
|
|
|
|
// Change to the UTF8 code page
|
|
builder.AppendLine("chcp 65001");
|
|
builder.Append(script);
|
|
|
|
File.WriteAllText(destinationPath, builder.ToString(), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
|
|
}
|
|
|
|
public static string AsQuoted(this string parameter)
|
|
{
|
|
var newValue = parameter;
|
|
if (!newValue.StartsWith("\""))
|
|
newValue = "\"" + newValue;
|
|
if (!newValue.EndsWith("\""))
|
|
newValue += "\"";
|
|
return newValue;
|
|
}
|
|
}
|
|
}
|