2011-02-09 12 views
7

Me gustaría crear y administrar una aplicación de servicio de Windows sin "ayuda" del diseñador de Visual Studio.Servicio de Windows sin interferencia de Visual Studio

Dado que este es .NET, ya juzgar por MSDN y lo que hace el diseñador, esto significa que heredan de Installer, y construir y hacer frente a ServiceProcessInstaller y ServiceInstaller para poder gestionar la ejecución tiempo de instalación del serivce.

Runtime, esto significa crear una subclase ServiceBase y comenzando desde Main usando ServiceBase.Run (y imperiosas diversos métodos de manipulación ServiceBase de eventos).

Sin embargo, cuando hago esto, Visual Studio insiste en tratar las subclases Installer y ServiceBase como archivos editados por el diseñador. Esto no ayuda exactamente a la legibilidad, sin mencionar el hecho de que, en general, no puede tratar con el código escrito a mano. Me gustaría evitar el diseñador para mantener las cosas manejables (para evitar el nebuloso quién sabe qué ejecutar, cuándo, particularmente para el código que es difícil de probar y depurar, como los servicios de Windows que después de todo deben instalar para ejecutarse), y también para poder especificar el nombre del servicio en tiempo de ejecución, en lugar de en tiempo de compilación, el diseñador no es compatible con eso.

¿Cómo puedo crear una aplicación de servicio de Windows sin toda la suciedad?

+2

Es posible que desee echar un vistazo al proyecto TopShelf - http://topshelf-project.com/ – stuartd

+0

hmm - limpio! Se ve un poco exagerado y aún no está maduro, pero si estuviera escribiendo una nueva aplicación, definitivamente lo consideraría. –

Respuesta

-1

VS agrega algunas cosas adicionales, pero realmente no me preocuparía. Aquí hay un tutorial para crear un servicio simple manualmente en VS2005, también debería funcionar bien para las nuevas versiones.

http://www.codeproject.com/KB/system/WindowsService.aspx

+1

El diseñador se bloquea cuando 'ServiceName' no es constante, y altera el código que escribí: Realmente no quiero el diseñador.Además, el código que produce es 5 veces más grande que el código necesario y mucho menos comprensible. –

+1

Déjeme ponerlo de esta manera: ¿hay * alguna * característica útil para el diseñador que sirva como plantilla inicial, incluidos los tipos necesarios? –

2

Bueno, simplemente borrar la llamada InitializeComponent() en el constructor y el diseñador de código generado es fuera de su pelo.

+0

Eso no funciona: Visual Studio es "inteligente": no le importa si ha agregado un archivo como clase o como componente: lo que importa es la jerarquía de herencia. Si hereda de 'Installer' y por lo tanto' IComponent', obtendrá el diseñador, incluso si creó originalmente el archivo a través de "Add Class". –

+0

Incluso intenté agregar una clase sin sentido antes del 'Instalador', todavía usa el diseñador. Una solución (insatisfactoria) es hacer clic derecho: Abrir-con y seleccionar CSharp Editor y configurarlo como predeterminado. No es satisfactorio porque una nueva verificación del control de la fuente en otra máquina perderá esa configuración de usuario y volverá al diseñador por favor-desordenar mi código. –

+1

I repro. Molesto, ¿verdad? –

5

Desde que a menudo crean servicios de hacerlo de esta manera:

que tienen una clase base común que se ve así:

internal class ServiceRunner : ServiceBase { 
    protected static void Startup(string[] args, ServiceRunner instance, bool interactiveWait) {  
    if (instance == null) 
     throw new ArgumentNullException("instance"); 

    if (Environment.UserInteractive) { 
     instance.OnStart(args); 
     if (interactiveWait) { 
      Console.WriteLine("Press any key to stop service"); 
      Console.ReadKey(); 
     } 
     instance.OnStop(); 
    } 
    else 
     Run(instance); 
} 

Luego de crear todos mis servicios como este

internal class MyService : ServiceRunner 
{ 
    public MyService() { 
     ServiceName = ConfigurationManager.AppSettings["MyServiceName"]; 
    } 

    private static void Main(string[] args) { 
     Startup(args, new MyService(), true); 
    } 

    protected override void OnStart(string[] args) { 
     base.OnStart(args); 
     ... 
    } 

    protected override void OnStop() { 
     ... 
     base.OnStop(); 
    } 
} 

Ahora puedo probar el servicio simplemente ejecutándolo en el depurador o en la línea de comando.

Al instalar utilizo la línea de comandos

sc create ServiceName binPath= C:\...\MyService.exe 

(no he podido dejar el diseñador de apertura el doble clic)

8

ServiceBase se deriva de Component. Para desactivar la vista del diseñador se puede conectar el atributo de este modo:

[System.ComponentModel.DesignerCategory("Code")] 
public class MyService : ServiceBase 
{ 

} 
+0

esto funciona, el diseñador no se crea siempre que agregue esta línea antes de agregar la herencia. – Matthew

+0

¡Esta es de hecho la respuesta correcta, funciona como un campeón! – Ronald

+1

Funcionó, pero tuve que eliminar y volver a agregar la referencia a 'System.ServiceProcess' antes de que esto surtiera efecto. –

Cuestiones relacionadas