2012-03-30 9 views
5

Estoy tratando de mediar en un pequeño servicio de Windows, haciendo que espere una señal de otro proceso durante el inicio. Por supuesto, sé que ese enfoque puede (o incluso lo hará) a veces llevar al tiempo de espera de inicio del servicio. Ese no es el caso.El servicio de Windows no puede ver el semáforo con nombre

El problema es con el nombre System.Thread.Sempaphore que uso con fines de mediación. Semaphore se crea y se adquiere en otro lugar utilizando la siguiente construcción. No hay cambio GC lo tiene ya que rompo explícitamente la ejecución justo debajo de la línea dada para fines de prueba.

Boolean newOne; 
System.Threading.Semaphore rootSemaphore = 
    new System.Threading.Semaphore(1, 1, "DummyServiceSemaphore", out newOne); 

El código anterior funciona bien, obviamente. Siguiente código funciona bien cuando se está ejecutando en modo de depuración o bajo aplicación de consola:

Boolean createdNew; 
System.Threading.Semaphore semaphore = 
    new System.Threading.Semaphore(1, 1, "DummyServiceSemaphore", out createdNew); 
if (createdNew) 
    throw new Exception("That's not what we wanted"); 

exactamente el mismo código falla cuando se está ejecutando como parte del servicio de Windows:

static class Program 
{ 
    static void Main(string[] args) 
    { 
     Boolean createdNew; 
     System.Threading.Semaphore semaphore = 
      new System.Threading.Semaphore(1, 1, "DummyServiceSemaphore", out createdNew); 
     if (createdNew) 
      throw new Exception("That's not what we wanted"); 

     ServiceBase[] ServicesToRun; 
     ServicesToRun = new ServiceBase[] { new Dummy() }; 
     ServiceBase.Run(ServicesToRun); 
    } 
} 

Así, lookig ayuda en esta.

PD: He estado tratando de usar Mutex en su lugar, sin embargo, había otro problema con él: la aplicación en espera no se pone al día cuando el propietario llama a Mutex.ReleaseMutex();

ACTUALIZACIÓN:

De acuerdo con la respuesta Anurag Ranjhan He editado semáforo de la creación de la rutina de la siguiente manera y esa cosa ahora funciona bien:

Boolean newOne = false; 

System.Security.Principal.SecurityIdentifier sid = 
    new System.Security.Principal.SecurityIdentifier(
     System.Security.Principal.WellKnownSidType.WorldSid, 
     null); 

System.Security.AccessControl.SemaphoreSecurity sec = 
    new System.Security.AccessControl.SemaphoreSecurity(); 
sec.AddAccessRule(new System.Security.AccessControl.SemaphoreAccessRule(
    sid, 
    System.Security.AccessControl.SemaphoreRights.FullControl, 
    System.Security.AccessControl.AccessControlType.Allow)); 

System.Threading.Semaphore rootSemaphore = 
    new Semaphore(1, 1, "Global\\DummyServiceSemaphore", out newOne, sec); 

Respuesta

5

trate de usar con Global\ prefijo

System.Threading.Semaphore rootSemaphore = 
new System.Threading.Semaphore(1, 1, "Global\DummyServiceSemaphore", out newOne); 

Desde comment section of MSDN

Si está utilizando un semáforo con nombre en Windows, el nombre que elija es regido por las pautas de nomenclatura Kernel. Algunas de esas pautas también incluyen los espacios de nombres de objeto Kernel 1, que describe el contexto del objeto kernel. De forma predeterminada, con Terminal Services instalado, kernel objects como events están limitados a la sesión actual. Esto es hecho para que las sesiones múltiples que se ejecutan en Servicios de Terminal Server no se afecten negativamente . Los espacios de nombres de objeto Kernel describen el uso de los prefijos "Local \", "Global" y "Session \" para crear objetos kernel que pueden aplicarse a espacios de nombres específicos y comunicarse con comunicación a procesos de un alcance específico.

+0

¡Gracias! Eso resolvió el problema. – Vitaly

+1

Recientemente tuve el mismo problema, e incluso con el prefijo "Global \", tuve que especificar explícitamente el objeto SemaphoreSecurity como se indica en la actualización de pregunta anterior para que funcione dentro de un servicio de Windows. Eso, sin embargo, hizo el trabajo! – mthierba

Cuestiones relacionadas