2012-07-05 22 views
12

Mi objetivo es ejecutar un ejecutable externo en mi programa. En primer lugar, utilicé la función system(), pero no quiero que el usuario vea la consola. Entonces, busqué un poco y encontré la función CreateProcess(). Sin embargo, cuando intento pasarle un parámetro, no sé por qué, falla. Tomé el código de MSDN y cambiado un poco:CreateProcess() falla con una infracción de acceso

#include <windows.h> 
#include <stdio.h> 
#include <tchar.h> 

void _tmain(int argc, TCHAR *argv[]) 
{ 
    STARTUPINFO si; 
    PROCESS_INFORMATION pi; 

    ZeroMemory(&si, sizeof(si)); 
    si.cb = sizeof(si); 
    ZeroMemory(&pi, sizeof(pi)); 
    /* 
    if(argc != 2) 
    { 
     printf("Usage: %s [cmdline]\n", argv[0]); 
     return; 
    } 
    */ 
    // Start the child process. 
    if(!CreateProcess(NULL, // No module name (use command line) 
     L"c:\\users\\e\\desktop\\mspaint.exe",  // Command line 
     NULL,   // Process handle not inheritable 
     NULL,   // Thread handle not inheritable 
     FALSE,   // Set handle inheritance to FALSE 
     0,    // No creation flags 
     NULL,   // Use parent's environment block 
     NULL,   // Use parent's starting directory 
     &si,   // Pointer to STARTUPINFO structure 
     &pi)   // Pointer to PROCESS_INFORMATION structure 
    ) 
    { 
     printf("CreateProcess failed (%d).\n", GetLastError()); 
     return; 
    } 

    // Wait until child process exits. 
    WaitForSingleObject(pi.hProcess, INFINITE); 

    // Close process and thread handles. 
    CloseHandle(pi.hProcess); 
    CloseHandle(pi.hThread); 
} 

Sin embargo, el código de acceso crated violación de alguna manera. ¿Puedo ejecutar mspaint sin mostrar al usuario la consola?

Muchas gracias.

+2

Por un lado, 'CreateProcess' requiere que su segundo parámetro (si se proporciona) sea una cadena no constante. No estoy seguro de que esto sea un problema en la práctica, pero quería mencionarlo para completarlo. – reuben

+0

... y de lo contrario, ¿dónde está pasando AV? ¿Tienes una pila de llamadas? – reuben

+0

@reuben Uhm ... No estoy muy seguro, pero supongo que este es el resultado de la pila de llamadas: 'kernel32.dll! 76da70ac() \t \t [Las siguientes tablas pueden ser incorrectas y/o no se han agregado símbolos para kernel32.dll] \t > \t msvcr100d.dll! _nh_malloc_dbg (unsigned int nTamaño, int nhFlag, int nBlockUse, const char * szFileName, int nLinea) Línea 302 + 0x1D bytes \t C++ ' –

Respuesta

7

Pruebe esto, debería funcionar.

TCHAR lpszClientPath[500]= TEXT("c:\\users\\e\\desktop\\mspaint.exe"); 
if(!CreateProcess(NULL, lpszClientPath, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE|CREATE_UNICODE_ENVIRONMENT,NULL, NULL, &si, &pi)) 
      { 
    printf("CreateProcess failed (%d).\n", GetLastError()); 
     return; 
      } 
... 
... 
18

El segundo argumento es un LPTSTR, es decir, un puntero a una matriz de caracteres no const. El docs dice específicamente:

este parámetro no puede ser un puntero a memoria de sólo lectura (como una variable const o una cadena literal)

La razón por la que pasa una cadena literal es un problema:

El sistema agrega un carácter nulo de terminación a la línea de comandos para separar el nombre del archivo de los argumentos. Esto divide la cadena original en dos cadenas para el procesamiento interno.

Lo que significa que en su caso, intenta modificar la memoria de solo lectura, de ahí el bloqueo.

+0

no puedo asignar un LPTSTR cualquiera . ¿Cuál debe ser mi segundo argumento, si puedo preguntar, para ejecutar mspaint que se encuentra en "c: \ users \ e \ desktop \"? Muchas gracias. –

+2

@JohnDoe: 'wchar_t ruta [] = L" C: \\ usuarios \\ e \\ desktop \\ "' – hmjd

+0

'wchar_t ruta [] = L" C: \\ blahblah "' no es lo mismo que 'LPWSTR path = L "C: \\ blahblah" 'pero es lo mismo que' wchar_t * path = L "C: \\ blahblah" '. Debería usar lo que @hmjd ha propuesto o debería definir 'LPWSTR path' y luego asignar memoria para esta var y copiar la ruta a ella. –

0

cambio que este código para:

#include <windows.h> 
#include <stdio.h> 
#include <tchar.h> 

void _tmain(int argc, TCHAR *argv[]) 
{ 
    TCHAR ProcessName[256]; 
    STARTUPINFO si; 
    PROCESS_INFORMATION pi; 

    wcscpy(ProcessName,L"c:\\users\\e\\desktop\\mspaint.exe"); 
    ZeroMemory(&si, sizeof(si)); 
    si.cb = sizeof(si); 
    ZeroMemory(&pi, sizeof(pi)); 
    /* 
    if(argc != 2) 
    { 
     printf("Usage: %s [cmdline]\n", argv[0]); 
     return; 
    } 
    */ 
    // Start the child process. 
    if(!CreateProcess(NULL, // No module name (use command line) 
     ProcessName,  // Command line 
     NULL,   // Process handle not inheritable 
     NULL,   // Thread handle not inheritable 
     FALSE,   // Set handle inheritance to FALSE 
     0,    // No creation flags 
     NULL,   // Use parent's environment block 
     NULL,   // Use parent's starting directory 
     &si,   // Pointer to STARTUPINFO structure 
     &pi)   // Pointer to PROCESS_INFORMATION structure 
    ) 
    { 
     printf("CreateProcess failed (%d).\n", GetLastError()); 
     return; 
    } 

    // Wait until child process exits. 
    WaitForSingleObject(pi.hProcess, INFINITE); 

    // Close process and thread handles. 
    CloseHandle(pi.hProcess); 
    CloseHandle(pi.hThread); 
} 
Cuestiones relacionadas