На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются.
4. Используйте теги [ code=cpp ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Старайтесь формулировать свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной и более давности без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта (C++) user posted image FAQ Форума user posted image Наши Исходники user posted image Поиск по Разделу user posted image MSDN Library Online (Windows Driver Kit) user posted image Google

Ваше мнение о модераторах: user posted image B.V.
Модераторы: B.V.
  
> Как программно выполнить команду консольного приложения? , Win7, XE7
    Посылаю команду консольному приложению, запущенного CreateProcess, которая выполняется только после закрытия хэндла = закрытия этого приложения. Вот рабочий пример (один из нашедшихся в сети):
    ExpandedWrap disabled
        HANDLE hReadIn, hWriteIn, hReadOut, hWriteOut, hWriteInDup, hWriteOutDup;
       
        SECURITY_ATTRIBUTES sa;
        PROCESS_INFORMATION pi;
        STARTUPINFO si;
       
          ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
          sa.nLength = sizeof(SECURITY_ATTRIBUTES);
          sa.bInheritHandle = TRUE;
          sa.lpSecurityDescriptor = NULL;
       
          CreatePipe(&hReadOut, &hWriteOut, &sa, NULL);
          DuplicateHandle(GetCurrentProcess(), hReadOut, GetCurrentProcess(), &hWriteOutDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
          CloseHandle(hReadOut);
       
          CreatePipe(&hReadIn, &hWriteIn, &sa, NULL);
          DuplicateHandle(GetCurrentProcess(), hWriteIn, GetCurrentProcess(), &hWriteInDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
          CloseHandle(hWriteIn);
       
          ZeroMemory(&si, sizeof(STARTUPINFO));
          si.cb=sizeof(STARTUPINFO);
          si.dwFlags     = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
          si.wShowWindow = SW_HIDE;
          si.hStdInput   = hReadIn;
          si.hStdOutput  = hWriteOut;
       
          CreateProcess(NULL, Cons_App.c_str(), NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
       
          WriteFile(hWriteInDup, buf, len, &count, NULL);   //  запись команды
       
          CloseHandle(hWriteInDup);           // команда выполняется только после CloseHandle = закрытия консольного приложения
       
          CloseHandle(hReadOut);
          CloseHandle(hWriteIn);
          CloseHandle(pi.hThread);
          CloseHandle(pi.hProcess);

    Как выполнять команды и читать из командной строки консольного приложения без закрытия самого приложения?
    Спасибо.
    Сообщение отредактировано: vlad2 -
      Цитата vlad2 @
      Посылаю команду консольному приложению, запущенного ...

      А каким образом консольное приложение читает команду ?

      "Как выполнять команды и читать из командной строки консольного приложения без закрытия самого приложения?"
      Интересен также вопрос, по какой причине ты сделал такой вывод..
      Если посмотреть твой исходник:
      ExpandedWrap disabled
          
        ...
            ZeroMemory(&si, sizeof(STARTUPINFO));
            si.cb=sizeof(STARTUPINFO);
            si.dwFlags     = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
            si.wShowWindow = SW_HIDE;
            si.hStdInput   = hReadIn;
            si.hStdOutput  = hWriteOut;
         
            CreateProcess(NULL, Cons_App.c_str(), NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
         
            WriteFile(hWriteInDup, buf, len, &count, NULL);   //  запись команды
         
            CloseHandle(hWriteInDup);           // команда выполняется только после CloseHandle = закрытия консольного приложения
        ...

      то все операции непрерывно следуют одна за другой.
      После WriteFile данные консольным приложением не успевают
      приняться до CloseHandle(hWriteInDup);
      попробуй:
      ExpandedWrap disabled
            WriteFile(hWriteInDup, buf, len, &count, NULL);   //  запись команды
            ::Sleep(10000);// 10 секунд
            CloseHandle(hWriteInDup);           // команда выполняется только после CloseHandle = закрытия консольного приложения
      Сообщение отредактировано: ЫукпШ -
        Цитата ЫукпШ @
        А каким образом консольное приложение читает команду ?

        Первый раз делаю такое приложение, которое работает с консольным. Думаю, что команда должна выполниться после WriteFile. Однако, не получается - ни с ожиданием, никак.
        Выполняется только во время CloseHandle.
        Команда - создание файла, который появляется только после CloseHandle.
          Цитата vlad2 @
          Цитата ЫукпШ @
          А каким образом консольное приложение читает команду ?

          Первый раз делаю такое приложение, которое работает с консольным.

          я задал этот вопрос чтобы взглянуть на исходник. :)
            Закешировалось?
              Цитата ЫукпШ @
              я задал этот вопрос чтобы взглянуть на исходник.

              Вот конкретный работающий код:
              ExpandedWrap disabled
                  UnicodeString Cons_App = L"Python";
                  HANDLE hReadIn, hWriteIn, hReadOut, hWriteOut, hWriteInDup, hWriteOutDup;
                 
                  SECURITY_ATTRIBUTES sa;
                  PROCESS_INFORMATION pi;
                  STARTUPINFO si;
                  try
                  {
                    SetCurrentDir(CurDir);
                 
                    ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
                    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
                    sa.bInheritHandle = TRUE;
                    sa.lpSecurityDescriptor = NULL;
                 
                    CreatePipe(&hReadOut, &hWriteOut, &sa, NULL);
                    DuplicateHandle(GetCurrentProcess(), hReadOut, GetCurrentProcess(), &hWriteOutDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
                    CloseHandle(hReadOut);
                 
                    CreatePipe(&hReadIn, &hWriteIn, &sa, NULL);
                    DuplicateHandle(GetCurrentProcess(), hWriteIn, GetCurrentProcess(), &hWriteInDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
                    CloseHandle(hWriteIn);
                 
                    ZeroMemory(&si, sizeof(STARTUPINFO));
                    si.cb=sizeof(STARTUPINFO);
                    si.dwFlags     = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
                    si.wShowWindow = SW_HIDE;
                    si.hStdInput   = hReadIn;
                    si.hStdOutput  = hWriteOut;
                 
                    CreateProcess(NULL, Cons_App.c_str(), NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
                 
                    DWORD count = 0;
                    char buf[] = {"f= open(\"D:\\__aa.txt\",\"w+\")\r\n"};
                 
                    WriteFile(hWriteInDup, buf, sizeof(buf), &count, NULL);   //  запись команды
                 
                //  Sleep(10000);
                 
                //  WriteFile(hWriteInDup, "f.close()\r\n", 11, &count, NULL);   //  запись команды
                 
                    CloseHandle(hWriteInDup);           // команда выполняется только после CloseHandle = закрытия консольного приложения
                 
                    CloseHandle(hReadOut);
                    CloseHandle(hWriteIn);
                    CloseHandle(pi.hThread);
                    CloseHandle(pi.hProcess);

              Файл появляется вместе с закрытием интерпретатора, а мне надо, чтобы файл образовался, но Питон остался, чтобы дать другие команды и что-то прочитвть из консоли (про чтение пока не думал, пока отлаживаю запись).
                Цитата ЫукпШ @
                Цитата vlad2 @
                Посылаю команду консольному приложению, запущенного ...

                А каким образом консольное приложение читает команду ?

                Хочется посмотреть исходник принимающей стороны.
                Твоего slave-приложения. Консольного, которым ты управляешь.
                ---
                Вызывает сомнения это:
                ExpandedWrap disabled
                  char buf[] = {"f= open(\"D:\\__aa.txt\",\"w+\")\r\n"};

                Когда ты пайпом управляешь консольным приложением, ты фактически
                подменяешь ручной ввод действиями приложения - Мастера.
                Пайп подключает консольный ввод/вывод к другому приложению.
                Что будет, если ввести "\r\n" ?
                я не знаю.
                С клавиатуры мы вводим только '\r'.
                ---
                Запусти управляемое консольное приложение отдельно.
                И делай вручную все необходимые команды.
                Будет ли работать правильным образом ?
                ---
                А что консольное приложение шлёт назад ?
                Когда юзер жмёт на клавиши, он получает эхо на скрин.
                Твоё мастер-приложение тоже должно получить весь этот вывод.
                Сообщение отредактировано: ЫукпШ -
                  Цитата ЫукпШ @
                  И делай вручную все необходимые команды.
                  Будет ли работать правильным образом ?

                  Да, это первое, что проверил: ручками работает, как надо: выполнил команду и ждёт следующей, пока не закрою. Хочу сделать то же самое, но из программы.
                  Цитата ЫукпШ @
                  Что будет, если ввести "\r\n" ?
                  я не знаю.

                  Любая комбинация \r и \n и её отсутствие никак не влияет (о чём это говорит?).
                  Цитата ЫукпШ @
                  Хочется посмотреть исходник принимающей стороны.

                  Консольное приложение - это интерпретатор Python. Вот установщик.
                    Цитата vlad2 @
                    Консольное приложение - это интерпретатор Python. Вот установщик.

                    Не всеми консольными приложениями можно управлять
                    посредством pipe. Да, у меня такое было.
                    Внутрь Питона не влезешь...
                    Что можно попробовать - напиши консольного "кролика"
                    и по-отлаживай твой комплекс с двух сторон.
                    Просто чтобы убедиться, что "Мастер" работает правильно.
                    Передавай "кролику" то же самое, что и Питону и изучай,
                    как идут данные в обе стороны.
                    ---
                    Других идей пока нет.
                    ---
                    Качай ситуацию, придумывай эксперименты.
                    Как юзер вводит информацию ? нажимает клавишу раз в секунду,
                    каждый раз дожидаясь эха на экране.
                    Сделай такой алгоритм - передай данные по-символьно с обязательным
                    ожиданием эха перед вводом следующего символа.
                    ---
                    А, вот я нашёл кусочек своего исходника - pipe я инициализировал иначе:
                    ExpandedWrap disabled
                      //----------------------------------------------------------------------------------
                      bool WINAPI MPIPE::Create(DWORD dwSize)
                      {
                       if(pipe)                                                               return false;
                       
                       SECURITY_DESCRIPTOR sd; ::ZeroMemory(&sd,sizeof(sd));//структура security для пайпов
                       SECURITY_ATTRIBUTES sa; ::ZeroMemory(&sa,sizeof(sa));
                       
                       sa.nLength              = sizeof(sa);
                       sa.lpSecurityDescriptor = NULL;
                       sa.bInheritHandle       = true;       //разрешаем наследование дескрипторов
                       
                       if(WinIsNT())
                       {
                        if(!::InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION)) return false;
                        if(!::SetSecurityDescriptorDacl(&sd, true, NULL, false))              return false;
                        sa.lpSecurityDescriptor = &sd;
                       }
                       
                       if(!::CreatePipe(hReadStd,hWriteStd,&sa,dwSize))                       return false;
                       
                       pipe=true;
                       return true;
                      }
                      //----------------------------------------------------------------------------------
                    Сообщение отредактировано: ЫукпШ -
                      Цитата ЫукпШ @
                      Не всеми консольными приложениями можно управлять

                      Спасибо, ЫукпШ. Прочитал про особенность Питона с предложением, как обойти проблему. Но это помогло только для одной команды. При попытке дать другую (создать ещё один файл), Питон закрывается и всё, вторая команда не выполняется.
                      Из консоли всё работает нормально. Теперь задача, как выполнить несколько команд в этом открытом Питоне.
                        vlad2, а зачем тебе запускать python процессом? Там же есть готовые библиотеки для интеграции скриптов внутрь твоего exe на плюсах.
                          Цитата vlad2 @
                          Прочитал про особенность Питона с предложением, как обойти проблему.
                          Ах, воночто. Ок, пиши ему в консольный ввод.

                          Добавлено
                          Нашёл у себя пример:
                          ExpandedWrap disabled
                              if (CreateProcess(NULL, &commandLine.front(), NULL, NULL, TRUE,
                                                CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW | BELOW_NORMAL_PRIORITY_CLASS,
                                                NULL, NULL, &startInfo, &processInfo) == FALSE)
                                logMsg("CreateProcess() failed", GetLastError());
                              else
                              { // при успехе
                                CloseHandle(processInfo.hThread);                                   // HANDLE нитки не нужен
                             
                                while (WaitForSingleObject(processInfo.hProcess, 1000) == WAIT_TIMEOUT)// пока менеджер работает
                                {
                                  if (fs::exists(stop)) continue;                   // досрочного стопа нет, продолжаем ждать
                             
                                  // Ок, прекращаем прогон
                                  if (!AttachConsole(processInfo.dwProcessId))      // присоединяемся к консоли менеджера
                                    logMsg("AttachConsole() failed", GetLastError());
                                  else
                                  {
                                    DWORD      written;
                                    INPUT_RECORD ev[2];                             // создаём два события
                             
                                    ev[0].EventType = ev[1].EventType = KEY_EVENT;  // кнопочные
                                    ev[0].Event.KeyEvent.bKeyDown = TRUE;           // нажали
                                    ev[1].Event.KeyEvent.bKeyDown = FALSE;          // отпустили
                                    ev[0].Event.KeyEvent.wRepeatCount    = ev[1].Event.KeyEvent.wRepeatCount    = 1;// ESC 1 раз
                                    ev[0].Event.KeyEvent.wVirtualKeyCode = ev[1].Event.KeyEvent.wVirtualKeyCode = VK_ESCAPE;
                                    ev[0].Event.KeyEvent.wVirtualScanCode= 0x01;    // скан коды ESC
                                    ev[1].Event.KeyEvent.wVirtualScanCode= 0x81;
                                    ev[0].Event.KeyEvent.uChar.AsciiChar = ev[1].Event.KeyEvent.uChar.AsciiChar = 27; // ASCII
                                    ev[0].Event.KeyEvent.dwControlKeyState=ev[1].Event.KeyEvent.dwControlKeyState=0;
                                    // пишем в консоль события
                                    if (!WriteConsoleInput(GetStdHandle(STD_INPUT_HANDLE), ev, 2, &written))
                                      logMsg("WriteConsoleInput() failed", GetLastError());
                                    FreeConsole();                                  // отсоединяемся от консоли
                                    break;
                                  }
                                }
                                // Ждём завершения менеджера
                                if (WaitForSingleObject(processInfo.hProcess, INFINITE) != WAIT_OBJECT_0)
                                  logMsg("UART manager failure", GetLastError());
                             
                                DWORD exitCode = -1;
                             
                                // Получить код завершения менеджера
                                GetExitCodeProcess(processInfo.hProcess, &exitCode);
                                CloseHandle(processInfo.hProcess);
                             
                                return exitCode;
                              }
                          Мне тут надо было только ESC послать, но никто не запрещает писать туда целые строки.

                          Добавлено
                          Неочевидные вещи:
                          • в CreateProcess() важен флаг CREATE_NEW_PROCESS_GROUP, который создаёт новую группу процессов с собственной консолью;
                          • Id этой консоли совпадает с Id создаваемого процесса;
                          • если в этой группе окажется несколько процессов, они все разделяют одну консоль;
                          • можно посылать любые консольные события; не помню точно, но, вроде бы, кроме ctrl-break; но можно ctrl-c;
                          • не исследовал, но вполне возможно, что прям-таки все поля структуры заполнять не надо; типа скан-кодов; вероятно, зависит от управляемого т.о. процесса.


                          Добавлено
                          Цитата vlad2 @
                          Но это помогло только для одной команды.
                          И вообще, что тебе мешает сразу написать все команды скриптом?
                          Сообщение отредактировано: Qraizer -
                            Цитата Qraizer @
                            И вообще, что тебе мешает сразу написать все команды скриптом?

                            Например, то, что следующая команда может быть определена не только результатом предыдущей, но вообще, работой других программ, и заранее неизвестной.

                            Добавлено
                            Цитата shm @
                            зачем тебе запускать python процессом?
                            Пока ничего не знаю об этом, питоновцы живут отдельно.
                              Цитата Qraizer @
                              Нашёл у себя пример
                              Пока довольно трудно разобраться.
                              Видимо, для строки будет что-то типа:
                              ExpandedWrap disabled
                                            INPUT_RECORD ev[2];                             // создаём два события
                                 
                                            ev[0].EventType = ev[1].EventType = KEY_EVENT;  // кнопочные
                                            ev[0].Event.KeyEvent.bKeyDown = TRUE;           // нажали
                                            ev[1].Event.KeyEvent.bKeyDown = FALSE;          // отпустили
                                            ev[0].Event.KeyEvent.wRepeatCount    = ev[1].Event.KeyEvent.wRepeatCount    = 1;  //  1 раз
                                 
                                          AttachConsole(pi.dwProcessId);      // присоединяемся к консоли менеджера
                                 
                                        while (WaitForSingleObject(pi.hProcess, 1000) == WAIT_TIMEOUT)// пока менеджер работает
                                        {
                                          if (fs::exists(stop)) continue;                   // досрочного стопа нет, продолжаем ждать         ???
                                 
                                          // Ок, прекращаем прогон
                                //        AttachConsole(pi.dwProcessId);      // присоединяемся к консоли менеджера
                                 
                                           for (int k = 0; k < sizeof(buf); ++k)
                                           {
                                            ev[0].Event.KeyEvent.wVirtualKeyCode = ev[1].Event.KeyEvent.wVirtualKeyCode = BYTE(buf[k]);
                                            ev[0].Event.KeyEvent.wVirtualScanCode= VkKeyScan(buf[k]);    // скан коды
                                            ev[1].Event.KeyEvent.wVirtualScanCode= 0x81;                                                    //  ???
                                            ev[0].Event.KeyEvent.uChar.AsciiChar = ev[1].Event.KeyEvent.uChar.AsciiChar = 27; // ASCII      //  ???
                                            ev[0].Event.KeyEvent.dwControlKeyState=ev[1].Event.KeyEvent.dwControlKeyState=0;                //  ???
                                 
                                            // пишем в консоль события
                                            WriteConsoleInput(GetStdHandle(STD_INPUT_HANDLE), ev, 2, &count);
                                            }
                                            FreeConsole();                                  // отсоединяемся от консоли
                                            break;
                                        }
                                        // Ждём завершения менеджера
                                        if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_OBJECT_0)
                                          logMsg("UART manager failure", GetLastError());
                                Ну, в примере хватает не относящегося к записи в консоль, да. Просто это логически цельный фрагмент. Если из него что-то вырезать, то получится некорректно спроектированный код, хотя и решающий задачу.
                                Давай сокращу чуть. Но учти, что опущенное тоже важно.
                                ExpandedWrap disabled
                                    if (CreateProcess(NULL, &commandLine.front(), NULL, NULL, TRUE,
                                                      CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW | BELOW_NORMAL_PRIORITY_CLASS,
                                                      NULL, NULL, &startInfo, &processInfo) == FALSE)
                                      /* сообщить об ошибке запуска менеджера */;
                                    else
                                    { // при успехе запуска
                                      CloseHandle(processInfo.hThread);                                   // HANDLE нитки не нужен
                                   
                                      while (/* проверяем, что менеджер не завершился сам по себе */ )
                                      {
                                        if (/* проверяем, что не поступило сигнала о принудительном завершении менеджера */) continue;
                                   
                                        /* Ок, сигналим менеджеру, чтоб выходил. Он это понимает, если ему в консоли нажали ESC.
                                           Т.к. консольного окна мы его лишили, пишем ему туда ESC программно. */
                                        if (!AttachConsole(processInfo.dwProcessId))      // присоединяемся к консоли менеджера
                                          /* сообщить об ошибке подачи сигнала менеджеру о выходе */;
                                        else
                                        {
                                          DWORD      written;
                                          INPUT_RECORD ev[2];                             // создаём два события
                                   
                                          ev[0].EventType = ev[1].EventType = KEY_EVENT;  // кнопочные
                                          ev[0].Event.KeyEvent.bKeyDown = TRUE;           // нажали
                                          ev[1].Event.KeyEvent.bKeyDown = FALSE;          // отпустили
                                          ev[0].Event.KeyEvent.wRepeatCount    = ev[1].Event.KeyEvent.wRepeatCount    = 1;// ESC 1 раз
                                          ev[0].Event.KeyEvent.wVirtualKeyCode = ev[1].Event.KeyEvent.wVirtualKeyCode = VK_ESCAPE;
                                          ev[0].Event.KeyEvent.wVirtualScanCode= 0x01;    // скан коды ESC
                                          ev[1].Event.KeyEvent.wVirtualScanCode= 0x81;
                                          ev[0].Event.KeyEvent.uChar.AsciiChar = ev[1].Event.KeyEvent.uChar.AsciiChar = 27; // ASCII
                                          ev[0].Event.KeyEvent.dwControlKeyState=ev[1].Event.KeyEvent.dwControlKeyState=0;
                                          // пишем в консоль два события
                                          if (!WriteConsoleInput(GetStdHandle(STD_INPUT_HANDLE), ev, 2, &written))
                                            /* сообщить об ошибке подачи сигнала менеджеру о выходе */;
                                          FreeConsole();                                  // отсоединяемся от консоли
                                          break;
                                        }
                                      }
                                      // Ждём, пока менеджер не слопает ESC и выйдет
                                      if (WaitForSingleObject(processInfo.hProcess, INFINITE) != WAIT_OBJECT_0)
                                        /* вообще-то, тут баги быть не должно */;
                                      CloseHandle(processInfo.hProcess);                  // не забываем чистить ресурсы


                                Добавлено
                                Если хочется больше конкретики. Есть некий менеджер, который знает своё дело. Он является консольным приложением, его запустили, передав в командной строке параметры, остальные он берёт из окружения сам – и вперёд, на очередные несколько минут он занят работой. Потом завершается, положив в файлы и в консоль результаты и логи. Ещё он умеет по ESC прерываться досрочно. Я же представляю собой робота, который тихонько работает себе в фоне на этой же машине и никого не трогает. И его задача принимать сетевые запросы на обслуживание этим менеджером, формировать параметры командной строки для него, перенаправить его консольный вывод в файлы, усиленно перед этим процессом делая вид, что с ним работают как обычно через консоль. (Естественно, я привёл лишь малую часть кода.) Т.о. люди получают возможность работать на этой машине по сети, а не только непосредственно за ней или по RDP.
                                Я запускаю дочерний процесс, который делает своё дело и выходит сам. Теоретически, я его и ждать-то не должен, запустил и хай работает себе. Но тут дело в том, что помимо сетевого запроса на запуск может прийти и запрос на прерывание ранее запущенного. Поэтому, во-первых, приходится ждать, пока менеджер не завершится сам, и если до этого времени пришёл запрос на его прерывание, передать ему эту команду. Как? Правильно, "нажав" ему ESC. Потому что таков штатный механизм прерывания.
                                Неважно, как конкретно организован рабочий цикл с дочерним процессом. У меня вот так. Тебе, думаю, достаточно взять за основу вон ту подготовку пары событий по каждой кнопке и циклом фигачить эти пары туда не знаю куда. Как? Я не знаю всего твоего кода, обрамление уж на твоей совести. Поэтому на всякий случай и привёл часть моего обрамления, где есть... ну, важные моменты организации диалога.
                                Сообщение отредактировано: Qraizer -
                                  Прани, сорри конечно ... но я совсем не вкурил, как производится запуск?

                                  Через сиспемный пайп? Типа:

                                  ExpandedWrap disabled
                                    proramm-1 | proramm-2


                                  Или как-то иначе??
                                    Цитата JoeUser @
                                    Или как-то иначе??
                                    Нет, сугубо программно. Но смысл ровно таков же с той лишь разницей, что пишуемое в пайп заранее неизвестно и формируется по ходу дела.
                                      Цитата Qraizer @
                                      Нет, сугубо программно.

                                      Qraizer, стоп. Есть две программы. Пайп - это решение обмена, стандартизованное ОС. Если это не оно - то что оно?

                                      Добавлено
                                      АДД: да, есть еще атавизмы в виде "мэйл-слотов", но это явно не они.
                                        Цитата vlad2 @
                                        Прочитал про особенность Питона с предложением, как обойти проблему.
                                        Вообще говоря, за такие вещи нужно по рукам и розгами. Вот что в голове у этих иксоидов творится, что они с пеной у рта рассказывают, какая у них вся из себя унифицированная архитектура, всё суть файлы, даже внешние устройства, даже процессор и память, а на деле чекают, чё им подсунули и меняют алгоритмы. Какая тебе нафик разница, что у тебя с той стороны stdin-а? Зла не хватает, половина кроссплатформенного оперсорса более кроссплатформенен на винде, чем в позиксе...

                                        Добавлено
                                        Цитата JoeUser @
                                        Пайп - это решение обмена, стандартизованное ОС. Если это не оно - то что оно?
                                        Это оно. Только оно для юзера. Оно программно как раз так и реализуется, через CreatePipe() etc. Только делает это оболочка. Ну, в винде это cmd. И ничего не надо программить. Но это решение статично. Если нужно динамически общаться, юзер не справится, ему придётся что-нить наскриптовать хотя бы.
                                        Сообщение отредактировано: Qraizer -
                                          Цитата Qraizer @
                                          Но оно статично.

                                          Ой ли ... ой лю ли ... :lol:

                                          ExpandedWrap disabled
                                            echo "Oi li, oi lu li" | program


                                          ExpandedWrap disabled
                                            cat myfile | program


                                          ExpandedWrap disabled
                                            ls /usr/local/bin | grep YO | program


                                          & etc ... !!!

                                          Все наоборот! Изначальная обработка может быть любая, но вывод в STDOUT будет одинаков. А вот как его отработает прога в STDIN - вопрос. ИМХО, И ящетаю - привязываться к API Венды (именно в этом случае) - это кощунство и сатанинство!!! И издевательство над православными!
                                            И где тут динамика, JoeUser? Наладь между grep и program двусторонний диалог.
                                              Цитата Qraizer @
                                              Наладь между grep и program двусторонний диалог.

                                              Ну я так понимаю, "двусторонность" не равна "динамичности"? Как я понимаю, динамичность может просто подразумевать какую-то зависимость исходящих величин - от входящих (читай функцию). А если обобщить - рассматриваем не только способ обработки, но и его построение, читай - получаем что-то типа "функтора". Хотя может я и загоняюсь :-?
                                                В результате получилась запись, но не получается чтение. Вот рабочий код:
                                                ExpandedWrap disabled
                                                    UnicodeString Cons_App = L"Python -i";
                                                    HANDLE hReadIn, hWriteIn, hReadOut, hWriteOut, hWriteInDup, hWriteOutDup;
                                                   
                                                    SECURITY_ATTRIBUTES sa;
                                                    PROCESS_INFORMATION pi;
                                                    STARTUPINFO si;
                                                    try
                                                    {
                                                      SetCurrentDir(CurDir);
                                                   
                                                      ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
                                                      sa.nLength = sizeof(SECURITY_ATTRIBUTES);
                                                      sa.bInheritHandle = TRUE;
                                                      sa.lpSecurityDescriptor = NULL;
                                                   
                                                      CreatePipe(&hReadOut, &hWriteOut, &sa, NULL);
                                                      DuplicateHandle(GetCurrentProcess(), hReadOut, GetCurrentProcess(), &hWriteOutDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
                                                      CloseHandle(hReadOut);
                                                   
                                                      CreatePipe(&hReadIn, &hWriteIn, &sa, NULL);
                                                      DuplicateHandle(GetCurrentProcess(), hWriteIn, GetCurrentProcess(), &hWriteInDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
                                                      CloseHandle(hWriteIn);
                                                   
                                                      ZeroMemory(&si, sizeof(STARTUPINFO));
                                                      si.cb=sizeof(STARTUPINFO);
                                                      si.dwFlags     = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
                                                      si.wShowWindow = SW_HIDE;
                                                      si.hStdInput   = hReadIn;
                                                      si.hStdOutput  = hWriteOut;
                                                   
                                                      CreateProcess(NULL, Cons_App.c_str(), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
                                                   
                                                      DWORD count = 0;
                                                      char buf[1024];
                                                   
                                                      strcpy(buf,"f= open(\"D:\\__aa.txt\",\"w+\")\r\n");
                                                      WriteFile(hWriteInDup, buf, strlen(buf), &count, NULL);   //  создание файла
                                                   
                                                      strcpy(buf,"f.write(\"1\n\")\r\n");
                                                      WriteFile(hWriteInDup, buf, strlen(buf), &count, NULL);   //  запись в файл "1\n"
                                                   
                                                   
                                                      DWORD cread = 0;                                          //  чтение
                                                      bool ret = true;
                                                   
                                                      for(int i=0; i < 10; i++)
                                                      {
                                                        ret = PeekNamedPipe(hWriteOutDup, NULL, 0, NULL, &count, NULL);
                                                        ret = ret && (count > 0);
                                                        if (ret) break;
                                                        Sleep(1000);
                                                      }
                                                      if (ret)
                                                      {
                                                        ret = ReadFile(hWriteOutDup, buf, count, &cread, NULL);
                                                      }
                                                   
                                                   
                                                  //  while (ret)
                                                  //  {
                                                  //    ret = ReadFile(hWriteOutDup, buf, strlen(buf), &count, NULL);   //  read from the pipe
                                                  //    if (!ret && GetLastError() != ERROR_MORE_DATA)
                                                  //      break;
                                                  //  }
                                                   
                                                   
                                                      strcpy(buf,"f.close()\r\n");
                                                      WriteFile(hWriteInDup, buf, strlen(buf), &count, NULL);   //  закрытие файла
                                                   
                                                      CloseHandle(hWriteInDup);
                                                   
                                                      CloseHandle(hReadOut);
                                                      CloseHandle(hWriteIn);
                                                      CloseHandle(pi.hThread);
                                                      CloseHandle(pi.hProcess);

                                                Результат PeekNamedPipe - всегда false.
                                                Те же действия в командной строке нормально работают - см. вложение. Как программно реализовать чтение?
                                                Прикреплённая картинка
                                                Прикреплённая картинка

                                                При этом команда записи в файл не проходит.
                                                Сообщение отредактировано: vlad2 -
                                                  А с чего ты уверен, что команды туда приходят? Я ради такого случая поставил себе Python, не факт, что твоей версии, правда, и ничего работающего не обнаружил. Написал свою простейшую аппликуху, без этого дурацкого ветвления по типу tty, и в ней всё работает как часы, в обе стороны.
                                                  Сообщение отредактировано: Qraizer -
                                                    Цитата Qraizer @
                                                    А с чего ты уверен, что команды туда приходят?

                                                    Файл образуется (f=open) и закрывается (f.close).

                                                    Добавлено
                                                    Цитата vlad2 @
                                                    без этого дурацкого ветвления по типу tty

                                                    Что имеется в виду?

                                                    Добавлено
                                                    В сообщении #8 давал ссылку на Питон. Запускать его надо с опцией -i.
                                                      У меня 3.8.1. Поведение отличается.
                                                      Короче, долби саппорт питона. Боюсь, без их помощи не обойтись. Тебе вот надо, чтобы твой код под каждую версию работал по-разному? Думаю, такое веселье никому не понравится.
                                                        Цитата Qraizer @
                                                        Думаю, такое веселье никому не понравится
                                                        Это точно(.
                                                          Цитата vlad2 @
                                                          Цитата Qraizer @
                                                          Думаю, такое веселье никому не понравится
                                                          Это точно(.

                                                          А у меня всё получилось - после "python -i".
                                                          Только я делал для x86.
                                                          Где то у тебя ошибка.
                                                          ---
                                                          А вот этого я не делал никогда.
                                                          ExpandedWrap disabled
                                                            ...
                                                             DuplicateHandle(GetCurrentProcess(), hReadOut, GetCurrentProcess(), &hWriteOutDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
                                                            ...
                                                             DuplicateHandle(GetCurrentProcess(), hWriteIn, GetCurrentProcess(), &hWriteInDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
                                                            ...
                                                          Сообщение отредактировано: ЫукпШ -
                                                            Цитата ЫукпШ @
                                                            А у меня всё получилось

                                                            Здорово! Я упростил код, убрал DuplicateHandle:
                                                            ExpandedWrap disabled
                                                                UnicodeString Cons_App = L"Python -i";
                                                                HANDLE hReadIn, hWriteIn, hReadOut, hWriteOut, hWriteInDup, hWriteOutDup;
                                                               
                                                                SECURITY_ATTRIBUTES sa;
                                                                PROCESS_INFORMATION pi;
                                                                STARTUPINFO si;
                                                                try
                                                                {
                                                                  ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
                                                                  sa.nLength = sizeof(SECURITY_ATTRIBUTES);
                                                                  sa.bInheritHandle = TRUE;
                                                                  sa.lpSecurityDescriptor = NULL;
                                                               
                                                                  CreatePipe(&hReadOut, &hWriteOut, &sa, NULL);
                                                                  CreatePipe(&hReadIn, &hWriteIn, &sa, NULL);
                                                               
                                                                  ZeroMemory(&si, sizeof(STARTUPINFO));
                                                                  si.cb=sizeof(STARTUPINFO);
                                                                  si.dwFlags     = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
                                                                  si.wShowWindow = SW_HIDE;
                                                                  si.hStdInput   = hReadIn;
                                                                  si.hStdOutput  = hWriteOut;
                                                                  si.hStdError   = hWriteOut;
                                                               
                                                                  CreateProcess(NULL, Cons_App.c_str(), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
                                                               
                                                                  DWORD count = 0;
                                                                  char buf[1024];
                                                               
                                                                  strcpy(buf,"f= open(\"D:\\__aa.txt\",\"w+\")\r\n");
                                                                  WriteFile(hWriteIn, buf, strlen(buf), &count, NULL);   //  создание файла
                                                               
                                                                  strcpy(buf,"f.write(\"1\n\")\r\n");
                                                                  WriteFile(hWriteIn, buf, strlen(buf), &count, NULL);   //  запись в файл "1\n"
                                                               
                                                                  DWORD cread = 0;                                       //  чтение
                                                                  bool ret = true;
                                                               
                                                                  for(int i=0; i < 10; i++)
                                                                  {
                                                                    ret = PeekNamedPipe(hWriteOut, NULL, 0, NULL, &count, NULL);
                                                                    ret = ret && (count > 0);
                                                                    if (ret) break;
                                                                    Sleep(1000);
                                                                  }
                                                                  if (ret)
                                                                  {
                                                                    if (count > strlen(buf)) count = strlen(buf);
                                                                    ret = ReadFile(hWriteOut, buf, count, &cread, NULL);
                                                                  }
                                                               
                                                                  strcpy(buf,"f.close()\r\n");
                                                                  WriteFile(hWriteIn, buf, strlen(buf), &count, NULL);   //  закрытие файла
                                                               
                                                                  strcpy(buf,"exit()\r\n");
                                                                  WriteFile(hWriteIn, buf, strlen(buf), &count, NULL);   //  выход из Питона
                                                               
                                                                  CloseHandle(hReadIn);
                                                                  CloseHandle(hWriteOut);
                                                               
                                                                  CloseHandle(hReadOut);
                                                                  CloseHandle(hWriteIn);
                                                                  CloseHandle(pi.hThread);
                                                                  CloseHandle(pi.hProcess);

                                                            Всё равно не записывает в файл и не читает. Остальные команды проходят.
                                                            Можешь посмотреть мой код на предмет ошибки или дать свой, который работает?
                                                            Сообщение отредактировано: vlad2 -
                                                              Цитата vlad2 @
                                                              Можешь посмотреть мой код на предмет ошибки или дать свой, который работает?

                                                              Да, но только вечером или ночью.
                                                              ---
                                                              Но я делал не так, как ты.
                                                              Чтобы мастерить такие приложения на постоянной основе,
                                                              я сделал некоторые классы и процедуры, которые занёс в библиотеку.
                                                              Поэтому исходников получается не один.
                                                              Но зато растёт производительность труда.

                                                              1. Делаем класс - Hahdle. Это весьма нужный класс.
                                                              2. Делаем класс - Pipe.
                                                              3. Делаем класс - Обёртку процесса для консольных приложений и .bat файлов.
                                                              4. Для удобства - обёртку вокруг памяти.
                                                              5. Класс - конвертор форматов
                                                              6. Делаем класс - обёртку для управления консольным приложением
                                                              На основе сделанного набора
                                                              И ещё там чего-то в виде библиотечных процедур.
                                                              В результате получился такой исходник:
                                                              ExpandedWrap disabled
                                                                #include "cmdShell.h"
                                                                 
                                                                bool WriteToPython(cmdShell& cSh, const char* pStr)
                                                                {
                                                                 bool bRetC=false;
                                                                 
                                                                 size_t sizeWr = strlen(pStr);
                                                                 if(sizeWr)
                                                                 {
                                                                //  ConvTchar2Char conv;
                                                                //  DbgStr::TypeDebugString(_T("%s %s"),_T(__FUNCTION__), conv.Char2Tchar(pStr));
                                                                  if(!cSh.WriteToPipe (pStr,sizeWr)) return false;
                                                                 }
                                                                 
                                                                 MEMT<char> buf;
                                                                 bRetC = cSh.ReadFromPipe  (buf);
                                                                 size_t size = buf.GetDataSize();
                                                                 
                                                                // _tprintf(_T("bRetC(ReadFromPipe)=%d size=%d\n"),bRetC,size);
                                                                 if((bRetC)&&(size))
                                                                 {
                                                                  for(size_t i=0;i<size;++i) { _tprintf(_T("%c"),buf[i]); }
                                                                 }
                                                                 
                                                                 _tprintf(_T("\n"));
                                                                 return bRetC;
                                                                }
                                                                // --------------------------------------------------------------------------
                                                                int __cdecl _tmain(int argc, char **argv)
                                                                {
                                                                 _tprintf(_T("\tHello, world!\n"));
                                                                 
                                                                  cmdShell cSh;
                                                                  bool bRetC = cSh.Install("python -i");
                                                                  if(bRetC)
                                                                  {
                                                                   WriteToPython(cSh, "");
                                                                // создаём файл aa.txt в папке d:\0
                                                                   WriteToPython(cSh, "f=open(\"d:\\\\0\\\\aa.txt\",\"w+\")\n");
                                                                   WriteToPython(cSh, "f.write(\"223\")\n");
                                                                   WriteToPython(cSh, "f.close()\n");
                                                                   WriteToPython(cSh, "exit()\n");
                                                                  }
                                                                  else
                                                                  {
                                                                   _tprintf(_T("bRetC(install)=%d\n"),bRetC);
                                                                  }
                                                                 return 0;
                                                                }

                                                              Приаттаченные исходники я надёргал из библиотеки, что-то мог и забыть.
                                                              Прикреплённый файлПрикреплённый файлForPython.zip (10,04 Кбайт, скачиваний: 337)
                                                              Сообщение отредактировано: ЫукпШ -
                                                                Цитата ЫукпШ @
                                                                Да, но только вечером или ночью.
                                                                Спасибо, отлично.
                                                                Максимально упростил свой код, чтобы оценить возможность. Чтобы написать оперативную прогу, буду ориентироваться на твой подход, который считаю совершенно верным.
                                                                  Цитата vlad2 @
                                                                  Как выполнять команды и читать из командной строки консольного приложения без закрытия самого приложения?
                                                                  Спасибо.

                                                                  Начнем с того, что термин "конвеер" (pipe) - это однонаправленный канал межпроцессного взаимодействия. Таким образом, одна программа пишет в STDOUT, вторая программа читает из STDIN, и что-то делает. Что делать чтобы вторая программа не закрывалась? Ответ простой - читать STDIN в бесконечном цикле, с возможностью выхода по условию. Увы, но не к сожалению, я Питона не знаю, приведу пример на Перле:

                                                                  first.pl
                                                                  ExpandedWrap disabled
                                                                    #/usr/local/bin/perl
                                                                    $| = 1; # flush сразу после очередной операции I/O
                                                                    print "print 1;\n";
                                                                    print "print 2;\n";
                                                                    sleep(2);
                                                                    print "print 3;\n";
                                                                    sleep(4);
                                                                    print "print 4;\n";
                                                                    print "EXIT\n";

                                                                  next.pl
                                                                  ExpandedWrap disabled
                                                                    #/usr/local/bin/perl
                                                                    $| = 1;  # flush сразу после очередной операции I/O
                                                                    while(1) {
                                                                      $in = <STDIN>;
                                                                      last if ($in =~ /^EXIT\s*$/);
                                                                      eval($in);
                                                                    }

                                                                  Тест запускаем так:
                                                                  ExpandedWrap disabled
                                                                    perl first.pl | perl next.pl

                                                                  В результате первые две команды будут прочитаны и сразу выполнены - выведутся два числа 1 и 2. Потом задержка. Потом вывод числа 3. Потом еще одна задержка. Потом вывод числа 4 и вторая программа "ловит" условие выхода "EXIT", и выполнение завершается.

                                                                  Сценарий интерпретаторов, что Перла, что Питона - одинаков. Выполнить скрипт и завершится. Вот Перлу приходит на помощь функция eval(), которая выполняет как код переданную ей строку в качестве аргумента. Может ли такое Питон - я не знаю.

                                                                  Далее. Если нужен двусторонний обмен, вангую - нужно определить два именованных пайпа. Для одной программы один канал для записи, второй для чтения. Для второй программы каналы меняются местами. Тогда взаимодействие программ не будет зависеть на каком из терминалов запущены программы.
                                                                    Спасибо, JoeUser. Питона тоже не знаю. Мне нужно из внешней программы периодически (не одним скриптом) давать команды Питону и читать его ответы, если они есть. Питон во время всех этих действий должен находиться в памяти. Тоже создаю два пайпа, как написано во многих примерах, правда анонимных...
                                                                      Цитата vlad2 @
                                                                      Питона тоже не знаю.

                                                                      Ну сверскоростное гугление говорит, что eval() в Питоне есть. Так что "принимающий скрипт" можешь писать по образу и подобию моего next.pl, и Питон будет висеть в памяти и читать что ему определишь. А вот для ответов делай именованный пайп.
                                                                        Кстати да, а попробуй именованные.
                                                                          Цитата JoeUser @
                                                                          для ответов делай именованный пайп
                                                                          Вроде, для чтения использую PeekNamedPipe, как во многих примерах.
                                                                            я несколько подправил класс "cmdShell", и максимально возможно выполнил
                                                                            его внутренности в стиле твоей программы.
                                                                            В итоге получилось так:
                                                                            ExpandedWrap disabled
                                                                              #include "cmdShell_b.h"
                                                                               
                                                                              bool WriteToPython(cmdShell_b& cSh, const char* pStr)
                                                                              {
                                                                               bool bRetC=false;
                                                                               
                                                                               size_t sizeWr = strlen(pStr);
                                                                               if(sizeWr)
                                                                               {
                                                                                if(!cSh.WriteToPipe (pStr,sizeWr)) return false;
                                                                               }
                                                                               
                                                                               MEMT<char> buf;
                                                                               bRetC = cSh.ReadFromPipe  (buf);
                                                                               size_t size = buf.GetDataSize();
                                                                               
                                                                               if((bRetC)&&(size))
                                                                               {
                                                                                for(size_t i=0;i<size;++i) { _tprintf(_T("%c"),buf[i]); }
                                                                               }
                                                                               
                                                                               _tprintf(_T("\n"));
                                                                               return bRetC;
                                                                              }
                                                                              // --------------------------------------------------------------------------
                                                                              int __cdecl _tmain(int argc, char **argv)
                                                                              {
                                                                               _tprintf(_T("\tHello, world!\n"));
                                                                               
                                                                                cmdShell_b cSh;
                                                                                bool bRetC = cSh.Install(_T("python -i"));
                                                                               
                                                                                if(bRetC)
                                                                                {
                                                                                 WriteToPython(cSh, "");
                                                                              // пишем файл aa.txt в папку d:\0
                                                                                 WriteToPython(cSh, "f=open(\"d:\\\\0\\\\aa.txt\",\"w+\")\n");
                                                                                 WriteToPython(cSh, "f.write(\"223\")\n");
                                                                                 WriteToPython(cSh, "f.close()\n");
                                                                                 WriteToPython(cSh, "exit()\n");
                                                                                }
                                                                                else
                                                                                {
                                                                                 _tprintf(_T("bRetC(install)=%d\n"),bRetC);
                                                                                }
                                                                               return 0;
                                                                              }

                                                                            Где:
                                                                            Скрытый текст


                                                                            Файл cmdShell_b.h :
                                                                            ExpandedWrap disabled
                                                                              // ---------------------------------------------------------------------------------
                                                                              // file cmdShell_b.h  2020.02.06
                                                                              // ---------------------------------------------------------------------------------
                                                                              #ifndef __cmdShell_b_H__
                                                                              #define __cmdShell_b_H__
                                                                              // ---------------------------------------------------------------------------------
                                                                              //#include "TypeDebugString.h"
                                                                              #include "memt.h"
                                                                              #include "mpipe.h"
                                                                              // ---------------------------------------------------------------------------------
                                                                              // DbgStr::TypeDebugString(_T("%s bConnected=%d"),_T(__FUNCTION__), bConnected);
                                                                              // DbgStr::TypeDebugString(_T("%s buf.GetDataSize()=%d"),_T(__FUNCTION__), buf.GetDataSize());
                                                                              // ---------------------------------------------------------------------------------
                                                                              class cmdShell_b
                                                                              {
                                                                               public:
                                                                               
                                                                              static const size_t TOUT_DEF_ms     = 3000;
                                                                              static const size_t TOUT_DEF_GET_ms = 250;
                                                                              static const size_t SIZE_IN         = 128*1024;
                                                                              static const size_t SIZE_PROXY_IN   = SIZE_IN;
                                                                               
                                                                              static const size_t MAX_COMMLINE_BUFF = 32768;
                                                                               
                                                                               private:
                                                                               
                                                                               protected:
                                                                                            bool       bInstalled;
                                                                                            MEMT<char> proxyIn;
                                                                               
                                                                                            MPIPE               In,Out;
                                                                                            STARTUPINFO         si;
                                                                                            PROCESS_INFORMATION pi;
                                                                                            TCHAR commLineBuff  [MAX_COMMLINE_BUFF];
                                                                                            DWORD               dwSizeIn;
                                                                                            DWORD               dwSizeOut;
                                                                               
                                                                               
                                                                                            size_t     sizePipeInBuf;
                                                                               
                                                                                virtual  bool WINAPI WaitPipeData     (size_t dwToutWait=TOUT_DEF_ms,DWORD* pdwSize=NULL);
                                                                                virtual  bool WINAPI GetPipeData      (MEMT<char>& buf, DWORD dwGot=0, size_t dwToutGet=TOUT_DEF_GET_ms);
                                                                                virtual  bool WINAPI ReadPipe         (bool RetBefore, MEMT<char>& buf, DWORD dwSize);
                                                                                virtual  bool WINAPI AddData          (MEMT<char>& tar, MEMT<char>& sou);
                                                                               
                                                                                         bool WINAPI CreatePipes      (void);
                                                                                         bool WINAPI PipesExist       (void);
                                                                                         bool WINAPI Wait__Process    (DWORD tout);
                                                                                         bool WINAPI Check__Pipe      (DWORD *pAvail);  
                                                                                         bool WINAPI Read__Pipe       (char *pData,DWORD size,DWORD *pGot);
                                                                                         bool WINAPI Write__Pipe      (char *pData,DWORD size,DWORD *pOut);  
                                                                               
                                                                               
                                                                               
                                                                               public:
                                                                                              WINAPI cmdShell_b      (void);
                                                                                virtual       WINAPI ~cmdShell_b     (void);  
                                                                               
                                                                                         void WINAPI PreSetPipeInSize (size_t size);
                                                                               
                                                                                virtual  bool WINAPI Install          (const TCHAR* pCommLine);
                                                                               
                                                                                virtual  bool WINAPI WriteToPipe      (const void* pB, size_t size=0);
                                                                                virtual  bool WINAPI WriteToPipe      (MEMT<char>& buf);
                                                                               
                                                                                virtual  bool WINAPI ReadFromPipe     (MEMT<char>& buf, size_t dwToutWait=TOUT_DEF_ms, size_t dwToutGet=TOUT_DEF_GET_ms);
                                                                                virtual  bool WINAPI WriteWaitRead    
                                                                                                     (
                                                                                                      const void* pB,
                                                                                                      size_t      size,
                                                                                                      MEMT<char>& buf,  
                                                                                                      size_t      dwToutWait  = TOUT_DEF_ms,
                                                                                                      size_t      dwToutGet   = TOUT_DEF_GET_ms
                                                                                                     );
                                                                               
                                                                                         bool WINAPI UnInstall       (void);
                                                                                         bool WINAPI Terminate       (UINT uiCode);
                                                                              };
                                                                              // ---------------------------------------------------------------------------------
                                                                              #endif

                                                                            Файл cmdShell_b.cpp :
                                                                            ExpandedWrap disabled
                                                                              // ---------------------------------------------------------------------------------
                                                                              //   FILE cmdShell_b.cpp 2020.02.05
                                                                              // ---------------------------------------------------------------------------------
                                                                              #include "stdafx.h"
                                                                              #include "cmdShell_b.h"
                                                                              // ---------------------------------------------------------------------------------
                                                                              WINAPI cmdShell_b::cmdShell_b () :
                                                                               
                                                                                    dwSizeIn         (0),
                                                                                    dwSizeOut        (0),
                                                                                    bInstalled       (false),
                                                                                    sizePipeInBuf    (SIZE_IN)
                                                                              {
                                                                               ::ZeroMemory(&si, sizeof(si));
                                                                               ::ZeroMemory(&pi, sizeof(pi));
                                                                              }
                                                                              // ---------------------------------------------------------------------------------
                                                                              WINAPI cmdShell_b::~cmdShell_b ()                                                    
                                                                              {
                                                                               UnInstall();
                                                                               if(pi.hProcess) {::CloseHandle(pi.hProcess);}
                                                                               if(pi.hThread)  {::CloseHandle(pi.hThread);}
                                                                              }
                                                                              // ---------------------------------------------------------------------------------
                                                                              void WINAPI cmdShell_b::PreSetPipeInSize (size_t size)                                                    
                                                                              {
                                                                               if(size < SIZE_IN) size = SIZE_IN;
                                                                               sizePipeInBuf = size;
                                                                              }
                                                                              // ---------------------------------------------------------------------------------
                                                                              bool WINAPI cmdShell_b::Install(const TCHAR* pCommLine)
                                                                              {
                                                                               if(!pCommLine) return false;
                                                                               if(bInstalled) return false;
                                                                               if(!proxyIn.Alloc(SIZE_PROXY_IN)) return false;
                                                                               
                                                                               dwSizeIn = (DWORD)sizePipeInBuf;
                                                                               
                                                                               if(!CreatePipes ()) return false;
                                                                               
                                                                               ::ZeroMemory(&si, sizeof(si));  si.cb = sizeof(si);
                                                                               ::ZeroMemory(&pi, sizeof(pi));
                                                                               ::GetStartupInfo(&si);
                                                                               
                                                                               si.dwFlags     = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
                                                                               si.wShowWindow = SW_HIDE;
                                                                               si.hStdOutput  = In.GetWriteHandle();
                                                                               si.hStdError   = In.GetWriteHandle();   //подменяем дескрипторы для
                                                                               si.hStdInput   = Out.GetReadHandle();  // дочернего процесса
                                                                               
                                                                               _sntprintf_s(commLineBuff,ARRAYSIZE(commLineBuff),_TRUNCATE,_T("%s"),pCommLine);
                                                                              // DbgStr::TypeDebugString(_T("%s %s"),_T(__FUNCTION__), commLineBuff);
                                                                               
                                                                                  if
                                                                                  (
                                                                                   !::CreateProcess
                                                                                      (
                                                                                       NULL,
                                                                                       commLineBuff,
                                                                                       NULL,
                                                                                       NULL,
                                                                                       TRUE,
                                                                                       CREATE_NEW_CONSOLE,
                                                                                       NULL,
                                                                                       NULL,
                                                                                       &si,
                                                                                       &pi
                                                                                      )
                                                                                  ) return false;
                                                                               
                                                                               bInstalled = true;
                                                                               
                                                                               return true;
                                                                              }
                                                                              // ---------------------------------------------------------------------------------
                                                                              bool WINAPI cmdShell_b::WriteToPipe(const void* pB, size_t size)
                                                                              {
                                                                               if(!bInstalled) return false;
                                                                               if(!pB)    return false;
                                                                               const char* pBuf = (const char*) pB;
                                                                               if(size==0) size=strlen(pBuf);
                                                                               DWORD out=0;
                                                                               bool RetC = false;
                                                                               
                                                                               RetC = Write__Pipe ((char*)pBuf, (DWORD)size, &out);
                                                                               
                                                                               return RetC;
                                                                              }
                                                                              // ---------------------------------------------------------------------------------
                                                                              bool WINAPI cmdShell_b::WriteToPipe(MEMT<char>& buf)
                                                                              {
                                                                               if(buf.GetDataSize()==0) return false;
                                                                               return WriteToPipe(buf.GetPointer(), buf.GetDataSize());
                                                                              }
                                                                              // ---------------------------------------------------------------------------------
                                                                              bool WINAPI cmdShell_b::ReadFromPipe(MEMT<char>& buf, size_t dwToutWait, size_t dwToutGet)
                                                                              {
                                                                               if(!bInstalled) return false;
                                                                               
                                                                               bool RetC    = false;
                                                                               DWORD dwSize = 0;
                                                                               buf.SetDataSize(0);
                                                                               for(int ii=0;ii==0;++ii,RetC=true)
                                                                               {
                                                                                if(!WaitPipeData(dwToutWait, &dwSize)) break;
                                                                                if(!GetPipeData(buf, dwSize, dwToutGet)) break;
                                                                               }
                                                                               return RetC;
                                                                              }
                                                                              // ---------------------------------------------------------------------------------
                                                                              bool WINAPI cmdShell_b::WriteWaitRead(const void* pB, size_t size, MEMT<char>& buf, size_t dwToutWait, size_t dwToutGet)
                                                                              {
                                                                               bool RetC = false;
                                                                               
                                                                               for(int ii=0;ii==0;++ii,RetC=true)
                                                                               {
                                                                                if(pB)
                                                                                {
                                                                                 if(!WriteToPipe(pB, size)) break;
                                                                                }
                                                                                if(!ReadFromPipe(buf, dwToutWait, dwToutGet)) break;
                                                                               }
                                                                               return RetC;
                                                                              }
                                                                              // ---------------------------------------------------------------------------------
                                                                              bool WINAPI cmdShell_b::UnInstall(void)
                                                                              {
                                                                               if(!bInstalled) return false;
                                                                               bool RetC=false;
                                                                               
                                                                               RetC = Terminate (0);
                                                                               bInstalled = false;
                                                                               return RetC;
                                                                              }
                                                                              // ---------------------------------------------------------------------------------
                                                                               
                                                                               
                                                                               
                                                                               
                                                                               
                                                                               
                                                                              // ---------------------------------------------------------------------------------
                                                                              // bRetC = exb.ExecBatFile(_T("plink -ssh hostOrIp -P port -l user -pw password"));
                                                                              // ---------------------------------------------------------------------------------
                                                                              bool WINAPI cmdShell_b::WaitPipeData(size_t dwToutWait, DWORD* pdwSize)
                                                                              {
                                                                               bool RetC=false;
                                                                               DWORD dwSize=0;
                                                                               
                                                                               if(pdwSize){*pdwSize=0;}
                                                                               for(size_t i=0;i<dwToutWait;++i)
                                                                               {
                                                                                ::Sleep(1);
                                                                               
                                                                                if(Wait__Process(0)) break;
                                                                               
                                                                                if(Check__Pipe (&dwSize))
                                                                                {
                                                                                 if(dwSize==0) continue;
                                                                                 else
                                                                                 {
                                                                                  RetC=true;
                                                                                  if(pdwSize){*pdwSize=dwSize;}
                                                                                  break;
                                                                                 }
                                                                                }
                                                                                else break;
                                                                               
                                                                               }
                                                                               return RetC;
                                                                              }
                                                                              // ---------------------------------------------------------------------------------
                                                                              bool WINAPI cmdShell_b::GetPipeData(MEMT<char>& buf, DWORD dwGot_, size_t dwToutGet)
                                                                              {
                                                                               bool RetC    = false;
                                                                               DWORD dwSize = 0;
                                                                               DWORD dwGot  = dwGot_;
                                                                               if(dwGot) RetC = true;
                                                                               
                                                                               for(size_t i=0;i<dwToutGet;++i)
                                                                               {
                                                                                ::Sleep(1);
                                                                               
                                                                                if(Wait__Process(0)) break;
                                                                               
                                                                                if(Check__Pipe (&dwSize))
                                                                                {
                                                                                 if(dwSize==0) {RetC=false; break;}
                                                                                 else
                                                                                 {
                                                                                  if(dwSize > dwGot)
                                                                                  {
                                                                                   RetC=true; dwGot=dwSize; i=0;
                                                                                  }
                                                                                 }
                                                                                }
                                                                                else {RetC=false;break;}
                                                                               
                                                                               }
                                                                               
                                                                               RetC = ReadPipe(RetC, buf, dwGot);
                                                                               
                                                                               return RetC;
                                                                              }
                                                                              // ---------------------------------------------------------------------------------
                                                                              bool WINAPI cmdShell_b::ReadPipe(bool RetBefore, MEMT<char>& buf, DWORD dwSize)
                                                                              {
                                                                               if(!RetBefore) return false;
                                                                               if(!buf.Alloc((size_t)dwSize*2)) return false;
                                                                               buf.MemSet(0);
                                                                               if(!buf.SetDataSize(0)) return false;
                                                                               
                                                                               DWORD dwGot=0;
                                                                               
                                                                               if(!Read__Pipe (buf.GetPointer(), (DWORD)buf.GetSize(), &dwGot)) return false;
                                                                               if(!buf.SetDataSize((size_t)dwGot)) return false;
                                                                               
                                                                               return true;
                                                                              }
                                                                              // ---------------------------------------------------------------------------------
                                                                              bool WINAPI cmdShell_b::AddData(MEMT<char>& tar, MEMT<char>& sou)
                                                                              {
                                                                               size_t sizetar = tar.GetDataSize();
                                                                               size_t sizesou = sou.GetDataSize();
                                                                               size_t sizeres = sizetar+sizesou;
                                                                               
                                                                               if(sizeres==0) {tar.SetDataSize(0); return true;}
                                                                               
                                                                               MEMT<char> tmp; if(!tmp.Alloc(sizeres)) return false;
                                                                               
                                                                               size_t ind = 0;
                                                                               for(size_t i=0;i<sizetar;++i){ tmp[ind++]=tar[i]; }
                                                                               for(size_t i=0;i<sizesou;++i){ tmp[ind++]=sou[i]; }
                                                                               tmp.SetDataSize(sizeres);
                                                                               tar = tmp;
                                                                               
                                                                               return true;
                                                                              }
                                                                              //----------------------------------------------------------------------------------
                                                                              bool WINAPI cmdShell_b::CreatePipes (void)
                                                                              {
                                                                               if(PipesExist ())          return true;
                                                                               
                                                                               if(!In. Create(dwSizeIn)) return false;
                                                                               if(!Out.Create(dwSizeOut))return false;
                                                                               
                                                                               return true;
                                                                              }
                                                                              //----------------------------------------------------------------------------------
                                                                              bool WINAPI cmdShell_b::PipesExist (void)
                                                                              {
                                                                               bool rIn  = In.PipeExist();
                                                                               bool rOut = Out.PipeExist();
                                                                               
                                                                               return (rIn && rOut);
                                                                              }
                                                                              //----------------------------------------------------------------------------------
                                                                              bool WINAPI cmdShell_b::Wait__Process (DWORD tout)  
                                                                              {
                                                                               DWORD RetC = ::WaitForSingleObject(pi.hProcess, tout);
                                                                               if(RetC==WAIT_OBJECT_0) return true;
                                                                               return false;
                                                                              }
                                                                              //----------------------------------------------------------------------------------
                                                                              bool WINAPI cmdShell_b::Check__Pipe (DWORD *pAvail)  
                                                                              {
                                                                               return In.CheckPipe(pAvail);  
                                                                              }
                                                                              //----------------------------------------------------------------------------------
                                                                              bool WINAPI cmdShell_b::Read__Pipe (char *pData,DWORD size,DWORD *pGot)  
                                                                              {
                                                                               return In.ReadPipe(pData,size,pGot);  
                                                                              }
                                                                              //----------------------------------------------------------------------------------
                                                                              bool WINAPI cmdShell_b::Write__Pipe (char *pData,DWORD size,DWORD *pOut)  
                                                                              {
                                                                               return Out.WritePipe(pData,size,pOut);  
                                                                              }
                                                                              //----------------------------------------------------------------------------------
                                                                              bool WINAPI cmdShell_b::Terminate (UINT uiCode)
                                                                              {
                                                                               if(!bInstalled) return false;
                                                                               if(!pi.hProcess) return false;
                                                                               
                                                                               if(::TerminateProcess(pi.hProcess, uiCode)) return true;
                                                                               return false;
                                                                              }
                                                                              //----------------------------------------------------------------------------------
                                                                              //  DbgStr::TypeDebugString(_T("%s WaitProcess bRet=%d"),_T(__FUNCTION__),bRet);
                                                                              // ---------------------------------------------------------------------------------


                                                                            Пробовал только для x86, но сборка x64 у меня тоже есть.
                                                                            Сообщение отредактировано: ЫукпШ -
                                                                              TerminateProcess()... абажаю. В чём проблема была послать ему "quit()"?
                                                                                Цитата Qraizer @
                                                                                TerminateProcess()... абажаю.

                                                                                :lool:
                                                                                  Цитата Qraizer @
                                                                                  TerminateProcess()... абажаю. В чём проблема была послать ему "quit()"?

                                                                                  Допустим, произошла ошибка при пользовании
                                                                                  Питоном.
                                                                                  Юзер забыл послать ему "exit()".
                                                                                  Ещё интереснее получится, если вообще произойдут какие-то ошибки
                                                                                  (в процессе отладки нашего приложения) и у нас останется висеть запущенный
                                                                                  процесс Питона.
                                                                                  А мы завершим работу своего приложения.
                                                                                  И задумаем его перезапустить.
                                                                                  А это не получится - дочерний процесс уже запущен. "Это фиаско, братан" ©
                                                                                  Или получится, но мы не сразу обнаружим вышеупомянутую ошибку
                                                                                  и начнём плодить "потерянные" процессы массово.
                                                                                  Terminate - это просто предохранитель.
                                                                                  Если Питон заканчивает работу штатным образом
                                                                                  посредством "exit()", Terminate фактически ничего и не делает.
                                                                                  ---
                                                                                  Terminate - не так уж редко нужно.
                                                                                  ---
                                                                                  На самом деле это решение можно критиковать с другой стороны.
                                                                                  Просто для упрощения примера я использовал такую реализацию.
                                                                                  Предположим, что Питон сам начал запускать различные приложения
                                                                                  для своей работы. Много различных процессов.
                                                                                  Так вот, нужно перечислить и грохнуть их все.
                                                                                  Иначе в результате любой аварии получится неудобная проблема.
                                                                                  Более корректный вариант у меня такой:
                                                                                  ExpandedWrap disabled
                                                                                    // ---------------------------------------------------------------------------------
                                                                                    bool WINAPI cmdShell::UnInstall(size_t dwTout)
                                                                                    {
                                                                                     bool RetC=false;
                                                                                     
                                                                                     if((bInstalled)&&(pExit))
                                                                                     {
                                                                                      RetC = WriteToPipe(pExit);
                                                                                     
                                                                                      if(!WaitProcess((DWORD)dwTout))
                                                                                      {
                                                                                       BOOL bRKPEX = KillChildProcessesEx();
                                                                                       if(!bRKPEX) RetC = false;
                                                                                      }
                                                                                     }
                                                                                     else
                                                                                     {
                                                                                      if(!KillChildProcessesEx()) RetC = false;
                                                                                     }
                                                                                     
                                                                                     bInstalled = false;
                                                                                     return RetC;
                                                                                    }
                                                                                    // ---------------------------------------------------------------------------------
                                                                                  Сообщение отредактировано: ЫукпШ -
                                                                                    Цитата ЫукпШ @
                                                                                    я несколько подправил класс "cmdShell"
                                                                                    Спасибо большое, буду разбираться.
                                                                                      ЫукпШ, ты комп тоже reset-ом ребутаешь? Ненуачё, а вдруг какая-то аппликуха откажется отвечать, какой-то драйвер не отпустит свою шелезяку...

                                                                                      Добавлено
                                                                                      Любое нормально работающее нормальное приложение имеет штатный режим завершения работы. Пользователь ими вполне пользуется. Ты же наверняка не запускаешь таск-менеджер и прибиваешь аппликуху из списка процессов каждый раз? Почему тогда советуешь другим программно делать именно так? Давно Рихтера открывал?

                                                                                      Добавлено
                                                                                      Цитата ЫукпШ @
                                                                                      Terminate - не так уж редко нужно.
                                                                                      Никогда не нужно. Ею должен пользоваться только пользователь только из таск-менеджера.
                                                                                        Цитата Qraizer @
                                                                                        ЫукпШ, ты комп тоже reset-ом ребутаешь? Ненуачё, а вдруг какая-то аппликуха откажется отвечать, какой-то драйвер не отпустит свою шелезяку...

                                                                                        Qraizer, ниочём.
                                                                                        -----
                                                                                        А вообще у меня есть такая функция - в софте у микроконтроллеров - аппаратный reset.
                                                                                        Можно даже дать по сети. "И чо ?". Никаких комплексов - если надо, значит сделаем.
                                                                                        -----
                                                                                        Есть даже такой характерный приём программирования системы.
                                                                                        Хорошо известный в узких кругах.
                                                                                        Аппаратный сброс на микроконтроллер подаётся от генератора постоянно.
                                                                                        Во временном промежутками между сбросами контроллер и выполняет
                                                                                        всю работу. Такая вычислительная система не может зависнуть...
                                                                                        -----
                                                                                        Ты преподавателем работаешь ?

                                                                                        Добавлено
                                                                                        Цитата Qraizer @
                                                                                        Любое нормально работающее нормальное приложение имеет штатный режим завершения работы.

                                                                                        А я тебе и ответил - что в штатном режиме Terminate и не используется.
                                                                                        Это предохранитель на не предвиденную ситуацию и не штатный режим.
                                                                                        Который всегда может возникнуть в любой момент.
                                                                                        В том числе и по прямой ошибке программиста.
                                                                                          Цитата ЫукпШ @
                                                                                          Аппаратный сброс на микроконтроллер подаётся от генератора постоянно.
                                                                                          Во временном промежутками между сбросами контроллер и выполняет
                                                                                          всю работу. Такая вычислительная система не может зависнуть...
                                                                                          :lool: Это пять.
                                                                                          Вэлкам ту Холиварс, ЫукпШ. Создавай тему, тут заканчиваем, бо B.V. счас взбесится. Перед созданием рекомендую ознакомиться с такими типами систем, как hosted и freestanding, пригодится.
                                                                                          Сообщение отредактировано: Qraizer -
                                                                                            Цитата Qraizer @
                                                                                            Цитата ЫукпШ @ Вчера, 23:56
                                                                                            Terminate - не так уж редко нужно.
                                                                                            Никогда не нужно. Ею должен пользоваться только пользователь только из таск-менеджера.

                                                                                            Бывает, нужно: сам применяю, когда идёт очередь выполнения задач, и задержка цикла гораздо критичнее принудительного завершения процесса. Приходится прибивать.
                                                                                              vlad2, в отладке юзай, что хочешь и как хочешь. В продакшн не переноси. Будешь сильно недоволен, например, тем, что очень важные отладочные логи не записались. Или там лицензия на сервере лицензий залипла на сутки. Или ещё чего.
                                                                                                Цитата Qraizer @
                                                                                                в отладке юзай, что хочешь и как хочешь. В продакшн не переноси.
                                                                                                Согласен. Только в крайнем случае).

                                                                                                ЫукпШ, спасибо за помощь. Только я немного разобрал твой код, что-то объединил и адаптировал к привычному для меня стилю. Вместо класса cmdShell_b сделал несколько функций. В результате не сразу, но всё заработало. Но всё-таки сделаю класс - так удобнее и элегантнее: мне понравился твой подход.
                                                                                                На этом тему пока закрою. Если опять возникнут вопросы при эксплуатации, задам снова. Всем спасибо.
                                                                                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                                                                0 пользователей:


                                                                                                Рейтинг@Mail.ru
                                                                                                [ Script execution time: 0,1391 ]   [ 20 queries used ]   [ Generated: 19.04.24, 19:40 GMT ]