2012-06-10 1 views
0

Donc, j'ai un petit fragment de code C en cours d'exécution sur une boîte de fenêtres, qui se lit ainsi:Pourquoi le processus de spawn de Windows déclenche-t-il parfois une erreur STATUS_SXS_ASSEMBLY_NOT_FOUND?

/* invoke command */ 
impl->procHandle = _spawnve(_P_NOWAIT, command, vargs, env); 
if (impl->procHandle == -1) { 
    printf("Failed to invoke command: %s\n", strerror(errno)); 
    impl->busy = false; 
} 
printf("VICTORY\n"); 

j'ai écrit quelques tests unitaires autour de ce où ma "commande" est C: \ windows \ system32 \ ipconfig. exe et ça marche, pas de problème.

Essayé de l'utiliser pour un lanceur d'application ... doo doo. A échoué avec l'erreur utile:

The application failed to initialize properly (0xc0150004). 
Click on OK to terminate the application. 

Ok ... je recherche autour découvert que le code d'erreur est STATUS_SXS_ASSEMBLY_NOT_FOUND, et il arrive lorsque je tente de lancer notepad.exe aussi bien. Assemblées manquantes?

Pourquoi cela se produit-il?

Comment puis-je contourner ce problème?

Je suis juste devinant ici, mais je soupçonne que cela a quelque chose à voir avec avoir besoin de la variable PATH à définir dans le _spawnve(), mais je ne sais pas ce qu'il devrait être. J'ai essayé de passer sur le chemin, mais cela ne semble pas aider. L'exécution de ce code:

int offset = 0; 
while (vargs[offset] != NULL) { 
    printf("vargs %d: %s\n", offset, vargs[offset]); 
    ++offset; 
} 
offset = 0; 
while (env[offset] != NULL) { 
    printf("env %d: %s\n", offset, env[offset]); 
    ++offset; 
} 

yeilds:

vargs 0: C:\windows\system32\notepad.exe 
env 0: PATH=c:\WINDOWS\system32 

ie. Je passe dans argv [0], et une valeur de chemin; pas d'autres variables ou arguments env.

Des idées?

-

Edit:

Ainsi, il semble que cette erreur se produit car le chemin est pas correctement quand j'invoque la commande à l'aide _spawnve(). Ceci est rendu évident en invoquant _spawnv() ou _spawnvpe(), qui semblent fonctionner correctement tous les deux.

Cependant, cela ne m'aide pas vraiment, parce que je dois spécifier un composant PATH supplémentaire pour l'application quand il s'exécute. Passer PATH = ... dans _spawnvpe() provoque la même erreur, et évidemment _spawnv n'est pas utilisé car il ne vous permet pas de spécifier le PATH.

Donc vraiment, la réponse à cette question est: Parce que la variable PATH est fausse.

... mais je n'ai encore aucune idée de ce que devrait être. Il ne semble y avoir aucun exemple de travail que je puisse trouver nulle part. J'accepte n'importe quelle réponse qui lie à un exemple de codage utilisant _spawnve() ou _spawnvpe() et passant la variable PATH dedans (et fonctionnant).

Édition 2:

Vraiment. Non, en fait, cela ne fonctionne pas. Voici un exemple ne fonctionne pas. Oubliez le lien vers un exemple qui fonctionne; il suffit de modifier mon exemple et de publier un diff qui 1) passe dans PATH et 2) s'exécute sans erreur.

Nb.Voulez-vous le voir fonctionner? changez pour _spawnv() ou faites la valeur d'env NULL et cela fonctionne très bien.

#include <stdio.h> 
#include <windows.h> 
#include <process.h> 
#include <errno.h> 

int main(int argc, char *argv[]) { 

    char *path_value; 
    char buffer[4000]; 
    const char *env[2]; 
    const char *args[1]; 
    char *command; 
    int result; 
    intptr_t procHandle; 

    path_value = getenv("PATH"); 
    sprintf(buffer, "PATH=%s", path_value); 
    env[0] = buffer; 
    env[1] = NULL; 

    args[0] = NULL; 

    int offset = 0; 
    while (env[offset] != NULL) { 
    printf("env %d: %s\n", offset, env[offset]); 
    ++offset; 
    } 

    offset = 0; 
    while (args[offset] != NULL) { 
    printf("arg %d: %s\n", offset, args[offset]); 
    ++offset; 
    } 

    command = "C:\\windows\\system32\\notepad.exe"; 

    procHandle = _spawnvpe(_P_NOWAIT, command, args, NULL); 
    if (procHandle == -1) { 
    printf("Failed to invoke command: %s\n", strerror(errno)); 
    exit(1); 
    } 

    _cwait(&result, procHandle, 0); 
    if (result != 0) 
    printf("Command exited with error code %d\n", result); 
} 

Sortie:

env 0: PATH=.;c:\Program Files\Common Files\Microsoft Shared\Windows Live;c:\WINDOWS\system32;c:\WINDOWS;c:\WINDOWS\System32\Wbem;c:\Program Files\Microsoft SQL Server\100\Tools\Binn\;c:\Program Files\Microsoft SQL Server\100\DTS\Binn\;c:\Program Files\CMake 2.8\bin;c:\Program Files\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\;c:\Program Files\Common Files\Microsoft Shared\Windows Live 
Command exited with error code -1072365564 
+0

Documentez ce que vous trouvez dans le journal des événements de l'application Windows. –

+1

Si vous parlez du journal "Application" dans l'afficheur d'événements, il n'y a rien là. J'ai couru le code défaillant une douzaine de fois et aucune nouvelle entrée de journal n'a été affichée. Si vous parlez d'autre chose, soyez plus précis. – Doug

+0

Cela peut simplement signifier que votre application a besoin de DLL qui ne sont pas là. Voir sur SO: http://stackoverflow.com/questions/1582844/vcredist-x86-dll-and-version-8-0-50727-4053 –

Répondre

2

Ceci est faux:

const char *args[1]; 
args[0] = NULL; 

vous avez besoin

const char *args[2]; 
args[0] = "notepad"; 
args[1] = NULL; 

Autre que cela, votre exemple de code fonctionne, au moins lorsque compilé avec Visual Studio 2010. Je l'ai testé sur Windows 7 et Windows XP, et cela fonctionne. Le bloc-notes s'exécute.

Quel compilateur utilisez-vous?

+0

Votre exemple de code ne passait pas dans le tableau env, mais il fonctionne toujours pour moi lorsque cela est modifié. –

+0

Il pourrait être intéressant de construire une machine virtuelle avec une installation vanillée de Windows XP, afin de déterminer si votre compilateur ou votre machine de test se comporte différemment des miens. J'ai accès à différentes versions de Visual Studio, donc si vous en utilisez un, je pourrais essayer ça aussi. –

+0

On dirait que c'était l'args [] qui causait l'erreur étrange (drôle, sur Windows 7 l'erreur est différente et sort comme argument invalide, seulement xp me renvoie STATUS_SXS_ASSEMBLY_NOT_FOUND); l'exemple fonctionne avec vos changements! Merci beaucoup! – Doug

0

Vous avez raison, le second paramètre à _ spawnev() prend le nom de l'application à exécuter inlcuding son chemin complet.

Pour se déplacer à connaître le chemin, vous pouvez appeler la commande processer cmd.exe et le transmettre le nom de l'application pour exécuter en tant que paramètre à l'aide de l'option de cmd.exe/C.

Cela fonctionne dans tous les cas où vous auriez pu démarrer l'application à partir de l'une des fenêtres de ligne de commande cmd.exe.

cmd.exe connaît la valeur de la variable d'environnement PATH et l'a utilisée pour la recherche du chemin de l'application à démarrer.

Le chemin vers cmd.exe lui-même peut être lu à partir de la variable d'environnement COMSPEC.

Mise à jour: Pour plus d'informations sur ce problème (y compris des exemples), veuillez lire here.

+0

Il n'y a rien de mal à l'argument 2 de ma commande. Si je permute avec _spawnv() au lieu de _spawnve() cela fonctionne parfaitement. ... mais évidemment je ne peux pas transmettre d'autres valeurs d'env que je veux. (Par exemple, 'command' est identique à la valeur de vargs [0]) – Doug

+0

Aussi, lorsque j'essaie d'utiliser "cmd.exe/C blah" dans _spawnve, j'obtiens une erreur de type "pas de telle commande". Pourriez-vous donner un exemple de la façon de faire ce travail? – Doug

+0

@doug vous devez préfixer '" cmd.exe "' avec ce que vous avez lu comme valeur de la variable d'environnement 'COMSPEC' en utilisant la fonction' getenv() '. – alk

-1

Comme spécifié ici _spawn, _wspawn Functions, seules les fonctions avec une lettre 'p' dans le nom utilisent implicitement la variable d'environnement PATH. Les autres ne le font pas.

donc vous devez faire ceci:

char *args[] = {"notepad.exe", NULL }; 
_spawnvpe(_P_NOWAIT, args[0], args, NULL); 
+0

Pas vrai. _spawn hérite aussi de la variable PATH. _spawnvpe hérite de PATH * et * vous permet de spécifier des variables d'environnement. Cependant, si vous essayez de spécifier PATH comme l'une de ces variables d'env, cela gâche. – Doug

+0

Eh bien, les documents officiels sont assez explicites à ce sujet * La variable d'environnement PATH est utilisée pour trouver le fichier à exécuter lorsque le suffixe de la fonction _spawn est p *, et il ne spécifie pas qu'il prend en charge la variable env. –

Questions connexes