Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 57 additions & 2 deletions RunAsService/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Text;

Expand All @@ -7,6 +7,7 @@
using System.Reflection;
using System.Diagnostics;
using System.ServiceProcess;
using System.Threading;

namespace RunAsService {
class RunAsService {
Expand Down Expand Up @@ -518,14 +519,68 @@ protected override void OnStart(string[] args) {
CreateNoWindow = true,
ErrorDialog = false,
WindowStyle = ProcessWindowStyle.Hidden,
WorkingDirectory = Path.GetDirectoryName(consoleApplicationExecutablePath)
};

process = Process.Start(oProcessStartInfo);
}

protected override void OnStop() {
process.Kill();
// send ctrl+c to process for graceful shutdown
StopProgram((uint)process.Id);
if (!process.HasExited) process.Kill();
process = null;
}

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AttachConsole(uint dwProcessId);

[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern bool FreeConsole();

[DllImport("kernel32.dll")]
static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate handler, bool add);

// Delegate type to be used as the Handler Routine for SCCH
delegate Boolean ConsoleCtrlDelegate(CtrlTypes type);

// Enumerated type for the control messages sent to the handler routine
enum CtrlTypes : uint
{
CTRL_C_EVENT = 0,
CTRL_BREAK_EVENT,
CTRL_CLOSE_EVENT,
CTRL_LOGOFF_EVENT = 5,
CTRL_SHUTDOWN_EVENT
}

[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GenerateConsoleCtrlEvent(CtrlTypes dwCtrlEvent, uint dwProcessGroupId);

public static void StopProgram(uint pid)
{
// It's impossible to be attached to 2 consoles at the same time,
// so release the current one.
FreeConsole();

// This does not require the console window to be visible.
if (AttachConsole(pid))
{
// Disable Ctrl-C handling for our program
SetConsoleCtrlHandler(null, true);
GenerateConsoleCtrlEvent(CtrlTypes.CTRL_C_EVENT, 0);

// Must wait here. If we don't and re-enable Ctrl-C
// handling below too fast, we might terminate ourselves.
Thread.Sleep(2000);

FreeConsole();

// Re-enable Ctrl-C handling or any subsequently started
// programs will inherit the disabled state.
SetConsoleCtrlHandler(null, false);
}
}
}
}