C ++ CreateProcess 'telnet' не распознается - PullRequest
0 голосов
/ 11 октября 2018

Когда я передаю команду ipconfig процессу, она сохраняет правильные результаты в файлах.

char cmd[] = "C:\\windows\\system32\\cmd.exe /c ipconfig";
SaveResult("ipconfig1.txt", NULL, cmd);

char appName[] = "C:\\windows\\system32\\cmd.exe";
char cmd2[] = "/c ipconfig";
SaveResult("ipconfig2.txt", appName, cmd2);

Но когда я передаю wuauclt или telnet

char cmd1[] = "C:\\windows\\system32\\cmd.exe /c telnet";
SaveResult("telnet1.txt", NULL, cmd1);

char appName3[] = "C:\\windows\\system32\\cmd.exe";
char cmd3[] = "/c telnet";
SaveResult("telnet2.txt", appName3, cmd3);

char cmd4[] = "C:\\windows\\system32\\cmd.exe /c wuauclt";
SaveResult("wuauclt1.txt", NULL, cmd4);

char appName5[] = "C:\\windows\\system32\\cmd.exe";
char cmd5[] = "/c wuauclt";
SaveResult("wuauclt2.txt", appName5, cmd5);

Я получаю

'wuauclt' не распознается как внутренняя или внешняя команда, работающая программа или командный файл.'telnet' не распознается как внутренняя или внешняя команда, работающая программа или командный файл.

Как решить эту проблему и почему это происходит?Можно ли запустить через cmd.exe telnet или wuauclt?

Также на этом компьютере wuauclt и telnet в общей консоли, открытой с самого начала, работают, как и ожидалось.

#include "stdafx.h"
#include "windows.h"

wchar_t *convertCharArrayToLPCWSTR(const char* charArray)
{
    wchar_t* wString = new wchar_t[4096];
    MultiByteToWideChar(CP_ACP, 0, charArray, -1, wString, 4096);
    return wString;
}

void SaveResult(const char *fileName, const char *appName, const char *commandLine)
{
    SECURITY_ATTRIBUTES sa;
    sa.nLength = sizeof(sa);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;

    HANDLE h = CreateFile(convertCharArrayToLPCWSTR(fileName),
        FILE_APPEND_DATA,
        FILE_SHARE_WRITE | FILE_SHARE_READ,
        &sa,
        OPEN_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,
        NULL);

    PROCESS_INFORMATION pi;
    STARTUPINFO si;
    BOOL ret = FALSE;
    DWORD flags = CREATE_NO_WINDOW;

    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
    ZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags |= STARTF_USESTDHANDLES;
    si.hStdInput = NULL;
    si.hStdError = h;
    si.hStdOutput = h;

    ret = CreateProcess(appName==NULL ? NULL : convertCharArrayToLPCWSTR(appName), commandLine == NULL ? NULL : convertCharArrayToLPCWSTR(commandLine), NULL, NULL, TRUE, flags, NULL, NULL, &si, &pi);

    if (ret)
    {
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
        CloseHandle(h);
    }
}
int main()
{
    char cmd[] = "C:\\windows\\system32\\cmd.exe /c ipconfig";
    SaveResult("ipconfig1.txt", NULL, cmd);

    char appName[] = "C:\\windows\\system32\\cmd.exe";
    char cmd2[] = "/c ipconfig";
    SaveResult("ipconfig2.txt", appName, cmd2);

    char cmd1[] = "C:\\windows\\system32\\cmd.exe /c telnet";
    SaveResult("telnet1.txt", NULL, cmd1);

    char appName3[] = "C:\\windows\\system32\\cmd.exe";
    char cmd3[] = "/c telnet";
    SaveResult("telnet2.txt", appName3, cmd3);

    char cmd4[] = "C:\\windows\\system32\\cmd.exe /c wuauclt";
    SaveResult("wuauclt1.txt", NULL, cmd4);

    char appName5[] = "C:\\windows\\system32\\cmd.exe";
    char cmd5[] = "/c wuauclt";
    SaveResult("wuauclt2.txt", appName5, cmd5);

    return -1;
}

1 Ответ

0 голосов
/ 13 октября 2018

Если вы введете ipconfig в окне консоли, процесс отобразит информацию об IP и выйдет.

С другой стороны, если вы введете telnet в окне консоли, процесс покажетподскажите и ждет ответа.Процесс не завершается автоматически.

Когда вы запустите эту команду с CreateProcess, CreateProcess немедленно вернется, но процесс не завершится.Затем вы пытаетесь закрыть дескриптор файла, который все еще используется telnet.

. Вы можете использовать WaitForSingleObject, чтобы дождаться завершения процесса.В случае telnet процесс не завершается.Пример ниже демонстрирует эту проблему.

Для CreateProcess укажите всю командную строку в качестве второго параметра.Убедитесь, что символьный буфер доступен для записи и освобожден в конце.

Примечание: рекомендуется использовать строку широких символов для программы Unicode.Это нормально для продвижения ANSI в UTF16, но в этом случае мало что получится.Вы также можете использовать CreateProcessA вместе с STARTUPINFOA si = { sizeof(si) };, которые принимают символ ANSI.

void SaveResult(const wchar_t *fileName, const wchar_t *commandLine)
{
    SECURITY_ATTRIBUTES sa;
    sa.nLength = sizeof(sa);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;

    HANDLE h = CreateFile(fileName, FILE_WRITE_DATA, FILE_SHARE_WRITE | FILE_SHARE_READ,
        &sa, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if(h == INVALID_HANDLE_VALUE)
        return;

    PROCESS_INFORMATION pi = { 0 };
    STARTUPINFO si = { sizeof(si) };
    si.dwFlags |= STARTF_USESTDHANDLES;
    si.hStdInput = NULL;
    si.hStdError = h;
    si.hStdOutput = h;

    wchar_t *writable_cmdline = _wcsdup(commandLine);
    BOOL success = CreateProcess(NULL, writable_cmdline,
        NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);

    bool finished = false;

    //wait for 1 second
    for(int i = 0; i < 10; i++)
    {
        if(WaitForSingleObject(pi.hProcess, 100) <= 0)
        {
            finished = true;
            break;
        }
    }

    if(success)
    {
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    }

    CloseHandle(h);
    free(writable_cmdline);

    if(!finished)
        printf("Process didn't finish\n");
}


int main()
{
    SaveResult(L"telnet.txt", L"C:\\windows\\system32\\cmd.exe /c telnet");
    SaveResult(L"ipconfig.txt", L"C:\\windows\\system32\\cmd.exe /c ipconfig");
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...