2010-03-03 9 views
25

J'ai une tâche MSBuild qui exécute (entre autres) un appel à xcopy. Ce que j'ai trouvé est que cet appel à xcopy s'exécute correctement lorsque j'exécute ma tâche MSBuild à partir d'un fichier de commandes, et ne parvient pas à exécuter ou produire une sortie qui me donnerait une idée de ce qui se passe Application C# avec un System.Diagnostics.Process.Que fait exactement System.Diagnostics.Process UseShellExecute?

Les deux processus sont lancés avec plus ou moins la même structure:

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

De plus en changeant le « UseShellExecute » de false à true sur la commande xcopy je peux en faire réussir dans les deux cas d'utilisation, mais la commande ne fonctionne pas dans un troisième cas d'utilisation. Le troisième cas d'utilisation est notre système de construction automatisé qui est un service Windows appelant directement msbuild. En cas d'échec sur notre machine de build, la commande de copie se bloque indéfiniment, ce qui est, je crois, parce que System.Diagnostics.Process essaie d'afficher une fenêtre, et les services n'ont pas de session de bureau Windows associée, donc ils ne peuvent pas afficher les fenêtres.

J'ai essayé d'utiliser la propriété "CreateNoWindow", et j'ai essayé de définir "WindowStyle" sur "ProcessWindowStyle.Hidden", mais cela ne change pas le comportement sur la machine de construction. Tout cela dit, ce que je veux vraiment savoir, c'est ce que fait exactement la propriété UseShellExecute, car elle semble faire beaucoup plus que ce que suggère la documentation MSDN.

Merci.

+0

Salut Chris, avez-vous déjà été plus loin avec ça? Je semble rencontrer une situation similaire: http://stackoverflow.com/questions/7085185/msbuild-buildinparallel-custom-task-spawning-process-that-fails-to-run –

Répondre

28

ProcessStartInfo.UseShellExecute indique au processus d'utiliser l'environnement Windows pour exécuter l'application spécifiée.

Sans cet ensemble, vous ne pouvez exécuter qu'un fichier EXE directement. En définissant cela, vous autorisez l'utilisation du shell Windows, ce qui permet notamment de spécifier un fichier .doc et d'ouvrir le fichier par le programme associé. Toutefois, l'utilisation de Windows Shell nécessite un contexte de bureau valide, ce qui explique pourquoi votre troisième cas d'utilisation échoue.

En général, l'utilisation de cmd.exe est problématique sauf si vous utilisez le shell Windows. Vous voudrez peut-être simplement écrire le code pour gérer directement votre opération "batch", c'est-à-dire: utiliser les méthodes des types dans le System.IO namespace pour faire votre copie. Cela permettrait d'éviter complètement ce problème.

+1

Avez-vous une idée pourquoi il a besoin d'un contexte de bureau valide? J'ai un peu supposé que c'était le cas quand il était accroché sur la machine de construction, mais je ne comprends vraiment pas pourquoi le shell de Windows aurait besoin de la capacité de dessiner à l'écran. – Beanz

+4

@Chris: Le "shell Windows" est essentiellement un explorateur, et est lancé lorsque vous vous connectez réellement. Malheureusement, c'est un problème courant avec les fichiers batch sur les machines de build - j'ai vu beaucoup de gens qui ont du mal avec ça, et je suis passé à simplement écrire mes "scripts" en C# pour éviter le problème;) –

+0

vous devez spécifier 'UseShellExecute' si vous souhaitez modifier les variables d'environnement du processus. –

1

De l'Documentation:

La définition de cette propriété sur false permet vous de rediriger l'entrée, la sortie et flux d'erreur.

Note: UseShellExecute doit être fausse si la propriété UserName est pas une référence null (Nothing en Visual Basic) ou une chaîne vide, ou un InvalidOperationException sera jeté lorsque le Process.Start (ProcessStartInfo) La méthode est appelée. Lorsque vous utilisez le shell système d'exploitation pour démarrer les processus, vous pouvez commencer tout document (ce qui est tout type de fichier enregistré associé à un fichier exécutable qui a une action par défaut ouverte ) et d'effectuer des opérations sur le fichier , telles que l'impression , avec le composant de processus . Lorsque UseShellExecute est false, vous pouvez démarrer uniquement les exécutables avec le composant de processus .

Remarque: UseShellExecute doit être true si vous définissez la propriété ErrorDialog sur true. La propriété WorkingDirectory se comporte différemment lorsque UseShellExecute est vrai que lorsque UseShellExecute est false. Lorsque UseShellExecute est true, la propriété WorkingDirectory spécifie l'emplacement de l'exécutable. Si WorkingDirectory est une chaîne vide, le répertoire en cours est compris comme contient l'exécutable.

Lorsque UseShellExecute est false, la propriété WorkingDirectory n'est pas utilisée pour rechercher l'exécutable. Au lieu de cela, il est utilisé par le processus qui est démarré et n'a de sens que dans le contexte du nouveau processus.

0

L'utilisation de IIRC « UseShellExecute », est de permettre à explorer (le shell principal) pour exécuter le processus et non le runtime .NET .... à moins que quelqu'un me corrige que je me trompe ...

+0

cette propriété indique au système d'exploitation d'exécuter cette application par console ou par shell. – Andrey

+0

@Michael - Pourquoi avez-vous retiré la signature? Sûrement je pensais que j'étais poli là en disant «meilleures salutations» au lieu d'en avoir aucune du tout ce qui est considéré impoli ... quelle est votre logique? FYI - J'ai répondu à plus de 800 questions et pas une plainte ... Je reçois un gentil 'Merci Tom' quand j'ai répondu correctement à la question de quelqu'un ou que le politiquement correct est devenu fou! soupir – t0mm13b

0

avez-vous spécifié WorkingDirectory correctement? Vous pouvez voir la sortie réelle de votre commande en ajoutant >c:\log.txt 2>c:\err.txt exécutez cette addition et vérifiez ces fichiers

Questions connexes