114 lines
3.8 KiB
C#
114 lines
3.8 KiB
C#
using System.Reflection;
|
|
|
|
namespace Plandent.MstscScriptHook.Configurator;
|
|
|
|
internal static class PluginInstaller
|
|
{
|
|
private const string ResourceName = "PlandentMstscScriptHook.Native.PlandentMstscScriptHook.dll";
|
|
public const string DllFileName = "PlandentMstscScriptHook.dll";
|
|
|
|
public static string InstallDirectory => Path.Combine(
|
|
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
|
"Plandent",
|
|
"MstscScriptHook");
|
|
|
|
public static string InstalledDllPath => Path.Combine(InstallDirectory, DllFileName);
|
|
|
|
public static void Install()
|
|
{
|
|
Directory.CreateDirectory(InstallDirectory);
|
|
ExtractPluginBinary(InstalledDllPath);
|
|
RegistryConfig.RegisterPlugin(InstalledDllPath);
|
|
}
|
|
|
|
public static UninstallResult Uninstall()
|
|
{
|
|
RegistryConfig.UnregisterPlugin();
|
|
|
|
if (!File.Exists(InstalledDllPath))
|
|
{
|
|
return new UninstallResult(true, "Plugin-Registrierung entfernt.");
|
|
}
|
|
|
|
try
|
|
{
|
|
File.Delete(InstalledDllPath);
|
|
TryDeleteEmptyInstallDirectory();
|
|
return new UninstallResult(true, "Plugin-Registrierung und DLL wurden entfernt.");
|
|
}
|
|
catch (IOException)
|
|
{
|
|
return new UninstallResult(
|
|
false,
|
|
"Die Registrierung wurde entfernt. Die DLL wird noch von mstsc.exe verwendet. " +
|
|
"Alle Remote-Desktop-Clients schließen und die Datei anschließend löschen bzw. erneut auf „Plugin entfernen“ klicken.");
|
|
}
|
|
catch (UnauthorizedAccessException ex)
|
|
{
|
|
return new UninstallResult(false, "Registrierung entfernt, DLL konnte aber nicht gelöscht werden: " + ex.Message);
|
|
}
|
|
}
|
|
|
|
public static bool IsInstalled(out string status)
|
|
{
|
|
string? registered = RegistryConfig.GetRegisteredPluginPath();
|
|
if (string.IsNullOrWhiteSpace(registered))
|
|
{
|
|
status = "Plugin ist nicht registriert.";
|
|
return false;
|
|
}
|
|
|
|
string expanded = Environment.ExpandEnvironmentVariables(registered);
|
|
if (!File.Exists(expanded))
|
|
{
|
|
status = $"Plugin ist registriert, DLL fehlt jedoch: {expanded}";
|
|
return false;
|
|
}
|
|
|
|
status = $"Plugin ist registriert: {expanded}";
|
|
return true;
|
|
}
|
|
|
|
private static void ExtractPluginBinary(string destination)
|
|
{
|
|
Assembly assembly = Assembly.GetExecutingAssembly();
|
|
using Stream? resource = assembly.GetManifestResourceStream(ResourceName);
|
|
if (resource is not null)
|
|
{
|
|
using FileStream output = new(destination, FileMode.Create, FileAccess.Write, FileShare.None);
|
|
resource.CopyTo(output);
|
|
return;
|
|
}
|
|
|
|
// Praktischer Fallback für Debugging/Entwicklung: DLL direkt neben der EXE akzeptieren.
|
|
string adjacent = Path.Combine(AppContext.BaseDirectory, DllFileName);
|
|
if (File.Exists(adjacent))
|
|
{
|
|
File.Copy(adjacent, destination, overwrite: true);
|
|
return;
|
|
}
|
|
|
|
throw new FileNotFoundException(
|
|
"Die native Plugin-DLL ist weder als Resource eingebettet noch neben der Konfigurations-EXE vorhanden. " +
|
|
"Bitte zuerst build-release.ps1 ausführen.",
|
|
DllFileName);
|
|
}
|
|
|
|
private static void TryDeleteEmptyInstallDirectory()
|
|
{
|
|
try
|
|
{
|
|
if (Directory.Exists(InstallDirectory) && !Directory.EnumerateFileSystemEntries(InstallDirectory).Any())
|
|
{
|
|
Directory.Delete(InstallDirectory);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// Unkritisch: ein leeres Verzeichnis darf bestehen bleiben.
|
|
}
|
|
}
|
|
}
|
|
|
|
internal sealed record UninstallResult(bool FullyRemoved, string Message);
|