2010-03-03 20 views
25

Tengo una tarea de MSBuild que ejecuta (entre otras cosas) una llamada a xcopy. Lo que he encontrado es que esta llamada a xcopy se ejecuta correctamente cuando ejecuto mi tarea MSBuild desde un archivo por lotes, y no se puede ejecutar o producir ningún resultado que me permita tener una idea de lo que sucede cuando se llama ese mismo archivo por lotes desde otro Aplicación C# con System.Diagnostics.Process.¿Qué hace exactamente System.Diagnostics.Process UseShellExecute?

Ambos procesos se ponen en marcha con más o menos la misma estructura:

waitProc.StartInfo.Arguments = "/C [executable]"; 
waitProc.StartInfo.FileName = "cmd.exe"; 
waitProc.StartInfo.UseShellExecute = false; 

Además, cambiando la "UseShellExecute" de falso a verdadero en el comando xcopy que puede hacer que este tenga éxito en ambos casos de uso, sin embargo, la comando no se ejecuta en un tercer caso de uso. El tercer caso de uso es nuestro sistema de compilación automatizado, que es un servicio de Windows que llama directamente a msbuild. En el caso de una falla en nuestra máquina de compilación, el comando de copia se bloquea indefinidamente, lo cual es, creo, porque System.Diagnostics.Process intenta mostrar una ventana y los servicios no tienen una sesión de escritorio de Windows asociada a ellos, por lo que no pueden mostrar ventanas

He intentado utilizar la propiedad "CreateNoWindow" y he intentado configurar el "WindowStyle" en "ProcessWindowStyle.Hidden", pero eso no cambia el comportamiento en la máquina de compilación.

Dicho todo esto, lo que realmente quiero saber es qué hace exactamente la propiedad UseShellExecute, porque parece hacer mucho más de lo que sugiere la documentación de MSDN.

Gracias.

+0

Hola Chris, ¿alguna vez has ido más lejos con esto? Parece que me encuentro con una situación similar: http://stackoverflow.com/questions/7085185/msbuild-buildinparallel-custom-task-spawning-process-that-fails-to-run –

Respuesta

28

ProcessStartInfo.UseShellExecute indica al Proceso que use el Windows Shell para ejecutar la aplicación especificada.

Sin este conjunto, solo puede ejecutar un archivo EXE directamente. Al configurar esto, permite que se use el Shell de Windows, lo que permite cosas tales como especificar un archivo .doc y tener el programa asociado para abrir el archivo.

Sin embargo, usar Windows Shell requiere un contexto de escritorio válido, por lo que su tercer caso de uso falla.

En general, usar cmd.exe es problemático a menos que esté usando el shell de Windows. Es posible que desee simplemente escribir el código para manejar su operación de "lote" directamente, es decir: use los métodos de los tipos en el System.IO namespace para hacer su copia. Esto evitaría este problema por completo.

+1

¿Tiene alguna idea de por qué necesita un contexto de escritorio válido? Asumí que ese era el caso cuando estaba colgado en la máquina de compilación, pero realmente no entiendo por qué el caparazón de Windows necesitaría la capacidad de dibujar en la pantalla. – Beanz

+4

@Chris: el "shell de Windows" es básicamente explorador, y se inicia cuando realmente inicias sesión. Desafortunadamente, este es un problema común con los archivos por lotes en las máquinas de compilación: he visto a muchas personas luchar con él, y he cambiado a simplemente escribir mis "guiones" en C# directamente para evitar el problema;) –

+0

Además, debe especificar 'UseShellExecute' si desea modificar las variables de entorno del proceso. –

1

Desde el Documentation:

se establece esta propiedad en false permite redirigir la entrada, salida, y corrientes de error.

Nota: UseShellExecute debe ser falsa si la propiedad nombre de usuario no es un nulo referencia (Nothing en Visual Basic) o una cadena vacía, o un InvalidOperationException se produce cuando el Process.Start (ProcessStartInfo) se llama al método . Cuando se utiliza la cáscara sistema operativo para iniciar procesos, que puede comenzar a cualquier documento (es decir, cualquier tipo fichero registrado asociado con un ejecutable que tiene una abierta acción por defecto) y realizar operaciones en el archivo , como la impresión , con el componente de proceso . Cuando UseShellExecute es falso, puede iniciar solo ejecutables con el componente de proceso .

Nota: UseShellExecute debe ser verdadero si establece la propiedad ErrorDialog en true. La propiedad WorkingDirectory se comporta de manera diferente cuando UseShellExecute es verdadero que cuando UseShellExecute es falso. Cuando UseShellExecute es verdadero, la propiedad WorkingDirectory especifica la ubicación del ejecutable. Si WorkingDirectory es una cadena vacía, se entiende que el directorio actual contiene el ejecutable.

Cuando UseShellExecute es falso, la propiedad WorkingDirectory no se utiliza para encontrar el ejecutable. En cambio, es utilizado por el proceso que se inició y tiene significado solo dentro del contexto del nuevo proceso.

0

El uso de IIRC 'UseShellExecute', es permitir que el explorador (la cáscara principal) para ejecutar el proceso y no el tiempo de ejecución .NET .... a menos que alguien me corrige que estoy equivocado ...

+0

esta propiedad le dice al sistema operativo que ejecute esta aplicación por consola o por shell. – Andrey

+0

@Michael - ¿Por qué eliminaste la firma? Seguramente pensé que estaba siendo educado al decir 'mis mejores deseos' en lugar de no tener nada que se considere grosero ... ¿cuál es tu lógica? FYI - He respondido más de 800 preguntas y ninguna queja ... Recibí un agradable 'Gracias Tom' cuando respondí la pregunta de alguien correctamente o ¡la Corrección política se ha vuelto loca! suspiro – t0mm13b

0

¿especificó WorkingDirectory correctamente? Puede ver el resultado real de su comando al agregar >c:\log.txt 2>c:\err.txt ejecutarlo con esta adición y verificar esos archivos

Cuestiones relacionadas