resolucion - C#Ejecuta la aplicación Windows Form desde el servicio(y en Vista)
form load c# (8)
Estoy escribiendo una aplicación en C # que necesita ejecutarse como un servicio pero también tiene interacción con el usuario. Entiendo que los servicios no tienen UI, etc., así que he dividido mi programa en una aplicación de formulario de Windows y un servicio que puede comunicarse entre sí.
El problema que tengo es que necesito el servicio para asegurarme de que la aplicación de formularios de Windows esté siempre ejecutándose y reiniciarlo si no es así. Puedo detectar si se está ejecutando y reiniciarlo con el siguiente código en Windows 2000 / XP:
System.Diagnostics.Process.Start("ExePath");
pero en Vista, ejecuta el nuevo proceso como un proceso Local / Sistema que es invisible para el usuario. ¿Alguien lo esquivo? ¿Hay alguna forma de detectar qué usuario está actualmente conectado y ejecutar el nuevo proceso como ese usuario? No necesito dar cuenta del cambio de usuario rápido en este punto. Algo, cualquier cosa, bastaría.
Le agradecería cualquier ayuda o consejo que tenga sobre el tema.
Debo aclarar que estoy configurando la opción "Permitir que el servicio interactúe con el escritorio" cuando se instala el servicio. Esto es lo que le permite trabajar en 2000 / XP. Sin embargo, Vista todavía tiene el problema antes mencionado.
En Windows 2000 y XP, hay una opción (casilla de verificación) en la pestaña Inicio de sesión de la ventana de propiedades del servicio para permitir que el servicio interactúe con el escritorio. Creo que esto es lo que estás buscando. Acabo de escribir un servicio rápido en VB.NET con Process.Start ("calc.exe") y la Calculadora de Windows abrió bien.
Aunque no estoy 100% seguro de que esto funcione de la misma manera en Vista.
En este caso, deberá tener un tercer proceso de monitoreo que detecte si el programa falla y reinícielo en ese caso.
Sin embargo, termina aquí con un problema irresoluble, ya que habrá que vigilar el proceso del monitor para asegurarse de que no se cierre, y así sucesivamente, y así sucesivamente.
Es posible que desee reconsiderar este enfoque.
Es una situación difícil. Como se mencionó en algunos lugares, si debe tener una IU, técnicamente no debería utilizar un servicio. Después de todo, los servicios se ejecutan sin que el usuario inicie sesión. Si nadie está conectado, no puede tener una IU.
Normalmente, cuando necesito que un servicio necesite comunicarse con el mundo exterior, hay dos cosas por las que opto. Puedo colocar una entrada en el registro de eventos o puedo colocar un mensaje en una cola.
En tu caso usaría una cola. Cuando un usuario inicia sesión, puede iniciar automáticamente una aplicación que supervisa la cola. Si la aplicación se está ejecutando, cuando se recibe el mensaje, también reciben una alerta de esa manera. Sin embargo, si el usuario cierra la aplicación, ocurre lo mismo ... no lo sabrán.
Parece que no es necesario que la mitad se ejecute como un servicio (a menos que exista un requisito de privilegios más altos), ya que su servicio tendría que funcionar cuando no haya ningún usuario interactivo conectado también.
Primero, una respuesta rápida: ¿la opción ''Permitir que el servicio interactúe con el escritorio'' (servicio -> Propiedades -> Inicio de sesión) o al especificar una cuenta permita lo que usted desea? De ser así, ambos pueden configurarse en su clase de instalador de servicio.
Al igual que los demás, sospecho que hay un mejor enfoque para esto y cualquiera de los siguientes es cierto: -El código dentro del servicio podría incluirse en la aplicación winforms (tal vez ejecutándose en un hilo de fondo), y agregarse al inicio de Windows. Ambos se ejecutarán: la aplicación de winforms solo puede escuchar el servicio cuando está activado y no necesita ser iniciado desde el servicio. O de manera similar, la aplicación podría agregarse al inicio.
Para que su servicio ejecute la aplicación como usuario (lo que parece ser lo que intenta hacer), debe hacer lo siguiente:
System.Security.SecureString ss = new System.Security.SecureString();
foreach (char c in password)
ss.AppendChar(c);
System.Diagnostics.Process proc = Process.Start(path, arguments, username, ss, domain);
Dónde:
- ruta = ruta completa (incluido el nombre de archivo) del ejecutable.
- arguments = cadena de argumentos (usar una cadena vacía es none)
- username = El nombre de una cuenta de usuario en su servidor / computadora
- dominio = su dominio de red (si usa una cuenta de red en blanco si no tiene ninguno)
Además, para que su servicio tenga permiso para iniciar una aplicación, también debe estar ejecutándose como un servicio. Para hacer esto, necesita agregar estas líneas a su clase de instalador de servicio:
serviceProcessInstaller.Account = ServiceAccount.User;
serviceProcessInstaller.Username = "yourdomain//yourAccountName"; //Or just "AccountName" for local accounts..
serviceProcessInstaller.Password = "yourPassword";
La idea general de este tipo de cosas es que, si el usuario necesita interactuar con un servicio, debería iniciar una aplicación por separado. Si desea ayudarlos, puede configurar esa aplicación por separado para comenzar con Windows, colocando un acceso directo en el menú de inicio. También puede crear una recuperación de fallos en su aplicación para que pueda reiniciarse automáticamente.
En realidad, no debe confiar en la supervisión de la aplicación de formularios, ¿qué pasa si nadie está conectado? ¿Qué ocurre si hay varias personas conectadas? Simplemente se pone complicado haciendo las cosas de esta manera.
Tener el servicio sentado y transmitir a los oyentes es el camino a seguir. Cuando se inicia la aplicación de formularios, puede notificar al servicio que desea escuchar los eventos.
Consulte la pregunta: ¿Cómo puede un Servicio de Windows ejecutar una aplicación GUI? . Trata la misma pregunta de C / C ++ (respuesta corta: CreateProcessAsUser), pero la respuesta sigue siendo válida (con algunos P / Invoke) para C #.