2010-10-01 39 views
5

HI,No se puede iniciar la aplicación de escritorio de servicio de Windows en Windows 7

tengo C# WCF servicio de Windows en Windows 7 está conectado como usuario con derechos de administrador. Estoy tratando de iniciar la aplicación de escritorio después del inicio del servicio. Todas las discusiones que encontré son sobre estaciones de Windows y escritorios ... Creé un hilo por separado, establecí la estación de hilos y el escritorio e intenté iniciar la aplicación de escritorio. El código funciona cuando lo comienzo desde VS2010 usando el servidor de desarrollo asp.net pero si se inició desde el servicio no hay errores, pero el proceso no se inició. Intenté iniciar el proceso como un usuario diferente e intenté llamar a CreateProcessWithLogonW (con la configuración startInfo.lpDesktop en "winsta0 \ default"; anteriormente). En ambos casos, he devuelto el proceso, pero no puedo ver la aplicación de escritorio. ¿Alguien puede ayudarme a ver dónde hay un error?

public class ExternalProcess 
{ 
    const int READ_CONTROL = 0x20000; 
    const int WRITE_DAC = 0x40000; 
    const int DESKTOP_WRITEOBJECTS = 0x80; 
    const int DESKTOP_READOBJECTS = 0x1; 

    private Process extProcess; 
    private string sFilePath = ""; 

    [DllImport("user32.dll")] 
    private static extern bool SetThreadDesktop(IntPtr hDesktop); 
    [DllImport("user32.dll")] 
    static extern IntPtr OpenDesktop(string lpszDesktop, uint dwFlags,bool fInherit, uint dwDesiredAccess); 
    [DllImport("user32.dll")] 
    private static extern IntPtr GetProcessWindowStation(); 
    [DllImport("user32.dll")] 
    private static extern IntPtr OpenWindowStation(string lpszWinSta, bool fInherit, ACCESS_MASK dwDesiredAccess); 
    [DllImport("user32.dll")] 
    private static extern IntPtr SetProcessWindowStation(IntPtr hWinsta); 

    public bool StartProcess(string filePath) 
    { 
     sFilePath = filePath; 
     Thread t = new Thread(new ThreadStart(Thread_StartProcess)); 
     t.Start(); 

     return true; 
    } 

    private void Thread_StartProcess() 
    { 
     IntPtr hwinstaSave; 
     IntPtr hwinsta, hwinsta2; 
     IntPtr hdesk; 

     hwinstaSave = GetProcessWindowStation(); 
      System.Console.WriteLine("GetProcessWindowStation Lasterror= " + Marshal.GetLastWin32Error().ToString()); 
      System.Console.WriteLine("GetProcessWindowStation hwinstaSave= " + hwinstaSave.ToString()); 
     //hwinsta = OpenWindowStation("winsta0", false, ACCESS_MASK.GENERIC_EXECUTE | ACCESS_MASK.DESKTOP_CREATEWINDOW | ACCESS_MASK.DESKTOP_CREATEMENU | ACCESS_MASK.DESKTOP_SWITCHDESKTOP | ACCESS_MASK.DESKTOP_WRITEOBJECTS); 
     hwinsta = OpenWindowStation("winsta0", false, ACCESS_MASK.WINSTA_ALL_ACCESS); // when call from windows service OpenWindowStation returns 0 
      System.Console.WriteLine("OpenWindowStation lasterror = " + Marshal.GetLastWin32Error().ToString()); 
      System.Console.WriteLine("OpenWindowStation hwinsta= " + hwinsta.ToString()); 
     hwinsta2 = SetProcessWindowStation(hwinsta); 
      System.Console.WriteLine("SetProcessWindowStation lasterror = " + Marshal.GetLastWin32Error().ToString()); 
      System.Console.WriteLine("SetProcessWindowStation hwinsta2= " + hwinsta2.ToString()); 
     hdesk = OpenDesktop("default", 0, true, READ_CONTROL | WRITE_DAC | DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS); 
      System.Console.WriteLine("OpenDesktop lasterror = " + Marshal.GetLastWin32Error().ToString()); 
      System.Console.WriteLine("OpenDesktop hdesk= " + hdesk.ToString()); 
     bool Success = SetThreadDesktop(hdesk); 
      System.Console.WriteLine("SetThreadDesktop lasterror = " + Marshal.GetLastWin32Error().ToString()); 
      System.Console.WriteLine("SetThreadDesktop Success= " + Success.ToString()); 

     try 
     { 
      extProcess = new Process(); 

      extProcess.StartInfo.FileName = sFilePath; 
      extProcess.StartInfo.WindowStyle = ProcessWindowStyle.Normal; 

      if (extProcess.Start()) 
       System.Console.WriteLine("Process started "); 
      else 
       System.Console.WriteLine("Not started!"); 
     } 
     catch (Win32Exception e) 
     { 
      System.Console.WriteLine("Start {0} failed. Error: " + e.Message); 
     } 
    } 

} 
+0

cualquier solución final con plena muestra de código fuente de trabajo al respecto? – Kiquenet

Respuesta

1
+0

Thx, ya lo leí, intenté marcar la casilla de verificación "Permitir que el servicio interactúe con el escritorio" en los servicios, cambiar el usuario que ejecuta el servicio ..., para el usuario específico, esa casilla de verificación no está permitida, intenté establecer manualmente en el registro pero sin resultado ... – Jovan

+0

Me refería más a esta afirmación: "Los servicios importantes no pueden interactuar directamente con un usuario a partir de Windows Vista. Por lo tanto, las técnicas mencionadas en la sección titulada Uso de un servicio interactivo no deben utilizarse en un nuevo código ". - Parece que ya no es posible tener un servicio que interactúe con el usuario directamente desde Windows Vista (es decir, Vista, 7 y Server 2008, supongo). Está funcionando en el depurador porque el depurador no es un servicio real. –

+0

bueno, sí, tenía miedo de esa parte. Eso significa que debes probar un diseño diferente. Muchas gracias. – Jovan

4

interactivos servicios de Windows recibió un cambio de imagen-seguridad centrada en Windows Vista. Los servicios ahora se ejecutan en la "sesión 0" aislada y no pueden inyectar fácilmente ventanas en sesiones de usuario interactivas. Su código anterior creará elementos de GUI en la Sesión 0, que no se muestran en el escritorio de ningún usuario, incluso con la opción "Permitir que el servicio interactúe con el escritorio".

Más detalles sobre las restricciones de Servicios de Windows en this technical document from Microsoft.

0

Estoy en el medio de esto ahora mismo, sé que UltraVNC lo hace así que miraría el código. No estoy 100% seguro de la respuesta en este momento, cuando lo descubra, actualizaré esta publicación.

Lo esencial es que usted haga un CreateProcessAsUser, entonces el proceso podría tener que hacer OpenInputDesktop y luego un SetThreadDesktop, pero al igual que no puedo hacerlo funcionar todavía.

Cuestiones relacionadas