Skip to content

Commit

Permalink
Project created
Browse files Browse the repository at this point in the history
  • Loading branch information
Sascha Kiefer committed Mar 30, 2010
0 parents commit 22bd00a
Show file tree
Hide file tree
Showing 10 changed files with 956 additions and 0 deletions.
20 changes: 20 additions & 0 deletions AnyService.sln
@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AnyService", "AnyService\AnyService.csproj", "{E600FAE1-2DAA-4175-831A-C917E8E72050}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E600FAE1-2DAA-4175-831A-C917E8E72050}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E600FAE1-2DAA-4175-831A-C917E8E72050}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E600FAE1-2DAA-4175-831A-C917E8E72050}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E600FAE1-2DAA-4175-831A-C917E8E72050}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
42 changes: 42 additions & 0 deletions AnyService/Disposable.cs
@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AnyService
{
public class Disposable : IDisposable
{
~Disposable()
{
this.Dispose(false);
}

protected virtual void Dispose(bool disposing)
{
if (!this.Disposed)
{
if (disposing) this.Release();
this.Disposed = true;
}
}

protected virtual void Release() { }

protected bool Disposed
{
get;
private set;
}

#region IDisposable Members

public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}

#endregion
}
}
156 changes: 156 additions & 0 deletions AnyService/Program.cs
@@ -0,0 +1,156 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace AnyService
{
class Program
{
public enum Cmd
{
Install, Uninstall, Start, Stop, Help, Run
};

static int Main(string[] args)
{
if (args.Length == 0)
args = new string[] { "help" };

int rc = 0;

string command = args[0].ToLowerInvariant();
try
{
Cmd cmd = (Cmd)Enum.Parse(typeof(Cmd), command, true);
switch(cmd)
{
case Cmd.Install: rc = Program.HandleInstall(args); break;
case Cmd.Uninstall: rc = Program.HandleUninstall(args); break;
case Cmd.Start: rc = Program.HandleStart(args); break;
case Cmd.Stop: rc = Program.HandleStop(args); break;
case Cmd.Run: rc = Program.HandleRun(args); break;
case Cmd.Help:
default: rc = Program.HandleHelp(null); break;
}

}
catch(Exception e)
{
rc = Program.HandleHelp(e.Message);
}

return rc;
}

static int HandleInstall(string[] args)
{
int retval = 0;

if (args.Length < 3)
throw new ArgumentException("Not enough arguments for 'install' command.");
string serviceName = args[1];
string externalCommandLine = args[args.Length - 1];

try
{

Service s = new Service(serviceName);
if (!s.CheckExternalImagePath(externalCommandLine))
throw new Exception("I do not understand your external program argument.");
s.Install(externalCommandLine);

Console.WriteLine(string.Format("Successfully installed an AnyService called: {0}", serviceName));
}
catch (Exception e)
{
Console.Error.WriteLine("Unable to install service: " + e.Message);
retval = -1;
}
return retval;
}

static int HandleUninstall(string[] args)
{
int retval = 0;

if (args.Length < 2)
throw new ArgumentException("Not enough arguments for 'uninstall' command.");
string serviceName = args[1];

try
{
Service s = new Service(serviceName);
s.Uninstall();

Console.WriteLine("Successfully uninstalled an AnyService called: " + serviceName);
}
catch (Exception e)
{
Console.Error.WriteLine("Unable to uninstall service: " + e.Message);
retval = -1;
}
return retval;
}

static int HandleRun(string[] args)
{
int retval = 0;

if (args.Length < 2)
throw new ArgumentException("Not enough arguments for 'run' command.");
string serviceName = args[1];
try
{

Service s = new Service(serviceName);
s.Run();
}
catch (Exception e)
{
Console.Error.WriteLine("Unable to install service: " + e.Message);
retval = -1;
}
return retval;
}

static int HandleStart(string[] args)
{
int retval = 0;

return retval;
}

static int HandleStop(string[] args)
{
int retval = 0;

return retval;
}

static int HandleHelp(string message)
{
int retval = 0;

if (!string.IsNullOrEmpty(message))
{
Console.WriteLine("Error handling command: " + message + Environment.NewLine);
retval = 1;
}
Console.WriteLine("AnyService, Copyright © 2010, Sascha Kiefer." + Environment.NewLine);
Console.WriteLine("Usage: AnyService.exe <command> <service name> [options] [file]" + Environment.NewLine);
Console.WriteLine("Command:");
Console.WriteLine("\tinstall\t\t- Installs an AnyService named <service name> with application [file]");
Console.WriteLine("\tuninstall\t- Uninstalls an AnyService name <service name>");
Console.WriteLine("\tstart\t\t- Tries to start an AnyService named <service name>");
Console.WriteLine("\tstop\t\t- Tries to stop an AnyService named <service name>");
Console.WriteLine("\thelp\t\t- Displays this help message.");
Console.WriteLine();
Console.WriteLine("Examples:");
Console.WriteLine("\tAnyService.exe install MyService c:\\Path\\To\\MyNotYetAService.exe");

return retval;
}
}
}
36 changes: 36 additions & 0 deletions AnyService/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("AnyService")]
[assembly: AssemblyDescription("Run anything as a service")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Sascha Kiefer")]
[assembly: AssemblyProduct("AnyService")]
[assembly: AssemblyCopyright("Copyright © 2010, Sascha Kiefer")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("f3938e67-a846-4d2b-9478-5e85d9b01d10")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("1.0.0.0")]
122 changes: 122 additions & 0 deletions AnyService/Service.cs
@@ -0,0 +1,122 @@
using System;
using System.IO;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading;

using AnyService.Win32;

namespace AnyService
{
public class Service : Win32.WinService
{
private RegistryHelper m_registry = null;
private Process m_externalProgram = null;

public Service(string name)
: base(name)
{
m_registry = new RegistryHelper(Microsoft.Win32.Registry.LocalMachine, @"SYSTEM\CurrentControlSet\Services\" + name);
}

public string ExternalImagePath
{
get { return m_registry.LoadString("ExternalImagePath", "", true); }
set
{
if (value == null) value = "";
value = value.Replace('\'', '"');
m_registry.SaveString("ExternalImagePath", value, true);
}
}

public bool CheckExternalImagePath(string externalImagePath)
{
string t1, t2;
return this.CheckExternalImagePath(externalImagePath, out t1, out t2);
}

private bool CheckExternalImagePath(string externalImagePath, out string imagePath, out string arguments)
{
bool retval = false;
imagePath = arguments = null;

int pos = externalImagePath.IndexOf(".exe", StringComparison.InvariantCultureIgnoreCase);
if (pos > 0)
{
imagePath = externalImagePath.Substring(0, pos + 4);
arguments = externalImagePath.Substring(pos + 4).Trim();
retval = true;
}

return retval;
}

protected override void OnStart(string[] args)
{
string externalImagePath = this.ExternalImagePath;
// cleanup and devide into imagepath and arguments
string imagePath = null, arguments = null;
if (this.CheckExternalImagePath(this.ExternalImagePath, out imagePath, out arguments))
{
ProcessStartInfo psi = new ProcessStartInfo(imagePath, arguments);
psi.WorkingDirectory = Path.GetDirectoryName(imagePath);

m_externalProgram = new Process();
m_externalProgram.Exited += new EventHandler(HandleProcessExited);
m_externalProgram.StartInfo = psi;
if(m_externalProgram.Start())
base.OnStart(args);
}
}

protected override void OnStop()
{
if (m_externalProgram != null)
{
m_externalProgram.Exited -= new EventHandler(HandleProcessExited);

int count = 4;
while (count < 8)
{
try { m_externalProgram.Kill(); break; }
catch (Win32Exception) { count++; Thread.Sleep(count * 50); }
catch { break; }
}
m_externalProgram.Close();
m_externalProgram = null;
}

base.OnStop();
}

private void HandleProcessExited(object sender, EventArgs e)
{
// External Program died or stopped
// so exit as well
int exitCode = -1;
try { exitCode = m_externalProgram.ExitCode; }
catch { }
Environment.Exit(exitCode);
}

protected override void Dispose(bool disposing)
{
if (disposing)
{
if (m_registry != null)
{
m_registry.Dispose();
m_registry = null;
}
}
base.Dispose(disposing);
}

public void Install(string externalCommandLine)
{
this.Install(false);
this.ExternalImagePath = externalCommandLine;
}
}
}

0 comments on commit 22bd00a

Please sign in to comment.