1

Тема: Підкажіть чому ОС не дає писати у "пайп"

Читати можу писати ні.

int main()
{
    HANDLE rIn, rOut, wIn, wOut;
    SECURITY_ATTRIBUTES sa = { 0 };
    STARTUPINFO si = { 0 };
    PROCESS_INFORMATION pi = { 0 };
    sa.nLength = sizeof(sa);
    sa.bInheritHandle = TRUE;
    sa.lpSecurityDescriptor = NULL;
    if (CreatePipe(&rIn, &wIn, &sa, 0) == 0)
    {
        printf("%d\n", GetLastError());
    }
    if (CreatePipe(&rOut, &wOut, &sa, 0) == 0)
    {
        printf("%d\n", GetLastError());
    }
    si.cb = sizeof(si);
    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    si.wShowWindow = SW_HIDE;
    si.hStdInput = wIn;
    si.hStdOutput = wOut;
    si.hStdError = wOut;
    wchar_t cmdline[1024] = L"cmd.exe";
    if (CreateProcessW(NULL, cmdline, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi) == 0)
    {
        printf("CreateProcess err:%d\n", GetLastError());
    }
    else
    {
        DWORD r = 0;
        char *buf = new char[4096];
        DWORD bwait = 0;
        for (;;)
        {
            if (PeekNamedPipe(rOut, 0, 0, 0, &bwait, 0) == FALSE)
            {
                printf("PeekNamedPipe err: %d\n", GetLastError());
            }
            else
            {
                if (bwait > 0)
                {
                    bwait = 0;
                    memset(buf, 0, 4096);
                    ReadFile(rOut, buf, 4096, &r, 0);
                    std::cout << buf;
                    //printf("%s", buf);
                }
                else
                {
                    memset(buf, 0, 4096);
                    std::cin >> buf;
                    DWORD w = 0;
                    if (WriteFile(rIn, buf, strlen(buf), &w, 0) == FALSE)
                    {
                        printf("wf err: %d\n", GetLastError());
                    }
                    //printf("w: %d", w);
                    if (strcmp(buf, "exit") == 0)
                    {
                        break;
                    }
                }
            }            
        }
        TerminateProcess(pi.hProcess, 0);
        CloseHandle(rIn);
        CloseHandle(wIn);
        CloseHandle(rOut);
        CloseHandle(wOut);
    }

    _getch();
    return 0;
}

Де я помилився?

2

Re: Підкажіть чому ОС не дає писати у "пайп"

Яку помилку видав код?

3

Re: Підкажіть чому ОС не дає писати у "пайп"

Будь ласка, замість негативних описів ("не дає писати", "не працює", "не запускається") давайте позитивні ("пише "помилка при спробі запису", "повідомляє про помилку компіляції") і т.д.

Подякували: ostap34PHP, Monolith2

4

Re: Підкажіть чому ОС не дає писати у "пайп"

Vi написав:

Яку помилку видав код?

WriteFile() ==0 GetLastError()==5

5 Востаннє редагувалося Vi (18.04.2017 14:26:12)

Re: Підкажіть чому ОС не дає писати у "пайп"

cheappi386 написав:

WriteFile() ==0 GetLastError()==5

ERROR_ACCESS_DENIED    5 (0x5)
   Access is denied.

А де ти цей код знайшов i яке в тебе завдання?

P.S. Доречi сюди варто зазирнути: https://msdn.microsoft.com/en-us/librar … s.85).aspx  *OK*

6 Востаннє редагувалося Betterthanyou (22.04.2017 23:30:49)

Re: Підкажіть чому ОС не дає писати у "пайп"

А навіщо ви створюєте два Pipe ? Я можу бути на прав, але по-моєму один pipe створюється для запису і читання

if (
        !CreatePipe(
            &hReadPipe,  // дескриптор для читання
            &hWritePipe, // дескриптор для запису
            nullptr,     // атрибути захисту за замовчуванням, в цьому випадку
                         // дескриптори hReadPipe і hWritePipe не успадковуються
            0              // розмір буфера за замовчуванням
        )
        )
    {
        printf("Create pipe failed %d .\n", GetLastError());
        printf("Press any key to finish.\n");
        getchar();
        return GetLastError();
    }

Спробуйте так

if (WriteFile(wIn, buf, strlen(buf), &w, 0) == FALSE)

rIn - read же ж, хіба ні ?

7

Re: Підкажіть чому ОС не дає писати у "пайп"

один pipe створюється для запису і читання

Ні. Пайпів повинно бути два чи три.

8

Re: Підкажіть чому ОС не дає писати у "пайп"

Не в той пайп писав, теперь алгоритмічне питання.Як позбудится Sleep ?

void CmdLaunch()
{
    HANDLE rIn, rOut, wIn, wOut;
    SECURITY_ATTRIBUTES sa = { 0 };
    STARTUPINFO si = { 0 };
    PROCESS_INFORMATION pi = { 0 };
    sa.nLength = sizeof(sa);
    sa.bInheritHandle = TRUE;
    sa.lpSecurityDescriptor = NULL;
    if (CreatePipe(&wIn, &rIn, &sa, 0) == 0)
    {
        printf("%d\n", GetLastError());
    }
    if (CreatePipe(&rOut, &wOut, &sa, 0) == 0)
    {
        printf("%d\n", GetLastError());
    }
    si.cb = sizeof(si);
    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    si.wShowWindow = SW_HIDE;
    si.hStdInput = wIn;
    si.hStdOutput = wOut;
    si.hStdError = wOut;

    wchar_t cmdline[1024] = L"cmd.exe";
    //wchar_t app[1024] = L"C:\\windows\\system32\\cmd.exe";
    if (CreateProcessW(/*app*/NULL, cmdline, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi) == 0)
    {
        printf("CreateProcess err:%d\n", GetLastError());
        _getch();
    }
    else
    {
        DWORD r = 0;
        char *buf = new char[4096];
        memset(buf, 0, 4096);
        ReadFile(rOut, buf, 4096, &r, 0);
        std::cout << "R: " << buf;
        DWORD bwait = 0, runCode = 0;
        for (;;)
        {
            Sleep(50);
            GetExitCodeProcess(pi.hProcess, &runCode);
            if (runCode != STILL_ACTIVE)
            {
                printf("EXIT!!!");
                break; 
            }
            if (PeekNamedPipe(rOut, 0, 0, 0, &bwait, 0) == FALSE)
            {
                printf("PeekNamedPipe err: %d\n", GetLastError());
            }
            else
            {
                if (bwait > 0)
                {
                    //bwait = 0;
                    memset(buf, 0, 4096);
                    ReadFile(rOut, buf, 4096, &r, 0);
                    std::cout << std::endl << "R: " << buf;
                    memset(buf, 0, 4096);
                }
                else
                {
                    memset(buf, 0, 4096);
                    //std::cin >> buf;
                    //std::cin.getline(buf, 4096);
                    //scanf("%s", buf);
                    fgets(buf, 4096, stdin);
                    std::cout<< std::endl << "ent: " << buf << std::endl;
                    //strcat(buf, "\n");
                    DWORD w = 0;
                    //FlushFileBuffers(rIn);
                    if (WriteFile(rIn, buf, strlen(buf), &w, 0) == FALSE)
                    {
                        printf("wf err: %d\n", GetLastError());
                    }
                    memset(buf, 0, 4096);
                }
            }
        }
        CloseHandle(rIn);
        CloseHandle(wIn);
        CloseHandle(rOut);
        CloseHandle(wOut);
    }
}

9

Re: Підкажіть чому ОС не дає писати у "пайп"

Краще огорни читання та писання до пайпу у Thread. Якщо тобі заважае sleep() то мабудь цей код у тебе в основному потоці.

10

Re: Підкажіть чому ОС не дає писати у "пайп"

Для синхронізації двох процесів можна використовувати події (CreateEvent). Один процес переводить подію у сигнальний стан (SetEvent) після того, як запише в пайп нові дані. А другий чекає на подію (WaitForSingleObject), потім зчитує дані, і переводить подію назад у не сигнальний стан (ResetEvent). Тільки тут треба бути уважним, бо можна отримати за один раз не одне, а одразу кілька повідомлень.