2008-09-27 3 views
2

Je suis en train d'obtenir soit CreateProcess ou CreateProcessW pour exécuter un processus avec un nom < MAX _ caractères PATH mais dans un chemin qui est supérieur à MAX _ Les caractères PATH. Selon les docs à: http://msdn.microsoft.com/en-us/library/ms682425.aspx, je dois m'assurer que lpApplicationName n'est pas NULL et que lpCommandLine peut avoir jusqu'à 32 768 caractères.Comment obtenir CreateProcess/CreateProcessW pour exécuter un processus dans un chemin> caractères MAX_PATH

J'ai essayé, mais j'obtiens ERREUR _ CHEMIN _ PAS _ TROUVE.

J'ai changé pour CreateProcessW, mais toujours la même erreur. Lorsque je préfixe lpApplicationName avec \\? \ Comme décrit dans http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx lorsque j'appelle CreateProcessW j'obtiens une erreur différente qui me fait penser que je suis un peu plus proche: ERREUR _ SXS _ CANT _ GEN _ ACTCTX.

Mon appel à CreateProcessW est:

CreateProcessW(w_argv0,arg_string,NULL,NULL,0,NULL,NULL,&si,&ipi);

où w_argv0 est \\?\<long absolute path>\foo.exe.

arg_string contient "< à long chemin absolu > \ foo.exe" foo

si est défini comme suit :

 
    memset(&si,0,sizeof(si)); 
    si.cb = sizeof(si); 
    si.dwFlags = STARTF_USESHOWWINDOW; 
    si.wShowWindow = SW_HIDE;> 

et pi est vide, comme dans:

 
    memset(&pi,0,sizeof(pi)); 

J'ai regardé dans le journal des événements système et il y a une nouvelle entrée chaque fois que j'essayer avec ID d'événement 59, la source SideBySide: générer un contexte d'activation a échoué pour .manifest. Message d'erreur de référence: L'opération s'est terminée avec succès.

Le fichier que j'essaie d'exécuter s'exécute correctement dans un chemin < caractères MAX_PATH.

Pour clarifier, aucun composant de < long chemin absolu > est supérieur à MAX _ caractères PATH. Le nom de l'exécutable lui-même n'est certainement pas, même avec .manifest à la fin. Mais, l'ensemble du chemin ensemble est plus long que MAX _ caractères PATH.

Je reçois la même erreur si j'intègre son manifeste ou non. Le manifeste s'appelle foo.exe.manifest et réside dans le même répertoire que l'exécutable lorsqu'il n'est pas incorporé. Il contient:

 
<?xml version='1.0' encoding='UTF-8' standalone='yes'?> 
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'> 
    <dependency> 
    <dependentAssembly> 
     <assemblyIdentity type='win32' name='Microsoft.VC80.DebugCRT' version='8.0.50727.762' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' /> 
    </dependentAssembly> 
    </dependency> 
</assembly> 

Quelqu'un sait-il comment cela fonctionne? Peut-être:

  • une autre façon d'appeler CreateProcess ou CreateProcessW pour exécuter un processus dans un chemin> caractères MAX_PATH

  • quelque chose que je peux faire dans le fichier manifeste

Je suis Construire avec Visual Studio 2005 sur XP SP2 et en cours d'exécution natif.

Merci pour votre aide.

Répondre

1

Je ne vois aucune référence dans la documentation CreateProcess indiquant que la syntaxe '\\? \' Est valide pour le nom du module. La page sur "Nommage d'un fichier ou d'un répertoire" n'indique pas non plus que CreateProcess le prend en charge, tandis que des fonctions telles que CreateFile sont liées à la page "Attribution d'un nom à un fichier".

Je ne voir que vous ne pouvez pas utiliser un nom de module plus long que MAX_PATH dans lpCommandLine, ce qui suggère que CreateProcess ne supporte pas les noms de fichiers très longs. Le message d'erreur suggère également qu'une erreur se produit lors de la tentative d'ajout de ".manifest" à votre chemin d'application (c'est-à-dire que la longueur dépasse désormais MAX_PATH). GetShortPathName() peut être d'une certaine aide ici, bien qu'il ne garantit pas de retourner un nom inférieur à MAX_PATH (il indique explicitement que la syntaxe '\\? \' Est valide, cependant)

Sinon, vous pouvez essayer d'ajuster la variable d'environnement PATH et la transmettre à CreateProcess() dans lpEnvironment. Ou vous pouvez utiliser SetCurrentDirectory() et transmettre uniquement le nom de l'exécutable.

2

L'incorporation du manifeste et l'utilisation de GetShortPathNameW l'ont fait pour moi. L'un ou l'autre seul n'était pas suffisant. ?

Avant d'appeler CreateProcessW utilisant le \\ - nom de chemin absolu préfixé du processus d'exécution comme premier argument, je vérifie:

 
wchar_t *w_argv0; 
wchar_t *w_short_argv0; 

... 

if (wcslen(w_argv0) >= MAX_PATH) 
{ 
    num_chars = GetShortPathNameW(w_argv0,NULL,0); 
    if (num_chars == 0) { 
     syslog(LOG_ERR,"GetShortPathName(%S) to get size failed (%d)",
w_argv0,GetLastError()); /* ** Might as well keep going and try with the long name */ } else { w_short_argv0 = malloc(num_chars * sizeof(wchar_t)); memset(w_short_argv0,0,num_chars * sizeof(wchar_t)); if (GetShortPathNameW(w_argv0,w_short_argv0,num_chars) == 0) { syslog(LOG_ERR,"GetShortPathName(%S) failed (%d)",w_argv0,
GetLastError()); free(w_short_argv0); w_short_argv0 = NULL; } else { syslog(LOG_DEBUG,"using short name %S for %S",w_short_argv0,
w_argv0); } } }

puis appelez CreateProcessW (w _ court _ argv0 w _? court _ argv0: w _ argv0 ...); Se souvenir de libérer (w _ court _ argv0); ensuite.

Cela peut ne pas résoudre tous les cas, mais cela me permet de générer plus de processus enfants que je ne le pouvais auparavant.

Questions connexes