2012-06-01 26 views
5

Estoy creando un servicio de ventana simple y cuando voy a depurar me aparece el error "No se puede evaluar la expresión porque un marco nativo está en la parte superior de la llamada apilar.". Además, cuando construyo el servicio en Release y lo ejecuto, simplemente cuelga.No se puede evaluar la expresión porque un marco nativo está en la parte superior de la pila de llamadas

static void Main() 
    { 
     ServiceBase[] ServicesToRun; 
     ServicesToRun = new ServiceBase[] { new MyService1() }; 

     ServiceBase.Run(ServicesToRun); 
    } 

Eso es todo lo que hay en el archivo Program.cs, donde normalmente se queda enganchada en la línea ServiceBase.Run (ServicesToRun).

Todo lo que he podido encontrar solo se relaciona con la expresión que no se evalúa porque el código está optimizado o tiene que tratar con asp.net y response.redirect.

Código del servicio.

public TruckRateClearService() 
    { 
     InitializeComponent(); 
    } 

    protected override void OnStart(string[] args) 
    { 
     tmrProcess.Enabled = true; 
    } 

    protected override void OnCustomCommand(int command) 
    { 
     base.OnCustomCommand(command); 
     if (command == 129) 
     { 
      OnStart(null); 
     } 
    } 

    protected override void OnStop() 
    { 
     tmrProcess.Enabled = false; 
    } 

    private void tmrProcess_Tick(object sender, EventArgs e) 
    { 
     tmrProcess.Enabled = false; 

     try 
     { 
      eventLog.WriteEntry("Clearing Truck Rates Start" + DateTime.Now.ToString()); 

      TruckRateClearingAgent.Process(); 

      eventLog.WriteEntry("Clearing Truck Rates Finished" + DateTime.Now.ToString()); 
     } 
     catch (Exception ex) 
     { 
      eventLog.WriteEntry(ex.ToString(), EventLogEntryType.Error); 
     } 

     tmrProcess.Enabled = true; 
    } 

    internal void Run() 
    { 
     tmrProcess_Tick(tmrProcess, null); 
    } 

The Run vacío interno() se añadió simplemente reciente sobre la sugerencia en los comentarios de Eren Ersönmez. Su idea ha sido muy útil para ayudar a depurar mi lógica hasta que pueda descifrar el resto.

Pude entrar en la pila de llamadas nativas y se encuentra en una ubicación, 76F17094 ret. Ahora no tengo idea de qué es esto, pero tal vez alguien más lo haga.

Además, cuando inicio el servicio y busco adjuntarlo a VS, noto dos instancias de este. Uno es el .exe normal y otro es un .vshost.exe. Cuando inicio otros servicios, solo veo el archivo .exe en la sección Adjuntar para procesar parte del depurador. ¿Podría ser porque uno está en el Framework v4 (servicio .vshost .exe) y otro en el Framework v2 (servicio .exe único)?

Creo que lo tengo funcionando. Parece que el problema mintió con el temporizador que estaba usando. El temporizador original que estaba usando era un temporizador System.Windows.Forms. Lo cambié a System.Timers.Timers y todo comenzó a funcionar de nuevo. Todavía no puedo adjuntar VS a él, pero puedo depurarlo aún utilizando el método Internal Run(). Gracias por toda la ayuda N, N

Respuesta

2

El problema

Esta notificación significa que el hilo está ejecutando actualmente el código no administrado, y por lo tanto no se puede utilizar para evaluar la expresión.

En algunas situaciones, podría esperar a que la llamada regrese al código administrado antes de evaluar la expresión. Desafortunadamente, en esta situación, eso no sucederá hasta que apagues el servicio.

Una alternativa

Usted podría considerar la sustitución del método ServiceBase.OnCustomCommand y poner un punto de interrupción allí para que pueda evaluar su expresión.

protected override void OnCustomCommand(int command) 
{ 
    //Debugger.Break() <- or just put a breakpoint in here. 
} 

puede invocar el comando personalizado de la siguiente manera:

c:\>sc control YourServiceName 129 
+0

Puse todo y ejecuté el comando y funcionó. Sin embargo, cuando salí de la función no me permitió avanzar más. Y cuando fui a Debug-> Break All, fue en el mismo punto en el que el servicio estaba fallando. Creo que estoy haciendo algo incorrecto aquí. –

+0

¿Qué tipo de falla estás viendo? ¿Un cuelgue o una excepción? –

+0

Lo mismo que antes "No puedo evaluar la expresión ...". Si el servicio se cuelga de la parte ServiceBase.Run (ServicesToRun). –

0

La excepción que estés significa que el código no administrado está lanzando una excepción de ver, por lo que el depurador .NET no se puede mostrar el habitual detalles útiles.

¿Qué estás haciendo en MyService1()? ¿Puedes publicar el código dentro de él?

También está intentando depurar el servicio simplemente al iniciarlo desde el entorno. Eso podría no funcionar.

que suelo escribir algo como esto:

static void Main(params string[] args) 
{ 
    if (args.Length > 0 && args[0] == "/console") 
    { 
     // Run whatever your service calls here 
    } 
    else 
    { 
     ServiceBase[] ServicesToRun; 
     ServicesToRun = new ServiceBase[] { new MyService1() }; 

     ServiceBase.Run(ServicesToRun); 
    } 
} 

Luego, en las propiedades del proyecto en la pestaña Depurar entrar /console como los argumentos de línea de comandos. Debería poder ingresar a la aplicación y depurarla. Solo puede depurar un servicio instalándolo primero: http://msdn.microsoft.com/en-us/library/7a50syb3(v=vs.80).aspx

+0

Al principio estaba reinstalando el servicio y adjuntando VS a él. Miro el consejo de Eren y lo agregué a mi código, así que solo pude usar el depurador normal. Sin embargo, todavía no he encontrado ningún código no administrado. ¿Sería seguro ingresar a las propiedades del proyecto y activar "Permitir código no seguro"? –

+0

Pruebe las instrucciones aquí: http://msdn.microsoft.com/en-us/library/tdw0c6sf(v=vs.80).aspx – greg84

2

Su problema principal es que está tratando de ejecutar directamente un servicio de Windows. Los servicios de Windows solo se pueden iniciar a través de Service Control Manager (SCM). Con el fin de ser capaz de depurar en VS, me gustaría recomendar algo como esto:

static void Main() 
{ 
    if (Environment.UserInteractive) 
    { 
     new MyService1().Run(); 
     Thread.Sleep(Timeout.Infinite); 
    } 
    else 
    { 
     ServiceBase.Run(new ServiceBase[] { new MyService1() }); 
    } 
} 

, debes crear un método MyService1.Run, que genera un nuevo hilo que corre el bucle de servicio. Además, llamaría al mismo método Run desde MyService1.Onstart.

Este esquema lo ejecuta como un servicio cuando lo inicia SCM, pero lo trata como un exe normal cuando se depura en VS (o se ejecuta directamente como un exe fuera de VS).

Cuestiones relacionadas