From f86f622f0ba76733bdeaa3fbf911808799ca8cff Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 17 Nov 2010 22:04:49 -0800 Subject: [PATCH] improving code to work better in UAC environment --- Main.cs | 38 +++++++++++++++++++++++++++++++++----- manifest.xml | 10 ++++++++++ winsw.csproj | 10 ++++++++++ 3 files changed, 53 insertions(+), 5 deletions(-) create mode 100755 manifest.xml diff --git a/Main.cs b/Main.cs index 4b6f25be..34d2a365 100644 --- a/Main.cs +++ b/Main.cs @@ -435,8 +435,12 @@ private static void CopyStream(Stream i, Stream o) public class WrapperService : ServiceBase { - [DllImport("ADVAPI32.DLL", EntryPoint = "SetServiceStatus")] + [DllImport("ADVAPI32.DLL")] private static extern bool SetServiceStatus(IntPtr hServiceStatus, ref SERVICE_STATUS lpServiceStatus); + + [DllImport("Kernel32.dll", SetLastError = true)] + public static extern int SetStdHandle(int device, IntPtr handle); + private SERVICE_STATUS wrapperServiceStatus; private Process process = new Process(); @@ -672,7 +676,7 @@ private void WriteEvent(String message) log.Close(); } - protected override void OnStart(string[] args) + protected override void OnStart(string[] _) { envs = descriptor.EnvironmentVariables; foreach (string key in envs.Keys) @@ -915,14 +919,38 @@ private static void ThrowNoSuchService() throw new WmiException(ReturnValue.NoSuchService); } - public static void Run(string[] args) + public static void Run(string[] _args) { - if (args.Length > 0) + if (_args.Length > 0) { var d = new ServiceDescriptor(); Win32Services svc = new WmiRoot().GetCollection(); Win32Service s = svc.Select(d.Id); + var args = new List(Array.AsReadOnly(_args)); + if (args[0] == "/redirect") + { + // Redirect output + // One might ask why we support this when the caller + // can redirect the output easily. The answer is for supporting UAC. + // On UAC-enabled Windows such as Vista, SCM operation requires + // elevated privileges, thus winsw.exe needs to be launched + // accordingly. This in turn limits what the caller can do, + // and among other things it makes it difficult for the caller + // to read stdout/stderr. Thus redirection becomes handy. + var f = new FileStream(args[1], FileMode.Create); + var w = new StreamWriter(f); + w.AutoFlush = true; + Console.SetOut(w); + Console.SetError(w); + + var handle = f.Handle; + SetStdHandle(-11, handle); // set stdout + SetStdHandle(-12, handle); // set stder + + args = args.GetRange(2, args.Count - 2); + } + args[0] = args[0].ToLower(); if (args[0] == "install") { @@ -999,7 +1027,7 @@ public static void Run(string[] args) if (args[0] == "test") { WrapperService wsvc = new WrapperService(); - wsvc.OnStart(args); + wsvc.OnStart(args.ToArray()); Thread.Sleep(1000); wsvc.OnStop(); } diff --git a/manifest.xml b/manifest.xml new file mode 100755 index 00000000..8ae1db8e --- /dev/null +++ b/manifest.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/winsw.csproj b/winsw.csproj index 4514e868..20a64244 100644 --- a/winsw.csproj +++ b/winsw.csproj @@ -14,6 +14,10 @@ 512 + false + false + + true @@ -51,6 +55,7 @@ + @@ -61,4 +66,9 @@ --> + + "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\mt.exe" -manifest "$(ProjectDir)manifest.xml" –outputresource:"$(TargetDir)$(TargetFileName)";#1 + +"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\signtool.exe" sign /f c:\winsw-do-not-add-to-scm.pfx /p winsw /t http://timestamp.comodoca.com/authenticode $(TargetFileName) + \ No newline at end of file