На главную Наши проекты:
Журнал   ·   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.
  
> Запуск процесса без видимого консольного окна
    Всем привет!

    Интересует сабж, а точнее Win API для него. Пишу скрипт на Lua, но не суть - мне и на Си норм будет совет.
    Сперва сунулся читать про ShellExecuteW, но похоже это не то, или я просто невнимателен :-?

    А еще ... мне от этого процесса по его завершении нужно считать его STDOUT.

    Добавлено
    Случаем это не оно?
      Только не говорите, что это оно - я повешусь всю эту портянку на Lua переводить! :'(

      Добавлено
      ЗЫ: Есличо - пишу для себя приблуду для FAR'а ... Пока код таков:
      ExpandedWrap disabled
        local inspect = require('inspect')
        local ScriptName = ...
         
        local EditorTools = function ()
          local CurPath = mf.fsplit(ScriptName,3)
          local ConfigName = ScriptName:gsub("[^.]+$","conf")
          local Conf = io.open(ConfigName,"r")
          if Conf == nil then
            far.Message('Файл конфигурации нельзя прочесть!', 'Ошибка', ';Ok', 'w')
            return
          else
            local Cmd = {}
            local Idx = 1
            for line in Conf:lines() do
              if regex.match(line,'^(F|C)') then
                for w1,w2,w3 in regex.gmatch(line, '^(F|C)\\s*,\\s*"\\s*([^"]+?)\\s*"\\s*,\\s*"\\s*([^"]+?)\\s*"\\s*$') do
                  Cmd[Idx] = {w1,w2,w3}
                end
                Idx = Idx + 1
              end
            end
            Conf:close()      
            local Choice = ''
            for Idx = 1, #Cmd do
              Choice = Choice..Cmd[Idx][2]..'\n';
            end
            local ChoiceIdx = Menu.Show(Choice, nil, 8+0x200)
            far.Show('Индекс = '..ChoiceIdx)
            far.Show(editor.GetFileName())
          end
        end
         
        Macro {
          area="Editor"; key="ShiftF12"; flags=""; description="EditorTools Dialog";
          action = function()
            EditorTools()
          end;
        }

      Выводит в редакторе список "Инструментов", и их два вида "Фильтры" и "Компиляторы". Дальше расскажу, если интересно ... :)
        Откопал в загашниках 15-летней давности.
        ExpandedWrap disabled
           function GetOutput(const FileName,Params:String):String;
           var
              SA: TSecurityAttributes;
              SI: TStartupInfo;
              PI: TProcessInformation;
              StdOutPipeRead, StdOutPipeWrite: THandle;
              WasOK: Boolean;
              Buffer: array[0..High(Byte)] of Char;
              BytesRead: Cardinal;
              WorkDir, Line: String;
           begin
             with SA do
             begin
               nLength := SizeOf(SA);
               bInheritHandle := True;
               lpSecurityDescriptor := nil;
             end;
             CreatePipe(StdOutPipeRead,StdOutPipeWrite,@SA,0);
             try
               with SI do
               begin
                 FillChar(SI, SizeOf(SI), 0);
                 cb := SizeOf(SI);
                 dwFlags:=STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
                 wShowWindow:=SW_HIDE;
                 hStdInput:=GetStdHandle(STD_INPUT_HANDLE);
                 hStdOutput:=StdOutPipeWrite;
                 hStdError := StdOutPipeWrite;
               end;
               WorkDir:=ExtractFilePath(FileName);
               WasOK:=CreateProcess(nil,PChar(FileName+Params),nil,nil,True,0,nil,
                                    PChar(WorkDir),SI,PI);
               CloseHandle(StdOutPipeWrite);
               if WasOK then
                  try
                    Line := '';
                    repeat
                      WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);
                      if BytesRead > 0 then begin
                         Buffer[BytesRead] := #0;
                         Line := Line + Buffer;
                      end;
                    until not WasOK or (BytesRead = 0);
                    WaitForSingleObject(PI.hProcess, INFINITE);
                  finally
                    CloseHandle(PI.hThread);
                    CloseHandle(PI.hProcess);
                  end;
             finally
               Result:=Line;
               CloseHandle(StdOutPipeRead);
             end;
           end;


        Добавлено
        Цитата JoeUser @
        Только не говорите, что это оно - я повешусь всю эту портянку на Lua переводить! :'(

        Да, это оно, через пайпы
          Пайпы нужны для интерактивного взаимодействия с запускаемым процессом. Если нужно просто схавать его аутпут, а предоставлять инпут не требуется, проще сделать через файлы.
          На вот пример. Что ты с ним будешь делать в LUA, смотри сам.
          ExpandedWrap disabled
            namespace fs = std::filesystem;
             
            /* Манипулятор для установки русской локали в поток вывода.
               Предыдущая локаль нигде не сохраняется. */
            template <typename Ch, typename Tr>
            std::basic_ostream<Ch, Tr>& rusLocale(std::basic_ostream<Ch, Tr>& os)
            {
              static std::locale rus("rus");
             
              os.imbue(rus);
              return os;
            }
             
            /* Написать что-нибудь в лог. Обычно это код ошибки, но не обязательно. */
            int logMsg(const std::string& msg, DWORD code)
            {
              static std::mutex log;        // многопоточный лок
              // сформировать сообщение в формате
              // [дата/время] сообщение: код ситуации в десятичной и шестнадцатеричной формах
              std::string show = std::move(static_cast<std::ostringstream&&>(
                                           std::ostringstream(msg, std::ios::ate) << ": "
                                                                                  << std::dec << code
                                                                                  << std::hex << " (0x"
                                                                                  << std::uppercase << code
              /* дата и время */                                                  << ')').str());
              std::time_t currentTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
              {
                std::lock_guard<std::mutex> lock(log);      // залочить лог
                std::tm  now = *localtime(&currentTime);    // преобразовать дату/время в структурный формат
             
                // логгировать
                std::ofstream("log.txt", std::ios::app) << rusLocale << '['  << std::put_time(&now, "%c")
                                                                     << "]\t"<< show << '\n';
              }
              return 2;     // на случай, если логировали ошибку, вернуть код, возвращаемый main() в ОС
            }
             
            /* Получить переменную окружения по её имени. */
            std::string getEnv(const std::string& env)
            {
              std::string res(GetEnvironmentVariable(env.c_str(), NULL, 0), '\0');          // длина строки
             
              if (GetEnvironmentVariable(env.c_str(), &res.front(), res.size()) == 0)       // контент строки
                return logMsg("GetEnvironmentVariable() failed", GetLastError()),
                       std::string();
              res.resize(res.size()-1);                                     // убрать финализирующий NUL
              return res;
            }
             
            /* Класс замыканий. Параметр - функциональный объект, выполняющий очистку замыкаемой сущности. */
            class Guard
            {
              std::function<void(void)> fn;         // функция очистки
             
            public:
              template <typename T> explicit Guard(T&& closure): fn(std::move(closure)) {}
              ~Guard() { fn(); }
            };
             
            /* ... */
             
            // -------------------------------     собственно код запуска     -------------------------------
             
              logMsg(dir.filename().string() + ": trying to reset", 0);
             
              // имя железки
              std::string nameCPU = /* ... */;
              // порт и пин управления ребутом
              std::string com     = "reset" + std::string(nameCPU.end() - 4, nameCPU.end()) + "_com";
              std::string pin     = "reset" + std::string(nameCPU.end() - 4, nameCPU.end()) + "_pin";
              // путь и имя ребутера
              fs::path exeReboot  = fs::path(getEnv("TestEnvironmentBase")) / "softReset.exe";
             
              // HANDLES наследуются
              SECURITY_ATTRIBUTES attr = { sizeof(attr), NULL, TRUE };
              // stdin из файла
              // не используется ребутером, но требуется для запуска с перенаправленными потоками вывода
              HANDLE hIn  = CreateFile((dir / "stdin.txt").string().c_str(),
                                       FILE_GENERIC_READ, FILE_SHARE_DELETE,&attr, CREATE_ALWAYS,
              /* stdout в файл */      FILE_ATTRIBUTE_NORMAL, NULL); Guard hInGuarded ([=]() { CloseHandle(hIn);  });
              HANDLE hOut = CreateFile((dir / "stdout.txt").string().c_str(),
                                       FILE_GENERIC_WRITE, FILE_SHARE_READ, &attr, CREATE_ALWAYS,
              /* stderr в файл */      FILE_ATTRIBUTE_NORMAL, NULL); Guard hOutGuarded([=]() { CloseHandle(hOut); });
              HANDLE hErr = CreateFile((dir / "stderr.txt").string().c_str(),
                                       FILE_GENERIC_WRITE, FILE_SHARE_READ, &attr, CREATE_ALWAYS,
                                       FILE_ATTRIBUTE_NORMAL, NULL); Guard hErrGuarded([=]() { CloseHandle(hErr); });
              // командная строка запуска ребутера
              std::string         commandLine = exeReboot.string() + ' ' + getEnv(com) + ' ' + getEnv(pin) + '\0';
              // HANDLES и ID процесса ребутера и его главной нитки
              PROCESS_INFORMATION processInfo;
              // параметры запуска процесса ребутера; стандартные потоки переопределены на файлы
              STARTUPINFO         startInfo = { sizeof(startInfo), NULL, NULL, NULL, 0, 0, 0, 0, 0, 0,
                                                0, STARTF_USESTDHANDLES, 0, 0, NULL,
                                                hIn, hOut, hErr };
              DWORD               exitCode  = -1;
             
              // Запустить ребутер (без окна).
              if (CreateProcess(NULL, &commandLine.front(), NULL, NULL, TRUE, CREATE_NO_WINDOW,
                                NULL, NULL, &startInfo, &processInfo) == FALSE)
                logMsg("CreateProcess() failed", GetLastError());
              else
              { // при успехе
                CloseHandle(processInfo.hThread);                                   // HANDLE нитки не нужен
                DeleteFile((dir / "stdin.txt").string().c_str()); // stdin удалить (отложенно)
             
                Guard hProcessGuarded([=]() { CloseHandle(processInfo.hProcess); });
             
                // подождать завершения
                if (WaitForSingleObject(processInfo.hProcess, INFINITE) != WAIT_OBJECT_0)
                  logMsg("Reset failure", GetLastError());
             
                // Получить код завершения ребутера
                GetExitCodeProcess(processInfo.hProcess, &exitCode);
              }
              logMsg(dir.filename().string() + ": reset done", exitCode);
             
            /* ... */
          Функции logMsg() и getEnv(), класс Guard и манипулятор rusLocale просто для понимания основного кода, собственно код запуска без окна с переназначением stdin, stdout и stderr на файлы приведён в конце. Впрочем, stdin не используется, но я не нашёл способа переопределить только два потока из трёх.
          Сообщение отредактировано: Qraizer -
            Цитата JoeUser @
            Есличо - пишу для себя приблуду для FAR'а ...

            Лет нндцать назад пилил плагины для фара, тоже на делфях, если надо - скину.
              https://stackoverflow.com/questions/224225/...ithout-a-window

              Вроде вот это что-то похожее?

              ExpandedWrap disabled
                #include <windows.h>
                #include <stdio.h>
                 
                int CALLBACK WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
                    MSG msg;
                    DWORD curThreadId;
                 
                    curThreadId = GetCurrentThreadId();
                 
                    // Send messages to self:
                    PostThreadMessage(curThreadId, WM_USER, 1, 2);
                    PostThreadMessage(curThreadId, WM_USER+1, 3, 4);
                    PostThreadMessage(curThreadId, WM_USER+2, 5, 6);
                    PostThreadMessage(curThreadId, WM_USER+3, 7, 8);
                    PostThreadMessage(curThreadId, WM_QUIT, 9, 10);
                 
                    while (GetMessage(&msg, NULL, 0, 0)) {
                        printf("message: %d; wParam: %d; lParam: %d\n", msg.message, msg.wParam, msg.lParam);
                    }
                 
                    return (int) msg.wParam;
                }
                Всем пасип! :good: Бум разбираться.
                  В общем, порешал просто через перенаправления во временные файлы и STDOUT и STDERR.
                  Подробнее тут.
                  0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                  0 пользователей:


                  Рейтинг@Mail.ru
                  [ Script execution time: 0,0467 ]   [ 17 queries used ]   [ Generated: 29.03.24, 05:55 GMT ]