Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.91.249.156] |
|
Сообщ.
#1
,
|
|
|
Всем привет!
Интересует сабж, а точнее Win API для него. Пишу скрипт на Lua, но не суть - мне и на Си норм будет совет. Сперва сунулся читать про ShellExecuteW, но похоже это не то, или я просто невнимателен А еще ... мне от этого процесса по его завершении нужно считать его STDOUT. Добавлено Случаем это не оно? |
Сообщ.
#2
,
|
|
|
Только не говорите, что это оно - я повешусь всю эту портянку на Lua переводить!
Добавлено ЗЫ: Есличо - пишу для себя приблуду для FAR'а ... Пока код таков: 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; } Выводит в редакторе список "Инструментов", и их два вида "Фильтры" и "Компиляторы". Дальше расскажу, если интересно ... |
Сообщ.
#3
,
|
|
|
Откопал в загашниках 15-летней давности.
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 переводить! Да, это оно, через пайпы |
Сообщ.
#4
,
|
|
|
Пайпы нужны для интерактивного взаимодействия с запускаемым процессом. Если нужно просто схавать его аутпут, а предоставлять инпут не требуется, проще сделать через файлы.
На вот пример. Что ты с ним будешь делать в LUA, смотри сам. 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(¤tTime); // преобразовать дату/время в структурный формат // логгировать 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); /* ... */ |
Сообщ.
#5
,
|
|
|
Цитата JoeUser @ Есличо - пишу для себя приблуду для FAR'а ... Лет нндцать назад пилил плагины для фара, тоже на делфях, если надо - скину. |
Сообщ.
#6
,
|
|
|
https://stackoverflow.com/questions/224225/...ithout-a-window
Вроде вот это что-то похожее? #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; } |
Сообщ.
#7
,
|
|
|
Всем пасип! Бум разбираться.
|
Сообщ.
#8
,
|
|
|
В общем, порешал просто через перенаправления во временные файлы и STDOUT и STDERR.
Подробнее тут. |