Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Message to change an edit field
#8
"running app via IntraWeb is, or should be, a valuable feature of your product"

That isn't the issue. The issue I can fully assure you has nothing to do with IW. IW does not interfere with pipes. It has to do with permissions of your app, threading, or the like. This is standard Delphi and can affect any Delphi app that is deployed in the same manner.

This is code we currently use to call out to a console app and get the response. I have not tested it in threads as it isnt needed for the same purpose. Pipes have a lot of issues though, and this code works around the common pitfalls.

As I stated previously I will try to help within limits as this is not an IW issue. But you may consider also asking on a general Delphi forum such as EMBTs forums. The issue here though is that you need to ask in a more generic way "im running in a thread, etc"... rather than "It an IW app", because it being an IW app is not the defining issue in this case.

When you are testing in your IW app, how are you deploying? Is it just an SA exe? If its a service or ISAPI there are extra permissions issues.

unit IW17.Design.ConsoleRunner;

interface

type
T17ConsoleRunner = class
public type
TTextProc = reference to procedure(const aText: string);
public
class function Run(const aCommand: string; aParams: string; aCallBack: TTextProc = nil): string;
end;

implementation

uses
Winapi.Windows, System.SysUtils, System.IOUtils, Vcl.Forms;

function CreateEnvironmentBlock(var lpEnvironment: Pointer; hToken: THandle; bInherit: BOOL): BOOL; stdcall; external 'Userenv.dll';
function DestroyEnvironmentBlock(pEnvironment: Pointer): BOOL; stdcall; external 'Userenv.dll';

class function T17ConsoleRunner.Run(const aCommand: string;
aParams: string; aCallBack: TTextProc = nil): string;
const
xBufSize = 2048;
var
xExitCode: Cardinal;
xSecurity: TSecurityAttributes;
xReadHandle, xWriteHandle: THandle;
xStartupInfo: TStartupInfo;
xProcessInfo: TProcessInformation;
xBuffer1, xBuffer2: array [0 .. xBufSize] of AnsiChar;
xRead, xRunning, xBytesAvail: DWORD;
xResult: TStringBuilder;
xWorkingDir: string;
xEnvironment: Pointer;
begin
xExitCode := 0;
xResult := TStringBuilder.Create; try
xSecurity.nLength := SizeOf(TSecurityAttributes);
xSecurity.bInheritHandle := true;
xSecurity.lpSecurityDescriptor := nil;

Win32Check(CreatePipe(xReadHandle, xWriteHandle, @xSecurity, 0));
try
FillChar(xStartupInfo, SizeOf(TStartupInfo), #0);
xStartupInfo.cb := SizeOf(TStartupInfo);
xStartupInfo.hStdInput := xReadHandle;
xStartupInfo.hStdOutput := xWriteHandle;
xStartupInfo.hStdError := xWriteHandle;
xStartupInfo.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
xStartupInfo.wShowWindow := SW_HIDE;

// We need this to load system paths else child processes called by any
// exe we call will fail.
Win32Check(CreateEnvironmentBlock(xEnvironment, 0, True)); try
xWorkingDir := TPath.GetDirectoryName(aCommand);
Win32Check(CreateProcess(nil, PChar(aCommand + ' ' + aParams), @xSecurity
, @xSecurity, true, CREATE_UNICODE_ENVIRONMENT, xEnvironment, PChar(xWorkingDir)
, xStartupInfo, xProcessInfo));
try
repeat
xRunning := WaitForSingleObject(xProcessInfo.hProcess, 100);
PeekNamedPipe(xReadHandle, nil, 0, nil, @xBytesAvail, nil);
if xBytesAvail > 0 then begin
repeat
Win32Check(ReadFile(xReadHandle, xBuffer1[0], xBufSize - 1, xRead, nil));
xBuffer1[xRead] := #0;
OemToCharA(xBuffer1, xBuffer2);

// To avoid using up unnecessary RAM, we only collect if no callback
if Assigned(aCallBack) then begin
aCallBack(string(xBuffer2));
end else begin
xResult.Append(string(xBuffer2));
end;
until xRead < xBufSize;
end;
Application.ProcessMessages;
until xRunning <> WAIT_TIMEOUT;
Win32Check(GetExitCodeProcess(xProcessInfo.hProcess, xExitCode));
finally
CloseHandle(xProcessInfo.hProcess);
CloseHandle(xProcessInfo.hThread);
end;
finally
CloseHandle(xReadHandle);
CloseHandle(xWriteHandle);
end;
finally
DestroyEnvironmentBlock(xEnvironment);
end;

Result := xResult.ToString;
if xExitCode <> 0 then raise Exception.Create(Result);
finally xResult.Free; end;
end;

end.
Reply


Messages In This Thread
Message to change an edit field - by davidbaxter - 02-23-2019, 09:24 PM
RE: Message to change an edit field - by kudzu - 02-24-2019, 03:59 PM
RE: Message to change an edit field - by kudzu - 02-25-2019, 04:27 PM
RE: Message to change an edit field - by kudzu - 02-26-2019, 02:23 PM
RE: Message to change an edit field - by kudzu - 02-27-2019, 02:22 PM
RE: Message to change an edit field - by kudzu - 02-28-2019, 03:56 PM

Forum Jump:


Users browsing this thread: 1 Guest(s)