Comment attendre un processus de shell pour terminer avant d'exécuter tout autre code en VB6
J'ai une petite application VB6 dans lequel j'utilise la Shell
commande d'exécution d'un programme. Je suis le stockage de la sortie du programme dans un fichier. Je suis alors dans la lecture de ce fichier et de mettre la sortie à l'écran à l'aide d'un msgbox en VB6.
C'est ce que mon code ressemble à ça:
sCommand = "\evaluate.exe<test.txt "
Shell ("cmd.exe /c" & App.Path & sCommand)
MsgBox Text2String(App.Path & "\experiments\" & genname & "\freq")
Le problème est que la sortie, ce qui le programme visual basic est en cours d'impression à l'aide de la msgbox est l'ancien état du fichier. Est-il un moyen de tenir l'exécution du code VB jusqu'à ce que ma commande shell programme se termine en sorte que je reçois le bon état du fichier de sortie et non pas un état antérieur?
C'est la façon de le faire: appspro.com/Tips/VBA%20Tips.htm par exemple appspro.com/Downloads/ShellAndWait.zip
OriginalL'auteur anubhav | 2011-04-16
Vous devez vous connecter pour publier un commentaire.
Le secret de la sauce nécessaire pour ce faire est la
WaitForSingleObject
function, qui bloque l'exécution de votre application jusqu'à ce que le processus se termine (ou heures). Il fait partie de l'API de Windows, facilement appelé à partir d'un VB 6 application après l'ajout de la déclaration appropriée de votre code.Cette déclaration devrait ressembler à quelque chose comme ceci:
Elle prend deux paramètres: une poignée pour le processus que vous voulez attendre, et l'intervalle de délai d'attente (en millisecondes) qui indique le montant maximal de fois que vous voulez attendre. Si vous ne spécifiez pas un intervalle de délai d'attente (une valeur de zéro), la fonction n'attend pas et retourne immédiatement. Si vous spécifiez un temps infini dans l'intervalle, la fonction renvoie seulement lorsque les signaux de processus qu'il a terminé.
Armés de cette connaissance, la seule tâche qui reste est de savoir comment obtenir un handle pour le processus que vous avez commencé. Qui s'avère être assez simple, et peut être accompli de différentes manières:
Une possibilité (et la façon dont je le ferais) est à l'aide de la
ShellExecuteEx
function, également à partir de l'API de Windows, comme une goutte d'eau en remplacement de laShell
fonction qui est intégrée à visual basic 6. Cette version est beaucoup plus polyvalent et puissant, mais toujours très facilement à l'aide de la déclaration.Il retourne un handle pour le processus qu'il crée. Tout ce que vous avez à faire est de passer ce handle à la
WaitForSingleObject
fonction que lehHandle
paramètre, et vous êtes en affaires. L'exécution de votre application sera bloquée (suspendu) jusqu'à ce que le processus que vous avez appelé termine.Une autre possibilité est d'utiliser le
CreateProcess
function (une fois de plus, à partir de l'API Windows). Cette fonction crée un nouveau processus et son thread principal dans le même contexte de sécurité que le processus appelant (c'est à dire, votre VB 6 application).Microsoft a publié un article de base de connaissances détaillant cette approche fournit même un exemple complet de mise en œuvre. Vous pouvez trouver cet article ici: Comment Utiliser une Application 32 Bits pour Déterminer si un Processus shell se Termine.
Enfin, peut-être l'approche la plus simple est encore de prendre avantage du fait que le haut-
Shell
fonction de la valeur de retour est une application d'identification de la tâche. C'est un numéro unique qui identifie le programme que vous avez commencé, et il peut être transmis à laOpenProcess
function pour obtenir un handle de processus qui peut être transmis à laWaitForSingleObject
fonction.Toutefois, la simplicité de cette approche ne un coût. Un très désavantage est qu'il sera la cause de votre VB 6 formulaire de demande pour devenir complètement insensible. Parce qu'il ne sera pas de traitement de messages de Windows, il ne répondra pas à l'interaction de l'utilisateur ou encore le rafraîchissement de l'écran.
Les bonnes gens plus à VBnet ont fait remplir un exemple de code disponible dans l'article suivant: WaitForSingleObject: Déterminer quand une Bombardé Application est Terminée.
j'aimerais être en mesure de reproduire le code ici pour aider à conjurer le lien de la pourriture (VB 6 est de se lever il y a dans ans maintenant; il n'y a aucune garantie que ces ressources seront autour de toujours), mais la licence de distribution dans le code lui-même semble interdire explicitement.
Cette réponse commence en disant qu'il n'est pas possible, puis montre comment il est possible. Un peu déroutant ou j'ai besoin de plus de café?
La première phrase dit qu'il n'est pas possible "grâce à
Shell
de commande". J'explique comment appeler les fonctions de l'API Windows pour le faire, à la place. Je n'ai pas été clair à ce sujet? Edit: Ouais, jamais l'esprit. Vous avez raison. Randy code t utiliserShell
. La première partie de la réponse était ce que j'avais avant de Googler pour de meilleures alternatives: je diraisShellExecuteEx
sans beaucoup de réflexion plus loin... je vais le corriger.Cody, il n'est pas sur NOS sentiments, mais Randys. Si ce commentaire est à prendre comme une licence, vous êtes violent. C'est un joli clair de binaires de distribution de chose. Peut-être que vous pouvez contacter Randy (celui qui est) et de lui demander?
Autant que je sache, VB6 de la fonction Shell est un assez mince wrapper sur la fonction CreateProcess (probablement WinExec en fait). ShellExecute/Ex est un poids lourd d'appel qui peuvent avoir des effets secondaires qui sont soit souhaitable ou undesireable. Par exemple: "Note Le ouvrir les fenêtres des dossiers dans un processus différent de paramètre dans les Options des Dossiers affecte ShellExecute. Si cette option est désactivée (réglage par défaut), ShellExecute utilise un ouvrir la fenêtre de l'Explorateur plutôt que de lancer un nouveau. Si aucune fenêtre de l'Explorateur est ouvert, ShellExecute lance un nouveau." L'appel de ShellExecute est de poser une fenêtre de l'Explorateur pour exécuter le programme.
OriginalL'auteur Cody Gray
Il n'est pas nécessaire de recourir à l'effort supplémentaire de l'appel de la fonction CreateProcess(), etc. Cette plus ou moins duplique le vieux Randy Bouleau code si elle n'était pas basée sur son exemple. Il ya seulement tellement de façons à la peau d'un chat.
Ici, nous avons un produit de Fonction pour une utilisation pratique, qui renvoie le code de sortie. Le déposer dans un statique (.BAS) de module ou de l'inclure dans un Formulaire ou d'une Classe.
Merci man! 🙂
OriginalL'auteur Bob77
Je sais que c'est un vieux thread, mais...
Comment sur l'utilisation de Windows Script Host est la méthode? Il a un bWaitOnReturn paramètre.
objet.Exécuter (strCommand, [intWindowStyle], [bWaitOnReturn])
intWindowStyle = 0, donc cmd sera caché
OriginalL'auteur csaba
Faire comme ceci :
Référence : http://support.microsoft.com/kb/129796
System.Diagnostics.Process.Start
, droit?Vous avez raison, l'édition de code d'échantillon/
Euh, non. Lire les étiquettes plus de prudence sur la question la prochaine fois: rien de cela n'existe dans visual basic 6. Elle n'a rien à voir avec .NET. Pas sûr de savoir comment ce jamais eu upvoted. Étant le plus rapide du répondeur ne prend en compte que si votre réponse est applicable.
comme vous le voyez j'ai fourni vb6 solution de trop !
Non, vous n'avez pas. Il n'y a pas
Environment.GetFolderPath
en VB 6. LeSystem.Environment
classe est de la partie .NET BCL. Il n'y a pasProcess
de classe, pas deMessageBox.Show
, etc. etc. Même l'article de MSDN vous lié à dit VB.NET.OriginalL'auteur Farzin Zaker
Grand code. Un tout petit peu de problème: vous devez déclarer dans le ExecCmd (après le Dim commencer Comme STARTUPINFO):
Dim ret tant
Vous obtenez un message d'erreur lorsque vous essayez de compiler en VB6 si vous ne le faites pas.
Mais il fonctionne très bien 🙂
Salutations
OriginalL'auteur Rui Fernandes
Dans mes mains, csaba solution se bloque avec intWindowStyle = 0, et jamais repasse le contrôle de VB. Le seul moyen de sortir est de terminer le processus dans le gestionnaire des tâches.
Réglage intWindowStyle = 3 et la fermeture de la fenêtre manuellement repasse le contrôle
OriginalL'auteur Shyaku