1
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 AnsiChar;
  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); // don't redirect stdin
      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;

I have copied updated method GetDosOutput from the below link and calling that in service's execute method. This method triggered for every 3 seconds.

Getting output from a shell/dos app into a Delphi app

procedure TMyFVODService.ServiceExecute(Sender: TService);
const SecBetweenRuns = 3;
var Count, WaitTimeMil: Integer;
begin
  while not Terminated do
  begin
    Inc(Count);
    if Count >= SecBetweenRuns then
    begin
      Count:=0;
      GetDosOutput('d:\usr\local\myApp -<SysName> STO','D:\');
    end;
    Sleep(1000);
    ServiceThread.ProcessRequests(False);
  end;
end;

Apart from these two methods, I don't have any code snippet in my service project.

Problem: When I start my service, memory consumption is increasing and after 7-10 days, system is going to not responding mode. Especially, private bytes of one of the instances of svcHost i.e. LocalServiceNetworkRestricted is increasing. There is no increase in private bytes of my service when observe in Resource Monitor. When I stop that service, there is no increase in the memory consumption.

NOTE: But, when I run same command "d:\usr\local\myApp - STO" for every 3 seconds using Task Scheduler, there is no increase in the memory consumption.

Query 1: Is there any memory leak in the copied code or I missed any. If yes, please suggest your solution.

Query 2: Why svcHost is taking memory, when I am running my service. Is there any relation between them.

Query 3: As a workaround, I thought to restart my service. But, its not releasing that memory. When I start it again, the memory consumption resumes from that point and finally system gets frozen.

James Z
  • 12,209
  • 10
  • 24
  • 44

0 Answers0