Отлов ответа из cmd
|
tatsu
|
Дата: Воскресенье, 24.01.2016, 18:04 | Сообщение # 1
|
Частый гость
Зарегистрирован: 17.05.2009
Группа: Пользователи
Сообщений: 27
Статус: Offline
|
Всем доброго времени суток. Собственно задача: Выполнять досовую команду, но ответ писать не в консоль приложения, а в переменную. Нагуглил функцию. Работает. Однако есть 1 нюанс. Функция возвращает байты точь в точь, поскольку использует именованный канал. Кирилическая винда в командную строку выплёвывает как правило ответ в кодировке 866. Однако на деле имеем вместо текста кучу знаков вопросов и всё. Для отладки выплюнул ответ в файл. Вооружлся notepad++ и hex-редактором. Сравнил байты, оказалось - инглишный текст соответствует ASCII, а вот там где должный быть кирилические символы - байты не известной кодировки. Подскажите, как привести это в читабельный вид. Функция:
Код
function GetDosOutput(
CommandLine: string; Work: string = 'C:\'): string;
var
SA: TSecurityAttributes;
SI: TStartupInfo;
PI: TProcessInformation;
StdOutPipeRead, StdOutPipeWrite: THandle;
WasOK: Boolean;
Buffer: array[0..255] of Char;
BytesRead: Cardinal;
WorkDir: string;
Handle: Boolean;
begin
Result := '';
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); // не переадресовывать stdinput
hStdOutput := StdOutPipeWrite;
hStdError := StdOutPipeWrite;
end;
WorkDir := Work;
Handle := CreateProcess(nil, PChar('cmd.exe /C ' + CommandLine),
nil, nil, True, 0, nil,
PChar(WorkDir), SI, PI);
CloseHandle(StdOutPipeWrite);
if Handle then
try
repeat
WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);
if BytesRead > 0 then
begin
Buffer[BytesRead] := #0;
Result := Result + Buffer;
end;
until not WasOK or (BytesRead = 0);
WaitForSingleObject(PI.hProcess, INFINITE);
finally
CloseHandle(PI.hThread);
CloseHandle(PI.hProcess);
end;
finally
CloseHandle(StdOutPipeRead);
end;
end;
Ибо маст дай!
|
|
|
|
|
dolphin
|
Дата: Воскресенье, 24.01.2016, 22:14 | Сообщение # 2
|
Администратор
Сообщений: 902
Статус: Offline
|
Код
procedure TCmdThread.Execute;
var
ExecInform : TShellExecuteInfo;
MemoryStream : TMemoryStream;
begin
ZeroMemory(@ExecInform,sizeOf(ExecInform));
with ExecInform do
begin
cbSize := SizeOf(ExecInform);
lpVerb := 'open';
lpFile := 'cmd.exe';
lpParameters := PChar('cmd /u /c '+ComandLine+'cmd.txt');
nShow := SW_HIDE;
fMask := $00000040;
end;
if not ShellExecuteEx(@ExecInform) then
case ExecInform.hInstApp of
2 : EndString:= 'Ôàéë íå íàéäåí';
3 : EndString:= 'Ïóòü íå íàéäåí';
5 : EndString:= 'Äîñòóï ê ôàéëó çàïðåùåí';
8 : EndString:= 'He õâàòàåò ïàìÿòè';
32 : EndString:= 'Íå íàéäåíà íåîáõîäèìàÿ DLL';
26 : EndString:= 'Ôàéë çàõâà÷åí äðóãèì ïîëüçîâàòåëåì';
27 : EndString:= 'Íå ïîëíàÿ èíôîðìàöèÿ î ñâÿçàííîì ñ ôàéëîì ïðèëîæåíèè';
28 : EndString:= 'Èñòåêëî âðåìÿ íà âûïîëíåíèå îïåðàöèè DDE';
29 : EndString:= 'Îøèáî÷íàÿ îïåðàöèÿ DDE';
30 : EndString:= 'Îïåðàöèÿ DDE çàíÿòà';
31 : EndString:= 'Íåò ïðèëîæåíèÿ, ñâÿçàííîãî ñ ôàéëîì';
end
else
begin
WaitForSingleObject(ExecInform.hProcess,INFINITE);
CloseHandle(ExecInform.hProcess);
MemoryStream := TMemoryStream.Create;
MemoryStream.LoadFromFile('cmd.txt');
OemToCharBuffA(MemoryStream.Memory,MemoryStream.Memory,MemoryStream.Size);
SetString(EndString,PAnsiChar(MemoryStream.Memory),MemoryStream.Size);
MemoryStream.Free;
end;
Synchronize(EndWork);
end;
procedure TCmdThread.EndWork;
begin
SendMessage(EndString);
end;
Надеюсь поможет
Система: Windows 10 x64, Windows XP
Среды программирования: Delphi 7, Delphi 10 Seattle
Я не профессионал, я всего лишь любитель
Я не вредитель, я всего лишь теоретик
|
|
|
|
|
tatsu
|
Дата: Воскресенье, 24.01.2016, 22:27 | Сообщение # 3
|
Частый гость
Зарегистрирован: 17.05.2009
Группа: Пользователи
Сообщений: 27
Статус: Offline
|
dolphin, В принципе суть ясна, но тебе не кажется, что использовать текстовики при такой задаче это малось костыльно. Собственно эту же задачу я уже реализовывал на питоне и думаю, что как раз таки копать надо в сторону перенаправления вывода, ранешь об этом не думал как-то, покопаю пайпы глубже.
Ибо маст дай!
|
|
|
|
|
Neo
|
Дата: Понедельник, 25.01.2016, 15:19 | Сообщение # 4
|
Модератор
Зарегистрирован: 04.05.2010
Группа: Модераторы
Сообщений: 316
Статус: Offline
|
Ч что, если тебе в cmd добавить chcp cp1251 или chcp utf8
??? |
|
|
|
|