web-dev-qa-db-fra.com

CreateProcess ne passe pas les arguments de la ligne de commande

Bonjour, j'ai le code suivant mais il ne fonctionne pas comme prévu, je ne peux pas comprendre quel est le problème.

Fondamentalement, j'exécute un processus (un processus .NET) et lui passe les arguments de ligne de commande, il est exécuté avec succès par CreateProcess () mais CreateProcess () ne transmet pas les arguments de ligne de commande

Qu'est-ce que je fais mal ici ??

int main(int argc, char* argv[])
{
    PROCESS_INFORMATION ProcessInfo; //This is what we get as an [out] parameter

    STARTUPINFO StartupInfo; //This is an [in] parameter

    ZeroMemory(&StartupInfo, sizeof(StartupInfo));
    StartupInfo.cb = sizeof StartupInfo ; //Only compulsory field

    LPTSTR cmdArgs = "[email protected]";

    if(CreateProcess("D:\\email\\smtp.exe", cmdArgs, 
        NULL,NULL,FALSE,0,NULL,
        NULL,&StartupInfo,&ProcessInfo))
    { 
        WaitForSingleObject(ProcessInfo.hProcess,INFINITE);
        CloseHandle(ProcessInfo.hThread);
        CloseHandle(ProcessInfo.hProcess);

        printf("Yohoo!");
    }  
    else
    {
        printf("The process could not be started...");
    }

    return 0;
}

EDIT: Hey encore une chose, si je passe ma cmdArgs comme ceci:

// a space as the first character
LPTSTR cmdArgs = " [email protected]";

Ensuite, j'obtiens l'erreur, puis CreateProcess renvoie TRUE mais mon processus cible n'est pas exécuté.

Object reference not set to an instance of an object
24
akif

Vous devez spécifier également le nom du module dans les paramètres: LPTSTR cmdArgs = "App [email protected]"; Il doit s'agir de la ligne de commande complète (y compris argv [0]).

23
EFraim

Si le premier paramètre à CreateProcess() est non-NULL, il l'utilisera pour localiser l'image à lancer.

Si c'est NULL, il analysera le 2ème argument pour essayer de lancer l'exécutable à partir du 1er jeton.

Dans les deux cas, le runtime C utilisera le deuxième argument pour renseigner le tableau argv. Ainsi, le premier jeton de ce paramètre apparaît dans argv[0].

Vous voulez probablement quelque chose comme ce qui suit (j'ai changé le programme smtp.exe en echoargs.exe - un utilitaire simple que je dois aider à comprendre ce genre de problème):

int main(int argc, char* argv[])
{
    PROCESS_INFORMATION ProcessInfo; //This is what we get as an [out] parameter

    STARTUPINFO StartupInfo; //This is an [in] parameter
    char cmdArgs[] = "echoargs.exe [email protected]";

    ZeroMemory(&StartupInfo, sizeof(StartupInfo));
    StartupInfo.cb = sizeof StartupInfo ; //Only compulsory field


    if(CreateProcess("C:\\util\\echoargs.exe", cmdArgs, 
        NULL,NULL,FALSE,0,NULL,
        NULL,&StartupInfo,&ProcessInfo))
    { 
        WaitForSingleObject(ProcessInfo.hProcess,INFINITE);
        CloseHandle(ProcessInfo.hThread);
        CloseHandle(ProcessInfo.hProcess);

        printf("Yohoo!");
    }  
    else
    {
        printf("The process could not be started...");
    }

    return 0;
}

Voici le résultat de ce programme:

echoargs.exe [email protected]
[0]: echoargs.exe
[1]: [email protected]

Yohoo!
17
Michael Burr

Vous trouverez ci-dessous une version simplifiée du code utilisé par le Zeus IDE pour exécuter des processus externes:

bool createProcess(const char *pszTitle, const char *pszCommand)
{
  STARTUPINFO StartInfo;

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

  StartInfo.cb      = sizeof(StartInfo);
  StartInfo.lpTitle = (pszTitle) ? (char *)pszTitle : (char *)pszCommand;

  StartInfo.wShowWindow = SW_NORMAL;
  StartInfo.dwFlags    |= STARTF_USESHOWWINDOW;

  if (CreateProcess(0, (char *)pszCommand, 
                    0, 0, TRUE,
                    CREATE_NEW_PROCESS_GROUP, 0, 0, 
                    &StartInfo, &ProcessInfo))
  {
    lErrorCode = 0;
  }
  else
  {
    lErrorCode = GetLastError();
  }

  return (lErrorCode == 0);
}

PszCommand serait le chemin complet de l'exécutable, le nom du fichier et les arguments, par exemple:

pszCommand = "D:\\email\\smtp.exe [email protected]";

D'après ce que je peux dire, la seule différence réelle entre les deux réside dans le fait que, dans l'exemple Zeus, l'argument dwCreationFlags a la valeur CREATE_NEW_PROCESS_GROUPvalue.

5
jussij

Vous ne semblez pas utiliser correctement CreateProcess, voir http://msdn.Microsoft.com/en-us/library/ms682425%28VS.85%29.aspx .

  • La ligne de commande à exécuter. La longueur maximale de cette chaîne est de 32 768 caractères, y compris le caractère nul final Unicode. Si lpApplicationName est NULL, la partie du nom de module de lpCommandLine est limitée à MAX_PATH.

  • Le paramètre lpCommandLine peut être NULL. Dans ce cas, la fonction utilise la chaîne pointée par lpApplicationName comme ligne de commande.

  • Si lpApplicationName et lpCommandLine sont tous deux non NULL, la chaîne terminée par un caractère null désignée par lpApplicationName spécifie le module à exécuter et la chaîne terminée par un caractère nul indiquée par lpCommandLine spécifie la ligne de commande . Le nouveau processus peut utiliser GetCommandLine pour récupérer la ligne de commande complète. Les processus de console écrits en C peuvent utiliser les arguments argc et argv pour analyser la ligne de commande. Argv [0] étant le nom du module, les programmeurs C répètent généralement le nom du module en tant que premier jeton de la ligne de commande.

Donc, dans votre cas, vous avez besoin de cela comme argument de commande et devez probablement passer un NULL pour le premier paramètre afin d'obtenir le comportement que vous souhaitez.

// NOTE THE Null-Terminated string too!
LPTSTR cmdArgs = "D:\\email\\smtp.exe [email protected]\0";
5
Ray Hayes

Essaye ça:

LPTSTR cmdArgs = "[email protected]";
CString szcmdline("D:\\email\\smtp.exe");
szcmdline += _T(" ") + cmdArgs ;

//Leave first param empty and pass path + argms in 
    if(CreateProcess(NULL, szcmdline, second
2
aJ.

La version Unicode de cette fonction, CreateProcessW, peut modifier le contenu de cette chaîne. Par conséquent, ce paramètre ne peut pas être un pointeur sur une mémoire en lecture seule (telle qu'une variable const ou une chaîne littérale). Si ce paramètre est une chaîne constante, la fonction peut provoquer une violation d'accès.

Par conséquent, vous pouvez essayer d'utiliser LPTSTR cmdArgs = _tcsdup("[email protected]").

Un autre problème est: comment le processus cible lit-il les arguments? utiliser argv [0] comme nom d'application? Ensuite, vous devez également ajouter le nom de l'application en tant que premier paramètre.

0
Vlagged

Vous pouvez ajouter un espace en tant que premier caractère de la chaîne cmdArgs: 

LPTSTR cmdArgs = " [email protected]"; 

Apparemment, Windows ajoute la deuxième chaîne d'argument au nom d'application représenté par le premier argument et le résultat est transmis sous forme d'argument de ligne de commande à l'exécutable. Donc, ajouter un espace séparera correctement les arguments.

0
kundrata

Vous n'allouez pas de mémoire pour votre chaîne.

Au lieu de:

LPTSTR cmdArgs = "[email protected]";

essayer:

TCHAR cmdArgs[] = "[email protected]";

Edit: Puis appelez:

 CreateProcess("D:\\email\\smtp.exe", &cmdArgs[0], ...

Cela créera un tableau local sur la pile, puis passera un pointeur sur ce tableau.

0
morechilli