2009-04-13 11 views
16

¿Existe alguna manera simple de que una biblioteca de códigos detecte automáticamente si se está llamando desde una aplicación de consola o desde una aplicación de Windows? Me gustaría que mi biblioteca no se reporte al registro de eventos de Windows si se llama desde una ventana de la consola, sino que se informa a la ventana de la consola. Sin embargo, si no se ejecuta desde una ventana de consola, debe informar al registro de eventos de Windows.¿Cómo puedo detectar si estoy ejecutándose en la consola?

Pensé en solicitar que mi componente logging pasara el objetivo de registro, pero sería genial si pudiera manejar automáticamente estos dos destinos de forma nativa. Todavía no necesito algo tan extenso como log4net, de hecho, si es necesario proporcionar soporte para iniciar sesión en una base de datos/archivo y otros objetivos de registro aún desconocidos, entonces puedo recomendar tal solución. Sin embargo, por ahora, basta con que mi componente detecte automáticamente el entorno y se registre en la consola o en el registro de eventos de acuerdo con el entorno.

Respuesta

8

Arquitectónicamente, pasar el contexto de registro al componente de la biblioteca es la elección correcta. La biblioteca no sabe, y de hecho no debería saber, mucho contexto sobre el entorno en el que se está ejecutando.

Como quiera admitir estos dos casos especiales de forma nativa dentro de la biblioteca, sugeriría un enfoque unificado.

  1. Continúe y cree el punto/perilla de entrada de registro más general que controla la persona que llama.
  2. Crea un punto de entrada/perilla independiente que establece automáticamente el generalizado para los casos que deseas admitir automáticamente.

Aunque parece demasiado complicado según su descripción. ¿Ha considerado usar simplemente los TraceListeners adecuados en su colección de Diagnósticos, donde la aplicación de la consola agrega el TraceListener apropiado para enviar a la consola y la aplicación que no es de la consola agrega el EventLog TraceListener apropiado para enviar al registro de eventos de Windows? Esto tiene la ventaja adicional de funcionar bien con todo el soporte de inicio de sesión de .NET sin asumir ninguna dependencia externa (por ejemplo, log4net).

+0

Para ser sincero, realmente no he hecho mucha experimentación en la forma de iniciar sesión antes de ahora. De hecho, solo he necesitado iniciar sesión en uno de los pocos lugares predeterminados. En consecuencia, nunca he experimentado con TraceListeners ... que está a punto de cambiar. Gracias, +1 – BenAlabaster

+0

¡Buen negocio, me alegro de poder ayudar! Regla de TraceListeners. : D –

1

Se han preguntado variantes de esta pregunta antes. A saber, here y here.

' Las soluciones parecen reducirse a dos opciones

  • utilizando la reflexión de averiguar lo le está llamando.
  • En el caso de la aplicación de consola ponga una llamada a la consola en un bloque try-catch y vea si falla o tiene éxito.

Mi propia recomendación es que su biblioteca exporte una interfaz. La interfaz tiene una función o propiedad que devuelve el tipo de la persona que llama. El objeto que llama tiene una clase que implementa la interfaz y devuelve el tipo que es. Debido a que la complejidad es una preocupación, puede controlar eso en cierta medida por lo que coloca en la interfaz.

Si una aplicación no se registra en la biblioteca, puede intentar arrojar un error o probar algún esquema de detección automática.

Al utilizar una interfaz y arrojar un error, lo explicita al programador que utiliza la biblioteca, exactamente lo que espera. La interacción entre los dos está definida por la interfaz.

Además, la interacción es más flexible que un esquema automático porque, como usuario, puedo elegir cómo mi binario llamante interactúa con su biblioteca en lugar de un misterioso conjunto de reglas.

0

Sé que es un truco, pero llamar a Console.Read arrojará una excepción cuando no haya consola.

bool isConsole = true; 
try 
{ 
    isconsole = Console.CursorLeft >= int.MinValue; 
} 
catch(IOException) 
{ 
    // Try to attach to parent process's console window 
    isConsole = AttachConsole(0xFFFFFFFF); 
} 

... 

[DllImport("kernel32", SetLastError = true)] 
private static extern bool AttachConsole(uint dwProcessId); 

Es un efecto secundario por lo que no puede ser un método fiable de detección, pero funciona por ahora.

+1

También requeriría que el usuario ingrese un carácter basura antes de ejecutar ¿no es así? Me pregunto si otro método de consola estática no tendría el mismo efecto, sin la interacción del usuario. –

6

Acabo de descubrir que "Console.Title" será una cadena en blanco en una aplicación de Windows y se configurará automáticamente en una aplicación de consola.

Aún así, es un hack.

Cuestiones relacionadas