2016-04-20 2 views
2

Я пытаюсь создать что-то похожее на cmd с Microsoft Visual Studio Express 2013 для Windows Desktop в C++, и одна из моих функций должна начать процесс, такой как открытый skype, набрав «skype.exe». Я искал в Интернете и нашел функцию CreateProcess, которая должна была выполнить эту работу для меня. когда я создал функцию, которая получает значение класса, которое я создал под названием «Линия» (имя класса, но оно не является обычным) и использовало функцию CreateProcess так, как показано ниже, мне нужно ввести мой «cmd» start skype.exe ", но я хочу, чтобы он работал, как в обычном cmd, написав только« skype.exe », как я могу это сделать? (l.parameter это просто строка, содержащая слово скайп)с помощью функции CreateProcess

void execute(Line l){ 

STARTUPINFO si; 
PROCESS_INFORMATION pi; 

ZeroMemory(&si, sizeof(si)); 
si.cb = sizeof(si); 
ZeroMemory(&pi, sizeof(pi)); 
LPSTR s = const_cast<char *>(l.parameter.c_str()); 
if (!CreateProcess(NULL, s, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) 
{ 
    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);} 

ответ

3

Первое, что:

LPSTR s = const_cast<char *>(l.parameter.c_str()); 

плохая идея, CreateFile принимает для lpCommandLine, не сопзЬ буфера по причине - он может изменить его:

Система добавляет завершающий нулевой символ в строку командной строки, чтобы отделить имя файла от аргументов. Это делит исходную строку на две строки для внутренней обработки.

так что вы должны передать массив, например:

TCHAR szCmd[MAX_PATH] = {0}; 

тогда на ваш вопрос, если «начать Skype.exe» работает для вас, и вы хотите ввести только Skype.exe в команде line - тогда почему бы не конкатенировать строки? например:

_tcscat(szCmd, _T("start ")); 
_tcscat(szCmd, parameter.c_str()); 

и передать szCmd в CreateProcess

вопрос в том, используется ли UNICODE строить, если да, то убедитесь, что параметр станд :: wstring, в противном случае, если вы используете не-UNICODE сборки (и похоже, что это правда), тогда std :: string в порядке.

+1

Поскольку код компиляции с 'LPSTR', то' UNICODE' явно не определены, а версия Анси из 'CreateProcess()' не изменяет буфер команд, только версия Unicode делает. Кроме того, запуск 'start', поскольку команда не будет работать в любом случае. –

3

start не является исполняемым, это особенность cmd.exe, так, чтобы вызвать start skype.exe через CreateProcess(), вы должны указать cmd.exe в качестве команды и /C start skype.exe в качестве параметра.

Line l; 
line.parameter = "cmd.exe /C start skype.exe"; 
execute(l); 

Но это излишество в этой ситуации, как start на самом деле не нужно, несмотря на то, что вы утверждаете. Совершенно корректно и предпочтительно вызывать skype.exe непосредственно в качестве команды.

Однако, вы должны предоставить полный путь кskype.exe (то же самое, если бы вы были вызвать start), в противном случае CreateProcess() не сможет найти ее, как Skype не регистрирует свой EXE-путь к файлу в App Paths ключа реестра или путь к его вложенной папке Phone (где skype.exe проживает) в переменной окружения системы %PATH%.

Например:

Line l; 
line.parameter = "C:\\Program Files (x86)\\Skype\\Phone\\Skype.exe"; 
execute(l); 

К счастью, Skype делает хранить полный путь к skype.exe в Реестре, в частности, в следующем ключе:

HKEY_CURRENT_USER\Software\Skype\Phone 

Он хранится в значении REG_SZ имени "SkypePath" ,

std::string GetSkypePath() 
{ 
    std::string sPath; 

    HKEY hKey; 
    if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Skype\\Phone", 0, KEY_QUERY_VALUE, &hKey) == 0) 
    { 
     char szPath[MAX_PATH+1] = {0}; 
     DWORD dwPathLen = MAX_PATH; 

     if (RegQueryValueExA(hKey, "SkypePath", NULL, NULL, (LPBYTE)szPath, &dwPathLen) == 0) 
      sPath = szPath;    

     RegCloseKey(hKey); 
    } 

    return sPath; 
}