mirror of https://github.com/winsw/winsw
initial import
git-svn-id: https://svn.kenai.com/svn/winsw~subversion/trunk@2 c8b2a3fe-9b5b-6a51-a37e-dc31b0e308faremotes/git-svn
parent
08eed56c39
commit
e94628badf
|
@ -0,0 +1,348 @@
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Reflection.Emit;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace DynamicProxy
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interface that a user defined proxy handler needs to implement. This interface
|
||||||
|
/// defines one method that gets invoked by the generated proxy.
|
||||||
|
/// </summary>
|
||||||
|
public interface IProxyInvocationHandler
|
||||||
|
{
|
||||||
|
/// <param name="proxy">The instance of the proxy</param>
|
||||||
|
/// <param name="method">The method info that can be used to invoke the actual method on the object implementation</param>
|
||||||
|
/// <param name="parameters">Parameters to pass to the method</param>
|
||||||
|
/// <returns>Object</returns>
|
||||||
|
object Invoke(object proxy, MethodInfo method, object[] parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Factory class used to cache Types instances
|
||||||
|
/// </summary>
|
||||||
|
public class MetaDataFactory
|
||||||
|
{
|
||||||
|
private static Hashtable typeMap = new Hashtable();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Class constructor. Private because this is a static class.
|
||||||
|
/// </summary>
|
||||||
|
private MetaDataFactory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
/// Method to add a new Type to the cache, using the type's fully qualified
|
||||||
|
/// name as the key
|
||||||
|
///</summary>
|
||||||
|
///<param name="interfaceType">Type to cache</param>
|
||||||
|
public static void Add(Type interfaceType)
|
||||||
|
{
|
||||||
|
if (interfaceType != null)
|
||||||
|
{
|
||||||
|
lock (typeMap.SyncRoot)
|
||||||
|
{
|
||||||
|
if (!typeMap.ContainsKey(interfaceType.FullName))
|
||||||
|
{
|
||||||
|
typeMap.Add(interfaceType.FullName, interfaceType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
/// Method to return the method of a given type at a specified index.
|
||||||
|
///</summary>
|
||||||
|
///<param name="name">Fully qualified name of the method to return</param>
|
||||||
|
///<param name="i">Index to use to return MethodInfo</param>
|
||||||
|
///<returns>MethodInfo</returns>
|
||||||
|
public static MethodInfo GetMethod(string name, int i)
|
||||||
|
{
|
||||||
|
Type type = null;
|
||||||
|
lock (typeMap.SyncRoot)
|
||||||
|
{
|
||||||
|
type = (Type)typeMap[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
return type.GetMethods()[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PropertyInfo GetProperty(string name, int i)
|
||||||
|
{
|
||||||
|
Type type = null;
|
||||||
|
lock (typeMap.SyncRoot)
|
||||||
|
{
|
||||||
|
type = (Type)typeMap[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
return type.GetProperties()[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
public class ProxyFactory
|
||||||
|
{
|
||||||
|
private static ProxyFactory instance;
|
||||||
|
private static Object lockObj = new Object();
|
||||||
|
|
||||||
|
private Hashtable typeMap = Hashtable.Synchronized(new Hashtable());
|
||||||
|
private static readonly Hashtable opCodeTypeMapper = new Hashtable();
|
||||||
|
|
||||||
|
private const string PROXY_SUFFIX = "Proxy";
|
||||||
|
private const string ASSEMBLY_NAME = "ProxyAssembly";
|
||||||
|
private const string MODULE_NAME = "ProxyModule";
|
||||||
|
private const string HANDLER_NAME = "handler";
|
||||||
|
|
||||||
|
// Initialize the value type mapper. This is needed for methods with intrinsic
|
||||||
|
// return types, used in the Emit process.
|
||||||
|
static ProxyFactory()
|
||||||
|
{
|
||||||
|
opCodeTypeMapper.Add(typeof(System.Boolean), OpCodes.Ldind_I1);
|
||||||
|
opCodeTypeMapper.Add(typeof(System.Int16), OpCodes.Ldind_I2);
|
||||||
|
opCodeTypeMapper.Add(typeof(System.Int32), OpCodes.Ldind_I4);
|
||||||
|
opCodeTypeMapper.Add(typeof(System.Int64), OpCodes.Ldind_I8);
|
||||||
|
opCodeTypeMapper.Add(typeof(System.Double), OpCodes.Ldind_R8);
|
||||||
|
opCodeTypeMapper.Add(typeof(System.Single), OpCodes.Ldind_R4);
|
||||||
|
opCodeTypeMapper.Add(typeof(System.UInt16), OpCodes.Ldind_U2);
|
||||||
|
opCodeTypeMapper.Add(typeof(System.UInt32), OpCodes.Ldind_U4);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ProxyFactory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ProxyFactory GetInstance()
|
||||||
|
{
|
||||||
|
if (instance == null)
|
||||||
|
{
|
||||||
|
CreateInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateInstance()
|
||||||
|
{
|
||||||
|
lock (lockObj)
|
||||||
|
{
|
||||||
|
if (instance == null)
|
||||||
|
{
|
||||||
|
instance = new ProxyFactory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object Create(IProxyInvocationHandler handler, Type objType, bool isObjInterface)
|
||||||
|
{
|
||||||
|
string typeName = objType.FullName + PROXY_SUFFIX;
|
||||||
|
Type type = (Type)typeMap[typeName];
|
||||||
|
|
||||||
|
// check to see if the type was in the cache. If the type was not cached, then
|
||||||
|
// create a new instance of the dynamic type and add it to the cache.
|
||||||
|
if (type == null)
|
||||||
|
{
|
||||||
|
if (isObjInterface)
|
||||||
|
{
|
||||||
|
type = CreateType(handler, new Type[] { objType }, typeName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
type = CreateType(handler, objType.GetInterfaces(), typeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
typeMap.Add(typeName, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// return a new instance of the type.
|
||||||
|
return Activator.CreateInstance(type, new object[] { handler });
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object Create(IProxyInvocationHandler handler, Type objType)
|
||||||
|
{
|
||||||
|
return Create(handler, objType, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Type CreateType(IProxyInvocationHandler handler, Type[] interfaces, string dynamicTypeName)
|
||||||
|
{
|
||||||
|
Type retVal = null;
|
||||||
|
|
||||||
|
if (handler != null && interfaces != null)
|
||||||
|
{
|
||||||
|
Type objType = typeof(System.Object);
|
||||||
|
Type handlerType = typeof(IProxyInvocationHandler);
|
||||||
|
|
||||||
|
AppDomain domain = Thread.GetDomain();
|
||||||
|
AssemblyName assemblyName = new AssemblyName();
|
||||||
|
assemblyName.Name = ASSEMBLY_NAME;
|
||||||
|
assemblyName.Version = new Version(1, 0, 0, 0);
|
||||||
|
|
||||||
|
// create a new assembly for this proxy, one that isn't presisted on the file system
|
||||||
|
AssemblyBuilder assemblyBuilder = domain.DefineDynamicAssembly(
|
||||||
|
assemblyName, AssemblyBuilderAccess.Run);
|
||||||
|
// assemblyName, AssemblyBuilderAccess.RunAndSave,"."); // to save it to the disk
|
||||||
|
|
||||||
|
// create a new module for this proxy
|
||||||
|
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(MODULE_NAME);
|
||||||
|
|
||||||
|
// Set the class to be public and sealed
|
||||||
|
TypeAttributes typeAttributes =
|
||||||
|
TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed;
|
||||||
|
|
||||||
|
// Gather up the proxy information and create a new type builder. One that
|
||||||
|
// inherits from Object and implements the interface passed in
|
||||||
|
TypeBuilder typeBuilder = moduleBuilder.DefineType(
|
||||||
|
dynamicTypeName, typeAttributes, objType, interfaces);
|
||||||
|
|
||||||
|
// Define a member variable to hold the delegate
|
||||||
|
FieldBuilder handlerField = typeBuilder.DefineField(
|
||||||
|
HANDLER_NAME, handlerType, FieldAttributes.Private);
|
||||||
|
|
||||||
|
|
||||||
|
// build a constructor that takes the delegate object as the only argument
|
||||||
|
//ConstructorInfo defaultObjConstructor = objType.GetConstructor( new Type[0] );
|
||||||
|
ConstructorInfo superConstructor = objType.GetConstructor(new Type[0]);
|
||||||
|
ConstructorBuilder delegateConstructor = typeBuilder.DefineConstructor(
|
||||||
|
MethodAttributes.Public, CallingConventions.Standard, new Type[] { handlerType });
|
||||||
|
|
||||||
|
#region( "Constructor IL Code" )
|
||||||
|
ILGenerator constructorIL = delegateConstructor.GetILGenerator();
|
||||||
|
|
||||||
|
// Load "this"
|
||||||
|
constructorIL.Emit(OpCodes.Ldarg_0);
|
||||||
|
// Load first constructor parameter
|
||||||
|
constructorIL.Emit(OpCodes.Ldarg_1);
|
||||||
|
// Set the first parameter into the handler field
|
||||||
|
constructorIL.Emit(OpCodes.Stfld, handlerField);
|
||||||
|
// Load "this"
|
||||||
|
constructorIL.Emit(OpCodes.Ldarg_0);
|
||||||
|
// Call the super constructor
|
||||||
|
constructorIL.Emit(OpCodes.Call, superConstructor);
|
||||||
|
// Constructor return
|
||||||
|
constructorIL.Emit(OpCodes.Ret);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
// for every method that the interfaces define, build a corresponding
|
||||||
|
// method in the dynamic type that calls the handlers invoke method.
|
||||||
|
foreach (Type interfaceType in interfaces)
|
||||||
|
{
|
||||||
|
GenerateMethod(interfaceType, handlerField, typeBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal = typeBuilder.CreateType();
|
||||||
|
|
||||||
|
// assemblyBuilder.Save(dynamicTypeName + ".dll");
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly MethodInfo INVOKE_METHOD = typeof(IProxyInvocationHandler).GetMethod("Invoke");
|
||||||
|
private static readonly MethodInfo GET_METHODINFO_METHOD = typeof(MetaDataFactory).GetMethod("GetMethod", new Type[] { typeof(string), typeof(int) });
|
||||||
|
|
||||||
|
private void GenerateMethod( Type interfaceType, FieldBuilder handlerField, TypeBuilder typeBuilder ) {
|
||||||
|
MetaDataFactory.Add( interfaceType );
|
||||||
|
MethodInfo[] interfaceMethods = interfaceType.GetMethods();
|
||||||
|
PropertyInfo[] props = interfaceType.GetProperties();
|
||||||
|
|
||||||
|
for ( int i = 0; i < interfaceMethods.Length; i++ ) {
|
||||||
|
MethodInfo methodInfo = interfaceMethods[i];
|
||||||
|
|
||||||
|
// Get the method parameters since we need to create an array
|
||||||
|
// of parameter types
|
||||||
|
ParameterInfo[] methodParams = methodInfo.GetParameters();
|
||||||
|
int numOfParams = methodParams.Length;
|
||||||
|
Type[] methodParameters = new Type[ numOfParams ];
|
||||||
|
|
||||||
|
// convert the ParameterInfo objects into Type
|
||||||
|
for ( int j = 0; j < numOfParams; j++ ) {
|
||||||
|
methodParameters[j] = methodParams[j].ParameterType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a new builder for the method in the interface
|
||||||
|
MethodBuilder methodBuilder = typeBuilder.DefineMethod(
|
||||||
|
methodInfo.Name,
|
||||||
|
/*MethodAttributes.Public | MethodAttributes.Virtual | */ methodInfo.Attributes&~MethodAttributes.Abstract,
|
||||||
|
CallingConventions.Standard,
|
||||||
|
methodInfo.ReturnType, methodParameters );
|
||||||
|
|
||||||
|
#region( "Handler Method IL Code" )
|
||||||
|
ILGenerator methodIL = methodBuilder.GetILGenerator();
|
||||||
|
|
||||||
|
// load "this"
|
||||||
|
methodIL.Emit( OpCodes.Ldarg_0 );
|
||||||
|
// load the handler
|
||||||
|
methodIL.Emit( OpCodes.Ldfld, handlerField );
|
||||||
|
// load "this" since its needed for the call to invoke
|
||||||
|
methodIL.Emit( OpCodes.Ldarg_0 );
|
||||||
|
// load the name of the interface, used to get the MethodInfo object
|
||||||
|
// from MetaDataFactory
|
||||||
|
methodIL.Emit( OpCodes.Ldstr, interfaceType.FullName );
|
||||||
|
// load the index, used to get the MethodInfo object
|
||||||
|
// from MetaDataFactory
|
||||||
|
methodIL.Emit( OpCodes.Ldc_I4, i );
|
||||||
|
// invoke GetMethod in MetaDataFactory
|
||||||
|
methodIL.Emit( OpCodes.Call, GET_METHODINFO_METHOD);
|
||||||
|
|
||||||
|
// load the number of parameters onto the stack
|
||||||
|
methodIL.Emit( OpCodes.Ldc_I4, numOfParams );
|
||||||
|
// create a new array, using the size that was just pused on the stack
|
||||||
|
methodIL.Emit( OpCodes.Newarr, typeof(object) );
|
||||||
|
|
||||||
|
// if we have any parameters, then iterate through and set the values
|
||||||
|
// of each element to the corresponding arguments
|
||||||
|
for ( int j = 0; j < numOfParams; j++ ) {
|
||||||
|
methodIL.Emit( OpCodes.Dup ); // this copies the array
|
||||||
|
methodIL.Emit( OpCodes.Ldc_I4, j );
|
||||||
|
methodIL.Emit( OpCodes.Ldarg, j + 1 );
|
||||||
|
if ( methodParameters[j].IsValueType ) {
|
||||||
|
methodIL.Emit( OpCodes.Box, methodParameters[j] );
|
||||||
|
}
|
||||||
|
methodIL.Emit( OpCodes.Stelem_Ref );
|
||||||
|
}
|
||||||
|
|
||||||
|
// call the Invoke method
|
||||||
|
methodIL.Emit( OpCodes.Callvirt, INVOKE_METHOD );
|
||||||
|
|
||||||
|
if ( methodInfo.ReturnType != typeof(void) ) {
|
||||||
|
// if the return type if a value type, then unbox the return value
|
||||||
|
// so that we don't get junk.
|
||||||
|
if ( methodInfo.ReturnType.IsValueType ) {
|
||||||
|
methodIL.Emit( OpCodes.Unbox, methodInfo.ReturnType );
|
||||||
|
if ( methodInfo.ReturnType.IsEnum ) {
|
||||||
|
methodIL.Emit( OpCodes.Ldind_I4 );
|
||||||
|
} else if ( !methodInfo.ReturnType.IsPrimitive ) {
|
||||||
|
methodIL.Emit( OpCodes.Ldobj, methodInfo.ReturnType );
|
||||||
|
} else {
|
||||||
|
methodIL.Emit( (OpCode) opCodeTypeMapper[ methodInfo.ReturnType ] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// pop the return value that Invoke returned from the stack since
|
||||||
|
// the method's return type is void.
|
||||||
|
methodIL.Emit( OpCodes.Pop );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return
|
||||||
|
methodIL.Emit( OpCodes.Ret );
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
//for (int i = 0; i < props.Length; i++)
|
||||||
|
//{
|
||||||
|
// PropertyInfo p = props[i];
|
||||||
|
|
||||||
|
// PropertyBuilder pb = typeBuilder.DefineProperty(p.Name, p.Attributes, p.PropertyType, new Type[] { p.PropertyType });
|
||||||
|
// pb.SetGetMethod((MethodBuilder)methodTable[p.GetGetMethod()]);
|
||||||
|
// pb.SetSetMethod((MethodBuilder)methodTable[p.GetSetMethod()]);
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Iterate through the parent interfaces and recursively call this method
|
||||||
|
foreach ( Type parentType in interfaceType.GetInterfaces() ) {
|
||||||
|
GenerateMethod( parentType, handlerField, typeBuilder );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,335 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Data;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.ServiceProcess;
|
||||||
|
using System.Text;
|
||||||
|
using System.IO;
|
||||||
|
using WMI;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Threading;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
|
||||||
|
namespace winsw
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// In-memory representation of the configuration file.
|
||||||
|
/// </summary>
|
||||||
|
public class ServiceDescriptor
|
||||||
|
{
|
||||||
|
private readonly XmlDocument dom = new XmlDocument();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Where did we find the configuration file?
|
||||||
|
/// </summary>
|
||||||
|
public readonly string BasePath;
|
||||||
|
|
||||||
|
public static string ExecutablePath
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
// this returns the executable name as given by the calling process, so
|
||||||
|
// it needs to be absolutized.
|
||||||
|
string p = Environment.GetCommandLineArgs()[0];
|
||||||
|
return Path.Combine(Environment.CurrentDirectory, p);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServiceDescriptor()
|
||||||
|
{
|
||||||
|
// find co-located configuration xml. We search up to the ancestor directories to simplify debugging,
|
||||||
|
// as well as trimming off ".vshost" suffix (which is used during debugging)
|
||||||
|
string p = ExecutablePath;
|
||||||
|
string baseName = Path.GetFileNameWithoutExtension(p);
|
||||||
|
if (baseName.EndsWith(".vshost")) baseName = baseName.Substring(0, baseName.Length - 7);
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
p = Path.GetDirectoryName(p);
|
||||||
|
if (File.Exists(Path.Combine(p, baseName + ".xml")))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// register the base directory as environment variable so that future expansions can refer to this.
|
||||||
|
Environment.SetEnvironmentVariable("BASE", p);
|
||||||
|
|
||||||
|
BasePath = Path.Combine(p, baseName);
|
||||||
|
|
||||||
|
dom.Load(BasePath+".xml");
|
||||||
|
}
|
||||||
|
|
||||||
|
private string SingleElement(string tagName)
|
||||||
|
{
|
||||||
|
var n = dom.SelectSingleNode("//" + tagName);
|
||||||
|
if (n == null) throw new InvalidDataException("<" + tagName + "> is missing in configuration XML");
|
||||||
|
return Environment.ExpandEnvironmentVariables(n.InnerText);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Path to the executable.
|
||||||
|
/// </summary>
|
||||||
|
public string Executable
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return SingleElement("executable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Arguments
|
||||||
|
/// </summary>
|
||||||
|
public string Arguments
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return SingleElement("arguments");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Id
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return SingleElement("id");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Caption
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return SingleElement("name");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Description
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return SingleElement("description");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True if the service can interact with the desktop.
|
||||||
|
/// </summary>
|
||||||
|
public bool Interactive
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return dom.SelectSingleNode("//interactive") != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Environment variable overrides
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<string, string> EnvironmentVariables
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Dictionary<string, string> map = new Dictionary<string, string>();
|
||||||
|
foreach (XmlNode n in dom.SelectNodes("//env"))
|
||||||
|
{
|
||||||
|
map[n.Attributes["name"].Value] = Environment.ExpandEnvironmentVariables(n.Attributes["value"].Value);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class WrapperService : ServiceBase
|
||||||
|
{
|
||||||
|
private Process process = new Process();
|
||||||
|
private ServiceDescriptor descriptor;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates to the watch dog thread that we are going to terminate the process,
|
||||||
|
/// so don't try to kill us when the child exits.
|
||||||
|
/// </summary>
|
||||||
|
private bool orderlyShutdown;
|
||||||
|
|
||||||
|
public WrapperService()
|
||||||
|
{
|
||||||
|
this.descriptor = new ServiceDescriptor();
|
||||||
|
this.ServiceName = descriptor.Id;
|
||||||
|
this.CanStop = true;
|
||||||
|
this.CanPauseAndContinue = false;
|
||||||
|
this.AutoLog = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Copy stuff from StreamReader to StreamWriter
|
||||||
|
/// </summary>
|
||||||
|
private void CopyStream(StreamReader i, StreamWriter o)
|
||||||
|
{
|
||||||
|
char[] buf = new char[1024];
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
int sz = i.Read(buf, 0, buf.Length);
|
||||||
|
if (sz == 0) break;
|
||||||
|
o.Write(buf, 0, sz);
|
||||||
|
o.Flush();
|
||||||
|
}
|
||||||
|
i.Close();
|
||||||
|
o.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnStart(string[] args)
|
||||||
|
{
|
||||||
|
EventLog.WriteEntry("Starting "+descriptor.Executable+' '+descriptor.Arguments);
|
||||||
|
string baseName = descriptor.BasePath;
|
||||||
|
|
||||||
|
var ps = process.StartInfo;
|
||||||
|
ps.FileName = descriptor.Executable;
|
||||||
|
ps.Arguments = descriptor.Arguments;
|
||||||
|
ps.CreateNoWindow = false;
|
||||||
|
ps.UseShellExecute = false;
|
||||||
|
ps.RedirectStandardInput = true; // this creates a pipe for stdin to the new process, instead of having it inherit our stdin.
|
||||||
|
ps.RedirectStandardOutput = true;
|
||||||
|
ps.RedirectStandardError = true;
|
||||||
|
|
||||||
|
var envs = descriptor.EnvironmentVariables;
|
||||||
|
foreach (string key in envs.Keys)
|
||||||
|
ps.EnvironmentVariables[key] = envs[key];
|
||||||
|
|
||||||
|
process.Start();
|
||||||
|
|
||||||
|
// send stdout and stderr to its respective output file.
|
||||||
|
new Thread(delegate() { CopyStream(process.StandardOutput, new StreamWriter(new FileStream(baseName + ".out.log", FileMode.Append))); }).Start();
|
||||||
|
new Thread(delegate() { CopyStream(process.StandardError, new StreamWriter(new FileStream(baseName + ".err.log", FileMode.Append))); }).Start();
|
||||||
|
|
||||||
|
// monitor the completion of the process
|
||||||
|
new Thread(delegate()
|
||||||
|
{
|
||||||
|
process.WaitForExit();
|
||||||
|
if (!orderlyShutdown)
|
||||||
|
{
|
||||||
|
EventLog.WriteEntry("Child process terminated with " + process.ExitCode,EventLogEntryType.Warning);
|
||||||
|
Environment.Exit(process.ExitCode);
|
||||||
|
}
|
||||||
|
}).Start();
|
||||||
|
|
||||||
|
process.StandardInput.Close(); // nothing for you to read!
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnStop()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
EventLog.WriteEntry("Stopping "+descriptor.Id);
|
||||||
|
orderlyShutdown = true;
|
||||||
|
process.Kill();
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException)
|
||||||
|
{
|
||||||
|
// already terminated
|
||||||
|
}
|
||||||
|
process.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static int Main(string[] args)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Run(args);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
catch (WmiException e)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine(e);
|
||||||
|
return (int)e.ErrorCode;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine(e);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ThrowNoSuchService()
|
||||||
|
{
|
||||||
|
throw new WmiException(ReturnValue.NoSuchService);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Run(string[] args)
|
||||||
|
{
|
||||||
|
if (args.Length > 0)
|
||||||
|
{
|
||||||
|
var d = new ServiceDescriptor();
|
||||||
|
Win32Services svc = new WmiRoot().GetCollection<Win32Services>();
|
||||||
|
Win32Service s = svc.Select(d.Id);
|
||||||
|
|
||||||
|
args[0] = args[0].ToLower();
|
||||||
|
if (args[0] == "install")
|
||||||
|
{
|
||||||
|
svc.Create(
|
||||||
|
d.Id,
|
||||||
|
d.Caption,
|
||||||
|
ServiceDescriptor.ExecutablePath,
|
||||||
|
WMI.ServiceType.OwnProcess,
|
||||||
|
ErrorControl.UserNotified,
|
||||||
|
StartMode.Automatic,
|
||||||
|
d.Interactive);
|
||||||
|
// update the description
|
||||||
|
/* Somehow this doesn't work, even though it doesn't report an error
|
||||||
|
Win32Service s = svc.Select(d.Id);
|
||||||
|
s.Description = d.Description;
|
||||||
|
s.Commit();
|
||||||
|
*/
|
||||||
|
|
||||||
|
// so using a classic method to set the description. Ugly.
|
||||||
|
Registry.LocalMachine.OpenSubKey("System").OpenSubKey("CurrentControlSet").OpenSubKey("Services")
|
||||||
|
.OpenSubKey(d.Id, true).SetValue("Description", d.Description);
|
||||||
|
}
|
||||||
|
if (args[0] == "uninstall")
|
||||||
|
{
|
||||||
|
if (s == null)
|
||||||
|
return; // there's no such service, so consider it already uninstalled
|
||||||
|
try
|
||||||
|
{
|
||||||
|
s.Delete();
|
||||||
|
}
|
||||||
|
catch (WmiException e)
|
||||||
|
{
|
||||||
|
if (e.ErrorCode == ReturnValue.ServiceMarkedForDeletion)
|
||||||
|
return; // it's already uninstalled, so consider it a success
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (args[0] == "start")
|
||||||
|
{
|
||||||
|
if (s == null) ThrowNoSuchService();
|
||||||
|
s.StartService();
|
||||||
|
}
|
||||||
|
if (args[0] == "stop")
|
||||||
|
{
|
||||||
|
if (s == null) ThrowNoSuchService();
|
||||||
|
s.StopService();
|
||||||
|
}
|
||||||
|
if (args[0] == "status")
|
||||||
|
{
|
||||||
|
if (s == null)
|
||||||
|
Console.WriteLine("NonExistent");
|
||||||
|
else if (s.Started)
|
||||||
|
Console.WriteLine("Started");
|
||||||
|
else
|
||||||
|
Console.WriteLine("Stopped");
|
||||||
|
}
|
||||||
|
if (args[0] == "test")
|
||||||
|
{
|
||||||
|
WrapperService wsvc = new WrapperService();
|
||||||
|
wsvc.OnStart(args);
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
wsvc.OnStop();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ServiceBase.Run(new WrapperService());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
[assembly: AssemblyTitle("Windows Service Wrapper")]
|
||||||
|
[assembly: AssemblyDescription("Allows arbitrary process to run as a Windows service by wrapping it")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("Sun Microsystems, Inc.")]
|
||||||
|
[assembly: AssemblyProduct("Windows Service Wrapper")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright 2008 Sun Micorsystems, Inc.")]
|
||||||
|
[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("59ce18df-cacb-4360-bb80-798bd6459ca3")]
|
||||||
|
|
||||||
|
// 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.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,216 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Management;
|
||||||
|
using DynamicProxy;
|
||||||
|
|
||||||
|
namespace WMI
|
||||||
|
{
|
||||||
|
//Reference: http://msdn2.microsoft.com/en-us/library/aa389390(VS.85).aspx
|
||||||
|
|
||||||
|
public enum ReturnValue
|
||||||
|
{
|
||||||
|
Success = 0,
|
||||||
|
NotSupported = 1,
|
||||||
|
AccessDenied = 2,
|
||||||
|
DependentServicesRunning = 3,
|
||||||
|
InvalidServiceControl = 4,
|
||||||
|
ServiceCannotAcceptControl = 5,
|
||||||
|
ServiceNotActive = 6,
|
||||||
|
ServiceRequestTimeout = 7,
|
||||||
|
UnknownFailure = 8,
|
||||||
|
PathNotFound = 9,
|
||||||
|
ServiceAlreadyRunning = 10,
|
||||||
|
ServiceDatabaseLocked = 11,
|
||||||
|
ServiceDependencyDeleted = 12,
|
||||||
|
ServiceDependencyFailure = 13,
|
||||||
|
ServiceDisabled = 14,
|
||||||
|
ServiceLogonFailure = 15,
|
||||||
|
ServiceMarkedForDeletion = 16,
|
||||||
|
ServiceNoThread = 17,
|
||||||
|
StatusCircularDependency = 18,
|
||||||
|
StatusDuplicateName = 19,
|
||||||
|
StatusInvalidName = 20,
|
||||||
|
StatusInvalidParameter = 21,
|
||||||
|
StatusInvalidServiceAccount = 22,
|
||||||
|
StatusServiceExists = 23,
|
||||||
|
ServiceAlreadyPaused = 24,
|
||||||
|
|
||||||
|
NoSuchService = 200
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Signals a problem in WMI related operations
|
||||||
|
/// </summary>
|
||||||
|
public class WmiException : Exception
|
||||||
|
{
|
||||||
|
public readonly ReturnValue ErrorCode;
|
||||||
|
|
||||||
|
public WmiException(string msg, ReturnValue code)
|
||||||
|
: base(msg)
|
||||||
|
{
|
||||||
|
ErrorCode = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WmiException(ReturnValue code)
|
||||||
|
: this(code.ToString(), code)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Associated a WMI class name to the proxy interface (which should extend from IWmiCollection)
|
||||||
|
/// </summary>
|
||||||
|
public class WmiClassName : Attribute
|
||||||
|
{
|
||||||
|
public readonly string Name;
|
||||||
|
public WmiClassName(string name) { this.Name = name; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Marker interface to denote a collection in WMI.
|
||||||
|
/// </summary>
|
||||||
|
public interface IWmiCollection {}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Marker interface to denote an individual managed object
|
||||||
|
/// </summary>
|
||||||
|
public interface IWmiObject
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Reflect updates made to this object to the WMI provider.
|
||||||
|
/// </summary>
|
||||||
|
void Commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class WmiRoot
|
||||||
|
{
|
||||||
|
private readonly ManagementScope scope;
|
||||||
|
|
||||||
|
public WmiRoot() : this(null) { }
|
||||||
|
|
||||||
|
public WmiRoot(string machineName)
|
||||||
|
{
|
||||||
|
ConnectionOptions options = new ConnectionOptions();
|
||||||
|
|
||||||
|
string path;
|
||||||
|
|
||||||
|
if (machineName != null)
|
||||||
|
path = String.Format(@"\\{0}\root\cimv2", machineName);
|
||||||
|
else
|
||||||
|
path = @"\root\cimv2";
|
||||||
|
scope = new ManagementScope(path, options);
|
||||||
|
scope.Connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string capitalize(string s)
|
||||||
|
{
|
||||||
|
return char.ToUpper(s[0]) + s.Substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class BaseHandler : IProxyInvocationHandler
|
||||||
|
{
|
||||||
|
public abstract object Invoke(object proxy, MethodInfo method, object[] args);
|
||||||
|
|
||||||
|
protected void CheckError(ManagementBaseObject result)
|
||||||
|
{
|
||||||
|
int code = Convert.ToInt32(result["returnValue"]);
|
||||||
|
if (code != 0)
|
||||||
|
throw new WmiException((ReturnValue)code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class InstanceHandler : BaseHandler, IWmiObject
|
||||||
|
{
|
||||||
|
private readonly ManagementObject mo;
|
||||||
|
|
||||||
|
public InstanceHandler(ManagementObject o) { this.mo = o; }
|
||||||
|
|
||||||
|
public override object Invoke(object proxy, MethodInfo method, object[] args)
|
||||||
|
{
|
||||||
|
if (method.DeclaringType == typeof(IWmiObject))
|
||||||
|
{
|
||||||
|
return method.Invoke(this, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: proper property support
|
||||||
|
if (method.Name.StartsWith("set_"))
|
||||||
|
{
|
||||||
|
mo[method.Name.Substring(4)] = args[0];
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (method.Name.StartsWith("get_"))
|
||||||
|
{
|
||||||
|
return mo[method.Name.Substring(4)];
|
||||||
|
}
|
||||||
|
|
||||||
|
// method invocations
|
||||||
|
ParameterInfo[] methodArgs = method.GetParameters();
|
||||||
|
|
||||||
|
ManagementBaseObject wmiArgs = mo.GetMethodParameters(method.Name);
|
||||||
|
for (int i = 0; i < args.Length; i++)
|
||||||
|
wmiArgs[capitalize(methodArgs[i].Name)] = args[i];
|
||||||
|
|
||||||
|
CheckError(mo.InvokeMethod(method.Name, wmiArgs, null));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Commit()
|
||||||
|
{
|
||||||
|
mo.Put();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClassHandler : BaseHandler
|
||||||
|
{
|
||||||
|
private readonly ManagementClass mc;
|
||||||
|
private readonly string wmiClass;
|
||||||
|
|
||||||
|
public ClassHandler(ManagementClass mc, string wmiClass) { this.mc = mc; this.wmiClass = wmiClass; }
|
||||||
|
|
||||||
|
public override object Invoke(object proxy, MethodInfo method, object[] args)
|
||||||
|
{
|
||||||
|
ParameterInfo[] methodArgs = method.GetParameters();
|
||||||
|
|
||||||
|
if (method.Name.StartsWith("Select"))
|
||||||
|
{
|
||||||
|
// select method to find instances
|
||||||
|
string query = "SELECT * FROM " + wmiClass + " WHERE ";
|
||||||
|
for (int i = 0; i < args.Length; i++)
|
||||||
|
{
|
||||||
|
if (i != 0) query += " AND ";
|
||||||
|
query += ' ' + capitalize(methodArgs[i].Name) + " = '" + args[i] + "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
ManagementObjectSearcher searcher = new ManagementObjectSearcher(mc.Scope, new ObjectQuery(query));
|
||||||
|
ManagementObjectCollection results = searcher.Get();
|
||||||
|
// TODO: support collections
|
||||||
|
foreach (ManagementObject manObject in results)
|
||||||
|
return ProxyFactory.GetInstance().Create(new InstanceHandler(manObject), method.ReturnType, true);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ManagementBaseObject wmiArgs = mc.GetMethodParameters(method.Name);
|
||||||
|
for (int i = 0; i < args.Length; i++)
|
||||||
|
wmiArgs[capitalize(methodArgs[i].Name)] = args[i];
|
||||||
|
|
||||||
|
CheckError(mc.InvokeMethod(method.Name, wmiArgs, null));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Obtains an object that corresponds to a table in WMI, which is a collection of a managed object.
|
||||||
|
/// </summary>
|
||||||
|
public T GetCollection<T>() where T : IWmiCollection
|
||||||
|
{
|
||||||
|
WmiClassName cn = (WmiClassName)typeof(T).GetCustomAttributes(typeof(WmiClassName), false)[0];
|
||||||
|
|
||||||
|
ObjectGetOptions getOptions = new ObjectGetOptions();
|
||||||
|
ManagementPath path = new ManagementPath(cn.Name);
|
||||||
|
ManagementClass manClass = new ManagementClass(scope, path, getOptions);
|
||||||
|
return (T)ProxyFactory.GetInstance().Create(new ClassHandler(manClass, cn.Name), typeof(T), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
|
||||||
|
namespace WMI
|
||||||
|
{
|
||||||
|
public enum ServiceType
|
||||||
|
{
|
||||||
|
KernalDriver = 1,
|
||||||
|
FileSystemDriver = 2,
|
||||||
|
Adapter = 4,
|
||||||
|
RecognizerDriver = 8,
|
||||||
|
OwnProcess = 16,
|
||||||
|
ShareProcess = 32,
|
||||||
|
InteractiveProcess = 256,
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ErrorControl
|
||||||
|
{
|
||||||
|
UserNotNotified = 0,
|
||||||
|
UserNotified = 1,
|
||||||
|
SystemRestartedWithLastKnownGoodConfiguration = 2,
|
||||||
|
SystemAttemptsToStartWithAGoodConfiguration = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum StartMode
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Device driver started by the operating system loader. This value is valid only for driver services.
|
||||||
|
/// </summary>
|
||||||
|
Boot,
|
||||||
|
/// <summary>
|
||||||
|
/// Device driver started by the operating system initialization process. This value is valid only for driver services.
|
||||||
|
/// </summary>
|
||||||
|
System,
|
||||||
|
/// <summary>
|
||||||
|
/// Service to be started automatically by the Service Control Manager during system startup.
|
||||||
|
/// </summary>
|
||||||
|
Automatic,
|
||||||
|
/// <summary>
|
||||||
|
/// Service to be started by the Service Control Manager when a process calls the StartService method.
|
||||||
|
/// </summary>
|
||||||
|
Manual,
|
||||||
|
/// <summary>
|
||||||
|
/// Service that can no longer be started.
|
||||||
|
/// </summary>
|
||||||
|
Disabled,
|
||||||
|
}
|
||||||
|
|
||||||
|
[WmiClassName("Win32_Service")]
|
||||||
|
public interface Win32Services : IWmiCollection
|
||||||
|
{
|
||||||
|
// ReturnValue Create(bool desktopInteract, string displayName, int errorControl, string loadOrderGroup, string loadOrderGroupDependencies, string name, string pathName, string serviceDependencies, string serviceType, string startMode, string startName, string startPassword);
|
||||||
|
void Create(string name, string displayName, string pathName, ServiceType serviceType, ErrorControl errorControl, StartMode startMode, bool desktopInteract);
|
||||||
|
|
||||||
|
Win32Service Select(string name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Win32Service : IWmiObject
|
||||||
|
{
|
||||||
|
string Description { get; set; }
|
||||||
|
bool Started { get; }
|
||||||
|
void Delete();
|
||||||
|
void StartService();
|
||||||
|
void StopService();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>com.sun.winsw</groupId>
|
||||||
|
<artifactId>winsw</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<version>1.0</version>
|
||||||
|
<name>Windows service wrapper</name>
|
||||||
|
|
||||||
|
<distributionManagement>
|
||||||
|
<repository>
|
||||||
|
<id>java.net-m2-repository</id>
|
||||||
|
<url>java-net:/maven2-repository/trunk/www/repository/</url>
|
||||||
|
</repository>
|
||||||
|
</distributionManagement>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<!-- fake out maven and install the binary artifact -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.jvnet.maven-antrun-extended-plugin</groupId>
|
||||||
|
<artifactId>maven-antrun-extended-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>run</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<tasks>
|
||||||
|
<attachArtifact file="bin/Debug/winsw.exe" type="exe" classifier="bin" />
|
||||||
|
</tasks>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
<extensions>
|
||||||
|
<extension>
|
||||||
|
<groupId>org.jvnet.wagon-svn</groupId>
|
||||||
|
<artifactId>wagon-svn</artifactId>
|
||||||
|
<version>1.8</version>
|
||||||
|
</extension>
|
||||||
|
</extensions>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>maven2-repository.dev.java.net</id>
|
||||||
|
<name>Java.net Repository for Maven</name>
|
||||||
|
<url>http://download.java.net/maven/2/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<pluginRepositories>
|
||||||
|
<pluginRepository>
|
||||||
|
<id>maven2-repository.dev.java.net</id>
|
||||||
|
<name>Java.net Repository for Maven</name>
|
||||||
|
<url>http://download.java.net/maven/2/</url>
|
||||||
|
</pluginRepository>
|
||||||
|
</pluginRepositories>
|
||||||
|
</project>
|
|
@ -0,0 +1,64 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProductVersion>9.0.21022</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{0DE77F55-ADE5-43C1-999A-0BC81153B039}</ProjectGuid>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>winsw</RootNamespace>
|
||||||
|
<AssemblyName>winsw</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<StartupObject>
|
||||||
|
</StartupObject>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Management" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.ServiceProcess" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="DynamicProxy.cs" />
|
||||||
|
<Compile Include="Main.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Wmi.cs" />
|
||||||
|
<Compile Include="WmiSchema.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="winsw.xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
|
@ -0,0 +1,30 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||||
|
# Visual Studio 2008
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "winsw", "winsw.csproj", "{0DE77F55-ADE5-43C1-999A-0BC81153B039}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Debug|Mixed Platforms = Debug|Mixed Platforms
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
Release|Mixed Platforms = Release|Mixed Platforms
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||||
|
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{0DE77F55-ADE5-43C1-999A-0BC81153B039}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
|
@ -0,0 +1,7 @@
|
||||||
|
<configuration>
|
||||||
|
<id>winsw</id>
|
||||||
|
<name>Winsw test service(2)</name>
|
||||||
|
<description>This service is a do-nothing test app. Really.</description>
|
||||||
|
<executable>C:\development\jdk6u7\bin\java.exe</executable>
|
||||||
|
<arguments>-classpath c:\cygwin\home\kohsuke\ws\hello-world\out\production\hello-world test.Main</arguments>
|
||||||
|
</configuration>
|
Loading…
Reference in New Issue