%%ID=DEMO
 //////////////////////////////////////////////////////////////////////////////
 // %ID% server - console daemon to connect to CRW-DAQ %ID% client thru pipe.
 //////////////////////////////////////////////////////////////////////////////
program %ID%_Server;
{$APPTYPE CONSOLE} // ! Declare application type as CONSOLE.
{$I _sysdef}       // ! By CRW conventions, include _SYSDEF,
uses               // ! ShareMem must to be FIRST USES UNIT,
 ShareMem,         // ! borlndmm.dll should present in path.
 SysUtils,Windows,Math,Classes,Forms,
 _alloc,_str,_mime,_rtc,_fio,_fifo,_ascio,_az,_polling,_task;
 //
 // General variables and constants
 //
const
 Terminated : Boolean = false; // Program should be terminated
 //
 // Request: @help
 // Reply:   help info
 // Comment: Show help.
 //
 procedure DoHelp(const cmnd,args:LongString);
 begin
  StdOut.Put:=Format('%s',[cmnd]);
  StdOut.Put:='>> Command list:';
  StdOut.Put:='>> @help                 This help.';
  StdOut.Put:='>> @exit=n               Exit program with code n.';
  StdOut.Put:='>> @errors               Return error counter.';
  StdOut.Put:='>> @memory               Return memory status.';
  StdOut.Put:='>> @processpriority=n    Set process priority:Idle/Low/Normal/High/RealTime.';
  StdOut.Put:='>> @threadpriority=n     Set thread priority:tpIdle/tpLow/tpNormal/tpHigh/tpTimeCritical.';
 end;
 //
 // Request: @exit
 // Request: @exit=n
 // Reply:   @exit=n
 // Comment: Terminate program with exit code n.
 //
 procedure DoExit(const cmnd,args:LongString);
 begin
  Terminated:=true;
  System.ExitCode:=StrToIntDef(args,0);
  StdOut.Put:=Format('%s=%d',[cmnd,System.ExitCode]);
 end;
 //
 // Request: @errors
 // Request: @errors=n
 // Reply:   @errors=n
 // Comment: Return value n of error counter.
 //
 procedure DoErrors(const cmnd,args:LongString);
 var
  n : LongInt;
 begin
  if Str2Long(args,n)
  then n:=LockedExchange(StdIoErrorCount,n)
  else n:=StdIoErrorCount;
  StdOut.Put:=Format('%s=%d',[cmnd,n]);
 end;
 //
 // Request: @memory
 // Request: @memory=n
 // Comment: Return AllocMemSize.
 //
 procedure DoMemory(const cmnd,args:LongString);
 begin
  StdOut.Put:=Format('%s=%d',[cmnd,GetAllocMemSize]);
 end;
 //
 // Request: @ProcessPriority
 // Request: @ProcessPriority=n
 // Reply:   @ProcessPriority=n
 // Comment: Set process priority class.
 //
 procedure DoProcessPriority(const cmnd,args:LongString);
 var p:DWORD;
 begin
  if not IsEmptyStr(args) then begin
   p:=GetPriorityClassByName(args);
   if p>0 then SetPriorityClass(GetCurrentProcess,p);
  end;
  StdOut.Put:=Format('%s=%s',[cmnd,GetPriorityClassName(GetPriorityClass(GetCurrentProcess))]);
 end;
 //
 // Request: @ThreadPriority
 // Request: @ThreadPriority=n
 // Reply:   @ThreadPriority=n
 // Comment: Set thread priority class.
 //
 procedure DoThreadPriority(const cmnd,args:LongString);
 var p:TThreadPriority;
 begin
  if not IsEmptyStr(args) then begin
   p:=GetPriorityByName(args);
   StdIn.Priority:=p;
   StdOut.Priority:=p;
   case p of
    tpIdle         : SetThreadPriority(GetCurrentThread,THREAD_PRIORITY_IDLE);
    tpLowest       : SetThreadPriority(GetCurrentThread,THREAD_PRIORITY_LOWEST);
    tpLower        : SetThreadPriority(GetCurrentThread,THREAD_PRIORITY_BELOW_NORMAL);
    tpNormal       : SetThreadPriority(GetCurrentThread,THREAD_PRIORITY_NORMAL);
    tpHigher       : SetThreadPriority(GetCurrentThread,THREAD_PRIORITY_ABOVE_NORMAL);
    tpHighest      : SetThreadPriority(GetCurrentThread,THREAD_PRIORITY_HIGHEST);
    tpTimeCritical : SetThreadPriority(GetCurrentThread,THREAD_PRIORITY_TIME_CRITICAL);
   end;
  end;
  StdOut.Put:=Format('%s=%s',[cmnd,GetPriorityName(StdIn.Priority)]);
 end;
 //
 // This callback handles unrecognized commands.
 //
 procedure DoSpecificCommands(const args:LongString);
 begin
  if Length(args)>0 then
  StdOut.Put:=Format('Could not recognize "%s"',[args]);
 end;
 //
 // Application specific initialization.
 //
 procedure SpecificInitialization;
 begin
  // 
  // Register user commands coming from StdIn.
  //
  SystemEchoProcedure:=StdOutEcho;
  StdIn.SpecHandler:=DoSpecificCommands;
  StdIn.AddCommand('@Help',            DoHelp);
  StdIn.AddCommand('@Exit',            DoExit);
  StdIn.AddCommand('@Errors',          DoErrors);
  StdIn.AddCommand('@Memory',          DoMemory);
  StdIn.AddCommand('@ProcessPriority', DoProcessPriority);
  StdIn.AddCommand('@ThreadPriority',  DoThreadPriority);
 end;
 //
 // Application specific finalization.
 //
 procedure SpecificFinalization;
 begin
 end;
 //
 // Application specific polling.
 //
 procedure SpecificPolling;
 begin
  if BecameZombie(FILE_TYPE_PIPE,1000) then StdIn.Put:='@Exit';
 end;
 //
 // Main program
 //
begin
 try
  try
   SpecificInitialization;
   while not Terminated do begin
    while StdIn.Count>0 do StdIn.Process(StdIn.Get);
    SpecificPolling;
    Sleep(1);
   end;
  finally
   SpecificFinalization;
  end;
 except
  on E:Exception do StdOut.Put:=E.Message;
 end;
 Sleep(100);
 if BecameZombie(FILE_TYPE_PIPE) then ExitProcess(1);
end.
