2012-02-03 15 views
5

tengo este siguiente programa de servicio simple:¿Cómo ejecutar un proceso separado como usuario de dominio con un servicio de "sistema local"?

using System.Diagnostics; 
using System.ServiceProcess; 

namespace BasicService 
{ 
    public partial class Service1 : ServiceBase 
    { 
     public Service1() 
     { 
      InitializeComponent(); 
     } 

     protected override void OnStart(string[] args) 
     { 
      ProcessStartInfo processStartInfo = new ProcessStartInfo 
                { 
                 Verb = "runas", 
                 UserName = "jdoe", 
                 Password = "XXXXXXX".ConvertToSecureString(), 
                 Domain = "abc.com", 
                 UseShellExecute =false, 
                 FileName = "notepad.exe" 
                }; 
      Process.Start(processStartInfo); 
     } 

     protected override void OnStop() 
     { 
     } 
    } 
} 

y estoy usando esto como mi servicio instalador:

using System.ComponentModel; 
using System.Configuration.Install; 
using System.ServiceProcess; 

namespace BasicService 
{ 
    [RunInstaller(true)] 
    public class ProjectInstaller : Installer 
    { 
     private readonly ServiceProcessInstaller _process; 
     private readonly ServiceInstaller _service; 

     public ProjectInstaller() 
     { 
      _process = new ServiceProcessInstaller {Account = ServiceAccount.LocalSystem}; 
      _service = new ServiceInstaller 
          { 
           ServiceName = "BasicService", 
           Description = "Just a testing service.", 
           StartType = ServiceStartMode.Automatic, 
          }; 

      Installers.Add(_process); 
      Installers.Add(_service); 
     } 
    } 
} 

Si me quedo este servicio sin un verbo, nombre de usuario, contraseña, dominio y useshellexecute especificado, todo funciona a la perfección. Tan pronto como especifico estos valores como se ve arriba, obtengo lo siguiente:

No se puede iniciar el servicio. System.ComponentModel.Win32Exception (0x80004005): Acceso denegado al System.Diagnostics.Process.StartWithCreateProcess (ProcessStartInfo startInfo) en System.Diagnostics.Process.Start() en System.Diagnostics.Process.Start (ProcessStartInfo startInfo) en BasicService.Service1.OnStart (String [] args) en C: \ BasicService \ BasicService \ Service1.cs: línea 24 en System.ServiceProcess.ServiceBase.ServiceQueuedMainCallback (Object estado)

Cualquier ideas ?

Respuesta

2

Desde Windows Vista, los servicios no pueden simplemente mostrar ui o interactuar con un usuario.
http://msdn.microsoft.com/en-us/library/ms683502(VS.85).aspx

Por lo tanto, para ejecutar una aplicación de interfaz gráfica de usuario de su servicio, tendrá que utilizar CreateProcessAsUser, que no está disponible directamente en .NET. Por lo que tendrá que confiar en Pinvoke, algo similar como se describe aquí

http://blogs.msdn.com/b/alejacma/archive/2007/12/20/how-to-call-createprocesswithlogonw-createprocessasuser-in-net.aspx

+0

¿Seguro? Los servicios ya no pueden interactuar con el usuario desde una cuenta de servicio, pero no sé cómo Windows podría saber que 'notepad.exe' es interactivo a menos que realmente lo ejecute. En cuyo caso, el proceso debería iniciarse. –

+1

@ ta.speot.is: sí, creo firmemente que CreateProcessAsUser es la forma correcta de crear aplicaciones de GUI visibles desde el servicio. Lo que causa exactamente "Acceso denegado" arriba, no estoy seguro, pero de la pila de llamadas ves que Windows realmente lo ejecuta. Cómo sabe Windows ... probablemente inspeccionando el símbolo de punto de entrada establecido por el interruptor '/ SUBSISTEMA' VS. – user1234883

+1

AFAIK esta fue la única forma en que pude hacerlo. Tuve que combinar CreateProcessAsUser y LogonUser para que esto funcione correctamente. – ymerej

Cuestiones relacionadas