2012-03-13 2 views
1

Я пытаюсь использовать devcon.exe для проверки состояния различных аппаратных средств. В этом примере я пытаюсь проверить статус SATA HBA, но devcon о нем скулит. Вот код:Аргументы, передаваемые CreateProcess, не обрабатываются, как я ожидал

int main(int argc, char** argv) { 
    std::string cmdLine("\"C:\\Users\\afalanga\\Documents\\Visual Studio 2010\\Projects\\PlayGround\\Debug\\devcon.exe\" status PCI\\VEN_8086^&DEV_3A22^&SUBSYS_75201462^&REV_00"); 

    char* pCmdLine(new char[cmdLine.length() + 10]); 
    memset(pCmdLine, 0, cmdLine.length() + 10); 

    for(int i(0); i < cmdLine.length(); i++) 
     pCmdLine[i] = cmdLine.at(i); 

    STARTUPINFO si = { sizeof(STARTUPINFO) }; 
    PROCESS_INFORMATION pi = {0}; 

    if(!CreateProcess(NULL, pCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { 
     std::cout << "Create child process failed. Error code: " 
        << GetLastError() << std::endl; 
     return 1; 
    } 

    WaitForSingleObject(pi.hProcess, INFINITE); 
    CloseHandle(pi.hThread); 
    CloseHandle(pi.hProcess); 

    return 0; 
} 

Проблема заключается в том, что, когда выше выполняется, Devcon жалуется, что «Нет соответствующих устройств обнаружено не было.» Однако, если я скопирую/вставлю эту командную строку из отладчика в мою командную строку и нажимаю клавишу ввода (или курс, удаляющий все охватывающие кавычки, которые размещает отладчик), команда выполняется отлично, как ожидалось.

В чем я ошибаюсь в моей передаче строки? То, что выше, является результатом чтения документов CreateProcess() в MSDN (выясняется, что первый аргумент необязательно необходим, и cmd-аргументы вообще не должны туда идти). Причина, по которой я выделяю 10 дополнительных байтов памяти для копирования строки, заключается в том, что «что угодно» может измениться в кишках функции CreateProcess(), это может сделать, не топая в другую память. По крайней мере, это была моя мысль, когда я это сделал.

+0

Unrelated, но вы утечку памяти, и почему на земле будет один использовать 'memset' вместо простого'() '? – ildjarn

ответ

5

Command line metacharacters are parsed by the command processor. В частности, вы используете ^, чтобы предотвратить отказ CMD.EXE от команды в амперсанде. Но вы выполняете программу напрямую, минуя CMD.EXE. Таким образом, ^ переходит к devcon.exe, который путает их.

Решение: удалить символы ^.

Ваша проблема на самом деле противоположна вашему названию. Командная строка, переданная в CreateProcess, передается непосредственно в приложение точно так же, как вы указали его.

+0

Спасибо! Вот и все. Как изменить заголовок для лучшей ссылки? –

1
std::string cmdLine("\"C:\\Users\\afalanga\\Documents\\Visual Studio 2010\\Projects\\PlayGround\\Debug\\devcon.exe\" status PCI\\VEN_8086^&DEV_3A22^&SUBSYS_75201462^&REV_00 

Предположительно ^ CARETS там находятся остатки команды, введенной в интерпретатор командной строки, где они служат для отключения специального значения &.

Просто удалите брошюры.

Также обратите внимание, что ваш текущий код теряет память.

Чтобы избежать этого, сделайте, например,

string commandLineArg = cmdLine + '\0'; 

... CreateProcess(0, &commandLineArg[0], ...) 
+0

Я чувствую себя довольно глупо. Я пропустил отказ удалить [] буфер. Это была простая программа, которую я использовал для отладки проблемы, которая была в большей части кода. Я фактически удаляю память там. Однако, я думаю, этот подход намного более изящный. Спасибо за предложение. –

0

Я использовал:

TCHAR var[] = _T(" C:\\filepathe\\foo");

CreateProcess(NULL, var,...);