-
hey guys, i'm having a problem with a custom function. i have the following function working on an usual VCL app:
procedure RunConv(const ACommand, AParameters: String);
const
CReadBuffer = 1200;
var
saSecurity: TSecurityAttributes;
hRead: THandle;
hWrite: THandle;
suiStartup: TStartupInfo;
piProcess: TProcessInformation;
pBuffer: array[0..CReadBuffer] of AnsiChar;
dRead: DWord;
dRunning: DWord;
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;
if CreateProcess(nil, PChar('cmd.exe /C ' + ACommand + ' ' + AParameters), @saSecurity,
@saSecurity, True, NORMAL_PRIORITY_CLASS, nil, nil, suiStartup, piProcess)
then
begin
repeat
dRunning := WaitForSingleObject(piProcess.hProcess, 100);
repeat
dRead := 0;
ReadFile(hRead, pBuffer[0], CReadBuffer, dRead, nil);
pBuffer[dRead] := #0;
OemToAnsi(pBuffer, pBuffer);
ProcessLine(String(pBuffer));
until (dRead < CReadBuffer);
until (dRunning <> WAIT_TIMEOUT);
ProcessLine('-end-');
CloseHandle(piProcess.hProcess);
CloseHandle(piProcess.hThread);
end
else
ShowMessage(':(');
CloseHandle(hRead);
CloseHandle(hWrite);
end;
end;
it's purpose is to execute an external console app and returns the output (to be processed in the ProcessLine() procedure), while running. I need it to capture some ongoing processes, and can't wait for them to finish to return the output, so basically normal ExecuteAndWait() or ShellExecute() can't be used. Anyway, the same function doesn't work on KOL, or more precisely, CreateProcess() doesn't return true (it triggers ShowMessage()). I changed PChar() to PKOLChar(), but other than that no changes are made. any ideas what i can do to fix it ? maybe some issue with CreateProcess() ? thank you thank you
-
I didn't hae a problem with CreateProcess. What are your compiler conditional defines? This works for me (just minor mods to your code):
program Test;
uses
Windows, KOL;
var
ButtonGo, ButtonStop, Memo: PControl;
StopFlag: Boolean;
procedure RunConv(const ACommand, AParameters: KOLString);
const
CReadBuffer = 1200;
var
saSecurity: TSecurityAttributes;
hRead: THandle;
hWrite: THandle;
suiStartup: TStartupInfo;
piProcess: TProcessInformation;
pBuffer: array[0..CReadBuffer] of AnsiChar;
dRead: DWord;
dRunning: DWord;
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;
if CreateProcess(nil, PKOLChar('cmd.exe /C ' + ACommand + ' ' + AParameters), @saSecurity,
@saSecurity, True, NORMAL_PRIORITY_CLASS, nil, nil, suiStartup, piProcess) then
begin
repeat
dRunning := WaitForSingleObject(piProcess.hProcess, 100);
repeat
if PeekNamedPipe(hRead, nil, 0, nil, @dRead, nil) and (dRead > 0) then
begin
ReadFile(hRead, pBuffer[0], CReadBuffer, dRead, nil);
pBuffer[dRead] := #0;
OemToAnsi(pBuffer, pBuffer);
Memo.Add(AnsiString(pBuffer));
Applet.Caption := Int2Str(Memo.Count);
Applet.ProcessMessagesEx;
end;
until (dRead < CReadBuffer) or (StopFlag = True);
until (dRunning <> WAIT_TIMEOUT) or (StopFlag = True);
Memo.Add('-end-');
CloseHandle(piProcess.hProcess);
CloseHandle(piProcess.hThread);
end
else
ShowMessage(':(');
CloseHandle(hRead);
CloseHandle(hWrite);
end;
StopFlag := False;
ButtonGo.Enabled := True;
end;
procedure ButtonGoClick(Dummy: Pointer; Sender: PControl);
begin
ButtonGo.Enabled := False;
RunConv('dir', '\"%windir%\system32\*.*\" /a/s');
end;
procedure ButtonStopClick(Dummy: Pointer; Sender: PControl);
begin
StopFlag := True;
end;
begin
Applet := NewForm(nil, 'Test').SetSize(380, 420).CenterOnParent;
ButtonGo := NewButton(Applet, 'Go');
ButtonGo.OnClick := TOnEvent(MakeMethod(nil, @ButtonGoClick));
ButtonStop := NewButton(Applet, 'Stop').PlaceRight;
ButtonStop.OnClick := TOnEvent(MakeMethod(nil, @ButtonStopClick));
Memo := NewEditBox(Applet, [eoMultiline]).PlaceDown.SetSize(360, 360);
Memo.Color := clWindow;
Run(Applet);
end.
-
Also, don't forget that you may need to terminate the process:
TerminateProcess(piProcess.hProcess,0);
CloseHandle(piProcess.hProcess);
CloseHandle(piProcess.hThread);
|