gpt4 book ai didi

delphi - 如何从 GUI 应用程序向控制台应用程序发送命令

转载 作者:行者123 更新时间:2023-12-03 14:43:38 28 4
gpt4 key购买 nike

我有一个从 GUI 应用程序启动的控制台应用程序。控制台应用程序采用文件名参数来解析和处理。目前我能够捕获它的输出并将其显示在 GUI 应用程序中,但我希望能够向它发送命令以控制甚至停止它的执行。

如何将命令或字符串或任何内容发送到控制台应用程序,最好使用我打开的管道来读取其输出?

const
CReadBuffer = 2400;
var
saSecurity: TSecurityAttributes;
hRead: THandle;
hWrite: THandle;
suiStartup: TStartupInfo;
piProcess: TProcessInformation;
pBuffer: array[0..CReadBuffer] of AnsiChar;
dRead: DWord;
dRunning: DWord;
dWritten: DWord;
Command: String;
BytesLeft: Integer;
BytesAvail: Integer;
begin
saSecurity.nLength := SizeOf(TSecurityAttributes);
saSecurity.bInheritHandle := True;
saSecurity.lpSecurityDescriptor := nil;

if CreatePipe(hRead, hWrite, @saSecurity, 0) then
begin
FillChar(suiStartup, SizeOf(TStartupInfo), #0);
suiStartup.cb := SizeOf(TStartupInfo);
suiStartup.hStdInput := hRead;
suiStartup.hStdOutput := hWrite;
suiStartup.hStdError := hWrite;
suiStartup.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
suiStartup.wShowWindow := SW_HIDE;
Command := 'messageparser.exe c:\messagefile.msg';
UniqueString(Command);
if CreateProcess(nil, PChar(Command), @saSecurity,
@saSecurity, True, NORMAL_PRIORITY_CLASS, nil, nil, suiStartup, piProcess) then
begin
repeat
dRunning := WaitForSingleObject(piProcess.hProcess, 100);
Application.ProcessMessages;
repeat
dRead := 0;

if not PeekNamedPipe(hread, @pbuffer, CReadBuffer, @dRead, @BytesAvail, @BytesLeft) then
RaiseLastOSError;
if dRead <> 0 then
begin
ReadFile(hRead, pBuffer[0], CReadBuffer, dRead, nil);
pBuffer[dRead] := #0;
OemToCharA(pBuffer, pBuffer);
// do something with the data
// if a condition is present then do the following:
// WriteFile(hWrite, some_command, size_of_buffer, DWritten, nil);
end;
until (dRead < CReadBuffer);
until (dRunning <> WAIT_TIMEOUT);
CloseHandle(piProcess.hProcess);
CloseHandle(piProcess.hThread);
end;
CloseHandle(hRead);
CloseHandle(hWrite);
end;

然后在控制台端,有一个线程在等待输入。这是执行方法:

  while not Terminated do
begin
ReadLn(Command);
// process command
Sleep(10);
end;

这对我来说是新的,所以如果有关于如何正确操作的提示,我欢迎他们:)。然而,每当我发送命令时,它都会作为我从 ReadPipe 在 pBuffer 中读取的内容出现,而不是命令是什么。

希望这有帮助。

--

根据 Nat 的提示找到了解决方案。

Bi-directional communication between gui and console

最佳答案

您需要两个管道,一个用于进程向您发送输出 (stdout),另一个用于您向进程发送输入 (stdin)。

从您的代码来看,您似乎将相同管道的两端放入TStartupInfo记录中。所以你实际上是在让流程自言自语。 :-)

因此,您需要调用 CreatePipe() 两次,以创建两个管道,一个用于 stdin,一个用于 stdout(以及 stderr)。

然后,将stdin的读取句柄放入suiStartup.hStdInput,将stdout的写入句柄放入suiStartup.hStdOutput

要将数据发送到进程,请写入 stdin 管道的写入句柄。要读取进程的输出,请读取 stdout 管道的读取句柄。

编辑:(再次)

至于 this page 中描述的所有重复句柄以及可继承和不可继承的内容(特别是在代码示例中),您需要确保发送到进程的句柄是可继承的(正如您所做的那样)。

您还应该确保父进程使用的管道句柄是不可继承的。但你不必必须这样做...我以前没有这样做过。

您可以通过在句柄上调用 DuplicateHandle() 来执行此操作,指定它们不可继承并关闭旧句柄,或者调用指定为 0 的 SetHandleInformation()对于标志(如讨论 here )。

我自己这样做已经有一段时间了,但我很确定这是为了使句柄的引用计数与调用进程相关联,而不是与子进程相关联。这可以防止句柄在您仍在使用时被关闭(例如,调用进程可能会关闭“stdin”)。但请确保关闭 handle ,否则最终会泄漏 handle 。

HTH。

N@

关于delphi - 如何从 GUI 应用程序向控制台应用程序发送命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2015388/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com