2010-07-02 7 views
5

Tengo un servicio de Windows que realiza varias actividades periódicas y deseo cambiar la configuración de este servicio desde una aplicación de Windows Forms . Sin embargo, no estoy seguro de cuál es la mejor manera de garantizar que el servicio tenga las preferencias de usuario más actualizadas (con qué frecuencia ejecutar, qué carpetas usar para las cosas, cualquier otra cosa que el usuario pueda especificar). El usuario puede cambiar la configuración en cualquier momento, a voluntad, y me gustaría que el servicio lo sepa casi de inmediato. Estas son las opciones que estoy un peso:Mantener las configuraciones sincronizadas entre la aplicación de formularios y el servicio de Windows (o cualquier n-tier, realmente)

  1. La forma y el servicio de cuota de utilizar el mismo objeto "Configuración" de un tercer proyecto, compartido, y la forma de WCF utiliza un "UpdateSettings (newSettings)" llamada para que el service sabe que ha habido cambios (u, opcionalmente, una llamada para actualizar cada configuración individual, aunque esto parece mucho sobre diferentes llamadas). Actualmente utilizo WCF para mensajes básicos, pero el objeto de configuración puede ser enorme, ya que hay muchas otras cosas allí
  2. Formulario y Servicio usan un archivo de configuración común (XML, o el mismo objeto de configuración de # 1, pero serializado en el disco). El formulario solo escribe una nueva copia del objeto después de haberlo cambiado, y el servicio verifica cada cierto tiempo y lo recoge si es nuevo, actualizando su copia de la configuración
  3. Igual que el n.º 2, pero con una llamada básica de WCF eso le dice al servicio que obtenga la configuración. Esencialmente, una versión "a pedido" en lugar de "encuesta" de # 2.

Sé mejor es subjetivo, pero estoy interesado en cualquier obvio pro o contra los motivos de estas opciones. Como tendré que guardar mi configuración entre las ejecuciones de la aplicación (reinicios, etc.), tendré que serializar las configuraciones en el disco de todos modos, así que ya me estoy inclinando hacia el n. ° 2 o el n. ° 3. Necesitaré un lugar en el disco donde pueda guardar la configuración, pero tal vez la carpeta AppData funcionará bien, aunque eso solo permitirá a los administradores cambiar la configuración, ya que son los únicos que tienen permiso para escribir en esta ubicación. (donde cada usuario, incluida la cuenta de servicio, puede leerlo).

¡Gracias por tu calificación!

Respuesta

3

poco uso el número 2.

Pero sólo estoy trabajando en .NET 2 con mi solicitud, pero todavía debe aplicarse.

Tengo una clase de configuración que utilizo en mis 2 programas. Dentro de esta clase de configuración configuro un objeto FileSystemWatcher que mira el archivo de Configuraciones.

Si la otra aplicación actualiza el archivo de configuración, mi actual recibe un activador de evento para indicar que la configuración debe volverse a cargar.

También puede aplicar el mismo principio en la pantalla de configuración de modo que si la aplicación (de servicio) actualiza algo durante la edición de configuraciones, eso se refleje en su pantalla.

Utilizo AppData (el directorio de nombre de mi empresa/aplicación) para almacenar el archivo.

La otra cosa a tener en cuenta es que puede haber un bloqueo en el archivo mientras se está escribiendo para poder usar un nombre temporal guardar, eliminar antiguo, cambiar el nombre de método temporal o poner algún bloqueo de protección en el archivo al leer después de que el evento del vigilante de archivos dispara que se han realizado cambios.

que utilizan este enfoque en mi FileSystemWatcher antes de proceder

IPSDependency.FileSystem.WaitForLockOnFile(Me.mFilePath) 

el código para que sea así. (Después de leer esto ahora, puede haber un método mejor mi usando un poco de sueño en aquí para reducir golear CPU)

Public Shared Function IsLockAvailable(ByVal filename As String, ByVal fnfIsOK As Boolean) As Boolean 
    Dim fi As FileInfo 
    fi = New FileInfo(filename) 
    Return IsLockAvailable(New FileInfo(filename), fnfIsOK) 
End Function 

Public Shared Function IsLockAvailable(ByVal theFile As FileInfo, ByVal fnfIsOK As Boolean) As Boolean 
    Dim fs As FileStream 
    Try 
     If theFile.Exists Then 
      fs = New FileStream(theFile.FullName, FileMode.Open, FileAccess.ReadWrite, FileShare.None) 
      fs.Close() 
      Return True 
     Else 
      Return fnfIsOK 
     End If 
    Catch ex As IOException 
     'we just let the exception go, because we are only testing the file rather than trying to use it. 
     Return False 
    End Try 
End Function 

Public Shared Sub WaitForLockOnFile(ByVal theFilename As String) 
    WaitForLockOnFile(New FileInfo(theFilename)) 
End Sub 

Public Shared Sub WaitForLockOnFile(ByVal theFile As FileInfo) 
    Dim lockAvailable As Boolean 
    If theFile.Exists Then 
     While Not lockAvailable 
      lockAvailable = IsLockAvailable(theFile, False) 
     End While 
    End If 
End Sub 
2

Por lo general, los servicios que realizan una 'operación de sondeo' (es decir, sincronización de archivos) tiene suficiente tiempo de retraso en su intervalo de encuesta que puede volver a leer fácilmente todos los ajustes de cada ciclo, o incluso según sea necesario.

Si su servicio es más similar a un servidor de SOA, los cambios pueden afectar a configuraciones que generalmente solo se usan una vez durante la vigencia de un servicio. Si este es su tipo de aplicación, entonces la opción n. ° 2 que describe arriba es la más confiable. No puedo decir que me importe mucho la implementación de Paul, ya que sondear un archivo como este arrojará resultados poco fiables. Recomendaría usar un identificador de espera con nombre global para señalar su proceso de cambios. Estoy seguro de que puedes encontrar un ejemplo aquí en SO. Si no desea hacer eso, puede sondear el cambio de hora del último cambio de la configuración.

En general, mi preferencia es para el primer enfoque que utiliza el registro para el almacenamiento. Escriba todas sus configuraciones en valores discretos en una sección de registro y léalas a pedido en su servicio. Es más rápido de lo que piensas y fácil de implementar tanto en el frente como en el back-end.

0

Tengo que estar de acuerdo con su inclinación inicial hacia # 2 y # 3. Particularmente me gusta el número 3 ya que no soy un fan de las encuestas, pero en última instancia, creo que la decisión entre el n. ° 2 o el n. ° 3 dependerá de los requisitos de su servicio.

En cuanto al almacenamiento de la configuración del usuario, recomendaría explorar Isolated Storage (http://msdn.microsoft.com/en-us/library/3ak841sy.aspx). Proporciona un mecanismo excelente para el acceso seguro, consistente y confiable a los archivos del usuario. No tendrá que preocuparse de que el usuario tenga permiso a menos que el administrador haya desactivado por completo el almacenamiento aislado. Además, si habilita el roaming, los usuarios pueden incluso llevar su configuración con ellos si utilizan diferentes sistemas en el mismo dominio, ¿bastante ingenioso?

+0

El uso de "Almacenamiento aislado" parece ser específico del usuario: en lo que respecta a mi configuración, son esencialmente por computadora. Quiero que los usuarios puedan verlos, pero solo un administrador puede editarlos y volver a guardarlos (o, con Vista/7, alguien que haya usado la elevación del administrador). ¿Puedo usar almacenamiento aislado para el administrador local o el almacenamiento de tipo "Todos los usuarios"? – SqlRyan

+0

@rwmnau Lectura adicional en tipos de almacenamiento aislado Veo que está como mínimo siempre restringido para el usuario que lo creó. Hay una bandera IsolatedStorageScope.User que pensé que podría desactivarse, pero ese no parece ser el caso. Trataré de pensar en una ruta alternativa. – Matthew

3

Suponiendo que todo lo que se está ejecutando en la misma máquina, ¿qué tal esto:

  1. definir una estructura # c común que define la configuración. Todos los proyectos incluyen este archivo .cs. Definir esta clase como una estructuracon un StructLayout de secuencial o explícita por lo que se puede asignar directamente en la memoria compartida no administrado. Por ejemplo:

    [StructLayout (LayoutKind.Sequential)] MySharedSettings struct inseguras { int público Ajuste1; public int setting2; cadena pública setting3; // agregue más campos aquí. }

  2. Uso llamado memoria compartida (aka: archivos mapeados en memoria). Esto permite que múltiples procesos en la misma computadora compartan datos, sin la sobrecarga de Remoting o WCF.La memoria compartida es extremadamente rápida y, a diferencia de las tuberías, ofrece acceso aleatorio a los datos de la memoria compartida. El servicio crearía la memoria compartida nombrada, y las aplicaciones de interfaz de usuario abrirían la memoria compartida. Tendría que usar pinvoke para usar las API de Windows subyacentes, pero esto no es gran cosa.

  3. Las aplicaciones de IU escriben MySharedSettings en la memoria compartida, mientras que el servicio lee la memoria compartida.

  4. Utilice un llamado Semáforo y/o objeto mutex llamado para proteger el acceso a la memoria compartida y para señalar la disponibilidad de nuevos ajustes. El servicio tiene un hilo de fondo dedicado que simplemente ejecuta WaitOne() en el semáforo, y el hilo de la interfaz de usuario indicará cuando se escriban nuevos datos.

+0

Siento que puedo aprender mucho de esta respuesta, pero estoy luchando por encontrar buenos ejemplos. ¿Serías tan amable de proporcionar estos? – Peter

Cuestiones relacionadas