<?xml version="1.0" encoding="utf-8"?>
<CrossEngineApp Version="1">
  <Options>object ProjOption: TProjectOptions
  Title = 'DIM Monitor'
  AppName = 'DimMonitor'
  Language = 'PASCAL'
  AppIcon.Data = {
[encoded data, 24771 characters]
    000000000000000000000000000000000000
  }
  AppAutor = 'Copyright(c) 2022-2023 Alexey Kuryakin kouriakine@mail.ru'
  MinVMajor = 2
  MinVMinor = 1
  MinVRevision = 2
  ExternalPath = '$DIESELPASCAL_EXTERNAL;$DIESEL_LOCALSET_DIR/external;$DIESEL_EXE_DIR/external;'
  AutoCreateExternal.Strings = (
    'dpAntiZombie'
    'dpGuiResMain'
    'dpGuiResTools'
  )
end
</Options>
  <Metadata>
    <DimMonitor ImageIndex="2">
      <Object ClassName=""/>
      <Code>program DimMonitor;

uses dpCmdArgs,dpSystem,dpSysUtils,dpWindows,dpVbs,dpCrwDaqSys,dpDaqConfig,
     dpGuiResMain,dpGuiResTools,dpDimMonitor,Main;

begin
  InitGuiResMain;  // Init GUI Resources - Main
  InitGuiResTools; // Init GUI Resources - Tools
  SetCrwDaqChildTitle(GetScriptName+' --number '+IntToStr(DimMonitor.Number));
  if InstanceRunning(ValidateInstanceName(GetCrwDaqChildTitle),true) then begin
   AppActivateByClassTitle('Window',GetCrwDaqChildTitle);
   Application.Terminate;
   Exit;
  end;
  MainForm := TMainForm.Create(Application);
end.
</Code>
      <Child>
        <dpDimMonitor ImageIndex="2">
          <Object ClassName=""/>
          <Code>////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2022 Alexey Kuryakin kouriakine@mail.ru under MIT license.   //
////////////////////////////////////////////////////////////////////////////////

unit dpDimMonitor; // Diesel Pascal routines for DIM Monitor Utility.

interface

uses dpCmdArgs,dpSystem,dpSysUtils,dpWindows,dpVbs,dpCrwDaqSys,dpTask,
     dpGuiUtils,dpColors;

type // DIM Service related
 TDimJobItem = class(TObject)
 private
  myTag         : Integer;
  myOnline      : Boolean;
  myServKind    : String;
  myServName    : String;
  myServForm    : String;
  myMonType     : String;
  myMonTime     : Integer;
  myFillHex     : String;
  myTitle       : String;
  myJobLine     : String;
  myFormType    : array of Char;
  myFormLeng    : array of Integer;
  myFormOffs    : array of Integer;
  myDataItems   : array of Variant;
  myDataTypes   : array of Char;
  myLastDataHex : String;
  myRowIndex    : Integer;
 private
  function  GetTitle:String;
 public // Properties
  property  Tag         : Integer read myTag;
  property  Online      : Boolean read myOnline write myOnline;
  property  ServKind    : String  read myServKind;
  property  ServName    : String  read myServName;
  property  ServForm    : String  read myServForm;
  property  MonType     : String  read myMonType;
  property  MonTime     : Integer read myMonTime;
  property  FillHex     : String  read myFillHex;
  property  Title       : String  read GetTitle;
  property  JobLine     : String  read myJobLine;
  property  LastDataHex : String  read myLastDataHex;
  property  RowIndex    : Integer read myRowIndex write myRowIndex;
 public // Data Format parsing
  function  FormCount:Integer;
  function  FormType(i:Integer):Char;
  function  FormVarType(i:Integer):Integer;
  function  FormSize(i:Integer):Integer;
  function  FormLeng(i:Integer):Integer;
  function  FormOffs(i:Integer):Integer;
  function  AddForm(aType:Char; aLeng,aOffs:Integer):Integer;
  function  ParseFormat:Boolean;
  procedure ClearFormat;
 public // Data array
  procedure ClearData;
  function  DataItemsCount:Integer;
  function  DataItems(i:Integer):Variant;
  function  DataTypesCount:Integer;
  function  DataTypes(i:Integer):Char;
  function  AddDataItem(aDataItem:Variant; aDataType:Char):Integer;
  function  SetDataItem(i:Integer; aDataItem:Variant):Boolean;
 public // Data parsing
  function  DecodeDataHex(DataHex:String):Boolean;
  function  DecodeDataHexAsText(DataHex:String; UpdatePanel:Boolean):String;
 public // Data drawing
  function  DisplayData:Boolean;
  function  CellHint(aCol,aRow:Integer):String;
 public // Data clearning
  procedure ZeroVariables;
 public
  constructor Create(aTag:Integer; aLine:String);
  destructor  Destroy;
 end;

type // Monitor DIM Services
 TDimMonitor = class(TObject)
 private
  myNumber         : Integer;      // Monitor number -n or --number
  myGuiPid         : Integer;      // PID of DimMonitor GUI process
  myMonitorJob     : TStringList;  // Monitor job as kind,serv,frmt,mntr,tsec,fill
  myMonitorOut     : TStringList;  // Monitor exe output lines list
  myMonitorTid     : Integer;      // Monitor exe server - task id
  myDefExecTimeOut : Integer;      // Default Timeout    for Exec
  myDefExecBuffKb  : Integer;      // Default BuffSizeKb for Exec
  myBigExecTimeOut : Integer;      // Big     Timeout    for Exec
  myBigExecBuffKb  : Integer;      // Big     BuffSizeKb for Exec
  myDnsRunningAns  : String;       // Last IsDnsRunning Answer
  myTimeTicks      : Integer;      // Time tick counter
  myPollCount      : array[0..4] of Integer;
  myPollLast       : array[0..4] of Integer;
  myPollRate       : array[0..4] of Integer;
  myLineCount      : Integer;      // Count of income lines
  myDimPadding     : Integer;      // DIM Padding flag
  myDimTaskName    : String;       // DIM Task name
  myStringGrid     : TStringGrid;  // String grid for data display
  myPause          : Boolean;      // Pause updates
  myColorOnline    : TColor;       // Color for Online state
  myColorGridOn    : TColor;       // Color for Online StringGrid
  myColorOffline   : TColor;       // Color for Offline state
  myColorGridOff   : TColor;       // Color for Offline StringGrid
  myColorUndefined : TColor;       // Color for undefined state
  myDnsStatusColor : TColor;       // clGreen=Ok,clRed=Offline,clMaroon=Undefined
 private
  function  GetMonitorPid:Integer;
  function  GetDIM_DNS_NODE:String;
  procedure SetDIM_DNS_NODE(aNode:String);
 public
  property  Number         : Integer     read myNumber;
  property  GuiPid         : Integer     read myGuiPid;
  property  MonitorJob     : TStringList read myMonitorJob;
  property  MonitorOut     : TStringList read myMonitorOut;
  property  MonitorTid     : Integer     read myMonitorTid;
  property  MonitorPid     : Integer     read GetMonitorPid;
  property  Pause          : Boolean     read myPause write myPause;
  property  ColorOnline    : TColor      read myColorOnline write myColorOnline;
  property  ColorGridOn    : TColor      read myColorGridOn write myColorGridOn;
  property  ColorOffline   : TColor      read myColorOffline write myColorOffline;
  property  ColorGridOff   : TColor      read myColorGridOff write myColorGridOff;
  property  ColorUndefined : TColor      read myColorUndefined write myColorUndefined;
  property  DnsStatusColor : TColor      read myDnsStatusColor write myDnsStatusColor;
 public
  function  DimStatExe(Mode:Integer):String;  // dimStat or dimStat.exe
  function  MonitorExe(Mode:Integer):String;  // ~~\Resource\DaqSite\DimServer\DimSrv.exe
 public
  function  MonitorJobItems(i:Integer):TDimJobItem;
  property  DefExecTimeOut : Integer     read myDefExecTimeOut write myDefExecTimeOut;
  property  DefExecBuffKb  : Integer     read myDefExecBuffKb  write myDefExecBuffKb;
  property  BigExecTimeOut : Integer     read myBigExecTimeOut write myBigExecTimeOut;
  property  BigExecBuffKb  : Integer     read myBigExecBuffKb  write myBigExecBuffKb;
  property  DIM_DNS_NODE   : String      read GetDIM_DNS_NODE  write SetDIM_DNS_NODE;
  property  DnsRunningAns  : String      read myDnsRunningAns;
  property  TimeTicks      : Integer     read myTimeTicks;
  property  LineCount      : Integer     read myLineCount;
  property  DimPadding     : Integer     read myDimPadding;
  property  DimTaskName    : String      read myDimTaskName write myDimTaskName;
  property  StringGrid     : TStringGrid read myStringGrid  write myStringGrid;
 public
  function  PollRate(i:Integer):Integer;
  function  PollCount(i:Integer):Integer;
  procedure IncPollCount(i:Integer; n:Integer=1);
  procedure PollRateHandler;
  procedure StringGridReset;
  function  DrawJobItems(Mode:Integer):Integer;
  function  CellHint(aCol,aRow:Integer):String;
 public
  function  Exec(cmd:String; timeout:Integer=0; BuffSizeKb:Integer=0):String;
  function  IsDnsRunning(UseDimStat:Boolean=true):Boolean;
  function  ListDimServers(aList:TStrings=nil):String;
  function  ListDimServerServices(aServer:String; aList:TStrings=nil):String;
  procedure MonitorReader(inString:String);
  function  StartMonitoring:Boolean;
  procedure StopMonitoring;
  procedure PollMonitoring;
  procedure Reset;
  procedure MonitorJobClear;
  function  IsMonitoring:Boolean;
  function  IsMonitorRunning:Boolean;
  function  IndexToTag(index:Integer):Integer;
  function  TagToIndex(tag:Integer):Integer;
  function  IsValidTag(tag:Integer):Boolean;
  function  FindDimJob(serv:String):Integer;
  procedure ClearPollCounts;
  procedure HandleTimeTick;
 public
  function  DIM_Send(msg:string):Integer;
 public
  constructor Create;
  destructor  Destroy;
 public
  procedure Trouble(Msg:String);
  procedure Success(Msg:String);
 end;

function DimMonitor:TDimMonitor;

function DimTypeSize(c:Char):Integer; // Data size of type (c) = (C,D,F,I,L,S,X)
function DimVarType(c:Char):Integer;  // Variant type corresponded to DIM type

function GetOptDns(def:String):String;         // --dns h
function GetOptPadding(def:Integer):Integer;   // --pad --padding n
function GetOptNumber(def:Integer):Integer;    // --num --number n
function GetOptIniFile(Mode:Integer=1):String; // --ini --inifile f; 1+2=Ini+DefNum
function GetOptLanguage(def:Integer):Integer;  // --lng --language l (ru/en)

//////////////////////////////////// Exec params:
const MinExecBuffKb  = 1;         // Minimal Exec buffer, kB
const MaxExecBuffKb  = 1024*64;   // Maximal Exec buffer, kB
const DivExecBuffKb  = 256;       // Default Exec buffer init value, kB
const BivExecBuffKb  = 1024*16;   // Bigsize Exec buffer init value, kB
const MinExecTimeOut = 1000;      // Minimal Exec timeout, ms
const MaxExecTimeout = 1000*60*5; // Maximal Exec timeout, ms
const DivExecTimeout = 1000*7;    // Default Exec timeout init value, ms
const BivExecTimeout = 1000*15;   // Bigsize Exec timeout init value, ms

//////////////////////////////////// DIM services:
const dis_info      = 1;          // DIM information server
const dis_cmnd      = 2;          // DIM command     server
const dic_info      = 3;          // DIM information client
const dic_cmnd      = 4;          // DIM command     client
const DimDefDataHex = '00000000'; // DIM default data as HEX
const DimDefFillHex = 'FFFFFFFF'; // DIM default fill as HEX
const DimPollList   = 'timed,monitored'; ////////////////////// Polling type
const DimKindList   = 'dis_info,dis_cmnd,dic_info,dic_cmnd'; // Service kind

function DimScanSpaces:String;

implementation

var TheDimMonitor:TDimMonitor=nil;

function DimMonitor:TDimMonitor;
begin
 if (TheDimMonitor=nil) then TheDimMonitor:=TDimMonitor.Create;
 Result:=TheDimMonitor;
end;

 /////////////////////////
 // Miscellaneous routines
 /////////////////////////

var _DimScanSpaces_:String='';
function DimScanSpaces:String;
begin
 if (_DimScanSpaces_='') then _DimScanSpaces_:=',= '+vbTab+vbCRLF;
 Result:=_DimScanSpaces_;
end;

function DimTypeSize(c:Char):Integer;
begin
 case c of
  'C' : Result:=1;
  'D' : Result:=8;
  'F' : Result:=4;
  'I' : Result:=4;
  'L' : Result:=4;
  'S' : Result:=2;
  'X' : Result:=8;
  else  Result:=0;
 end;
end;

function DimVarType(c:Char):Integer;
begin
 case c of
  'C' : Result:=varString;
  'D' : Result:=varDouble;
  'F' : Result:=varSingle;
  'I' : Result:=varInteger;
  'L' : Result:=varInteger;
  'S' : Result:=varSmallInt;
  'X' : Result:=varInt64;
  else  Result:=0;
 end;
end;

function DimTypeName(c:Char):String;
begin
 case c of
  'C' : Result:='Char';
  'D' : Result:='Double';
  'F' : Result:='Float';
  'I' : Result:='Integer';
  'L' : Result:='Long';
  'S' : Result:='Short';
  'X' : Result:='eXtralong';
  else  Result:='Unknown';
 end;
end;

 /////////////////////////////
 // TDimJobItem implementation
 /////////////////////////////
constructor TDimJobItem.Create(aTag:Integer; aLine:String);
begin
 inherited Create;
 ZeroVariables;
 myTag:=aTag;
 myOnline:=false;
 myServKind:=ExtractWord(1,aLine,DimScanSpaces);
 myServName:=ExtractWord(2,aLine,DimScanSpaces);
 myServForm:=ExtractWord(3,aLine,DimScanSpaces);
 myMonType:=ExtractWord(4,aLine,DimScanSpaces);
 myMonTime:=StrToIntDef(ExtractWord(5,aLine,DimScanSpaces),0);
 myFillHex:=RecodeStr(ExtractWord(6,aLine,DimScanSpaces),'base64,hex');
 myTitle:=RecodeStr(ExtractWord(7,aLine,DimScanSpaces),'base64,rawbyte');
 myJobLine:=aLine;
 ClearData;
 ParseFormat;
end;

destructor  TDimJobItem.Destroy;
begin
 ClearData;
 ClearFormat;
 ZeroVariables;
 inherited Destroy;
end;

procedure TDimJobItem.ZeroVariables;
begin
 myTag:=0;
 myServKind:='';
 myServName:='';
 myServForm:='';
 myMonType:='';
 myMonTime:=0;
 myFillHex:='';
 myTitle:='';
 myJobLine:='';
 myLastDataHex:='';
 myRowIndex:=0;
end;

function TDimJobItem.GetTitle:String;
begin
 Result:=myTitle;
 if IsEmptyStr(Result) then Result:=ServName;
end;

function TDimJobItem.FormCount:Integer;
begin
 Result:=ArrayLength(myFormType);
end;

function  TDimJobItem.FormType(i:Integer):Char;
begin
 if (i&gt;=0) and (i&lt;ArrayLength(myFormType))
 then Result:=myFormType[i] else Result:='?';
end;

function  TDimJobItem.FormVarType(i:Integer):Integer;
begin
 Result:=DimVarType(FormType(i));
end;

function  TDimJobItem.FormSize(i:Integer):Integer;
begin
 Result:=DimTypeSize(FormType(i));
end;

function  TDimJobItem.FormLeng(i:Integer):Integer;
begin
 if (i&gt;=0) and (i&lt;ArrayLength(myFormLeng))
 then Result:=myFormLeng[i] else Result:=0;
end;

function  TDimJobItem.FormOffs(i:Integer):Integer;
begin
 if (i&gt;=0) and (i&lt;ArrayLength(myFormOffs))
 then Result:=myFormOffs[i] else Result:=0;
end;

function  TDimJobItem.AddForm(aType:Char; aSize,aOffs:Integer):Integer;
var n:Integer;
begin
 n:=ArrayLength(myFormType)+1;
 SetArrayLength(myFormType,n); myFormType[n-1]:=aType;
 SetArrayLength(myFormLeng,n); myFormLeng[n-1]:=aLeng;
 SetArrayLength(myFormOffs,n); myFormOffs[n-1]:=aOffs;
 Result:=n;
end;

procedure TDimJobItem.ClearFormat;
begin
 SetArrayLength(myFormType,0);
 SetArrayLength(myFormLeng,0);
 SetArrayLength(myFormOffs,0);
end;

procedure TDimJobItem.ClearData;
var i,n:Integer;
begin
 n:=ArrayLength(myDataItems);
 for i:=0 to n-1 do myDataItems[i]:=Unassigned;
 SetArrayLength(myDataItems,0);
 n:=ArrayLength(myDataTypes);
 for i:=0 to n-1 do myDataTypes[i]:=Unassigned;
 SetArrayLength(myDataTypes,0);
end;

function  TDimJobItem.DataItemsCount:Integer;
begin
 Result:=ArrayLength(myDataItems);
end;

function  TDimJobItem.DataItems(i:Integer):Variant;
begin
 if (i&gt;=0) and (i&lt;ArrayLength(myDataItems))
 then Result:=myDataItems[i] else Result:=Unassigned;
end;

function  TDimJobItem.SetDataItem(i:Integer; aDataItem:Variant):Boolean;
begin
 Result:=false;
 if (i&gt;=0) and (i&lt;ArrayLength(myDataItems))
 then begin myDataItems[i]:=aDataItem; Result:=true; end;
end;

function  TDimJobItem.DataTypesCount:Integer;
begin
 Result:=ArrayLength(myDataTypes);
end;

function  TDimJobItem.DataTypes(i:Integer):Char;
begin
 if (i&gt;=0) and (i&lt;ArrayLength(myDataTypes))
 then Result:=myDataTypes[i] else Result:='?';
end;

function  TDimJobItem.AddDataItem(aDataItem:Variant; aDataType:Char):Integer;
var n:Integer;
begin
 n:=ArrayLength(myDataTypes)+1;
 SetArrayLength(myDataTypes,n); myDataTypes[n-1]:=aDataType;
 n:=ArrayLength(myDataItems)+1;
 SetArrayLength(myDataItems,n); myDataItems[n-1]:=aDataItem;
 Result:=n;
end;

function TDimJobItem.ParseFormat:Boolean;
var List:TStringList; i,p,leng,offs,size:Integer; c:Char; line:String;
begin
 Result:=false;
 try
  ClearFormat;
  List:=TStringList.Create;
  try
   offs:=0;
   List.Text:=UpperCase(StringReplace(ServForm,';',EOL,rfReplaceAll));
   for i:=0 to List.Count-1 do begin
    line:=List.Strings[i]; c:=StrFetch(line,1); p:=Pos(':',line);
    if (p&gt;2) then RaiseException('Invalid format (pos): '+ServForm+'.');
    if (p&gt;0) then leng:=StrToIntDef(Copy(line,p+1,MaxInt),0) else leng:=0;
    if (p=0) and (leng=0) and (length(line)=1) and (i&lt;List.Count-1) then leng:=1;
    if (p&gt;0) and (leng=0) then RaiseException('Invalid format (leng): '+ServForm+'.');
    if (p=0) and (i&lt;List.Count-1) then RaiseException('Invalid format: '+ServForm+'.');
    size:=DimTypeSize(c);
    if (size=0) then RaiseException('Invalid format (size): '+ServForm+'.');
    AddForm(c,leng,offs); inc(offs,size*leng);
   end;
   Result:=true;
  finally
   List.Free;
  end;
 except
  on E:Exception do BugReport(E,Self,'ParseFormat');
 end;
 if not Result then ClearFormat;
end;

function TDimJobItem.DecodeDataHex(DataHex:String):Boolean;
var hex:String; i,j,k,p,n,l,t:Integer; c:Char; first:Boolean;
begin
 Result:=false;
 try
  if SameText(DataHex,FillHex) then Exit; // Disconnected.
  k:=0;
  myLastDataHex:=DataHex;
  first:=(ArrayLength(myDataItems)=0);
  for i:=0 to FormCount-1 do begin
   c:=FormType(i);
   t:=FormVarType(i);
   p:=FormOffs(i)*2+1;
   n:=FormSize(i)*2;
   l:=FormLeng(i);
   if (l=0) then begin
    l:=(Length(DataHex)-p+1) div n;
    if (c='C') then begin
     n:=n*l; l:=1;
    end;
   end;
   for j:=0 to l-1 do
   if (Length(DataHex)&gt;=p+n-1) then begin
    hex:=Copy(DataHex,p,n);
    if first
    then AddDataItem(HexToVar(hex,t),c)
    else SetDataItem(k,HexToVar(hex,t));
    inc(p,n);
    inc(k);
   end;
  end;
  Result:=(ArrayLength(myDataItems)&gt;0);
  if first and Result then DimMonitor.DrawJobItems(7);
 except
  on E:Exception do BugReport(E,Self,'DecodeDataHex');
 end;
end;

 // Replace comma to dot 3,14 -&gt; 3.14
procedure ValidateFloat(var s:String; vt:Integer);
begin
 if vt in [varSingle,varDouble] then
 if (Pos(',',s)&gt;0) then s:=StringReplace(s,',','.',0);
end;

function TDimJobItem.DecodeDataHexAsText(DataHex:String; UpdatePanel:Boolean):String;
var i:Integer; s:String; List:TStringList; Item:Variant;
begin
 Result:='';
 try
  List:=nil;
  if DecodeDataHex(DataHex) then
  try
   if (DataItemsCount&gt;2)
   then List:=TStringList.Create;
   for i:=0 to DataItemsCount-1 do begin
    Item:=DataItems(i); s:=VarToStr(Item);
    ValidateFloat(s,VarType(Item));
    if (List&lt;&gt;nil) then List.Add(s)
    else Result:=Result+EOL;
    Online:=true;
   end;
   if (List&lt;&gt;nil) then Result:=List.Text;
  finally
   if (List&lt;&gt;nil) then List.Free;
  end else if SameText(DataHex,FillHex) then Online:=false;
  if not Online then Result:='OFFLINE';
  if UpdatePanel then DisplayData;
 except
  on E:Exception do BugReport(E,Self,'DecodeDataHexAsText');
 end;
end;

function TDimJobItem.DisplayData:Boolean;
var i:Integer; Item:Variant; DataType:Char; s,StatusMsg:String;
begin
 Result:=false;
 if (RowIndex=0) then Exit;
 if DimMonitor.Pause then Exit;
 if (DataItemsCount=0) then Exit;
 if (DimMonitor.StringGrid=nil) then Exit;
 try
  if (DimMonitor.StringGrid.ColCount&lt;5)
  then DimMonitor.StringGrid.ColCount:=5;
  if (DimMonitor.StringGrid.RowCount&lt;RowIndex+DataItemsCount)
  then DimMonitor.StringGrid.RowCount:=RowIndex+DataItemsCount;
  if Online then StatusMsg:='ON' else StatusMsg:='OF';
  for i:=0 to DataItemsCount-1 do begin
   Item:=DataItems(i); DataType:=DataTypes(i);
   s:=VarToStr(Item); ValidateFloat(s,VarType(Item));
   DimMonitor.StringGrid.Cells[0,RowIndex+i]:=' '+Title+' ';
   DimMonitor.StringGrid.Cells[1,RowIndex+i]:=' '+StatusMsg+' ';
   DimMonitor.StringGrid.Cells[2,RowIndex+i]:=' '+IntToStr(i+1)+' ';
   DimMonitor.StringGrid.Cells[3,RowIndex+i]:=' '+DataType+' ';
   DimMonitor.StringGrid.Cells[4,RowIndex+i]:=' '+TrimRight(s);
  end;
  Result:=true;
 except
  on E:Exception do BugReport(E,Self,'DisplayData');
 end;
end;

function TDimJobItem.CellHint(aCol,aRow:Integer):String;
var i:Integer; Item:Variant; DataType:Char; s,StatusMsg:String;
begin
 Result:='';
 if (RowIndex=0) then Exit;
 if (DataItemsCount=0) then Exit;
 if (DimMonitor.StringGrid=nil) then Exit;
 if (aCol&lt;0) or (aCol&gt;DimMonitor.StringGrid.ColCount-1) then Exit;
 if (aRow&lt;0) or (aRow&gt;DimMonitor.StringGrid.RowCount-1) then Exit;
 if (aRow&lt;RowIndex) or (aRow&gt;RowIndex+DataItemsCount-1) then Exit;
 try
  for i:=0 to DataItemsCount-1 do
  if (aRow=RowIndex+i) then begin
   Item:=DataItems(i); DataType:=DataTypes(i);
   s:=VarToStr(Item); ValidateFloat(s,VarType(Item));
   if Online then StatusMsg:='ONLINE' else StatusMsg:='OFFLINE';
   case aCol of
    0: Result:=RusEng('Сервис : ','Service Name  : ')+ServName+EOL
              +RusEng('Имя    : ','Service Title : ')+Title;
    1: Result:=RusEng('Сервис : ','Service Name  : ')+ServName+EOL
              +RusEng('Статус : ','Service State : ')+StatusMsg;
    2: Result:=RusEng('Сервис : ','Service Name : ')+ServName+EOL
              +RusEng('Номер  : ','Item`s Index : ')+IntToStr(i+1);
    3: Result:=RusEng('Сервис : ','Service Name : ')+ServName+EOL
              +RusEng('Тип    : ','Items`s Type : ')+DimTypeName(DataType);
    4: Result:=RusEng('Сервис   : ','Service Name : ')+ServName+EOL
              +RusEng('Значение : ','Items`s Data : ')+TrimRight(s);
   end;
   Break;
  end;
 except
  on E:Exception do BugReport(E,Self,'CellHint');
 end;
end;

 /////////////////////////////
 // TDimMonitor implementation
 /////////////////////////////

function TDimMonitor.DimStatExe(Mode:Integer):String;
var exe:String;
begin
 Result:='';
 if IsUnix    then Result:='dimStat';
 if IsWindows then Result:='dimStat.exe';
 if (Result&lt;&gt;'') and (Mode&gt;0) then begin
  exe:=FileSearch(Result,GetEnv('PATH'),false);
  if not IsEmptyStr(exe) then Result:=Trim(exe);
  if IsWindows and (WordCount(Result,' ')&gt;1)
  then Result:=AnsiQuotedStr(Result,'"');
 end;
end;

function TDimMonitor.MonitorExe(Mode:Integer):String;
var exe,dir,list:String; i:Integer;
begin
 Result:='';
 if IsUnix    then Result:='dimsrv';
 if IsWindows then Result:='DimSrv.exe';
 if (Result&lt;&gt;'') and (Mode&gt;0) then begin
  if IsUnix then begin
   if RunCommand('unix which dimsrv',exe) then
   if not IsEmptyStr(exe) and FileExists(Trim(exe))
   then Result:=Trim(exe);
  end;
  if IsWindows then begin
   dir:=CRW_DAQ_SYS_HOME_DIR;
   list:=ExpEnv('%SystemDrive% C: D: E: F: G: H: I: J: K: L: M: N: O: P: Q:');
   for i:=1 to WordCount(list,' ') do begin
    if not IsEmptyStr(dir) and DirectoryExists(dir) then Break;
    dir:=ExtractWord(i,list,' ')+'\Crw32exe';
    if not DirectoryExists(dir) then dir:='';
   end;
   if not IsEmptyStr(dir) and DirectoryExists(dir) then
   Result:=dir+'\Resource\DaqSite\DimServer\DimSrv.exe';
  end;
  if IsWindows and (WordCount(Result,' ')&gt;1)
  then Result:=AnsiQuotedStr(Result,'"');
 end;
end;

function TDimMonitor.GetMonitorPid:Integer;
begin
 if (MonitorTid&lt;&gt;0)
 then Result:=task_pid(MonitorTid)
 else Result:=0;
end;

function TDimMonitor.GetDIM_DNS_NODE:String;
begin
 Result:=GetEnv('DIM_DNS_NODE');
end;

procedure TDimMonitor.SetDIM_DNS_NODE(aNode:String);
begin
 SetEnv('DIM_DNS_NODE',Trim(aNode));
end;

function TDimMonitor.MonitorJobItems(i:Integer):TDimJobItem;
begin
 if (i&gt;=0) and (i&lt;MonitorJob.Count)
 then Result:=TDimJobItem(MonitorJob.Objects[i])
 else Result:=nil;
end;

function GetOptDns(def:String=''):String;
begin
 Result:='';
 if (Result='') then Result:=CmdArgs.GetOptionValue('-dns');
 if (Result='') then Result:=CmdArgs.GetOptionValue('--dns');
 if (Result='') then Result:=def;
end;

function GetOptPadding(def:Integer):Integer;
var snum:String;
begin
 Result:=def; snum:='';
 if (snum='') then snum:=CmdArgs.GetOptionValue('-pad');
 if (snum='') then snum:=CmdArgs.GetOptionValue('--pad');
 if (snum='') then snum:=CmdArgs.GetOptionValue('-padding');
 if (snum='') then snum:=CmdArgs.GetOptionValue('--padding');
 if (snum&lt;&gt;'') then Result:=iMax(1,StrToIntDef(snum,def));
 Result:=Ord(Result&lt;&gt;0);
end;

function GetOptNumber(def:Integer):Integer;
var snum:String;
begin
 Result:=def; snum:='';
 if (snum='') then snum:=CmdArgs.GetOptionValue('-n');
 if (snum='') then snum:=CmdArgs.GetOptionValue('--n');
 if (snum='') then snum:=CmdArgs.GetOptionValue('-num');
 if (snum='') then snum:=CmdArgs.GetOptionValue('--num');
 if (snum='') then snum:=CmdArgs.GetOptionValue('-number');
 if (snum='') then snum:=CmdArgs.GetOptionValue('--number');
 if (snum&lt;&gt;'') then Result:=iMax(1,StrToIntDef(snum,def));
end;

function GetOptIniFile(Mode:Integer=1):String;
var DataDir:String; ini,def:Boolean;
begin
 Result:=''; DataDir:='';
 ini:=HasFlags(Mode,1); def:=HasFlags(Mode,2);
 DataDir:=GetAppDataDir(false,true);
 if IsEmptyStr(DataDir) then Exit;
 if not DirectoryExists(DataDir) then MakeDir(DataDir);
 if (Result='') then if ini then Result:=CmdArgs.GetOptionValue('-ini');
 if (Result='') then if ini then Result:=CmdArgs.GetOptionValue('--ini');
 if (Result='') then if ini then Result:=CmdArgs.GetOptionValue('-inifile');
 if (Result='') then if ini then Result:=CmdArgs.GetOptionValue('--inifile');
 if (Result='') then if def then Result:=GetScriptBaseName+'_'+IntToStr(DimMonitor.Number);
 if (Result&lt;&gt;'') and (ExtractFileExt(Result)='') then Result:=ReplaceFileExt(Result,'.ini');
 if (Result&lt;&gt;'') and (ExtractFileDir(Result)='') then Result:=AddPathDelim(DataDir)+Result;
end;

function GetOptLanguage(def:Integer):Integer;
var slng:String;
begin
 Result:=def; slng:='';
 if (slng='') then slng:=CmdArgs.GetOptionValue('-l');
 if (slng='') then slng:=CmdArgs.GetOptionValue('-lng');
 if (slng='') then slng:=CmdArgs.GetOptionValue('-lang');
 if (slng='') then slng:=CmdArgs.GetOptionValue('-language');
 if (slng='') then slng:=CmdArgs.GetOptionValue('--lng');
 if (slng='') then slng:=CmdArgs.GetOptionValue('--lang');
 if (slng='') then slng:=CmdArgs.GetOptionValue('--language');
 if (slng='') then Exit;
 if WordIndex(slng,'ru,rus,russian',', ')&gt;0 then Result:=lng_Russian;
 if WordIndex(slng,'en,eng,english',', ')&gt;0 then Result:=lng_English;
end;

constructor TDimMonitor.Create;
begin
 inherited Create;
 myGuiPid:=GetProcessId;
 myNumber:=GetOptNumber(1);
 myMonitorJob:=TStringList.Create;
 myMonitorOut:=TStringList.Create;
 myMonitorTid:=0;
 myDefExecBuffKb:=DivExecBuffKb;
 myDefExecTimeOut:=DivExecTimeOut;
 myBigExecBuffKb:=BivExecBuffKb;
 myBigExecTimeOut:=BivExecTimeOut;
 myDnsRunningAns:='';
 myTimeTicks:=0;
 myLineCount:=0;
 myPause:=false;
 myColorOnline:=clGreen;
 myColorGridOn:=clLime;
 myColorOffline:=clRed;
 myColorGridOff:=clRed;
 myColorUndefined:=clMaroon;
 myDnsStatusColor:=ColorUndefined;
 ClearPollCounts;
 myDimPadding:=GetOptPadding(0);
 myDimTaskName:=FormatVar('DimMonitor_%d',guiPID);
 myStringGrid:=nil;
 if (TheDimMonitor=nil) then TheDimMonitor:=Self;
end;

destructor TDimMonitor.Destroy;
begin
 if (TheDimMonitor=Self) then TheDimMonitor:=nil;
 StopMonitoring;
 myDnsRunningAns:='';
 myDimTaskName:='';
 myMonitorJob.Free;
 myMonitorOut.Free;
 inherited Destroy;
end;

procedure TDimMonitor.Reset;
begin
 try
  StopMonitoring;
  ClearPollCounts;
  StringGridReset;
  MonitorOut.Clear;
  myDnsRunningAns:='';
 except
  on E:Exception do BugReport(E,Self,'Reset');
 end;
end;

function TDimMonitor.IndexToTag(index:Integer):Integer;
begin
 Result:=index+1;
end;

function TDimMonitor.TagToIndex(tag:Integer):Integer;
begin
 Result:=tag-1;
end;

function TDimMonitor.IsValidTag(tag:Integer):Boolean;
begin
 Result:=(tag&gt;0) and (tag&lt;=MonitorJob.Count);
end;

function TDimMonitor.FindDimJob(serv:String):Integer;
var i:Integer;
begin
 Result:=-1;
 if (serv='') then Exit;
 for i:=0 to MonitorJob.Count-1 do
 if SameText(serv,ExtractWord(2,MonitorJob.Strings[i],DimScanSpaces)) then begin
  Result:=i;
  Exit;
 end;
end;

function TDimMonitor.PollRate(i:Integer):Integer;
begin
 if (i in [0..4]) then Result:=myPollRate[i] else Result:=0;
end;

function TDimMonitor.PollCount(i:Integer):Integer;
begin
 if (i in [0..4]) then Result:=myPollCount[i] else Result:=0;
end;

procedure TDimMonitor.IncPollCount(i:Integer; n:Integer=1);
begin
 if (i in [0..4]) then myPollCount[i]:=myPollCount[i]+n;
end;

procedure TDimMonitor.PollRateHandler;
var i:Integer;
begin
 for i:=0 to 4 do begin
  myPollRate[i]:=myPollCount[i]-myPollLast[i];
  myPollLast[i]:=myPollCount[i];
 end;
end;

procedure TDimMonitor.ClearPollCounts;
var i:Integer;
begin
 for i:=0 to 4 do myPollRate[i]:=0;
 for i:=0 to 4 do myPollLast[i]:=0;
 for i:=0 to 4 do myPollCount[i]:=0;
end;

function TDimMonitor.DIM_Send(msg:string):Integer;
begin
 Result:=0;
 if (MonitorTid&lt;&gt;0) then
 if (Length(msg)&gt;0) then begin
  Result:=task_send(MonitorTid,msg+EOL);
  if (Result=0) then Trouble('Error sending '+msg);
 end;
end;

procedure TDimMonitor.StringGridReset;
var row,col:Integer;
begin
 if (DimMonitor.StringGrid=nil) then Exit;
 try
  StringGrid.Font.Size:=14;
  StringGrid.RowCount:=2;
  StringGrid.ColCount:=5;
  StringGrid.FixedRows:=1;
  StringGrid.FixedCols:=4;
  for row:=0 to StringGrid.RowCount-1 do
  for col:=0 to StringGrid.ColCount-1 do StringGrid.Cells[col,row]:='';
  DrawJobItems(255);
 except
  on E:Exception do BugReport(E,Self,'StringGridReset');
 end;
end;

procedure TDimMonitor.DrawJobItems(Mode:Integer):Integer;
var Job:TDimJobItem; i,n:Integer;
begin
 Result:=1;
 if (StringGrid=nil) then Exit;
 try
  for i:=0 to MonitorJob.Count-1 do begin
   Job:=TDimJobItem(MonitorJob.Objects[i]);
   if (Job=nil) then continue;
   if HasFlags(Mode,1) then Job.RowIndex:=0;
   n:=Job.DataItemsCount; if (n=0) then continue;
   if HasFlags(Mode,1) then Job.RowIndex:=Result;
   if HasFlags(Mode,2) then Job.DisplayData;
   Result:=Result+n;
  end;
  if HasFlags(Mode,8) then begin
   SetDefaultFontName(StringGrid.Font);
   StringGrid.Font.Style:=[fsBold];
   StringGrid.Color:=clBtnFace;
 //StringGrid.Color:=StringToColor('btnface');
 //StringGrid.Color:=StringToColor('_3dface');
 //StringGrid.Color:=StringToColor('lavenderblush');
   StringGrid.FixedColor:=StringToColor('lavender');
   StringGrid.TitleFont.Assign(StringGrid.Font);
   StringGrid.TitleFont.Size:=(StringGrid.Font.Size*120) div 100;
   StringGrid.TitleFont.Color:=clBlue;
  end;
  if HasFlags(Mode,4) then begin
   StringGrid.AutoSizeColumn(0);
   StringGrid.AutoSizeColumn(1);
   StringGrid.AutoSizeColumn(2);
   StringGrid.AutoSizeColumn(3);
  end;
  if HasFlags(Mode,8) then begin
   StringGrid.Cells[0,0]:=RusEng(' Сервис ',' Service ');
   StringGrid.Cells[1,0]:=RusEng(' СТ ',' ST ');
   StringGrid.Cells[2,0]:=RusEng(' № ',' N ');
   StringGrid.Cells[3,0]:=RusEng(' Т ',' T ');
   StringGrid.Cells[4,0]:=RusEng('Значения Данных',' Data Value ');
  end;
 except
  on E:Exception do BugReport(E,Self,'CalcRowIndexes');
 end;
end;

function TDimMonitor.CellHint(aCol,aRow:Integer):String;
var Job:TDimJobItem; i:Integer;
begin
 Result:='';
 if (StringGrid=nil) then Exit;
 Result:=StringGrid.Hint;
 if (aCol&lt;0) or (aCol&gt;StringGrid.ColCount-1) then Exit;
 if (aRow&lt;0) or (aRow&gt;StringGrid.RowCount-1) then Exit;
 try
  if (aRow=0) then begin
   case aCol of
    0: Result:=RusEng('Имя Сервиса или его Заголовок (отображаемое имя).',
                      'Service Name or User`s defined Title (Display Name).');
    1: Result:=RusEng('Статус подключения Сервиса - ONLINE/OFFLINE.',
                      'Service connection State - ONLINE/OFFLINE.');
    2: Result:=RusEng('Имена полей данных Сервисов.',
                      'Service Item`s Index.');
    3: Result:=RusEng('Типы полей данных сервисов.',
                      'Service Item`s Data Type.');
    4: Result:=RusEng('Значения полей данных сервисов.',
                      'Service Item`s Data Value.');
   end;
   Exit;
  end;
  for i:=0 to MonitorJob.Count-1 do begin
   Job:=TDimJobItem(MonitorJob.Objects[i]);
   if (Job=nil) then continue;
   if (aRow&lt;Job.RowIndex) then continue;
   if (aRow&gt;Job.RowIndex+Job.DataItemsCount-1) then continue;
   Result:=Job.CellHint(aCol,aRow);
   Break;
  end;
 except
  on E:Exception do BugReport(E,Self,'CellHint');
 end;
end;

function TDimMonitor.StartMonitoring:Boolean;
var tid,tag,i:Integer; cmd,line:String;
begin
 Result:=false;
 try
  StopMonitoring;
  cmd:=MonitorExe(1);
  tid:=task_init(cmd); myMonitorTid:=tid;
  task_ctrl(tid,'StdOutPipeSize='+IntToStr(1024*DefExecBuffKb));
  task_ctrl(tid,'StdInPipeSize='+IntToStr(1024*DefExecBuffKb));
  task_ctrl(tid,'HomeDir='+GetEnv('Temp'));
  task_ctrl(tid,'Display=SW_HIDE');
  if task_run(tid) then begin
   Success(FormatVar('Run[%d]: ',task_pid(tid))+cmd+EOL+'DIM monitor started.');
   DIM_Send('@padding='+IntToStr(DimPadding));
   DIM_Send('@dnsnode='+DIM_DNS_NODE);
   DIM_Send('@priority=0,0,0,0');
   DIM_Send('@dns.exe');
   for i:=0 to MonitorJob.Count-1 do begin
    tag:=IndexToTag(i); line:=FormatVar('+%d=',tag)+MonitorJob.Strings[i];
    MonitorJob.Objects[i]:=TDimJobItem.Create(tag,MonitorJob.Strings[i]);
    DIM_Send(line);
   end;
   DIM_Send('@start='+DimTaskName);
   Result:=true;
  end else begin
   Trouble('Could not run: '+cmd+EOL+'DIM Monitor failed.');
   StopMonitoring;
  end;
 except
  on E:Exception do BugReport(E,Self,'StartMonitoring');
 end;
end;

procedure TDimMonitor.MonitorJobClear;
var i:Integer; obj:TObject;
begin
 for i:=0 to MonitorJob.Count-1 do begin
  obj:=MonitorJob.Objects[i];
  MonitorJob.Objects[i]:=nil;
  if (obj&lt;&gt;nil) then obj.Free;
 end;
 MonitorJob.Clear;
end;

procedure TDimMonitor.StopMonitoring;
var tid,pid,cod:Integer;
begin
 tid:=myMonitorTid;
 myMonitorTid:=0;
 myTimeTicks:=0;
 myLineCount:=0;
 if (tid&lt;&gt;0) then
 try
  MonitorJobClear;
  DIM_Send('@stop');
  DIM_Send('@exit');
  if task_wait(tid,1000) then task_kill(tid,1,0,1000);
  if task_wait(tid,0) then task_kill(tid,0,0,0);
  cod:=task_result(tid);
  pid:=task_pid(tid);
  task_free(tid);
  Success(FormatVar('Stop[%d]',pid)+FormatVar(' with code %d',cod)+EOL+'DIM Monitor stopped.');
 except
  on E:Exception do BugReport(E,Self,'StopMonitoring');
 end;
end;

procedure TDimMonitor.PollMonitoring;
var tid,i:Integer; lines:String;
begin
 tid:=myMonitorTid;
 if (tid&lt;&gt;0) then
 try
  if task_wait(tid,0) then begin
   if task_rxcount(tid)&gt;0 then begin
    lines:=task_recv(tid,MaxInt);
    if (Length(lines)&gt;0) then StringsAppendFromText(MonitorOut,lines);
    for i:=0 to MonitorOut.Count-1 do MonitorReader(MonitorOut.Strings[i]);
   end;
  end;
 except
  on E:Exception do BugReport(E,Self,'PollMonitoring');
 end;
end;

procedure TDimMonitor.MonitorReader(inString:String);
var c1:Char; peq,tag,index:Integer; b64,hex,sv:String; Item:TDimJobItem;
begin
 if (Length(inString)&gt;0) then
 try
  myLineCount:=myLineCount+1;
  c1:=inString[1];
  case c1 of
   '#': begin
    peq:=Pos('=',inString);
    if (peq&gt;0) then begin
     tag:=StrToIntDef(Copy(inString,2,peq-2),0);
     index:=TagToIndex(tag);
     if IsValidTag(tag) then begin
      b64:=Copy(inString,peq+1,MaxInt);
      hex:=RecodeStr(b64,'Base64,Hex');
      Item:=TDimJobItem(MonitorJob.Objects[index]);
      if (Item&lt;&gt;nil) then begin
       sv:=Item.DecodeDataHexAsText(hex,true);
       //LogEvents(now,sv);
      end;
      //LogEvents(now,FormatVar('#%d=',tag)+hex);
      IncPollCount(0);
     end;
    end;
   end;
   '+': begin
    peq:=Pos('=',inString);
    if (peq&gt;0) then begin
     tag:=StrToIntDef(Copy(inString,2,peq-2),0);
     index:=TagToIndex(tag);
     if IsValidTag(tag) then begin
     end;
    end;
    LogEvents(Now,inString);
   end;
   else begin
    LogEvents(Now,inString);
   end;
  end;
 except
  on E:Exception do BugReport(E,Self,'MonitorReader');
 end;
end;

function TDimMonitor.Exec(cmd:String; timeout:Integer=0; BuffSizeKb:Integer=0):String;
var tid:Integer;
begin
 Result:='';
 try
  cmd:=Trim(cmd);
  if (Length(cmd)=0) then Exit;
  if (timeout&lt;MinExecTimeOut) then timeout:=DefExecTimeOut;
  if (timeout&gt;MaxExecTimeOut) then timeout:=BigExecTimeOut;
  if (BuffSizeKb&lt;MinExecBuffKb) then BuffSizeKb:=DefExecBuffKb;
  if (BuffSizeKb&gt;MaxExecBuffKb) then BuffSizeKb:=BigExecBuffKb;
  tid:=task_init(cmd);
  task_ctrl(tid,'Display=SW_HIDE');
  task_ctrl(tid,'StdInPipeSize='+IntToStr(1024*BuffSizeKb));
  task_ctrl(tid,'StdOutPipeSize='+IntToStr(1024*BuffSizeKb));
  if IsWindows then task_ctrl(tid,'CodePage='+IntToStr(WinApi.GetACP));
  if task_run(tid) then begin
   task_wait(tid,timeout);
   Result:=task_recv(tid,MaxInt);
   if task_wait(tid,0) then task_kill(tid,1,0,500);
   if task_wait(tid,0) then task_kill(tid,0,0,0);
   Success(FormatVar('Exec[%d]: ',task_pid(tid))+cmd);
  end else begin
   Trouble('Could not Exec: '+cmd);
  end;
  task_free(tid);
 except
  on E:Exception do BugReport(E,Self,'Exec');
 end;
end;

function TDimMonitor.IsDnsRunning(UseDimStat:Boolean=true):Boolean;
begin
 if UseDimStat then begin
  myDnsRunningAns:=Exec(FormatVar(DimStatExe(1)+' --dns %s --running',DIM_DNS_NODE));
  Result:=SameText(ExtractWord(1,DnsRunningAns,' '+vbTab),'RUNNING');
 end else begin
  myDnsRunningAns:=Exec('dnsRunning.exe');
  Result:=SameText(ExtractWord(1,DnsRunningAns,' '+vbTab),'YES');
 end;
end;

function TDimMonitor.ListDimServers(aList:TStrings=nil):String;
var i,n:Integer; Lines,Items:TStringList; s:String;
begin
 Result:='';
 try
  Lines:=TStringList.Create;
  Items:=TStringList.Create;
  try
   Lines.Text:=Exec(FormatVar(DimStatExe(1)+' --dns %s --servers',DIM_DNS_NODE));
   if (aList&lt;&gt;nil) then Items.Text:=aList.Text;
   for i:=0 to Lines.Count-1 do
   if SameText(ExtractWord(1,Lines.Strings[i],' '+vbTab),'Server') then
   if TryStrToInt(ExtractWord(2,Lines.Strings[i],' '+vbTab),n) then begin
    s:=ExtractWord(3,Lines.Strings[i],' '+vbCrLf+vbTab);
    if (s&lt;&gt;'') and (Items.IndexOf(s)&lt;0) then Items.Add(s);
   end;
   Result:=Items.Text;
   if (aList&lt;&gt;nil) then aList.Text:=Items.Text;
  finally
   Lines.Free;
   Items.Free;
  end;
 except
  on E:Exception do BugReport(E,Self,'ListDimServers');
 end;
end;

function TDimMonitor.ListDimServerServices(aServer:String; aList:TStrings=nil):String;
var i,n:Integer; Lines,Items:TStringList; s:String;
begin
 Result:='';
 aServer:=Trim(aServer);
 if (aServer&lt;&gt;'') then
 try
  Lines:=TStringList.Create;
  Items:=TStringList.Create;
  try
   Lines.Text:=Exec(FormatVar(DimStatExe(1)+' --dns %s --serverservices ',DIM_DNS_NODE)+aServer,BigExecTimeOut,BigExecBuffKb);
   if (aList&lt;&gt;nil) then Items.Text:=aList.Text;
   for i:=0 to Lines.Count-1 do
   if SameText(ExtractWord(1,Lines.Strings[i],' '+vbTab),'Service') then
   if TryStrToInt(ExtractWord(2,Lines.Strings[i],' '+vbTab),n) then begin
    s:=SkipWords(2,Lines.Strings[i],' '+vbCrLf+vbTab);
    if (s&lt;&gt;'') and (Items.IndexOf(s)&lt;0) then Items.Add(s);
   end;
   Result:=Items.Text;
   if (aList&lt;&gt;nil) then aList.Text:=Items.Text;
  finally
   Lines.Free;
   Items.Free;
  end;
 except
  on E:Exception do BugReport(E,Self,'ListDimServerServices');
 end;
end;

procedure TDimMonitor.Trouble(Msg:String);
begin
 LogEvents(Now,Msg);
end;

procedure TDimMonitor.Success(Msg:String);
begin
 LogEvents(Now,Msg);
end;

function TDimMonitor.IsMonitoring:Boolean;
begin
 Result:=(MonitorTid&lt;&gt;0);
end;

function TDimMonitor.IsMonitorRunning:Boolean;
begin
 Result:=(MonitorTid&lt;&gt;0) and task_wait(MonitorTid,0);
end;

procedure TDimMonitor.HandleTimeTick;
begin
 myTimeTicks:=myTimeTicks+1;
end;

end.
</Code>
        </dpDimMonitor>
        <Main ImageIndex="1">
          <Object ClassName="TMainForm">object MainForm: TForm
  Left = 352
  Height = 560
  Top = 135
  Width = 810
  BorderWidth = 4
  Caption = 'MainForm'
  ClientHeight = 560
  ClientWidth = 810
  Constraints.MinHeight = 560
  Constraints.MinWidth = 810
  Font.CharSet = RUSSIAN_CHARSET
  Font.Color = clBlack
  Font.Height = -13
  Font.Name = 'PT Mono'
  Font.Pitch = fpFixed
  Font.Quality = fqDraft
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  ShowHint = True
  LCLVersion = '2.2.6.0'
  object PanelMain: TPanel
    Left = 4
    Height = 552
    Top = 4
    Width = 802
    Align = alClient
    BorderWidth = 4
    ClientHeight = 552
    ClientWidth = 802
    TabOrder = 0
    object PageControlMain: TPageControl
      Left = 5
      Height = 542
      Top = 5
      Width = 792
      ActivePage = TabSheetDimJob
      Align = alClient
      Images = DataModuleGuiResMain.ImageListMain32x32
      TabIndex = 1
      TabOrder = 0
      object TabSheetDimDns: TTabSheet
        Caption = ' Connect  '
        ClientHeight = 498
        ClientWidth = 782
        ImageIndex = 228
        object PanelDimDns: TPanel
          Left = 0
          Height = 82
          Top = 0
          Width = 782
          Align = alTop
          BorderWidth = 4
          ClientHeight = 82
          ClientWidth = 782
          TabOrder = 0
          object GroupBoxDimDnsNode: TGroupBox
            Left = 5
            Height = 72
            Hint = 'DIM DNS NODE to be connected.'
            Top = 5
            Width = 324
            Align = alLeft
            Caption = ' DIM_DNS_NODE for connection: '
            ClientHeight = 56
            ClientWidth = 322
            TabOrder = 0
            object ComboBoxDimDnsNode: TComboBox
              Left = 8
              Height = 27
              Hint = 'Set DIM_DNS_NODE - DIM Name Server node.'
              Top = 4
              Width = 305
              ItemHeight = 0
              Items.Strings = (
                'localhost'
                '127.0.0.1'
              )
              TabOrder = 0
            end
            object LabelDimDnsStatusTitle: TLabel
              Left = 13
              Height = 15
              Hint = 'DIM DNS connection status.'
              Top = 32
              Width = 56
              Caption = 'Status:'
              ParentColor = False
            end
            object LabelDimDnsStatusValue: TLabel
              Left = 85
              Height = 15
              Hint = 'DIM DNS connection status.'
              Top = 32
              Width = 72
              Caption = 'UNDEFINED'
              ParentColor = False
            end
          end
          object GroupBoxDimMonitorControl: TGroupBox
            Left = 329
            Height = 72
            Top = 5
            Width = 448
            Align = alClient
            Caption = ' DIM Monitor Control: '
            ClientHeight = 56
            ClientWidth = 446
            TabOrder = 1
            object BitBtnStartDimMonitor: TBitBtn
              Left = 157
              Height = 46
              Top = 0
              Width = 163
              Action = ActionDimJobStartMonitor
              Images = DataModuleGuiResMain.ImageListMain32x32
              ImageIndex = 114
              TabOrder = 1
            end
            object BitBtnDimDnsRefresh: TBitBtn
              Left = 8
              Height = 46
              Top = 0
              Width = 143
              Action = ActionDimDnsRefresh
              Images = DataModuleGuiResMain.ImageListMain32x32
              ImageIndex = 27
              TabOrder = 0
            end
            object BitBtnDimAbout: TBitBtn
              Left = 324
              Height = 46
              Top = 0
              Width = 115
              Action = ActionDimAbout
              Images = DataModuleGuiResMain.ImageListMain32x32
              ImageIndex = 124
              TabOrder = 2
            end
          end
        end
        object PanelDimBrowser: TPanel
          Left = 0
          Height = 416
          Top = 82
          Width = 782
          Align = alClient
          ClientHeight = 416
          ClientWidth = 782
          TabOrder = 1
          object GroupBoxDimServers: TGroupBox
            Left = 1
            Height = 414
            Hint = 'List of DIM Servers available.'
            Top = 1
            Width = 185
            Align = alLeft
            Caption = ' DIM Servers: '
            ClientHeight = 398
            ClientWidth = 183
            TabOrder = 0
            object ListBoxDimServers: TListBox
              Left = 0
              Height = 398
              Top = 0
              Width = 183
              Align = alClient
              ItemHeight = 0
              OnClick = ListBoxDimServersClick
              TabOrder = 0
              TopIndex = -1
            end
          end
          object GroupBoxDimServerServices: TGroupBox
            Left = 186
            Height = 414
            Hint = 'List of DIM Services for selected DIM Server.'
            Top = 1
            Width = 361
            Align = alClient
            Caption = ' DIM Server Services: '
            ClientHeight = 398
            ClientWidth = 359
            TabOrder = 1
            object ListBoxDimServerServices: TListBox
              Left = 0
              Height = 398
              Top = 0
              Width = 359
              Align = alClient
              ItemHeight = 0
              MultiSelect = True
              TabOrder = 0
              TopIndex = -1
            end
          end
          object PanelDimDnsButtons: TPanel
            Left = 547
            Height = 414
            Top = 1
            Width = 234
            Align = alRight
            BorderWidth = 4
            ClientHeight = 414
            ClientWidth = 234
            TabOrder = 2
            object ImageDimLogoBig: TImage
              Cursor = crHandPoint
              Left = 8
              Height = 144
              Hint = 'DIM site index (local copy).'
              Top = 260
              Width = 216
              OnClick = ImageDimLogoBigClick
              Picture.Data = {
[encoded data, 8748 characters]
                91B80617FAA1289AA2B4970000
              }
              Proportional = True
            end
            object BitBtnDimServiceSelect: TBitBtn
              Left = 8
              Height = 54
              Hint = 'Copy Selected Services(s) to DIM Job to be monitored.'
              Top = 141
              Width = 219
              Anchors = [akTop, akLeft, akRight]
              Caption = 'Select Service(s)'
              Images = DataModuleGuiResMain.ImageListMain32x32
              ImageIndex = 62
              OnClick = BitBtnDimServiceSelectClick
              TabOrder = 0
            end
            object GroupBoxDimSelParams: TGroupBox
              Left = 5
              Height = 129
              Top = 5
              Width = 224
              Align = alTop
              Caption = ' Parameters: '
              ClientHeight = 113
              ClientWidth = 222
              TabOrder = 1
              object SpinEditDimSelPeriod: TSpinEdit
                Left = 8
                Height = 25
                Hint = 'Period (sec) of polling.'
                Top = 28
                Width = 74
                MaxValue = 300
                OnChange = SpinEditDimSelPeriodChange
                TabOrder = 1
                Value = 1
              end
              object LabelDimSelPeriod: TLabel
                Left = 88
                Height = 15
                Hint = 'Period (sec) of polling in case of timed monitoring.'
                Top = 32
                Width = 96
                Caption = 'sec - Period'
                ParentColor = False
              end
              object LabelDimSelFillHex: TLabel
                Left = 8
                Height = 15
                Hint = 'Data Fill (as HEX) in case of NO LINK event occured.'
                Top = 60
                Width = 184
                Caption = 'Fill (HEX) on "NO LINK"'
                ParentColor = False
              end
              object ComboBoxDimSelFillHex: TComboBox
                Left = 8
                Height = 27
                Hint = 'Data Fill (as HEX) in case of NO LINK event occured.'
                Top = 80
                Width = 206
                Anchors = [akTop, akLeft, akRight]
                ItemHeight = 0
                ItemIndex = 1
                Items.Strings = (
                  '00000000'
                  'FFFFFFFF'
                  'DEADDEAD'
                )
                TabOrder = 2
                Text = 'FFFFFFFF'
              end
              object LabelDimSelMonitoring: TLabel
                Left = 4
                Height = 15
                Hint = 'DIM Monitoring Type.'
                Top = 4
                Width = 88
                Caption = 'Monitoring:'
                ParentColor = False
              end
              object ComboBoxDimSelMonitoring: TComboBox
                Left = 100
                Height = 27
                Hint = 'DIM Monitoring Type.'
                Top = 0
                Width = 116
                ItemHeight = 0
                ItemIndex = 0
                Items.Strings = (
                  'timed'
                  'monitored'
                )
                OnChange = ComboBoxDimSelMonitoringTypeChange
                Style = csDropDownList
                TabOrder = 0
                Text = 'timed'
              end
            end
            object BitBtnDimServiceSelectAndGoToJob: TBitBtn
              Left = 8
              Height = 54
              Hint = 'Copy Selected Services(s) to DIM Job to be monitored, then Go To DIM Job Page.'
              Top = 200
              Width = 219
              Caption = 'Select &amp;&amp; GoTo Job'
              Layout = blGlyphRight
              Images = DataModuleGuiResMain.ImageListMain32x32
              ImageIndex = 60
              OnClick = BitBtnDimServiceSelectAndGoToJobClick
              TabOrder = 2
            end
            object ImageCernLogo: TImage
              Cursor = crHandPoint
              Left = 120
              Height = 48
              Hint = 'CERN home site - https://cern.ch'
              Top = 264
              Width = 48
              OnClick = ImageCernLogoClick
              Picture.Data = {
[encoded data, 11421 characters]
                2204FE1B119B516ED068F0880000000049454E44AE426082
              }
              Stretch = True
            end
            object ImageDimLogo: TImage
              Cursor = crHandPoint
              Left = 172
              Height = 48
              Hint = 'DIM home site - https://dim.web.cern.ch'
              Top = 264
              Width = 48
              OnClick = ImageDimLogoClick
              Picture.Data = {
[encoded data, 18711 characters]
                000000000000020200000000000002020000000000000202
              }
              Stretch = True
            end
          end
        end
      end
      object TabSheetDimJob: TTabSheet
        Caption = ' Job '
        ClientHeight = 498
        ClientWidth = 782
        ImageIndex = 0
        object PanelDimJob: TPanel
          Left = 0
          Height = 498
          Top = 0
          Width = 782
          Align = alClient
          ClientHeight = 498
          ClientWidth = 782
          TabOrder = 0
          object GroupBoxDimJob: TGroupBox
            Left = 1
            Height = 496
            Top = 1
            Width = 546
            Align = alClient
            Caption = ' DIM Job - Services to be monitored'
            ClientHeight = 480
            ClientWidth = 544
            TabOrder = 0
            object ListBoxDimJob: TListBox
              Left = 0
              Height = 480
              Top = 0
              Width = 544
              Align = alClient
              ItemHeight = 0
              OnClick = ListBoxDimJobClick
              TabOrder = 0
              TopIndex = -1
            end
          end
          object PanelDimJobButtons: TPanel
            Left = 547
            Height = 496
            Top = 1
            Width = 234
            Align = alRight
            BorderWidth = 4
            ClientHeight = 496
            ClientWidth = 234
            TabOrder = 1
            object GroupBoxDimJobParams: TGroupBox
              Left = 5
              Height = 281
              Top = 5
              Width = 224
              Align = alTop
              Caption = ' Parameters: '
              ClientHeight = 265
              ClientWidth = 222
              TabOrder = 0
              object SpinEditDimJobPeriod: TSpinEdit
                Left = 8
                Height = 25
                Hint = 'DIM Job - Period (sec) of polling.'
                Top = 140
                Width = 74
                MaxValue = 300
                OnChange = SpinEditDimJobPeriodChange
                TabOrder = 2
                Value = 1
              end
              object LabelDimJobPeriod: TLabel
                Left = 88
                Height = 15
                Hint = 'Period (sec) of polling in case of timed monitoring.'
                Top = 144
                Width = 96
                Caption = 'sec - Period'
                ParentColor = False
              end
              object LabelDimJobFillHex: TLabel
                Left = 8
                Height = 15
                Hint = 'Data Fill (as HEX) in case of NO LINK event occured.'
                Top = 172
                Width = 184
                Caption = 'Fill (HEX) on "NO LINK"'
                ParentColor = False
              end
              object ComboBoxDimJobFillHex: TComboBox
                Left = 8
                Height = 27
                Hint = 'Data Fill (as HEX) in case of NO LINK event occured.'
                Top = 188
                Width = 206
                Anchors = [akTop, akLeft, akRight]
                ItemHeight = 0
                ItemIndex = 1
                Items.Strings = (
                  '00000000'
                  'FFFFFFFF'
                  'DEADDEAD'
                )
                TabOrder = 3
                Text = 'FFFFFFFF'
              end
              object GroupBoxDimJobKind: TGroupBox
                Left = 0
                Height = 105
                Top = 0
                Width = 222
                Align = alTop
                Caption = 'Service Type,Name,Format: '
                ClientHeight = 89
                ClientWidth = 220
                TabOrder = 0
                object ComboBoxDimJobKind: TComboBox
                  Left = 4
                  Height = 27
                  Hint = 'DIM Job - Service Type.'
                  Top = 0
                  Width = 212
                  Anchors = [akTop, akLeft, akRight]
                  ItemHeight = 0
                  ItemIndex = 0
                  Items.Strings = (
                    'dis_info'
                    'dis_cmnd'
                    'dic_info'
                    'dic_cmnd'
                  )
                  Style = csDropDownList
                  TabOrder = 0
                  Text = 'dis_info'
                end
                object EditDimJobService: TEdit
                  Left = 4
                  Height = 27
                  Hint = 'DIM Job - Service Name.'
                  Top = 28
                  Width = 212
                  Anchors = [akTop, akLeft, akRight]
                  TabOrder = 1
                end
                object EditDimJobFormat: TEdit
                  Left = 4
                  Height = 27
                  Hint = 'DIM Job - Service Format.'
                  Top = 56
                  Width = 208
                  TabOrder = 2
                end
              end
              object LabelDimJobMonitoring: TLabel
                Left = 4
                Height = 15
                Hint = 'DIM Job - Monitoring Type.'
                Top = 116
                Width = 88
                Caption = 'Monitoring:'
                ParentColor = False
                OnClick = LabelDimJobMonitoringClick
              end
              object ComboBoxDimJobMonitoringType: TComboBox
                Left = 100
                Height = 27
                Hint = 'DIM Job - Monitoring Type.'
                Top = 112
                Width = 116
                ItemHeight = 0
                ItemIndex = 0
                Items.Strings = (
                  'timed'
                  'monitored'
                )
                OnChange = ComboBoxDimJobMonitoringTypeChange
                Style = csDropDownList
                TabOrder = 1
                Text = 'timed'
              end
              object LabelDimJobTitle: TLabel
                Left = 8
                Height = 15
                Top = 216
                Width = 160
                Caption = 'Title (display name)'
                ParentColor = False
              end
              object EditDimJobTitle: TEdit
                Left = 8
                Height = 27
                Hint = 'DIM Job - Title, i.e. name to display.'
                Top = 232
                Width = 204
                TabOrder = 4
              end
            end
            object GroupBoxDimJobControl: TGroupBox
              Left = 5
              Height = 193
              Top = 286
              Width = 224
              Align = alTop
              Caption = ' DIM Job Control: '
              ClientHeight = 177
              ClientWidth = 222
              TabOrder = 1
              object BitBtnDimJobClear: TBitBtn
                Left = 108
                Height = 34
                Top = 40
                Width = 107
                Action = ActionDimJobClear
                Images = DataModuleGuiResMain.ImageListMain16x16
                ImageIndex = 23
                TabOrder = 4
              end
              object BitBtnDimJobAdd: TBitBtn
                Left = 0
                Height = 34
                Top = 4
                Width = 107
                Action = ActionDimJobAdd
                Images = DataModuleGuiResMain.ImageListMain16x16
                ImageIndex = 57
                TabOrder = 0
              end
              object BitBtnDimJobDel: TBitBtn
                Left = 108
                Height = 34
                Top = 4
                Width = 107
                Action = ActionDimJobDel
                Images = DataModuleGuiResMain.ImageListMain16x16
                ImageIndex = 58
                TabOrder = 1
              end
              object BitBtnDimJobSaveIni: TBitBtn
                Left = 108
                Height = 46
                Top = 76
                Width = 107
                Action = ActionDimJobSaveIni
                Images = DataModuleGuiResMain.ImageListMain32x32
                ImageIndex = 5
                TabOrder = 6
              end
              object BitBtnDimJobLoadIni: TBitBtn
                Left = 0
                Height = 46
                Top = 76
                Width = 107
                Action = ActionDimJobLoadIni
                Images = DataModuleGuiResMain.ImageListMain32x32
                ImageIndex = 3
                TabOrder = 5
              end
              object BitBtnDimJobStartMonitor: TBitBtn
                Left = 0
                Height = 46
                Top = 124
                Width = 215
                Action = ActionDimJobStartMonitor
                Images = DataModuleGuiResMain.ImageListMain32x32
                ImageIndex = 114
                TabOrder = 7
              end
              object BitBtnDimJobMoveUp: TBitBtn
                Left = 0
                Height = 34
                Top = 40
                Width = 55
                Action = ActionDimJobMoveUp
                Images = DataModuleGuiResMain.ImageListMain16x16
                ImageIndex = 61
                TabOrder = 2
              end
              object BitBtnDimJobMoveDown: TBitBtn
                Left = 56
                Height = 34
                Top = 40
                Width = 51
                Action = ActionDimJobMoveDown
                Images = DataModuleGuiResMain.ImageListMain16x16
                ImageIndex = 62
                TabOrder = 3
              end
            end
          end
        end
      end
      object TabSheetDimMonitor: TTabSheet
        Caption = 'Monitor  '
        ClientHeight = 498
        ClientWidth = 782
        ImageIndex = 164
        object PanelDimMonitor: TPanel
          Left = 0
          Height = 498
          Top = 0
          Width = 782
          Align = alClient
          BorderWidth = 4
          ClientHeight = 498
          ClientWidth = 782
          TabOrder = 0
          object StatusBarDimMonitor: TStatusBar
            Left = 5
            Height = 17
            Top = 476
            Width = 772
            Panels = &lt;&gt;
          end
          object GroupBoxDimMonitor: TGroupBox
            Left = 5
            Height = 433
            Top = 5
            Width = 772
            Align = alClient
            Caption = ' DIM Monitor: '
            ClientHeight = 417
            ClientWidth = 770
            TabOrder = 1
            object StringGridDimMonitor: TStringGrid
              Left = 0
              Height = 417
              Hint = 'DIM Monitor Data:'#10' Service    : The DIM Service Name or User defined Title (Display Name)'#10' S          : State of connection (ONLINE/OFFLINE)'#10' N          : Item`s Number'#10' T          : Item`s Type (Char,Short,Int,Long,eXtralong,Float,Double)'#10' Data Value : Item`s Data Value ot the DIM Service as specified Type.'
              Top = 0
              Width = 770
              Align = alClient
              AutoFillColumns = True
              Color = clBtnFace
              ColCount = 4
              DoubleBuffered = True
              FixedCols = 3
              Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goColSizing, goAutoAddRows, goSmoothScroll, goFixedColSizing, goCellHints]
              ParentDoubleBuffered = False
              TabOrder = 0
              OnDrawCell = StringGridDimMonitorDrawCell
              OnGetCellHint = StringGridDimMonitorGetCellHint
              ColWidths = (
                64
                64
                64
                574
              )
            end
          end
          object PanelDimMonitorButtons: TPanel
            Left = 5
            Height = 38
            Top = 438
            Width = 772
            Align = alBottom
            BorderWidth = 4
            ClientHeight = 38
            ClientWidth = 772
            TabOrder = 2
            object CheckBoxDimMonitorPause: TCheckBox
              Left = 124
              Height = 21
              Hint = 'Pause - stop data updates.'
              Top = 8
              Width = 72
              Caption = 'Pause '
              TabOrder = 0
            end
            object ComboBoxDimMonitorFontSize: TComboBox
              Left = 272
              Height = 27
              Hint = 'Set FontSize,pt for Monitor Table.'
              Top = 4
              Width = 60
              DropDownCount = 25
              ItemHeight = 0
              Items.Strings = (
                '10'
                '12'
                '14'
                '16'
                '18'
                '20'
                '22'
                '24'
                '26'
                '28'
                '30'
                '32'
                '34'
                '36'
                '38'
                '40'
                '42'
                '44'
                '48'
              )
              OnChange = ComboBoxDimMonitorFontSizeChange
              TabOrder = 1
              Text = '14'
            end
            object LabelDimMonitorFontSize: TLabel
              Left = 204
              Height = 15
              Hint = 'Set FontSize,pt for Monitor Table.'
              Top = 12
              Width = 56
              Caption = 'Font,pt'
              ParentColor = False
              OnClick = LabelDimMonitorFontSizeClick
            end
            object BitBtnDimMonitorRefresh: TBitBtn
              Left = 4
              Height = 30
              Top = 4
              Width = 115
              Action = ActionDimMonitorRefresh
              Images = DataModuleGuiResMain.ImageListMain16x16
              ImageIndex = 298
              TabOrder = 2
            end
            object BitBtnDimMonitorGridCopy: TBitBtn
              Left = 336
              Height = 30
              Top = 4
              Width = 91
              Action = ActionDimMonitorGridCopy
              Images = DataModuleGuiResMain.ImageListMain16x16
              ImageIndex = 25
              TabOrder = 3
            end
            object BitBtnDimMonitorStart: TBitBtn
              Left = 500
              Height = 30
              Top = 4
              Width = 139
              Action = ActionDimJobStartMonitor
              Images = DataModuleGuiResMain.ImageListMain16x16
              ImageIndex = 64
              TabOrder = 4
            end
            object BitBtnDimMonitorReset: TBitBtn
              Left = 644
              Height = 30
              Top = 4
              Width = 119
              Action = ActionDimDnsRefresh
              Images = DataModuleGuiResMain.ImageListMain16x16
              ImageIndex = 27
              TabOrder = 5
            end
          end
        end
      end
      object TabSheetDimMonitorConsole: TTabSheet
        Caption = 'Console '
        ClientHeight = 498
        ClientWidth = 782
        ImageIndex = 162
        object PanelDimMonitorConsole: TPanel
          Left = 0
          Height = 432
          Top = 0
          Width = 782
          Align = alClient
          BorderWidth = 4
          ClientHeight = 432
          ClientWidth = 782
          TabOrder = 0
          object GroupBoxDimMonitorConsole: TGroupBox
            Left = 5
            Height = 422
            Top = 5
            Width = 772
            Align = alClient
            Caption = ' DIM Monitor Console: '
            ClientHeight = 420
            ClientWidth = 770
            TabOrder = 0
            object PanelDimMonitorConsoleControl: TPanel
              Left = 0
              Height = 30
              Top = 0
              Width = 770
              Align = alTop
              BorderWidth = 4
              ClientHeight = 26
              ClientWidth = 766
              TabOrder = 0
              object CheckBoxDimMonitorConsole: TCheckBox
                Left = 8
                Height = 21
                Top = 0
                Width = 384
                Caption = 'Use DIM Monitor Console.  Use history, lines:'
                Checked = True
                State = cbChecked
                TabOrder = 0
              end
              object SpinEditDimMonitorConsoleHistory: TSpinEdit
                Left = 396
                Height = 25
                Hint = 'DIM Monitor Console History, lines.'
                Top = 0
                Width = 74
                MaxValue = 10000
                TabOrder = 1
                Value = 50
              end
              object BitBtnDimMonitorConsoleClear: TBitBtn
                Left = 682
                Height = 26
                Top = 0
                Width = 79
                Action = ActionDimMonitorConsoleClear
                Anchors = [akTop, akRight]
                Images = DataModuleGuiResMain.ImageListMain16x16
                ImageIndex = 23
                TabOrder = 2
              end
              object BitBtnDimMonitorConsoleCopy: TBitBtn
                Left = 606
                Height = 26
                Top = 0
                Width = 75
                Action = ActionDimMonitorConsoleCopy
                Anchors = [akTop, akRight]
                Images = DataModuleGuiResMain.ImageListMain16x16
                ImageIndex = 25
                TabOrder = 3
              end
              object BitBtnDimMonitorConsoleUnselect: TBitBtn
                Left = 530
                Height = 26
                Top = 0
                Width = 75
                Action = ActionDimMonitorConsoleUnselect
                Anchors = [akTop, akRight]
                Images = DataModuleGuiResMain.ImageListMain16x16
                ImageIndex = 34
                TabOrder = 4
              end
              object BitBtnDimMonitorConsoleSelectAll: TBitBtn
                Left = 458
                Height = 26
                Top = 0
                Width = 71
                Action = ActionDimMonitorConsoleSelectAll
                Anchors = [akTop, akRight]
                Images = DataModuleGuiResMain.ImageListMain16x16
                ImageIndex = 33
                TabOrder = 5
              end
            end
            object PanelDimMonitorConsoleOutput: TPanel
              Left = 0
              Height = 356
              Top = 30
              Width = 770
              Align = alClient
              BorderWidth = 4
              ClientHeight = 352
              ClientWidth = 766
              TabOrder = 1
              object MemoDimMonitorConsole: TMemo
                Left = 5
                Height = 342
                Top = 5
                Width = 756
                Align = alClient
                Color = clInfoBk
                HideSelection = False
                ReadOnly = True
                ScrollBars = ssAutoBoth
                TabOrder = 0
                WordWrap = False
              end
            end
            object PanelDimMonitorConsoleInput: TPanel
              Left = 0
              Height = 34
              Top = 386
              Width = 770
              Align = alBottom
              BorderWidth = 4
              ClientHeight = 34
              ClientWidth = 770
              TabOrder = 2
              object LabelDimMonitorConsoleInput: TLabel
                Left = 4
                Height = 15
                Top = 8
                Width = 48
                Caption = 'Input:'
                ParentColor = False
              end
              object ComboBoxDimMonitorConsoleInput: TComboBox
                Left = 56
                Height = 27
                Top = 4
                Width = 598
                Anchors = [akTop, akLeft, akRight]
                ItemHeight = 0
                ItemIndex = 1
                Items.Strings = (
                  '@start=DimMonitor_1'
                  '@stop'
                  '@memory'
                  '@errors'
                )
                TabOrder = 0
                Text = '@stop'
              end
              object BitBtnDimMonitorConsoleSend: TBitBtn
                Left = 658
                Height = 26
                Top = 4
                Width = 107
                Action = ActionDimMonitorConsoleSend
                Anchors = [akTop, akRight]
                Images = DataModuleGuiResMain.ImageListMain16x16
                ImageIndex = 59
                TabOrder = 1
              end
            end
          end
        end
        object PanelMainButtons: TPanel
          Left = 0
          Height = 66
          Top = 432
          Width = 782
          Align = alBottom
          BorderWidth = 8
          ClientHeight = 66
          ClientWidth = 782
          TabOrder = 1
          object LabeMainSendUserCmnd: TLabel
            Left = 8
            Height = 15
            Top = 11
            Width = 160
            Anchors = [akLeft, akBottom]
            Caption = 'User command to send'
            ParentColor = False
          end
          object EditMainSendUserCmnd: TEdit
            Left = 8
            Height = 27
            Hint = 'Input command to send to CRW-DAQ console.'
            Top = 23
            Width = 364
            Anchors = [akLeft, akRight, akBottom]
            TabOrder = 0
            Text = '@run /sw7 dim gui'
          end
          object BitBtnMainSendUserCmnd: TBitBtn
            Left = 376
            Height = 46
            Top = 12
            Width = 107
            Action = ActionMainSendUserCmnd
            Anchors = [akRight, akBottom]
            Images = DataModuleGuiResMain.ImageListMain32x32
            ImageIndex = 59
            TabOrder = 1
          end
          object BitBtnMainExecUserCmnd: TBitBtn
            Left = 486
            Height = 46
            Top = 12
            Width = 91
            Action = ActionMainExecUserCmnd
            Anchors = [akRight, akBottom]
            Images = DataModuleGuiResMain.ImageListMain32x32
            ImageIndex = 114
            TabOrder = 2
          end
          object BitBtnMainProgramExit: TBitBtn
            Left = 582
            Height = 46
            Top = 12
            Width = 91
            Action = ActionMainProgramExit
            Anchors = [akRight, akBottom]
            ModalResult = 11
            Images = DataModuleGuiResMain.ImageListMain32x32
            ImageIndex = 113
            TabOrder = 3
          end
          object BitBtnMainParentShow: TBitBtn
            Left = 678
            Height = 46
            Top = 12
            Width = 91
            Action = ActionMainParentShow
            Anchors = [akRight, akBottom]
            ModalResult = 11
            Images = DataModuleGuiResMain.ImageListMain32x32
            ImageIndex = 234
            TabOrder = 4
          end
        end
      end
      object TabSheetDimParams: TTabSheet
        Caption = 'Params'
        ClientHeight = 498
        ClientWidth = 782
        ImageIndex = 161
        object PanelDimParams: TPanel
          Left = 0
          Height = 498
          Top = 0
          Width = 782
          Align = alClient
          ClientHeight = 498
          ClientWidth = 782
          TabOrder = 0
          object GroupBoxExecParams: TGroupBox
            Left = 1
            Height = 97
            Top = 1
            Width = 780
            Align = alTop
            Caption = ' Exec Parameters '
            ClientHeight = 81
            ClientWidth = 778
            TabOrder = 0
            object ScrollBoxExecParams: TScrollBox
              Left = 0
              Height = 81
              Top = 0
              Width = 778
              HorzScrollBar.Page = 716
              VertScrollBar.Page = 67
              Align = alClient
              ClientHeight = 77
              ClientWidth = 774
              TabOrder = 0
              object LabelDefExecBuffKb: TLabel
                Left = 12
                Height = 15
                Hint = 'Default I/O Buffer for Exec (to run tasks with normal output), kB.'
                Top = 12
                Width = 248
                Caption = 'Default I/O Buffer for Exec, Kb'
                ParentColor = False
              end
              object ComboBoxDefExecBuffKb: TComboBox
                Left = 276
                Height = 23
                Hint = 'Default I/O Buffer for Exec (to run tasks with normal output), kB.'
                Top = 8
                Width = 100
                DropDownCount = 24
                ItemHeight = 0
                ItemIndex = 8
                Items.Strings = (
                  '1'
                  '2'
                  '4'
                  '8'
                  '16'
                  '32'
                  '64'
                  '128'
                  '256'
                  '512'
                  '1024'
                  '2048'
                  '4096'
                  '8192'
                  '16384'
                  '32768'
                  '65536'
                )
                OnChange = ComboBoxDefExecBuffKbChange
                Style = csDropDownList
                TabOrder = 0
                Text = '256'
              end
              object LabelDefExecTimeOut: TLabel
                Left = 396
                Height = 15
                Hint = 'Default Timeout for Exec (to run tasks with normal output), ms.'
                Top = 12
                Width = 192
                Caption = 'Default Exec TimeOut, ms'
                ParentColor = False
              end
              object ComboBoxDefExecTimeOut: TComboBox
                Left = 616
                Height = 25
                Hint = 'Default Timeout for Exec (to run tasks with normal output), ms.'
                Top = 8
                Width = 100
                ItemHeight = 0
                ItemIndex = 4
                Items.Strings = (
                  '1000'
                  '2000'
                  '3000'
                  '4000'
                  '5000'
                  '7000'
                  '10000'
                  '15000'
                  '20000'
                  '30000'
                  '45000'
                  '60000'
                  '90000'
                  '120000'
                  '180000'
                  '300000'
                )
                TabOrder = 1
                Text = '5000'
              end
              object LabelBigExecBuffKb: TLabel
                Left = 12
                Height = 15
                Hint = 'BigSize I/O Buffer for Exec (to run tasks with big output), kB.'
                Top = 44
                Width = 248
                Caption = 'BigSize I/O Buffer for Exec, kB'
                ParentColor = False
              end
              object ComboBoxBigExecBuffKb: TComboBox
                Left = 276
                Height = 23
                Hint = 'BigSize I/O Buffer for Exec (to run tasks with big output), kB.'
                Top = 40
                Width = 100
                ItemHeight = 0
                ItemIndex = 7
                Items.Strings = (
                  '64'
                  '128'
                  '256'
                  '512'
                  '1024'
                  '2048'
                  '4096'
                  '8192'
                  '16384'
                  '32768'
                  '65536'
                )
                Style = csDropDownList
                TabOrder = 2
                Text = '8192'
              end
              object LabelBigExecTimeOut: TLabel
                Left = 396
                Height = 15
                Hint = 'BigSize Timeout for Exec (to run tasks with big output), ms.'
                Top = 44
                Width = 192
                Caption = 'BigSize Exec TimeOut, ms'
                ParentColor = False
              end
              object ComboBoxBigExecTimeOut: TComboBox
                Left = 616
                Height = 25
                Hint = 'BigSize Timeout for Exec (to run tasks with big output), ms.'
                Top = 40
                Width = 100
                ItemHeight = 0
                ItemIndex = 7
                Items.Strings = (
                  '1000'
                  '2000'
                  '3000'
                  '4000'
                  '5000'
                  '7000'
                  '10000'
                  '15000'
                  '20000'
                  '30000'
                  '45000'
                  '60000'
                  '90000'
                  '120000'
                  '180000'
                  '300000'
                )
                TabOrder = 3
                Text = '15000'
              end
            end
          end
          object GroupBoxDisplayParams: TGroupBox
            Left = 1
            Height = 65
            Top = 98
            Width = 780
            Align = alTop
            Caption = ' Display Parameters'
            ClientHeight = 63
            ClientWidth = 778
            TabOrder = 1
            object BitBtnDisplayLanguageRussian: TBitBtn
              Left = 8
              Height = 34
              Hint = 'Set display language Russian.'
              Top = 4
              Width = 139
              Caption = ' Russian '
              Images = DataModuleGuiResMain.ImageListMain32x32
              ImageIndex = 200
              OnClick = BitBtnDisplayLanguageRussianClick
              TabOrder = 0
            end
            object BitBtnDisplayLanguageEnglish: TBitBtn
              Left = 152
              Height = 34
              Hint = 'Set display language English.'
              Top = 4
              Width = 139
              Caption = ' English '
              Images = DataModuleGuiResMain.ImageListMain32x32
              ImageIndex = 201
              OnClick = BitBtnDisplayLanguageEnglishClick
              TabOrder = 1
            end
            object LabelLogEventsHistory: TLabel
              Left = 316
              Height = 15
              Hint = 'Events log History length, lines.'
              Top = 16
              Width = 200
              Caption = 'Log Events History, Lines'
              ParentColor = False
            end
            object SpinEditLogEventsHistory: TSpinEdit
              Left = 528
              Height = 25
              Hint = 'Events log History length, lines.'
              Top = 12
              Width = 102
              Increment = 100
              MaxValue = 1000000
              MinValue = 100
              OnChange = SpinEditLogEventsHistoryChange
              TabOrder = 2
              Value = 200
            end
          end
        end
      end
      object TabSheetLogEvents: TTabSheet
        BorderWidth = 8
        Caption = 'Log  '
        ClientHeight = 498
        ClientWidth = 782
        ImageIndex = 168
        object PanelLogEventsContent: TPanel
          Left = 0
          Height = 436
          Top = 0
          Width = 782
          Align = alClient
          BorderWidth = 8
          ClientHeight = 436
          ClientWidth = 782
          TabOrder = 0
          object LabelLogEvents: TLabel
            Left = 9
            Height = 15
            Top = 9
            Width = 764
            Align = alTop
            Caption = 'Event log (list of events occurred):'
            ParentColor = False
          end
          object MemoLogEvents: TMemo
            Left = 9
            Height = 386
            Top = 24
            Width = 764
            Align = alClient
            Color = clInfoBk
            ReadOnly = True
            ScrollBars = ssAutoBoth
            TabOrder = 0
            WordWrap = False
          end
          object StatusBarLogEvents: TStatusBar
            Left = 9
            Height = 17
            Top = 410
            Width = 764
            Panels = &lt;&gt;
          end
        end
        object PanelLogEventsButtons: TPanel
          Left = 0
          Height = 62
          Top = 436
          Width = 782
          Align = alBottom
          BorderWidth = 8
          ClientHeight = 62
          ClientWidth = 782
          TabOrder = 1
          object BitBtnLogEventsTest: TBitBtn
            Left = 459
            Height = 46
            Hint = 'Raise exception for test.'
            Top = 8
            Width = 95
            Anchors = [akTop, akRight]
            Caption = ' Test'
            Images = DataModuleGuiResMain.ImageListMain32x32
            ImageIndex = 115
            OnClick = BitBtnLogEventsTestClick
            TabOrder = 0
          end
          object BitBtnLogEventsClear: TBitBtn
            Left = 559
            Height = 46
            Top = 8
            Width = 111
            Action = ActionLogEventsClear
            Anchors = [akTop, akRight]
            Images = DataModuleGuiResMain.ImageListMain32x32
            ImageIndex = 119
            TabOrder = 1
          end
          object BitBtnLogEventsGoBack: TBitBtn
            Left = 675
            Height = 46
            Top = 8
            Width = 99
            Action = ActionLogEventsGoBack
            Anchors = [akTop, akRight]
            Images = DataModuleGuiResMain.ImageListMain32x32
            ImageIndex = 59
            TabOrder = 2
          end
          object LabelMainListSysInfo: TLabel
            Left = 8
            Height = 15
            Top = 8
            Width = 88
            Caption = 'Info topic:'
            ParentColor = False
          end
          object ComboBoxMainListSysInfo: TComboBox
            Left = 8
            Height = 27
            Top = 28
            Width = 182
            DropDownCount = 24
            ItemHeight = 0
            ItemIndex = 0
            Items.Strings = (
              'list environ'
              'list session'
              'list modules 0'
              'list process 0 0 *'
              'list windows 0 * *'
            )
            TabOrder = 3
            Text = 'list environ'
          end
          object LabelMainListSysInfoTimeOut: TLabel
            Left = 190
            Height = 15
            Top = 8
            Width = 56
            Caption = 'TimeOut'
            ParentColor = False
          end
          object SpinEditMainListSysInfoTimeOut: TSpinEdit
            Left = 190
            Height = 25
            Hint = 'Timeout for execution, sec.'
            Top = 26
            Width = 54
            MaxValue = 60
            MinValue = 1
            TabOrder = 4
            Value = 5
          end
          object BitBtnMainListSysInfo: TBitBtn
            Left = 246
            Height = 46
            Top = 8
            Width = 91
            Action = ActionMainListSysInfo
            Images = DataModuleGuiResMain.ImageListMain32x32
            ImageIndex = 124
            TabOrder = 5
          end
        end
      end
    end
  end
  object TimerLogEventsUpdater: TTimer
    OnTimer = TimerLogEventsUpdaterTimer
    Left = 652
  end
  object ActionListMain: TActionList
    Images = DataModuleGuiResMain.ImageListMain32x32
    Left = 616
    object ActionMainProgramExit: TAction
      Caption = 'Exit'
      Hint = 'Exit program.'
      ImageIndex = 113
      OnExecute = ActionMainExitExecute
    end
    object ActionMainParentShow: TAction
      Caption = 'Show'
      Hint = 'Open (activate) patent Crw32 program window.'
      ImageIndex = 234
      OnExecute = ActionMainParentShowExecute
    end
    object ActionMainFormShow: TAction
      Caption = 'Show MainForm'
      ImageIndex = 164
      OnExecute = ActionMainFormShowExecute
    end
    object ActionMainSendUserCmnd: TAction
      Caption = 'Send'
      Hint = 'Send command to CRW-DAQ  console.'
      ImageIndex = 59
      OnExecute = ActionMainSendUserCmndExecute
    end
    object ActionMainExecUserCmnd: TAction
      Caption = 'Exec'
      Hint = 'Run command from Crw32.ini list.'
      ImageIndex = 114
      OnExecute = ActionMainExecUserCmndExecute
    end
    object ActionLogEventsClear: TAction
      Caption = 'Clear'
      Hint = 'Clear event log.'
      ImageIndex = 119
      OnExecute = ActionMainLogEventsClearExecute
    end
    object ActionLogEventsGoBack: TAction
      Caption = 'Back'
      Hint = 'Go back to main page.'
      ImageIndex = 59
      OnExecute = ActionMainLogEventsGoBackExecute
    end
    object ActionDimAbout: TAction
      Caption = 'About'
      Hint = 'Show information about program.'
      ImageIndex = 21
      OnExecute = ActionDimAboutExecute
    end
    object ActionDimJobClear: TAction
      Caption = 'Clear'
      Hint = 'Clear DIM Job.'
      ImageIndex = 23
      OnExecute = ActionDimJobClearExecute
    end
    object ActionDimJobAdd: TAction
      Caption = 'Add'
      Hint = 'Add DIM Job to Monitor.'
      ImageIndex = 57
      OnExecute = ActionDimJobAddExecute
    end
    object ActionDimJobDel: TAction
      Caption = 'Del'
      Hint = 'Delete selected DIM Job from Monitor.'
      ImageIndex = 58
      OnExecute = ActionDimJobDelExecute
    end
    object ActionDimJobLoadIni: TAction
      Caption = 'LoadINI'
      Hint = 'Load DIM Job from INI file.'
      ImageIndex = 3
      OnExecute = ActionDimJobLoadIniExecute
    end
    object ActionDimJobSaveIni: TAction
      Caption = 'SaveINI'
      Hint = 'Save DIM Job to INI file.'
      ImageIndex = 5
      OnExecute = ActionDimJobSaveIniExecute
    end
    object ActionDimJobStartMonitor: TAction
      Caption = 'Start Monitor'
      Hint = 'Start DIM Monitoring.'
      ImageIndex = 114
      OnExecute = ActionDimJobStartMonitorExecute
    end
    object ActionDimMonitorConsoleClear: TAction
      Caption = 'Clear'
      Hint = 'Clear DIM Monitor Console.'
      ImageIndex = 23
      OnExecute = ActionDimMonitorConsoleClearExecute
    end
    object ActionDimMonitorConsoleCopy: TAction
      Caption = 'Copy'
      Hint = 'Copy DIM Monotor Console.'
      ImageIndex = 25
      OnExecute = ActionDimMonitorConsoleCopyExecute
    end
    object ActionDimMonitorConsoleUnselect: TAction
      Caption = 'None'
      Hint = 'Unselect DIM Monitor Console.'
      ImageIndex = 34
      OnExecute = ActionDimMonitorConsoleUnselectExecute
    end
    object ActionDimMonitorConsoleSelectAll: TAction
      Caption = 'All'
      Hint = 'Select All DIM Monitor Console.'
      ImageIndex = 33
      OnExecute = ActionDimMonitorConsoleSelectAllExecute
    end
    object ActionDimMonitorConsoleSend: TAction
      Caption = 'Send'
      Hint = 'Send command to DIM Monitor.'
      ImageIndex = 59
      OnExecute = ActionDimMonitorConsoleSendExecute
    end
    object ActionMainListSysInfo: TAction
      Caption = 'Info'
      Hint = 'Print system information on specified topic.'
      ImageIndex = 124
      OnExecute = ActionMainListSysInfoExecute
    end
    object ActionDimMonitorRefresh: TAction
      Caption = 'Refresh'
      Hint = 'Refresh (redraw, autosize).'
      ImageIndex = 298
      OnExecute = ActionDimMonitorRefreshExecute
    end
    object ActionDimMonitorGridCopy: TAction
      Caption = 'Copy'
      Hint = 'Copy StringGrid Data to Clipboard.'
      ImageIndex = 25
      OnExecute = ActionDimMonitorGridCopyExecute
    end
    object ActionDimDnsRefresh: TAction
      Caption = 'Reset DNS'
      Hint = 'Reset DNS.'#13#10'Stop DIM Monitoring.'
      ImageIndex = 27
      OnExecute = ActionDimDnsRefreshExecute
    end
    object ActionDimJobMoveUp: TAction
      Caption = 'Up'
      Hint = 'Move DIM Job Up.'
      ImageIndex = 61
      OnExecute = ActionDimJobMoveUpExecute
    end
    object ActionDimJobMoveDown: TAction
      Caption = 'Dn'
      Hint = 'Move DIM Job Down.'
      ImageIndex = 62
      OnExecute = ActionDimJobMoveDownExecute
    end
    object ActionDimJobItemSelect: TAction
      Caption = 'Select DIM Jomb Item.'
      ImageIndex = 250
      OnExecute = ActionDimJobItemSelectExecute
    end
  end
  object TrayIconMain: TTrayIcon
    PopUpMenu = PopupMenuTray
    Icon.Data = {
[encoded data, 16401 characters]
      020200000000000002020000000000000202
    }
    OnClick = TrayIconMainClick
    OnDblClick = TrayIconMainDblClick
    Left = 688
  end
  object PopupMenuTray: TPopupMenu
    Images = DataModuleGuiResMain.ImageListMain32x32
    Left = 728
    object MenuItemTrayFormShow: TMenuItem
      Action = ActionMainFormShow
    end
    object MenuItemTrayParentShow: TMenuItem
      Action = ActionMainParentShow
    end
    object N1: TMenuItem
      Caption = '-'
    end
    object MenuItemTrayProgramExit: TMenuItem
      Action = ActionMainProgramExit
    end
  end
  object TimerDimMonitoring: TTimer
    Interval = 50
    OnTimer = TimerDimMonitoringTimer
    Left = 764
  end
  object TimerDimPollRate: TTimer
    OnTimer = TimerDimPollRateTimer
    Left = 800
  end
  object OpenDialogDimJobLoadIni: TOpenDialog
    Title = 'DimMonitor - Open INI file'
    DefaultExt = '.ini'
    Filter = 'Ini files|*.ini|All files|*.*'
    Left = 836
  end
  object SaveDialogDimJobSaveIni: TSaveDialog
    DefaultExt = '.ini'
    Filter = 'Ini files|*.ini|All files|*.*'
    Left = 872
  end
end
</Object>
          <Code>unit Main;

uses  dpCmdArgs,dpSystem,dpSysUtils,dpVbs,dpWindows,dpGuiUtils,
      dpCrwDaqSys,dpDaqConfig,dpAntiZombie,dpGuiResMain,dpTask,
      dpColors, dpDimMonitor;

type
  TMainForm = class(TForm)
    TimerLogEventsUpdater: TTimer;
    ActionListMain: TActionList;
    ActionMainProgramExit: TAction;
    ActionMainParentShow: TAction;
    ActionMainFormShow: TAction;
    ActionMainSendUserCmnd: TAction;
    ActionMainExecUserCmnd: TAction;
    ActionLogEventsClear: TAction;
    ActionLogEventsGoBack: TAction;
    // TrayIcon
    TrayIconMain: TTrayIcon;
    PopupMenuTray: TPopupMenu;
    MenuItemTrayFormShow: TMenuItem;
    MenuItemTrayParentShow: TMenuItem;
    MenuItemTrayProgramExit: TMenuItem;
    MenuItemTrayProgramExitSeparator: TMenuItem;
    // Main Panel
    PanelMain: TPanel;
    // Main TabSheep
    TabSheetDimMonitorConsole: TTabSheet;
    PageControlMain: TPageControl;
    PanelDimMonitorConsole: TPanel;
    PanelMainButtons: TPanel;
    LabeMainSendUserCmnd: TLabel;
    EditMainSendUserCmnd: TEdit;
    BitBtnMainSendUserCmnd: TBitBtn;
    BitBtnMainExecUserCmnd: TBitBtn;
    BitBtnMainProgramExit: TBitBtn;
    BitBtnMainParentShow: TBitBtn;
    // LogEvents TabSheet
    TabSheetLogEvents: TTabSheet;
    PanelLogEventsContent: TPanel;
    LabelLogEvents: TLabel;
    MemoLogEvents: TMemo;
    StatusBarLogEvents: TStatusBar;
    PanelLogEventsButtons: TPanel;
    BitBtnLogEventsTest: TBitBtn;
    BitBtnLogEventsClear: TBitBtn;
    BitBtnLogEventsGoBack: TBitBtn;
    TabSheetDimParams: TTabSheet;
    PanelDimParams: TPanel;
    GroupBoxExecParams: TGroupBox;
    ScrollBoxExecParams: TScrollBox;
    LabelDefExecBuffKb: TLabel;
    ComboBoxDefExecBuffKb: TComboBox;
    LabelDefExecTimeOut: TLabel;
    ComboBoxDefExecTimeOut: TComboBox;
    LabelBigExecBuffKb: TLabel;
    ComboBoxBigExecBuffKb: TComboBox;
    LabelBigExecTimeOut: TLabel;
    ComboBoxBigExecTimeOut: TComboBox;
    // DimDns
    TabSheetDimDns: TTabSheet;
    PanelDimDns: TPanel;
    GroupBoxDimDnsNode: TGroupBox;
    ComboBoxDimDnsNode: TComboBox;
    LabelDimDnsStatusTitle: TLabel;
    LabelDimDnsStatusValue: TLabel;
    PanelDimBrowser: TPanel;
    GroupBoxDimServers: TGroupBox;
    ListBoxDimServers: TListBox;
    GroupBoxDimServerServices: TGroupBox;
    ListBoxDimServerServices: TListBox;
    PanelDimDnsButtons: TPanel;
    BitBtnDimServiceSelect: TBitBtn;
    GroupBoxDimSelParams: TGroupBox;
    SpinEditDimSelPeriod: TSpinEdit;
    LabelDimSelPeriod: TLabel;
    LabelDimSelFillHex: TLabel;
    ComboBoxDimSelFillHex: TComboBox;
    TimerDimMonitoring: TTimer;
    TabSheetDimMonitor: TTabSheet;
    PanelDimMonitor: TPanel;
    StatusBarDimMonitor: TStatusBar;
    TimerDimPollRate: TTimer;
    GroupBoxDimMonitorControl: TGroupBox;
    BitBtnStartDimMonitor: TBitBtn;
    BitBtnDimDnsRefresh: TBitBtn;
    ActionDimJobClear: TAction;
    ActionDimJobAdd: TAction;
    ActionDimJobDel: TAction;
    // TabSheetDimJob
    TabSheetDimJob: TTabSheet;
    PanelDimJob: TPanel;
    GroupBoxDimJob: TGroupBox;
    ListBoxDimJob: TListBox;
    PanelDimJobButtons: TPanel;
    GroupBoxDimJobParams: TGroupBox;
    SpinEditDimJobPeriod: TSpinEdit;
    LabelDimJobPeriod: TLabel;
    LabelDimJobFillHex: TLabel;
    ComboBoxDimJobFillHex: TComboBox;
    GroupBoxDimJobKind: TGroupBox;
    ComboBoxDimJobKind: TComboBox;
    EditDimJobService: TEdit;
    GroupBoxDimJobControl: TGroupBox;
    BitBtnDimJobClear: TBitBtn;
    EditDimJobFormat: TEdit;
    LabelDimJobMonitoring: TLabel;
    ComboBoxDimJobMonitoringType: TComboBox;
    BitBtnDimJobAdd: TBitBtn;
    BitBtnDimJobDel: TBitBtn;
    LabelDimJobTitle: TLabel;
    EditDimJobTitle: TEdit;
    BitBtnDimJobSaveIni: TBitBtn;
    BitBtnDimJobLoadIni: TBitBtn;
    LabelDimSelMonitoring: TLabel;
    ComboBoxDimSelMonitoring: TComboBox;
    OpenDialogDimJobLoadIni: TOpenDialog;
    SaveDialogDimJobSaveIni: TSaveDialog;
    ActionDimJobLoadIni: TAction;
    ActionDimJobSaveIni: TAction;
    ActionDimJobStartMonitor: TAction;
    GroupBoxDimMonitor: TGroupBox;
    GroupBoxDimMonitorConsole: TGroupBox;
    PanelDimMonitorConsoleControl: TPanel;
    CheckBoxDimMonitorConsole: TCheckBox;
    PanelDimMonitorConsoleOutput: TPanel;
    MemoDimMonitorConsole: TMemo;
    SpinEditDimMonitorConsoleHistory: TSpinEdit;
    BitBtnDimMonitorConsoleClear: TBitBtn;
    ActionDimMonitorConsoleClear: TAction;
    ActionDimMonitorConsoleCopy: TAction;
    BitBtnDimMonitorConsoleCopy: TBitBtn;
    ActionDimMonitorConsoleUnselect: TAction;
    BitBtnDimMonitorConsoleUnselect: TBitBtn;
    ActionDimMonitorConsoleSelectAll: TAction;
    BitBtnDimMonitorConsoleSelectAll: TBitBtn;
    PanelDimMonitorConsoleInput: TPanel;
    LabelDimMonitorConsoleInput: TLabel;
    ComboBoxDimMonitorConsoleInput: TComboBox;
    ActionDimMonitorConsoleSend: TAction;
    BitBtnDimMonitorConsoleSend: TBitBtn;
    BitBtnDimServiceSelectAndGoToJob: TBitBtn;
    BitBtnDimJobStartMonitor: TBitBtn;
    ActionDimAbout: TAction;
    BitBtnDimAbout: TBitBtn;
    ActionMainListSysInfo: TAction;
    LabelMainListSysInfo: TLabel;
    ComboBoxMainListSysInfo: TComboBox;
    LabelMainListSysInfoTimeOut: TLabel;
    SpinEditMainListSysInfoTimeOut: TSpinEdit;
    BitBtnMainListSysInfo: TBitBtn;
    ImageCernLogo: TImage;
    ImageDimLogo: TImage;
    ImageDimLogoBig: TImage;
    PanelDimMonitorButtons: TPanel;
    CheckBoxDimMonitorPause: TCheckBox;
    StringGridDimMonitor: TStringGrid;
    ComboBoxDimMonitorFontSize: TComboBox;
    LabelDimMonitorFontSize: TLabel;
    ActionDimMonitorRefresh: TAction;
    BitBtnDimMonitorRefresh: TBitBtn;
    ActionDimMonitorGridCopy: TAction;
    BitBtnDimMonitorGridCopy: TBitBtn;
    GroupBoxDisplayParams: TGroupBox;
    BitBtnDisplayLanguageRussian: TBitBtn;
    BitBtnDisplayLanguageEnglish: TBitBtn;
    LabelLogEventsHistory: TLabel;
    SpinEditLogEventsHistory: TSpinEdit;
    BitBtnDimMonitorStart: TBitBtn;
    BitBtnDimMonitorReset: TBitBtn;
    ActionDimDnsRefresh: TAction;
    ActionDimJobMoveUp: TAction;
    ActionDimJobMoveDown: TAction;
    BitBtnDimJobMoveUp: TBitBtn;
    BitBtnDimJobMoveDown: TBitBtn;
    ActionDimJobItemSelect: TAction;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure TrayIconMainClick(Sender: TObject);
    procedure TrayIconMainDblClick(Sender: TObject);
    procedure TimerLogEventsUpdaterTimer(Sender: TObject);
    procedure TimerDimMonitoringTimer(Sender: TObject);
    procedure ActionMainExitExecute(Sender: TObject);
    procedure ActionMainParentShowExecute(Sender: TObject);
    procedure ActionMainFormShowExecute(Sender: TObject);
    procedure ActionMainSendUserCmndExecute(Sender: TObject);
    procedure ActionMainExecUserCmndExecute(Sender: TObject);
    procedure ActionMainLogEventsClearExecute(Sender: TObject);
    procedure ActionMainLogEventsGoBackExecute(Sender: TObject);
    procedure ActionMainListSysInfoExecute(Sender: TObject);
    procedure ActionDimDnsRefreshExecute(Sender: TObject);
    procedure BitBtnLogEventsTestClick(Sender: TObject);
    procedure ListBoxDimServersClick(Sender: TObject);
    procedure BitBtnDimServiceSelectClick(Sender: TObject);
    procedure TimerDimPollRateTimer(Sender: TObject);
    procedure ActionDimJobClearExecute(Sender: TObject);
    procedure ListBoxDimJobClick(Sender: TObject);
    procedure ActionDimJobAddExecute(Sender: TObject);
    procedure ActionDimJobDelExecute(Sender: TObject);
    procedure SpinEditDimSelPeriodChange(Sender: TObject);
    procedure SpinEditDimJobPeriodChange(Sender: TObject);
    procedure ComboBoxDimSelMonitoringTypeChange(Sender: TObject);
    procedure ComboBoxDimJobMonitoringTypeChange(Sender: TObject);
    procedure ActionDimJobSaveIniExecute(Sender: TObject);
    procedure ActionDimJobLoadIniExecute(Sender: TObject);
    procedure ActionDimJobStartMonitorExecute(Sender: TObject);
    procedure ActionDimMonitorConsoleClearExecute(Sender: TObject);
    procedure ActionDimMonitorConsoleCopyExecute(Sender: TObject);
    procedure ActionDimMonitorConsoleUnselectExecute(Sender: TObject);
    procedure ActionDimMonitorConsoleSelectAllExecute(Sender: TObject);
    procedure ActionDimMonitorConsoleSendExecute(Sender: TObject);
    procedure BitBtnDimServiceSelectAndGoToJobClick(Sender: TObject);
    procedure ActionDimAboutExecute(Sender: TObject);
    procedure ImageCernLogoClick(Sender: TObject);
    procedure ImageDimLogoClick(Sender: TObject);
    procedure ImageDimLogoBigClick(Sender: TObject);
    procedure ComboBoxDimMonitorFontSizeChange(Sender: TObject);
    procedure ActionDimMonitorRefreshExecute(Sender: TObject);
    procedure ActionDimMonitorGridCopyExecute(Sender: TObject);
    procedure StringGridDimMonitorDrawCell(Sender: TObject; aCol: LongInt; aRow: LongInt; aRect: TRect; aState: TGridDrawState);
    procedure StringGridDimMonitorGetCellHint(Sender: TObject; ACol: LongInt; ARow: LongInt; var HintText: AnsiString);
    procedure BitBtnDisplayLanguageRussianClick(Sender: TObject);
    procedure BitBtnDisplayLanguageEnglishClick(Sender: TObject);
    procedure SpinEditLogEventsHistoryChange(Sender: TObject);
    procedure ActionDimJobMoveUpExecute(Sender: TObject);
    procedure ActionDimJobMoveDownExecute(Sender: TObject);
    procedure ActionDimJobItemSelectExecute(Sender: TObject);
  private
    EngCaptions : TStringList;
    EngHints    : TStringList;
    RusCaptions : TStringList;
    RusHints    : TStringList;
  private
    function  GetDimSelMonitoringType:String;
    function  GetDimSelPeriod:Integer;
    function  GetDimSelFillHex:String;
  protected
  public
    property  DimSelMonitoringType:String read GetDimSelMonitoringType;
    property  DimSelPeriod:Integer        read GetDimSelPeriod;
    property  DimSelFillHex:String        read GetDimSelFillHex;
  public
    procedure ShowTrayIcon;
    procedure AdjustComponents;
    procedure UpdateGuiLanguage(lng:Integer);
    procedure BugReport(E:Exception; Sender:TObject; Where:String);
    procedure SendCommandToCrwDaq(S:String; Activate:Boolean=true);
    procedure PostCommandToCrwDaq(S:String);
  public
    procedure DimDnsRefresh;
    procedure UpdateDnsStatus;
    procedure UpdateDimServerServices(aServer:String);
    procedure SelectServerServices;
    function  DefExecBuffKb:Integer;
    function  BigExecBuffKb:Integer;
    function  DefExecTimeOut:Integer;
    function  BigExecTimeOut:Integer;
    procedure UpdateDimMonitorOptions;
    function  Exec(cmd:String; timeout:Integer=0; BuffSizeKb:Integer=0):String;
    procedure Trouble(Msg:String);
    procedure Success(Msg:String);
    function  ComposeDimJob(kind,serv,frmt,mntr,tmon,fill,titl:String):String;
    function  FindDimJob(serv:String):Integer;
    function  AddDimJob(job:String):Integer;
    procedure DimJobMove(Step:Integer);
    procedure StartMonitoring;
    procedure DoMonitoring;
    procedure DoPollRate;
    function  DimJobLoadIni(FileName,Section:String):String;
    function  DimJobSaveIni(FileName,Section,JobText:String):Integer;
    procedure DimJobLoadIniFromArgs;
  end;

var MainForm: TMainForm;

const // Section identifiers
 sid_DimMonitorJob    = 'DimMonitorJob';
 sid_DimMonitorParams = 'DimMonitorParams';

implementation

procedure TMainForm.FormCreate(Sender: TObject);
begin
 try
  defIpcInit;
  defParamsInit;
  InitAppFolders;
  SetDefaultFontName(Font);
  InitAntiZombie(1000,true);
  Caption:=GetCrwDaqChildTitle;
  FormCenterToScreen(Self,0,0);
  SetButtonCursorToHandPoint(Self);
  StatusBarLogEvents.Font.Size:=10;
  PageControlMain.ActivePage:=TabSheetDimDns;
  LogEvents(Now,GetBriefEngineScriptInfo);
  LogEvents(Now,'Start.');
  EngCaptions:=TStringList.Create;
  RusCaptions:=TStringList.Create;
  EngHints:=TStringList.Create;
  RusHints:=TStringList.Create;
  EngCaptions.Sorted:=true;
  RusCaptions.Sorted:=true;
  EngHints.Sorted:=true;
  RusHints.Sorted:=true;
  AdjustComponents;
  ShowTrayIcon;
  if (CRW_DAQ_SYS_EXE_PID=0) then begin
   ActionMainParentShow.Enabled:=false;
   ActionMainSendUserCmnd.Enabled:=false;
   //RaiseException('Parent Crw32.exe process is not specified.');
  end;
 except
  on E:Exception do Self.BugReport(E,Self,'FormCreate');
 end;
end;

procedure TMainForm.FormDestroy(Sender: TObject);
begin
 DimMonitor.StopMonitoring;
 DimMonitor.Reset;
end;

procedure TMainForm.ShowTrayIcon;
begin
 Application.Title:=GetScriptName;
 TrayIconMain.Visible:=true;
 TrayIconMain.Hint:=GetScriptName+EOL+Caption;
 MenuItemTrayFormShow.Caption:=FormatVar('Show Window [%s]',Caption);
 MenuItemTrayProgramExit.Caption:=FormatVar('Exit from [%s]',Caption);
 MenuItemTrayParentShow.Caption:=FormatVar('Show Parent Window [%s]',ParentCrwDaqTitle);
 HideApplicationIconFromTaskBar(true);
end;

function GetCommonProgramFilesDimBin:String;
begin
 Result:=''; if not IsWindows then Exit;
 Result:=Trim(ExpEnv('%CommonProgramFiles%\CRW-DAQ\Resource\DimSite\dim\bin'));
 if (Result&lt;&gt;'') and DirectoryExists(Result) then Exit else Result:='';
 Result:=Trim(ExpEnv('%CommonProgramFiles(x86)%\CRW-DAQ\Resource\DimSite\dim\bin'));
 if (Result&lt;&gt;'') and DirectoryExists(Result) then Exit else Result:='';
 Result:=Trim(ExpEnv('%CommonProgramW6432%\CRW-DAQ\Resource\DimSite\dim\bin'));
 if (Result&lt;&gt;'') and DirectoryExists(Result) then Exit else Result:='';
end;

procedure UpdatePath;
const optDimDir='/opt/dim';
var inipath,path,dir:String;
begin
 if IsUnix then begin
  inipath:=GetEnv('PATH');
  if DirectoryExists(optDimDir)
  then SetEnv('PATH',inipath+PathSep+optDimDir);
  if RunCommand('unix printenv PATH',path) and (path&lt;&gt;'') then begin
   path:=StringReplace(Trim(path),inipath+PathSep,'',0);
   SetEnv('PATH',GetEnv('PATH')+PathSep+Trim(path));
  end;
 end;
 if IsWindows then begin
  inipath:=GetEnv('PATH');
  dir:=GetCommonProgramFilesDimBin;
  if (dir&lt;&gt;'') and DirectoryExists(dir)
  then SetEnv('PATH',inipath+PathSep+dir);
 end;
 LogEvents(Now,'PATH='+GetEnv('PATH'));
end;

function GetCaptionOfComponent(Comp:TComponent):String;
begin
 if (Comp is TMenuItem)         then Result:=TMenuItem(Comp).Caption;
 if (Comp is TLabel)            then Result:=TLabel(Comp).Caption;
 if (Comp is TButton)           then Result:=TButton(Comp).Caption;
 if (Comp is TCheckBox)         then Result:=TCheckBox(Comp).Caption;
 if (Comp is TRadioButton)      then Result:=TRadioButton(Comp).Caption;
 if (Comp is TToggleBox)        then Result:=TToggleBox(Comp).Caption;
 if (Comp is TGroupBox)         then Result:=TGroupBox(Comp).Caption;
 if (Comp is TRadioGroup)       then Result:=TRadioGroup(Comp).Caption;
 if (Comp is TCheckGroup)       then Result:=TCheckGroup(Comp).Caption;
 if (Comp is TPanel)            then Result:=TPanel(Comp).Caption;
 if (Comp is TCustomAction)     then Result:=TCustomAction(Comp).Caption;
 if (Comp is TAction)           then Result:=TAction(Comp).Caption;
 if (Comp is TBitBtn)           then Result:=TBitBtn(Comp).Caption;
 if (Comp is TSpeedButton)      then Result:=TSpeedButton(Comp).Caption;
 if (Comp is TStaticText)       then Result:=TStaticText(Comp).Caption;
 if (Comp is TToolBar)          then Result:=TToolBar(Comp).Caption;
 if (Comp is TToolButton)       then Result:=TToolButton(Comp).Caption;
 if (Comp is TTabSheet)         then Result:=TTabSheet(Comp).Caption;
 if (Comp is TForm)             then Result:=TForm(Comp).Caption;
 if (Comp is TDBCheckBox)       then Result:=TDBCheckBox(Comp).Caption;
 if (Comp is TDBRadioGroup)     then Result:=TDBRadioGroup(Comp).Caption;
 if (Comp is TDBNavigator)      then Result:=TDBNavigator(Comp).Caption;
 if (Comp is TDBNavButton)      then Result:=TDBNavButton(Comp).Caption;
 if (Comp is TxSpeedBtn)        then Result:=TxSpeedBtn(Comp).Caption;
 if (Comp is TxBitBtn)          then Result:=TxBitBtn(Comp).Caption;
 if (Comp is TEmbededLabel)     then Result:=TEmbededLabel(Comp).Caption;
 if (Comp is TxDBCheckBox)      then Result:=TxDBCheckBox(Comp).Caption;
 if (Comp is TSuFrame)          then Result:=TSuFrame(Comp).Caption;
 if (Comp is TColorButton)      then Result:=TColorButton(Comp).Caption;
 if (Comp is TPanelBitBtn)      then Result:=TPanelBitBtn(Comp).Caption;
 if (Comp is TfrPreview)        then Result:=TfrPreview(Comp).Caption;
end;
procedure SetCaptionOfComponent(Comp:TComponent; aCaption:String);
begin
 if (Comp is TMenuItem)         then TMenuItem(Comp).Caption:=aCaption;
 if (Comp is TLabel)            then TLabel(Comp).Caption:=aCaption;
 if (Comp is TButton)           then TButton(Comp).Caption:=aCaption;
 if (Comp is TCheckBox)         then TCheckBox(Comp).Caption:=aCaption;
 if (Comp is TRadioButton)      then TRadioButton(Comp).Caption:=aCaption;
 if (Comp is TToggleBox)        then TToggleBox(Comp).Caption:=aCaption;
 if (Comp is TGroupBox)         then TGroupBox(Comp).Caption:=aCaption;
 if (Comp is TRadioGroup)       then TRadioGroup(Comp).Caption:=aCaption;
 if (Comp is TCheckGroup)       then TCheckGroup(Comp).Caption:=aCaption;
 if (Comp is TPanel)            then TPanel(Comp).Caption:=aCaption;
 if (Comp is TCustomAction)     then TCustomAction(Comp).Caption:=aCaption;
 if (Comp is TAction)           then TAction(Comp).Caption:=aCaption;
 if (Comp is TBitBtn)           then TBitBtn(Comp).Caption:=aCaption;
 if (Comp is TSpeedButton)      then TSpeedButton(Comp).Caption:=aCaption;
 if (Comp is TStaticText)       then TStaticText(Comp).Caption:=aCaption;
 if (Comp is TToolBar)          then TToolBar(Comp).Caption:=aCaption;
 if (Comp is TToolButton)       then TToolButton(Comp).Caption:=aCaption;
 if (Comp is TTabSheet)         then TTabSheet(Comp).Caption:=aCaption;
 if (Comp is TForm)             then TForm(Comp).Caption:=aCaption;
 if (Comp is TDBCheckBox)       then TDBCheckBox(Comp).Caption:=aCaption;
 if (Comp is TDBRadioGroup)     then TDBRadioGroup(Comp).Caption:=aCaption;
 if (Comp is TDBNavigator)      then TDBNavigator(Comp).Caption:=aCaption;
 if (Comp is TDBNavButton)      then TDBNavButton(Comp).Caption:=aCaption;
 if (Comp is TxSpeedBtn)        then TxSpeedBtn(Comp).Caption:=aCaption;
 if (Comp is TxBitBtn)          then TxBitBtn(Comp).Caption:=aCaption;
 if (Comp is TEmbededLabel)     then TEmbededLabel(Comp).Caption:=aCaption;
 if (Comp is TxDBCheckBox)      then TxDBCheckBox(Comp).Caption:=aCaption;
 if (Comp is TSuFrame)          then TSuFrame(Comp).Caption:=aCaption;
 if (Comp is TColorButton)      then TColorButton(Comp).Caption:=aCaption;
 if (Comp is TPanelBitBtn)      then TPanelBitBtn(Comp).Caption:=aCaption;
 if (Comp is TfrPreview)        then TfrPreview(Comp).Caption:=aCaption;
end;
function GetHintOfComponent(Comp:TComponent):String;
begin
 if (Comp is TControl) then Result:=TControl(Comp).Hint;
end;
procedure SetHintOfComponent(Comp:TComponent; aHint:String);
begin
 if (Comp is TControl) then TControl(Comp).Hint:=aHint;
end;

procedure TMainForm.AdjustComponents;
 procedure SaveFormComponentsCaptionsHints(aForm:TForm);
 var aName,aCaption,aHint:String; i:Integer;
 begin
  if not Assigned(aForm) then Exit;
  for i:=0 to aForm.ComponentCount-1 do begin
   aName:=aForm.Components[i].Name;
   aHint:=GetHintOfComponent(aForm.Components[i]);
   aCaption:=GetCaptionOfComponent(aForm.Components[i]);
   if not IsEmptyStr(aHint) then EngHints.Values[aName]:=RecodeStr(aHint,'rawbyte,base64');
   if not IsEmptyStr(aCaption) then EngCaptions.Values[aName]:=RecodeStr(aCaption,'rawbyte,base64');
  end;
 end;
begin
 UpdatePath;
 GetOptIniFile;
 DimMonitor.StringGrid:=StringGridDimMonitor;
 DimMonitor.StringGridReset;
 DimMonitor.ColorGridOn:=StringToColor('PaleGreen',clLime);
 DimMonitor.ColorGridOff:=StringToColor('MistyRose',clRed);
 DimMonitor.DnsStatusColor:=DimMonitor.ColorUndefined;
 LogEventsHistoryLimit:=SpinEditLogEventsHistory.Value;
 PageControlMain.ActivePage:=TabSheetDimDns;
 MemoLogEvents.Font.Size:=10;
 ScrollBoxExecParams.Font.Size:=10;
 LabelDimDnsStatusValue.Font.Style:=LabelDimDnsStatusValue.Font.Style+[fsBold];
 LabelDimDnsStatusValue.Font.Color:=clMaroon;
 if (ComboBoxDimDnsNode.Text='') then ComboBoxDimDnsNode.Text:=GetOptDns(DimMonitor.DIM_DNS_NODE);
 ComboBoxDimDnsNode.Items.Text:='localhost'+EOL+'127.0.0.1'+EOL+GetHostName+EOL;
 ComboBoxDimSelMonitoring.Items.Text:=StringReplace(DimPollList,',',EOL,rfReplaceAll);
 ComboBoxDimSelMonitoring.ItemIndex:=0;
 ComboBoxDimJobKind.Items.Text:=StringReplace(DimKindList,',',EOL,rfReplaceAll);
 ComboBoxDimJobMonitoringType.Items.Text:=StringReplace(DimPollList,',',EOL,rfReplaceAll);
 EditDimJobService.Font.Size:=9;
 EditDimJobTitle.Font.Size:=9;
 MemoDimMonitorConsole.Font.Size:=10;
 OpenDialogDimJobLoadIni.Title:=DimMonitor.DimTaskName+' - Load INI file';
 SaveDialogDimJobSaveIni.Title:=DimMonitor.DimTaskName+' - Save INI file';
 ComboBoxDimMonitorConsoleInput.Items.Text:='@start='+DimMonitor.DimTaskName+EOL
                                           +'@stop'+EOL
                                           +'@memory'+EOL
                                           +'@errors'+EOL
                                           +'@padding'+EOL
                                           +'@priority=0,0,0,0'+EOL
                                           +'@exit'+EOL;
 DimDnsRefresh;
 DimJobLoadIniFromArgs;
 if not IsEmptyStr(ComboBoxDimDnsNode.Text) then
 if (DimMonitor.DnsStatusColor&lt;&gt;DimMonitor.ColorOnline) then DimDnsRefresh;
 if (ListBoxDimJob.Count&gt;0) then ActionDimJobStartMonitor.Execute;
 SetDefaultSansFontName(LabelMainListSysInfoTimeOut.Font);
 SaveFormComponentsCaptionsHints(Self);
 LanguageId:=GetOptLanguage(LanguageId);
 UpdateGuiLanguage(LanguageId);
 UpdateDnsStatus;
 LogEvents(Now,'VendorName = '+VendorName);
 LogEvents(Now,'ApplicationName = '+ApplicationName);
 LogEvents(Now,'GetAppDataDir(0,0) = '+GetAppDataDir(false,false));
 LogEvents(Now,'GetAppDataDir(0,1) = '+GetAppDataDir(false,true));
 LogEvents(Now,'GetAppDataDir(1,0) = '+GetAppDataDir(true,false));
 LogEvents(Now,'GetAppDataDir(1,1) = '+GetAppDataDir(true,true));
 LogEvents(Now,'GetAppConfigDir(0,0) = '+GetAppConfigDir(false,false));
 LogEvents(Now,'GetAppConfigDir(0,1) = '+GetAppConfigDir(false,true));
 LogEvents(Now,'GetAppConfigDir(1,0) = '+GetAppConfigDir(true,false));
 LogEvents(Now,'GetAppConfigDir(1,1) = '+GetAppConfigDir(true,true));
end;

procedure TMainForm.UpdateGuiLanguage(lng:Integer);
 procedure AddRusCaptions(Comp:TComponent; S:String);
 begin
  if (Comp=nil) then Exit;
  if (RusCaptions.IndexOfName(Comp.Name)&gt;=0) then Exit;
  RusCaptions.Values[Comp.Name]:=RecodeStr(S,'rawbyte,base64');
 end;
 procedure TranslateCaption(Comp:TComponent; ruCaption:String);
 var aCaption:String;
 begin
  if (Comp=nil) then Exit;
  AddRusCaptions(Comp,ruCaption);
  aCaption:=GetCaptionOfComponent(Comp);
  if (lng=lng_Russian) then aCaption:=RecodeStr(RusCaptions.Values[Comp.Name],'base64,rawbyte');
  if (lng=lng_English) then aCaption:=RecodeStr(EngCaptions.Values[Comp.Name],'base64,rawbyte');
  if (aCaption&lt;&gt;GetCaptionOfComponent(Comp))
  then SetCaptionOfComponent(Comp,aCaption);
 end;
 procedure AddRusHints(Comp:TComponent; S:String);
 begin
  if (Comp=nil) then Exit;
  if (RusHints.IndexOfName(Comp.Name)&gt;=0) then Exit;
  RusHints.Values[Comp.Name]:=RecodeStr(S,'rawbyte,base64');
 end;
 procedure TranslateTheHint(Comp:TComponent; ruHint:String);
 var aHint:String;
 begin
  if (Comp=nil) then Exit;
  AddRusHints(Comp,ruHint);
  aHint:=GetHintOfComponent(Comp);
  if (lng=lng_Russian) then aHint:=RecodeStr(RusHints.Values[Comp.Name],'base64,rawbyte');
  if (lng=lng_English) then aHint:=RecodeStr(EngHints.Values[Comp.Name],'base64,rawbyte');
  if (aHint&lt;&gt;GetHintOfComponent(Comp))
  then SetHintOfComponent(Comp,aHint);
 end;
begin
 case lng of
  lng_Unknown : LanguageId:=lng;
  lng_English : LanguageId:=lng;
  lng_Russian : LanguageId:=lng;
  else          Exit;
 end;
 ///////////////////////////////////////////////
 TranslateCaption(TabSheetDimDns,               ' Связь ');
 TranslateCaption(GroupBoxDimDnsNode,           ' Узел DIM_DNS_NODE для подключения: ');
 TranslateTheHint(GroupBoxDimDnsNode,           'Узел DIM_DNS_NODE - сервер имен для подключения к сети DIM.');
 TranslateTheHint(ComboBoxDimDnsNode,           'Задать узел DIM_DNS_NODE, к которому надо подключиться.');
 TranslateCaption(LabelDimDnsStatusTitle,       'Статус:');
 TranslateCaption(LabelDimDnsStatusValue,       'НЕОПРЕДЕЛЕННЫЙ');
 TranslateTheHint(LabelDimDnsStatusTitle,       'Статус подключения DIM DNS.');
 TranslateTheHint(LabelDimDnsStatusValue,       'Статус подключения DIM DNS.');
 TranslateCaption(GroupBoxDimMonitorControl,    ' Управление DIM Монитором: ');
 TranslateTheHint(BitBtnStartDimMonitor,        'Запуск DIM Монитора.');
 TranslateCaption(ActionDimDnsRefresh,          'Сброс DNS');
 TranslateTheHint(BitBtnDimDnsRefresh,          'Сброс DNS.'+EOL+'Остановка DIM Монитора.');
 TranslateTheHint(BitBtnDimMonitorReset,        'Сброс DNS.'+EOL+'Остановка DIM Монитора.');
 TranslateCaption(ActionDimAbout,               'Помощь');
 TranslateTheHint(BitBtnDimAbout,               'Показать информацию о программе.');
 TranslateCaption(GroupBoxDimServers,           ' DIM Серверы: ');
 TranslateTheHint(GroupBoxDimServers,           'Список доступных DIM серверов для данного DNS узла.');
 TranslateCaption(GroupBoxDimServerServices,    ' Сервисы DIM Сервера: ');
 TranslateTheHint(GroupBoxDimServerServices,    'Список доступных DIM сервисов для данного DIM сервера.');
 TranslateCaption(BitBtnDimServiceSelect,       'Выбрать Сервис(ы)');
 TranslateTheHint(BitBtnDimServiceSelect,       'Добавить выбранные DIM сервисы в Задания для Монитора.');
 TranslateCaption(GroupBoxDimSelParams,         ' Параметры: ');
 TranslateCaption(LabelDimSelPeriod,            'сек - Период');
 TranslateTheHint(LabelDimSelPeriod,            'Период (сек) обновления данных в режиме timed Монитора.');
 TranslateTheHint(SpinEditDimSelPeriod,         'Период (сек) обновления данных в режиме timed Монитора.');
 TranslateCaption(LabelDimSelFillHex,           'Маркер "НЕТ СВЯЗИ" (HEX)');
 TranslateTheHint(LabelDimSelFillHex,           'Маркер "НЕТ СВЯЗИ" (HEX) в случае разрыва связи.');
 TranslateTheHint(ComboBoxDimSelFillHex,        'Маркер "НЕТ СВЯЗИ" (HEX) в случае разрыва связи.');
 TranslateCaption(LabelDimSelMonitoring,        'Монитор:');
 TranslateTheHint(LabelDimSelMonitoring,        'Тип монитора: (периодический,событийный).');
 TranslateTheHint(ComboBoxDimSelMonitoring,     'Тип монитора: (периодический,событийный).');
 TranslateCaption(BitBtnDimServiceSelectAndGoToJob, 'Выбрать &amp;&amp; к Заданиям');
 TranslateTheHint(BitBtnDimServiceSelectAndGoToJob, 'Добавить выбранные сервисы в Задания и перейти к Заданиям Монитора.');
 TranslateTheHint(ImageDimLogoBig,              'Вход на сайт DIM (локальная копия).');
 TranslateTheHint(ImageCernLogo,                'Домашний сайт CERN - https://cern.ch');
 TranslateTheHint(ImageDimLogo,                 'Домашний сайт DIM - https://dim.web.cern.ch');
 ///////////////////////////////////////////////
 TranslateCaption(TabSheetDimJob,               ' Задания ');
 TranslateCaption(GroupBoxDimJob,               ' Задания DIM - Сервисы для отображения в Мониторе ');
 TranslateCaption(GroupBoxDimJobParams,         ' Параметры: ');
 TranslateCaption(LabelDimJobPeriod,            'сек - Период');
 TranslateTheHint(LabelDimJobPeriod,            'Период (сек) обновления данных в режиме timed Монитора.');
 TranslateTheHint(SpinEditDimJobPeriod,         'Период (сек) обновления данных в режиме timed Монитора.');
 TranslateCaption(LabelDimJobFillHex,           'Маркер "НЕТ СВЯЗИ" (HEX)');
 TranslateTheHint(LabelDimJobFillHex,           'Маркер "НЕТ СВЯЗИ" (HEX) в случае разрыва связи.');
 TranslateTheHint(ComboBoxDimJobFillHex,        'Маркер "НЕТ СВЯЗИ" (HEX) в случае разрыва связи.');
 TranslateCaption(GroupBoxDimJobKind,           ' Имя,Тип,Формат Сервиса: ');
 TranslateTheHint(ComboBoxDimJobKind,           'Задание - Тип Сервиса (Клиент/Сервер,Команда/Данные).');
 TranslateTheHint(EditDimJobService,            'Задание - Имя для идентификации Сервиса в сети.');
 TranslateTheHint(EditDimJobFormat,             'Задание - Описание Формата Данных Сервиса.');
 TranslateCaption(LabelDimJobMonitoring,        'Монитор:');
 TranslateTheHint(LabelDimJobMonitoring,        'Тип монитора: (периодический,событийный).');
 TranslateCaption(LabelDimJobTitle,             'Заголовок (видимое имя)');
 TranslateTheHint(EditDimJobTitle,              'Заголовок (отображаемое имя) Сервиса.');
 TranslateCaption(GroupBoxDimJobControl,        ' Управление DIM Заданиями: ');
 TranslateCaption(ActionDimJobClear,            'Очистить');
 TranslateTheHint(BitBtnDimJobClear,            'Очистить все задания DIM Монитора.');
 TranslateCaption(ActionDimJobAdd,              'Добавить');
 TranslateTheHint(BitBtnDimJobAdd,              'Добавить задание к DIM Монитору.');
 TranslateCaption(ActionDimJobDel,              'Удалить');
 TranslateTheHint(BitBtnDimJobDel,              'Удалить задание DIM Монитора.');
 TranslateTheHint(BitBtnDimJobMoveUp,           'Сдвинуть задание DIM Монитора Вверх по списку.');
 TranslateTheHint(BitBtnDimJobMoveDown,         'Сдвинуть задание DIM Монитора Вниз по списку.');
 TranslateCaption(ActionDimJobSaveIni,          'Запись');
 TranslateTheHint(BitBtnDimJobSaveIni,          'Сохранить Задания в INI файл.');
 TranslateCaption(ActionDimJobLoadIni,          'Чтение');
 TranslateTheHint(BitBtnDimJobLoadIni,          'Загрузить Задания из INI файла.');
 TranslateCaption(ActionDimJobStartMonitor,     'Пуск Монитора');
 TranslateTheHint(BitBtnDimJobStartMonitor,     'Запуск DIM Монитора.');
 TranslateTheHint(BitBtnDimMonitorStart,        'Запуск DIM Монитора.');
 ///////////////////////////////////////////////
 TranslateCaption(TabSheetDimMonitor,           ' Монитор ');
 TranslateCaption(GroupBoxDimMonitor,           ' DIM Монитор: ');
 TranslateCaption(CheckBoxDimMonitorPause,      'Пауза');
 TranslateTheHint(CheckBoxDimMonitorPause,      'Пауза - приостановить обновление данных.');
 TranslateCaption(LabelDimMonitorFontSize,      'Шрифт,pt');
 TranslateTheHint(LabelDimMonitorFontSize,      'Установить Размер Шрифта,pt для таблицы Монитора.');
 TranslateTheHint(ComboBoxDimMonitorFontSize,   'Установить Размер Шрифта,pt для таблицы Монитора.');
 TranslateCaption(ActionDimMonitorRefresh,      'Обновить');
 TranslateTheHint(BitBtnDimMonitorRefresh,      'Обновить (перерисовать, настроить размеры столбцов).');
 TranslateCaption(ActionDimMonitorGridCopy,     'Копия');
 TranslateTheHint(BitBtnDimMonitorGridCopy,     'Копировать данные Таблицы в Буфер Обмена.');
 ///////////////////////////////////////////////
 TranslateCaption(TabSheetDimMonitorConsole,    ' Консоль ');
 TranslateCaption(GroupBoxDimMonitorConsole,    ' Консоль DIM Монитора: ');
 TranslateCaption(CheckBoxDimMonitorConsole,    'Включить Консоль DIM Монитора. История, строк:');
 TranslateTheHint(SpinEditDimMonitorConsoleHistory, 'История Консоли DIM Монитора, строк');
 TranslateCaption(ActionDimMonitorConsoleClear, 'Чистка');
 TranslateTheHint(BitBtnDimMonitorConsoleClear, 'Очистка Консоли DIM Монитора.');
 TranslateCaption(ActionDimMonitorConsoleCopy,  'Копия');
 TranslateTheHint(BitBtnDimMonitorConsoleCopy,  'Копия Консоли DIM Монитора в Буфер Обмена');
 TranslateCaption(ActionDimMonitorConsoleUnselect, 'Нет');
 TranslateTheHint(BitBtnDimMonitorConsoleUnselect, 'Отменить выбор текста в Консоли DIM Монитора.');
 TranslateCaption(ActionDimMonitorConsoleSelectAll, 'Всё');
 TranslateTheHint(BitBtnDimMonitorConsoleSelectAll, 'Выбор всего текста в Консоли DIM Монитора.');
 TranslateCaption(LabelDimMonitorConsoleInput,    'Ввод:');
 TranslateCaption(ActionDimMonitorConsoleSend,  'Послать');
 TranslateTheHint(BitBtnDimMonitorConsoleSend,  'Послать команду в DIM Монитор.');
 TranslateCaption(LabeMainSendUserCmnd,         'Послать введенную команду');
 TranslateTheHint(EditMainSendUserCmnd,         'Ввод команды для Консоли CRW-DAQ.');
 TranslateCaption(ActionMainSendUserCmnd,       'Послать');
 TranslateTheHint(BitBtnMainSendUserCmnd,       'Послать команду в консоль CRW-DAQ.');
 TranslateCaption(ActionMainExecUserCmnd,       'Пуск');
 TranslateTheHint(BitBtnMainExecUserCmnd,       'Запустить команду.');
 TranslateCaption(ActionMainFormShow,           'Открыть форму');
 TranslateTheHint(ActionMainFormShow,           'Открыть главную форму программы.');
 TranslateCaption(ActionMainProgramExit,        'Выход');
 TranslateTheHint(BitBtnMainProgramExit,        'Выйти из программы.');
 TranslateCaption(ActionMainParentShow,         'Открыть');
 TranslateTheHint(BitBtnMainParentShow,         'Открыть (активировать) родительский процесс CRW-DAQ.');
 ///////////////////////////////////////////////
 TranslateCaption(TabSheetDimParams,            ' Параметры ');
 TranslateCaption(GroupBoxExecParams,           ' Параметры пуска ');
 TranslateCaption(LabelDefExecBuffKb,           'Буфер I/O для обычных задач, КБ');
 TranslateTheHint(LabelDefExecBuffKb,           'Размер Буфера Ввода/Вывода для запуска обычных задач, КБ.');
 TranslateTheHint(ComboBoxDefExecBuffKb,        'Размер Буфера Ввода/Вывода для запуска обычных задач, КБ.');
 TranslateCaption(LabelBigExecBuffKb,           'Буфер I/O для больших задач, КБ');
 TranslateTheHint(LabelBigExecBuffKb,           'Размер Буфера Ввода/Вывода для запуска больших задач, КБ.');
 TranslateTheHint(ComboBoxBigExecBuffKb,        'Размер Буфера Ввода/Вывода для запуска больших задач, КБ.');
 TranslateCaption(LabelDefExecTimeOut,          'Время для обычных задач, мс');
 TranslateTheHint(LabelDefExecTimeOut,          'Время ожидания выполнения обычных задач, мс.');
 TranslateTheHint(ComboBoxDefExecTimeOut,       'Время ожидания выполнения обычных задач, мс.');
 TranslateCaption(LabelBigExecTimeOut,          'Время для больших задач, мс');
 TranslateTheHint(LabelBigExecTimeOut,          'Время ожидания выполнения больших задач, мс.');
 TranslateTheHint(ComboBoxBigExecTimeOut,       'Время ожидания выполнения больших задач, мс.');
 TranslateCaption(GroupBoxDisplayParams,        ' Параметры отображения: ');
 TranslateCaption(BitBtnDisplayLanguageRussian, ' Русский ');
 TranslateTheHint(BitBtnDisplayLanguageRussian, 'Установить для отображения Русский язык.');
 TranslateCaption(BitBtnDisplayLanguageEnglish, ' Английский ');
 TranslateTheHint(BitBtnDisplayLanguageEnglish, 'Установить для отображения Английский язык.');
 TranslateCaption(LabelLogEventsHistory,        'История событий, строк');
 TranslateTheHint(LabelLogEventsHistory,        'Длина истории событий, строк.');
 TranslateTheHint(SpinEditLogEventsHistory,     'Длина истории событий, строк.');
 ///////////////////////////////////////////////
 TranslateCaption(TabSheetLogEvents,            ' Журнал ');
 TranslateCaption(LabelLogEvents,               'Журнал событий:');
 TranslateCaption(LabelMainListSysInfo,         'Инфо тема:');
 TranslateCaption(LabelMainListSysInfoTimeOut,  'TimeOut');
 TranslateTheHint(SpinEditMainListSysInfoTimeOut, 'Время ожидания при запуске команд, мс.');
 TranslateCaption(ActionMainListSysInfo,        'Инфо');
 TranslateTheHint(BitBtnMainListSysInfo,        'Печать системной информации на выбранную тему.');
 TranslateCaption(BitBtnLogEventsTest,          ' Тест');
 TranslateTheHint(BitBtnLogEventsTest,          'Возбудить тестовое исключение.');
 TranslateCaption(ActionLogEventsClear,         'Очистка');
 TranslateTheHint(BitBtnLogEventsClear,         'Очистить журнал событий.');
 TranslateCaption(ActionLogEventsGoBack,        'Назад');
 TranslateTheHint(BitBtnLogEventsGoBack,        'Назад, на главную страницу.');
 ///////////////////////////////////////////////
 ActionDimMonitorRefresh.Execute;
end;

procedure TMainForm.BugReport(E:Exception; Sender:TObject; Where:String);
begin
 SystemBugReport(E,Sender,Where);
 PageControlMain.ActivePage:=TabSheetLogEvents;
end;

procedure TMainForm.SendCommandToCrwDaq(S:String; Activate:Boolean=true);
begin
 try
  if (CRW_DAQ_SYS_EXE_PID=0)
  then RaiseException('Parent Crw32.exe process is not specified.');
  S:=Trim(S); if (S='') then Exit;
  if (CRW_DAQ_SYS_EXE_PID=0) then Exit;
  if Activate then AppActivateByTitle(ParentCrwDaqTitle);
  if (Send2CrwDaq(CRW_DAQ_SYS_EXE_PID,S,Handle)=0)
  then LogEvents(Now,'Sent command: '+S)
  else LogEvents(Now,'Fail command: '+S);
 except
  on E:Exception do Self.BugReport(E,Self,'SendCommandToCrwDaq');
 end;
end;

procedure TMainForm.PostCommandToCrwDaq(S:String);
begin
 SendCommandToCrwDaq(S,false);
end;

procedure TMainForm.TimerDimMonitoringTimer(Sender: TObject);
begin
 DoMonitoring;
end;

procedure TMainForm.TimerDimPollRateTimer(Sender: TObject);
begin
 DoPollRate;
end;

procedure TMainForm.ActionDimJobClearExecute(Sender: TObject);
begin
 ListBoxDimJob.Clear;
end;

procedure TMainForm.ListBoxDimJobClick(Sender: TObject);
begin
 ActionDimJobItemSelect.Execute;
end;

procedure TMainForm.ActionDimJobMoveUpExecute(Sender: TObject);
begin
 DimJobMove(-1);
 ActionDimJobItemSelect.Execute;
end;

procedure TMainForm.ActionDimJobMoveDownExecute(Sender: TObject);
begin
 DimJobMove(+1);
 ActionDimJobItemSelect.Execute;
end;

procedure TMainForm.ActionDimJobItemSelectExecute(Sender: TObject);
var i:Integer; item:String;
begin
 i:=ListBoxDimJob.ItemIndex;
 if (i&gt;=0) and (i&lt;ListBoxDimJob.Count) then begin
  item:=ListBoxDimJob.Items.Strings[i];
  ComboBoxDimJobKind.Text:=ExtractWord(1,item,DimScanSpaces);
  EditDimJobService.Text:=ExtractWord(2,item,DimScanSpaces);
  EditDimJobFormat.Text:=ExtractWord(3,item,DimScanSpaces);
  ComboBoxDimJobMonitoringType.Text:=ExtractWord(4,item,DimScanSpaces);
  SpinEditDimJobPeriod.Value:=StrToIntDef(ExtractWord(5,item,DimScanSpaces),1);
  ComboBoxDimJobFillHex.Text:=RecodeStr(ExtractWord(6,item,DimScanSpaces),'base64,hex');
  EditDimJobTitle.Text:=RecodeStr(ExtractWord(7,item,DimScanSpaces),'base64,rawbyte');
 end;
end;

procedure TMainForm.ActionDimJobAddExecute(Sender: TObject);
var job,kind,serv,frmt,mntr,tmon,fill,titl:String;
begin
 try
  kind:= Trim(ComboBoxDimJobKind.Text);
  serv:=Trim(EditDimJobService.Text);
  frmt:=Trim(EditDimJobFormat.Text);
  mntr:=Trim(ComboBoxDimJobMonitoringType.Text);
  tmon:=IntToStr(SpinEditDimJobPeriod.Value);
  fill:=RecodeStr(Trim(ComboBoxDimJobFillHex.Text),'Hex,Base64');
  titl:=RecodeStr(EditDimJobTitle.Text,'rawbyte,base64');
  job:=ComposeDimJob(kind,serv,frmt,mntr,tmon,fill,titl);
  AddDimJob(job);
 except
  on E:Exception do BugReport(E,Self,'ActionDimJobAddExecute');
 end;
end;

procedure TMainForm.ActionDimJobDelExecute(Sender: TObject);
var i:Integer;
begin
 try
  i:=ListBoxDimJob.ItemIndex;
  if (i&gt;=0) then ListBoxDimJob.Items.Delete(i);
  if (ListBoxDimJob.Items.Count&gt;0) then begin
   ListBoxDimJob.ItemIndex:=iMin(i,ListBoxDimJob.Items.Count-1);
   ListBoxDimJobClick(Sender);
  end;
 except
  on E:Exception do BugReport(E,Self,'ActionDimJobDelExecute');
 end;
end;

procedure TMainForm.SpinEditDimSelPeriodChange(Sender: TObject);
begin
 if (SpinEditDimSelPeriod.Value=0)
 then ComboBoxDimSelMonitoring.ItemIndex:=1;
end;

procedure TMainForm.SpinEditDimJobPeriodChange(Sender: TObject);
begin
 if (SpinEditDimJobPeriod.Value=0)
 then ComboBoxDimJobMonitoringType.ItemIndex:=1;
end;

procedure TMainForm.ComboBoxDimSelMonitoringTypeChange(Sender: TObject);
begin
 if (ComboBoxDimSelMonitoring.ItemIndex=0)
 then SpinEditDimSelPeriod.Value:=iMax(1,SpinEditDimSelPeriod.Value);
end;

procedure TMainForm.ComboBoxDimJobMonitoringTypeChange(Sender: TObject);
begin
 if (ComboBoxDimJobMonitoringType.ItemIndex=0)
 then SpinEditDimJobPeriod.Value:=iMax(1,SpinEditDimJobPeriod.Value);
end;

procedure TMainForm.DimJobLoadIniFromArgs;
var ini:String;
begin
 ini:=GetOptIniFile(1); if (ini='') then Exit;
 ListBoxDimJob.Items.Text:=DimJobLoadIni(ini,sid_DimMonitorJob);
end;

function TMainForm.DimJobSaveIni(FileName,Section,JobText:String):Integer;
var IniFile:TIniFile; JobList:TStrings; i:Integer;
begin
 Result:=0;
 try
  IniFile:=nil;
  JobList:=nil;
  Section:=Trim(Section); if (Section='') then Exit;
  FileName:=Trim(FileName); if (FileName='') then Exit;
  if (ExtractFileDir(FileName)='') then FileName:=AddPathDelim(ExtractFileDir(GetOptIniFile(2)))+FileName;
  if not DirectoryExists(ExtractFileDir(FileName)) then Exit;
  try
   JobList:=TStringList.Create;
   JobList.Text:=JobText;
   IniFile:=TIniFile.Create(FileName);
   IniFile.EraseSection(Section);
   IniFile.WriteString(Section,'JobCount',IntToStr(JobList.Count));
   for i:=0 to JobList.Count-1 do begin
    IniFile.WriteString(Section,FormatVar('Job%d',DimMonitor.IndexToTag(i)),JobList.Strings[i]);
   end;
   IniFile.WriteString(sid_DimMonitorParams,'DNS',Trim(ComboBoxDimDnsNode.Text));
   IniFile.WriteString(sid_DimMonitorParams,'Top',IntToStr(Top));
   IniFile.WriteString(sid_DimMonitorParams,'Left',IntToStr(Left));
   IniFile.WriteString(sid_DimMonitorParams,'Width',IntToStr(Width));
   IniFile.WriteString(sid_DimMonitorParams,'Height',IntToStr(Height));
   IniFile.WriteString(sid_DimMonitorParams,'DimMonitorFontSize',Trim(ComboBoxDimMonitorFontSize.Text));
   IniFile.WriteString(sid_DimMonitorParams,'Language',RusEng('ru','en'));
   IniFile.WriteString(sid_DimMonitorParams,'LogEventsHistory',IntToStr(SpinEditLogEventsHistory.Value));
   IniFile.UpdateFile;
   Result:=(JobList.Count);
  finally
   IniFile.Free;
   JobList.Free;
  end;
 except
  on E:Exception do BugReport(E,Self,'DimJobSaveIni');
 end;
end;

function  TMainForm.DimJobLoadIni(FileName,Section:String):String;
var IniFile:TIniFile; JobList:TStrings; n,i,l:Integer; line:String;
begin
 Result:='';
 try
  IniFile:=nil;
  JobList:=nil;
  Section:=Trim(Section); if (Section='') then Exit;
  FileName:=Trim(FileName); if (FileName='') then Exit;
  if (ExtractFileDir(FileName)='') then FileName:=AddPathDelim(ExtractFileDir(GetOptIniFile(2)))+FileName;
  if not FileExists(FileName) then Exit;
  try
   JobList:=TStringList.Create;
   IniFile:=TIniFile.Create(FileName);
   n:=StrToIntDef(IniFile.ReadString(Section,'JobCount',''),0);
   for i:=0 to n-1 do begin
    line:=Trim(IniFile.ReadString(Section,FormatVar('Job%d',DimMonitor.IndexToTag(i)),''));
    if (line&lt;&gt;'') then JobList.Add(line);
   end;
   Result:=JobList.Text;
   if (Trim(ComboBoxDimDnsNode.Text)='')
   then ComboBoxDimDnsNode.Text:=Trim(IniFile.ReadString(sid_DimMonitorParams,'DNS',''));
   Top:=StrToIntDef(IniFile.ReadString(sid_DimMonitorParams,'Top',''),Top);
   Left:=StrToIntDef(IniFile.ReadString(sid_DimMonitorParams,'Left',''),Left);
   Width:=StrToIntDef(IniFile.ReadString(sid_DimMonitorParams,'Width',''),Width);
   Height:=StrToIntDef(IniFile.ReadString(sid_DimMonitorParams,'Height',''),Height);
   ComboBoxDimMonitorFontSize.Text:=Trim(IniFile.ReadString(sid_DimMonitorParams,'DimMonitorFontSize',ComboBoxDimMonitorFontSize.Text));
   l:=WordIndex(Trim(IniFile.ReadString(sid_DimMonitorParams,'Language','')),'en,ru',', ');
   if (l in [1,2]) then UpdateGuiLanguage(l);
   if not IsEmptyStr(ComboBoxDimDnsNode.Text) then DimDnsRefresh;
   SpinEditLogEventsHistory.Value:=StrToIntDef(IniFile.ReadString(sid_DimMonitorParams,'LogEventsHistory',''),SpinEditLogEventsHistory.Value);
  finally
   IniFile.Free;
   JobList.Free;
  end;
 except
  on E:Exception do BugReport(E,Self,'DimJobLoadIni');
 end;
end;

procedure TMainForm.ActionDimJobSaveIniExecute(Sender: TObject);
begin
 try
  if (SaveDialogDimJobSaveIni.InitialDir='')
  then SaveDialogDimJobSaveIni.InitialDir:=ExtractFileDir(GetOptIniFile(2));
  if (SaveDialogDimJobSaveIni.FileName='')
  then SaveDialogDimJobSaveIni.FileName:=GetOptIniFile(3);
  if SaveDialogDimJobSaveIni.Execute then begin
   DimJobSaveIni(SaveDialogDimJobSaveIni.FileName,sid_DimMonitorJob,ListBoxDimJob.Items.Text);
  end;
 except
  on E:Exception do BugReport(E,Self,'ActionDimJobSaveIniExecute');
 end;
end;

procedure TMainForm.ActionDimJobLoadIniExecute(Sender: TObject);
begin
 try
  if (OpenDialogDimJobLoadIni.InitialDir='')
  then OpenDialogDimJobLoadIni.InitialDir:=ExtractFileDir(GetOptIniFile(2));
  if (OpenDialogDimJobLoadIni.FileName='')
  then OpenDialogDimJobLoadIni.FileName:=GetOptIniFile(3);
  if OpenDialogDimJobLoadIni.Execute then begin
   ListBoxDimJob.Items.Text:=DimJobLoadIni(OpenDialogDimJobLoadIni.FileName,sid_DimMonitorJob);
  end;
 except
  on E:Exception do BugReport(E,Self,'ActionDimIniLoadExecute');
 end;
end;

procedure TMainForm.ActionDimJobStartMonitorExecute(Sender: TObject);
begin
 StartMonitoring;
 if DimMonitor.IsMonitoring then PageControlMain.ActivePage:=TabSheetDimMonitor;
end;

procedure TMainForm.ActionDimMonitorConsoleClearExecute(Sender: TObject);
begin
 MemoDimMonitorConsole.Clear;
end;

procedure TMainForm.ActionDimMonitorConsoleCopyExecute(Sender: TObject);
begin
 try
  Clipboard.AsText:=MemoDimMonitorConsole.SelText;
 except
  on E:Exception do Self.BugReport(E,Self,'ActionDimMonitorConsoleCopyExecute');
 end;
end;

procedure TMainForm.ActionDimMonitorConsoleUnselectExecute(Sender: TObject);
begin
 try
  MemoDimMonitorConsole.SelStart:=MaxInt;
  MemoDimMonitorConsole.SelLength:=0;
 except
  on E:Exception do Self.BugReport(E,Self,'ActionDimMonitorConsoleUnselectExecute');
 end;
end;

procedure TMainForm.ActionDimMonitorConsoleSelectAllExecute(Sender: TObject);
begin
 try
  MemoDimMonitorConsole.SelectAll;
  MemoDimMonitorConsole.Invalidate;
 except
  on E:Exception do Self.BugReport(E,Self,'ActionDimMonitorConsoleSelectAllExecute');
 end;
end;

procedure TMainForm.ActionDimMonitorConsoleSendExecute(Sender: TObject);
var cmd:String;
begin
 try
  cmd:=Trim(ComboBoxDimMonitorConsoleInput.Text); if (cmd='') then Exit;
  DimMonitor.Dim_Send(cmd);
 except
  on E:Exception do Self.BugReport(E,Self,'ActionDimMonitorConsoleSendExecute');
 end;
end;

procedure TMainForm.BitBtnDimServiceSelectAndGoToJobClick(Sender: TObject);
begin
 SelectServerServices;
 PageControlMain.ActivePage:=TabSheetDimJob;
end;

procedure TMainForm.ActionDimAboutExecute(Sender: TObject);
var msg:String;
begin
 msg:=GetScriptBaseName+' - GUI Utility to observe DIM Service(s).'+EOL
     +'Copyright (c) 2022-2023 Alexey Kuryakin daqgroup@mail.ru'+EOL
     +'Usage: '+GetScriptBaseName+' [Option Param]'+EOL
     +'Options:'+EOL
     +' --number n   - set instance number (1..9)'+EOL
     +' --padding p  - set DIM data padding (0,1)'+EOL
     +' --lang l     - set GUI language l=(en,ru)'+EOL
     +' --ini file   - set INI file name to load'+EOL
     +' --dns node   - set DIM DNS node hostname'+EOL
     +'Example:'+EOL
     +' '+GetScriptBaseName+' --number 1 --dns localhost --ini '
     +GetScriptBaseName+'_1.ini'+' --lang ru'+EOL;
 ShowMessage(msg);
end;

function Browser:String;
begin
 Result:='firefox';
 if IsWindows then Result:='unix getapppath firefox.exe chrome.exe opera.exe iexplore.exe .html --start';
end;

procedure TMainForm.ImageCernLogoClick(Sender: TObject);
var site:String;
begin
 site:='https://cern.ch';
 Exec(Browser+' '+site);
end;

procedure TMainForm.ImageDimLogoClick(Sender: TObject);
var site:String;
begin
 site:='https://dim.web.cern.ch';
 Exec(Browser+' '+site);
end;

procedure TMainForm.ImageDimLogoBigClick(Sender: TObject);
const index='/../../dim.web.cern.ch/index.html';
var site,s:String;
begin
 site:=DimMonitor.DimStatExe(1); s:=site;
 if IsUnix then if RunCommand('realpath '+site,s) then site:=Trim(s);
 if IsWindows then site:=ExpandFileName(AnsiDeQuotedStr(site,'"'));
 site:=ExpandFileName(AddPathDelim(ExtractFileDir(site))+index);
 if FileExists(site)
 then LogEvents(Now,'Browse '+site)
 else LogEvents(Now,'Missed '+site);
 if not FileExists(site) then Exit;
 if IsWindows and (Pos(' ',site)&gt;0) then site:=AnsiQuotedStr(site,'"');
 if IsUnix then site:='file://'+site;
 Exec(Browser+' '+site);
end;

procedure TMainForm.ComboBoxDimMonitorFontSizeChange(Sender: TObject);
var fs:Integer; sz:String;
begin
 if (DimMonitor.StringGrid=nil) then Exit;
 fs:=DimMonitor.StringGrid.Font.Size;
 sz:=Trim(ComboBoxDimMonitorFontSize.Text);
 DimMonitor.StringGrid.Font.Size:=StrToIntDef(sz,fs);
 DimMonitor.DrawJobItems(255);
end;

procedure TMainForm.ActionDimMonitorRefreshExecute(Sender: TObject);
begin
 DimMonitor.DrawJobItems(255);
end;

procedure TMainForm.ActionDimMonitorGridCopyExecute(Sender: TObject);
var Lines:TStringList; row,col:Integer; Line:String;
begin
 if (DimMonitor.StringGrid=nil) then Exit;
 try
  Lines:=TStringList.Create;
  try
   for row:=0 to DimMonitor.StringGrid.RowCount-1 do begin
    Line :='';
    for col:=0 to DimMonitor.StringGrid.ColCount-1 do begin
     Line:=Line+vbTab+Trim(DimMonitor.StringGrid.Cells[col,row]);
    end;
    Line:=Trim(Line);
    Lines.Add(Line);
   end;
   Clipboard.AsText:=Lines.Text;
  finally
   Lines.Free;
  end;
 except
  on E:Exception do BugReport(E,Self,'ActionDimMonitorGridCopyExecute');
 end;
end;

procedure TMainForm.StringGridDimMonitorDrawCell(Sender: TObject; aCol: LongInt; aRow: LongInt; aRect: TRect; aState: TGridDrawState);
var StringGrid:TStringGrid; Color:TColor; Cell:String;
begin
 if (Sender is TStringGrid) then
 try
  StringGrid:=TStringGrid(Sender);
  Cell:=StringGrid.Cells[aCol,aRow];
  Color:=StringGrid.FixedColor; // Calculate fill color
  if (aCol&gt;=StringGrid.FixedCols) and (aRow&gt;=StringGrid.FixedRows)
  then Color:=StringGrid.Color;
  if (aCol=1) and (aRow&gt;0) then begin
   if SameText(Trim(Cell),'ON') then Color:=DimMonitor.ColorGridOn else
   if SameText(Trim(Cell),'OF') then Color:=DimMonitor.ColorGridOff;
  end;
  StringGrid.Canvas.Brush.Color:=Color;
  StringGrid.Canvas.FillRect(aRect.Left,ARect.Top,aRect.Right,aRect.Bottom);
  StringGrid.Canvas.TextOut(aRect.Left+2,aRect.Top+2,Cell);
 except
  on E:Exception do BugReport(E,Self,'StringGridDimMonitorDrawCell');
 end;
end;

procedure TMainForm.StringGridDimMonitorGetCellHint(Sender: TObject; ACol: LongInt; ARow: LongInt; var HintText: AnsiString);
var aHint:AnsiString;
begin
 aHint:=DimMonitor.CellHint(aCol,aRow);
 if (aHint&lt;&gt;'') then HintText:=aHint;
end;

procedure TMainForm.BitBtnDisplayLanguageRussianClick(Sender: TObject);
begin
 UpdateGuiLanguage(lng_Russian);
end;

procedure TMainForm.BitBtnDisplayLanguageEnglishClick(Sender: TObject);
begin
 UpdateGuiLanguage(lng_English);
end;

procedure TMainForm.SpinEditLogEventsHistoryChange(Sender: TObject);
begin
 LogEventsHistoryLimit:=SpinEditLogEventsHistory.Value;
end;

procedure TMainForm.DimJobMove(Step:Integer);
var i1,i2:Integer; Item:String;
begin
 if not DimMonitor.IsMonitoring then
 if (ListBoxDimJob.ItemIndex&gt;=0) then
 if (ListBoxDimJob.Items.Count&gt;1) then
 try
  i1:=ListBoxDimJob.ItemIndex;
  i2:=ListBoxDimJob.ItemIndex+Step;
  if (i1&lt;0) or (i1&gt;=ListBoxDimJob.Items.Count) then Exit;
  if (i2&lt;0) or (i2&gt;=ListBoxDimJob.Items.Count) then Exit;
  Item:=ListBoxDimJob.Items.Strings[i1];
  ListBoxDimJob.Items.Strings[i1]:=ListBoxDimJob.Items.Strings[i2];
  ListBoxDimJob.Items.Strings[i2]:=Item;
  ListBoxDimJob.ItemIndex:=i2;
 except
  on E:Exception do BugReport(E,Self,'DimJobMove');
 end;
end;

procedure TMainForm.StartMonitoring;
begin
 if not DimMonitor.IsMonitoring then
 if (ListBoxDimJob.Items.Count&gt;0) then
 try
  DimMonitor.MonitorJob.Text:=ListBoxDimJob.Items.Text;
  if DimMonitor.MonitorJob.Count&gt;0 then DimMonitor.StartMonitoring;
 except
  on E:Exception do BugReport(E,Self,'StartMonitoring');
 end;
end;

procedure TMainForm.DoMonitoring;
var HistLen:Integer;
 procedure UpdateState(Mon:Boolean);
 begin
  PanelDimJob.Enabled:=not Mon;
  PanelDimBrowser.Enabled:=not Mon;
  GroupBoxDimDnsNode.Enabled:=not Mon;
  //PanelDimMonitorConsole.Enabled:=Mon;
  ActionDimJobStartMonitor.Enabled:=(ListBoxDimJob.Count&gt;0) and not Mon;
  ActionDimJobMoveUp.Enabled:=not Mon and (ListBoxDimJob.ItemIndex&gt;0);
  ActionDimJobMoveDown.Enabled:=not Mon and (ListBoxDimJob.ItemIndex&gt;=0)
    and (ListBoxDimJob.ItemIndex&lt;ListBoxDimJob.Count-1);
 end;
begin
 try
  DimMonitor.Pause:=CheckBoxDimMonitorPause.Checked;
  if DimMonitor.IsMonitoring then begin
   DimMonitor.PollMonitoring;
   if CheckBoxDimMonitorConsole.Checked then begin
    if (DimMonitor.MonitorOut.Count&gt;0) then begin
     try
      MemoDimMonitorConsole.Lines.BeginUpdate;
      AddTextAsEventLog(MemoDimMonitorConsole.Lines,Now,DimMonitor.MonitorOut.Text);
      //StringsAppendFromStrings(MemoDimMonitorConsole.Lines,DimMonitor.MonitorOut);
      HistLen:=SpinEditDimMonitorConsoleHistory.Value;
      if (HistLen&gt;0) then begin
       while (MemoDimMonitorConsole.Lines.Count&gt;HistLen)
       do MemoDimMonitorConsole.Lines.Delete(0);
      end;
     finally
      MemoDimMonitorConsole.Lines.EndUpdate;
     end;
     MemoDimMonitorConsole.SelStart:=MaxInt;
    end;
   end else begin
    //if (MemoDimMonitorConsole.Lines.Count&gt;0)
    //then MemoDimMonitorConsole.Lines.Clear;
   end;
   DimMonitor.MonitorOut.Clear;
   UpdateState(true);
  end else begin
   UpdateState(false);
  end;
 except
  on E:Exception do BugReport(E,Self,'DoMonitoring');
 end;
end;

procedure TMainForm.DoPollRate;
var s,status:String;
begin
 try
  if DimMonitor.IsMonitoring then begin
   DimMonitor.HandleTimeTick;
   DimMonitor.PollRateHandler;
   if DimMonitor.IsMonitorRunning
   then s:=RusEng('Работает ','Running ')
   else s:=RusEng('Завершен ','Stopped ');
   s:=s+FormatVar('PID: %u  ',DimMonitor.MonitorPid);
   s:=s+FormatVar('Ticks:%u  ',DimMonitor.TimeTicks);
   s:=s+FormatVar('Lines:%u  ',DimMonitor.LineCount);
   s:=s+FormatVar('PollRate:%-4u ',DimMonitor.PollRate(0));
   s:=s+FormatVar('dis_info:%-4u ',DimMonitor.PollRate(dis_info));
   s:=s+FormatVar('dis_cmnd:%-4u ',DimMonitor.PollRate(dis_cmnd));
   s:=s+FormatVar('dic_info:%-4u ',DimMonitor.PollRate(dic_info));
   s:=s+FormatVar('dic_cmdn:%-4u ',DimMonitor.PollRate(dic_cmnd));
   s:=s+FormatVar('PollCount:%u  ',DimMonitor.PollCount(0));
   s:=s+FormatVar('dis_info:%u  ',DimMonitor.PollCount(dis_info));
   s:=s+FormatVar('dis_cmnd:%u  ',DimMonitor.PollCount(dis_cmnd));
   s:=s+FormatVar('dic_info:%u  ',DimMonitor.PollCount(dic_info));
   s:=s+FormatVar('dic_cmdn:%u  ',DimMonitor.PollCount(dic_cmnd));
   StatusBarDimMonitor.SimpleText:=s;
   if DimMonitor.IsMonitorRunning
   then status:=RusEng('Работает PID ','Running PID ')+IntToStr(DimMonitor.MonitorPid)
   else status:=RusEng('Завершен PID ','Stopped PID ')+IntToStr(DimMonitor.MonitorPid);
  end else begin
   status:=RusEng('Неактивен','Inactive');
   StatusBarDimMonitor.SimpleText:=status;
  end;
  GroupBoxDimMonitorControl.Caption:=RusEng(' Статус DIM Монитора: ',' DIM Monitor Control: ')+status;
  GroupBoxDimMonitorConsole.Caption:=RusEng(' Консоль DIM Монитора: ',' DIM Monitor Console: ')+status;
  GroupBoxDimMonitor.Caption:=RusEng(' DIM Монитор: ',' DIM Monitor: ')+status;
 except
  on E:Exception do BugReport(E,Self,'DoMonitoring');
 end;
end;

procedure TMainForm.UpdateDimMonitorOptions;
begin
 DimMonitor.DefExecBuffKb:=DefExecBuffKb;
 DimMonitor.DefExecTimeOut:=DefExecTimeOut;
end;

procedure TMainForm.DimDnsRefresh;
begin
 try
  DimMonitor.Reset;
  DimMonitor.DIM_DNS_NODE:=Trim(ComboBoxDimDnsNode.Text);
  ListBoxDimServers.Items.Clear;
  UpdateDimServerServices('');
  UpdateDimMonitorOptions;
  UpdateDnsStatus;
 except
  on E:Exception do BugReport(E,Self,'DimDnsRefresh');
 end;
end;

procedure TMainForm.UpdateDnsStatus;
var IsDns:Boolean; DnsStatus:String;
begin
 try
  IsDns:=false;
  DnsStatus:=RusEng('НЕОПРЕДЕЛЕННЫЙ','UNDEFINED');
  if (DimMonitor.DIM_DNS_NODE&lt;&gt;'') then begin
   IsDns:=DimMonitor.IsDnsRunning;
   LogEvents(Now,DimMonitor.DnsRunningAns);
   if IsDns then DnsStatus:=RusEng('РАБОТАЕТ','RUNNING') else
   if (DimMonitor.DnsRunningAns&lt;&gt;'') then DnsStatus:=RusEng('НЕДОСТУПНЫЙ','UNAVAILABLE');
   if IsDns
   then DimMonitor.DnsStatusColor:=DimMonitor.ColorOnline
   else DimMonitor.DnsStatusColor:=DimMonitor.ColorOffline;
  end else begin
   DimMonitor.DnsStatusColor:=DimMonitor.ColorUndefined;
  end;
  LabelDimDnsStatusValue.Font.Color:=DimMonitor.DnsStatusColor;
  LabelDimDnsStatusValue.Caption:=DnsStatus;
  ListBoxDimServers.Items.Text:=DimMonitor.ListDimServers;
 except
  on E:Exception do BugReport(E,Self,'UpdateDnsStatus');
 end;
end;

procedure TMainForm.UpdateDimServerServices(aServer:String);
begin
 try
  aServer:=Trim(aServer);
  if (aServer='') then begin
   GroupBoxDimServerServices.Caption:=RusEng(' Сервисы DIM сервера: ',' DIM Server Services: ');
   ListBoxDimServerServices.Items.Clear;
  end else begin
   GroupBoxDimServerServices.Caption:=FormatVar(RusEng(' Сервисы %s: ',' %s Services: '),aServer);
   ListBoxDimServerServices.Items.Text:=DimMonitor.ListDimServerServices(aServer);
  end;
 except
  on E:Exception do BugReport(E,Self,'UpdateDimServerServices');
 end;
end;

function TMainForm.FindDimJob(serv:String):Integer;
var i:Integer; List:TStrings;
begin
 Result:=-1;
 if (serv='') then Exit;
 List:=ListBoxDimJob.Items;
 for i:=0 to List.Count-1 do
 if SameText(serv,ExtractWord(2,List.Strings[i],DimScanSpaces)) then begin
  Result:=i;
  Exit;
 end;
end;

function TMainForm.ComposeDimJob(kind,serv,frmt,mntr,tmon,fill,titl:String):String;
begin
 Result:=kind+','+serv+','+frmt+','+mntr+','+tmon+','+fill+','+titl;
end;

function TMainForm.AddDimJob(job:String):Integer;
var i:Integer; serv:String;
begin
 Result:=-1;
 try
  if (WordCount(job,DimScanSpaces)&lt;6) then Exit;
  serv:=ExtractWord(2,job,DimScanSpaces);
  i:=FindDimJob(serv);
  if (i&lt;0)
  then ListBoxDimJob.Items.Add(job)
  else ListBoxDimJob.Items.Strings[i]:=job;
  Result:=FindDimJob(serv);
 except
  on E:Exception do BugReport(E,Self,'AddDimJob');
 end;
end;

procedure TMainForm.SelectServerServices;
var i:Integer; line,kind,serv,frmt,mntr,tmon,fill,titl:String;
begin
 try
  for i:=0 to ListBoxDimServerServices.Items.Count-1 do begin
   if ListBoxDimServerServices.Selected[i] then begin
    line:=ListBoxDimServerServices.Items.Strings[i];
    serv:=ExtractWord(1,line,DimScanSpaces);
    frmt:=ExtractWord(2,line,DimScanSpaces);
    kind:=ExtractWord(3,line,DimScanSpaces);
    mntr:=DimSelMonitoringType;
    tmon:=IntToStr(DimSelPeriod);
    fill:=RecodeStr(DimSelFillHex,'hex,base64');
    titl:=RecodeStr(serv,'rawbyte,base64');
    if SameText(kind,'INFO') then begin
     kind:=ExtractWord(dic_info,DimKindList,DimScanSpaces);
     AddDimJob(ComposeDimJob(kind,serv,frmt,mntr,tmon,fill,titl));
    end;
    if SameText(kind,'CMD') then begin
     kind:=ExtractWord(dic_cmnd,DimKindList,DimScanSpaces);
     AddDimJob(ComposeDimJob(kind,serv,frmt,mntr,tmon,fill,titl));
    end;
   end;
  end;
 except
  on E:Exception do BugReport(E,Self,'SelectServerServices');
 end;
end;

function TMainForm.DefExecBuffKb:Integer;
begin
 Result:=StrToIntDef(Trim(ComboBoxDefExecBuffKb.Text),DivExecBuffKb);
 Result:=iMax(MinExecBuffKb,iMin(MaxExecBuffKb,Result));
end;

function TMainForm.BigExecBuffKb:Integer;
begin
 Result:=StrToIntDef(Trim(ComboBoxBigExecBuffKb.Text),BivExecBuffKb);
 Result:=iMax(MinExecBuffKb,iMin(MaxExecBuffKb,Result));
end;

function TMainForm.DefExecTimeOut:Integer;
begin
 Result:=StrToIntDef(Trim(ComboBoxDefExecTimeOut.Text),DivExecTimeout);
 Result:=iMax(MinExecTimeOut,iMin(MaxExecTimeOut,Result));
end;

function TMainForm.BigExecTimeOut:Integer;
begin
 Result:=StrToIntDef(Trim(ComboBoxBigExecTimeOut.Text),BivExecTimeout);
 Result:=iMax(MinExecTimeOut,iMin(MaxExecTimeOut,Result));
end;

function TMainForm.GetDimSelPeriod:Integer;
begin
 Result:=SpinEditDimSelPeriod.Value;
end;

function TMainForm.GetDimSelMonitoringType:String;
begin
 Result:=Trim(ComboBoxDimSelMonitoring.Text);
end;

function TMainForm.GetDimSelFillHex:String;
begin
 Result:=Trim(ComboBoxDimSelFillHex.Text);
end;

function TMainForm.Exec(cmd:String; timeout:Integer=0; BuffSizeKb:Integer=0):String;
var tid:Integer;
begin
 Result:='';
 try
  cmd:=Trim(cmd);
  if (Length(cmd)=0) then Exit;
  if (timeout&lt;MinExecTimeOut) then timeout:=DefExecTimeOut;
  if (BuffSizeKb&lt;MinExecBuffKb) then BuffSizeKb:=DefExecBuffKb;
  tid:=task_init(cmd);
  task_ctrl(tid,'Display=SW_HIDE');
  task_ctrl(tid,'StdInPipeSize='+IntToStr(1024*BuffSizeKb));
  task_ctrl(tid,'StdOutPipeSize='+IntToStr(1024*BuffSizeKb));
  task_ctrl(tid,'CodePage='+IntToStr(WinApi.GetACP));
  if task_run(tid) then begin
   task_wait(tid,timeout);
   Result:=task_recv(tid,MaxInt);
   if task_wait(tid,0) then task_kill(tid,1,0,500);
   if task_wait(tid,0) then task_kill(tid,0,0,0);
   Success(FormatVar('Exec[%d]: ',task_pid(tid))+cmd);
  end else begin
   Trouble('Could not Exec: '+cmd);
  end;
  task_free(tid);
 except
  on E:Exception do BugReport(E,Self,'Exec');
 end;
end;

procedure TMainForm.Trouble(Msg:String);
begin
 LogEvents(Now,Msg);
end;

procedure TMainForm.Success(Msg:String);
begin
 LogEvents(Now,Msg);
end;

procedure TMainForm.TrayIconMainClick(Sender: TObject);
begin
 ActionMainFormShow.Execute;
end;

procedure TMainForm.TrayIconMainDblClick(Sender: TObject);
begin
 ActionMainFormShow.Execute;
end;

procedure TMainForm.TimerLogEventsUpdaterTimer(Sender: TObject);
begin
 try
  MoveBugReportListToLogger(nil);
  MoveLogEventsListToLoggerMemo(MemoLogEvents);
  if (PageControlMain.ActivePage=TabSheetLogEvents) then
  StatusBarLogEvents.SimpleText:=DateTimePrompt(Now)+GetHeapStatusBrief
   +FormatVar('. Events: %d',LogCountTotal)
   +FormatVar(', Bugs: %d',BugCountTotal)+'.';
  HandlePendingHideApplicationIconFromTaskBar;
 except
  on E:Exception do Self.BugReport(E,Self,'TimerLogEventsUpdaterTimer');
 end;
end;

procedure TMainForm.ActionMainExitExecute(Sender: TObject);
begin
 Application.Terminate;
end;

procedure TMainForm.ActionMainParentShowExecute(Sender: TObject);
begin
 AppActivateByTitle(ParentCrwDaqTitle);
end;

procedure TMainForm.ActionMainFormShowExecute(Sender: TObject);
begin
 ShowAndActivateFormByReference(Self,SW_SHOW);
end;

procedure TMainForm.ActionMainSendUserCmndExecute(Sender: TObject);
begin
 try
  if (CRW_DAQ_SYS_EXE_PID=0)
  then RaiseException('Parent Crw32.exe process is not specified.');
  EditMainSendUserCmnd.Text:=Trim(EditMainSendUserCmnd.Text);
  if (Pos('@',EditMainSendUserCmnd.Text)&lt;&gt;1)
  then RaiseException('Invalid format of command.');
  SendCommandToCrwDaq(EditMainSendUserCmnd.Text);
 except
  on E:Exception do Self.BugReport(E,Self,'ActionMainSendUserCmndExecute');
 end;
end;

procedure TMainForm.ActionMainExecUserCmndExecute(Sender: TObject);
begin
 try
  MemoDimMonitorConsole.Lines.Text:=DateTimePrompt(Now)+'Exec user command:'+EOL
   +'ListOfProcesses:'+EOL
   +'****************'+EOL
   +GetListOfProcesses(0,0,'')+EOL;
 except
  on E:Exception do Self.BugReport(E,Self,'ActionMainExecUserCmndExecute');
 end;
end;

procedure TMainForm.ActionMainLogEventsClearExecute(Sender: TObject);
begin
 MemoLogEvents.Lines.Clear;
 LogCountTotal:=0; BugCountTotal:=0;
 LogEvents(Now,GetBriefEngineScriptInfo);
 LogEvents(Now,'Start.');
end;

procedure TMainForm.ActionMainLogEventsGoBackExecute(Sender: TObject);
begin
 if DimMonitor.IsMonitoring then begin
  PageControlMain.ActivePage:=TabSheetDimMonitor;
  Exit;
 end;
 if (ListBoxDimJob.Count&gt;0) then begin
  PageControlMain.ActivePage:=TabSheetDimJob;
  Exit;
 end;
 PageControlMain.ActivePage:=TabSheetDimDns;
end;

procedure TMainForm.ActionMainListSysInfoExecute(Sender: TObject);
var What,Info:String; Timeout:Integer;
begin
 Timeout:=1000*SpinEditMainListSysInfoTimeOut.Value;
 What:=Trim(ComboBoxMainListSysInfo.Text);
 Info:=ListSysInfoAsText(What,Timeout);
 LogEvents(Now,What);
 LogEvents(0,Info);
end;

var BugTestNum:Integer=0;

procedure TMainForm.BitBtnLogEventsTestClick(Sender: TObject);
begin
 try
  Inc(BugTestNum);
  RaiseException('This is exception test '+IntToStr(BugTestNum));
 except
  on E:Exception do Self.BugReport(E,Self,'BitBtnLogEventsTestClick');
 end;
end;

procedure TMainForm.ActionDimDnsRefreshExecute(Sender: TObject);
begin
 DimDnsRefresh;
end;

procedure TMainForm.ListBoxDimServersClick(Sender: TObject);
var i:Integer; item:String;
begin
 i:=ListBoxDimServers.ItemIndex;
 if (i&gt;=0) and (i&lt;ListBoxDimServers.Items.Count) then begin
  item:=ListBoxDimServers.Items.Strings[i];
  UpdateDimServerServices(item);
 end;
end;

procedure TMainForm.BitBtnDimServiceSelectClick(Sender: TObject);
begin
 SelectServerServices;
end;

end.
</Code>
        </Main>
      </Child>
    </DimMonitor>
  </Metadata>
</CrossEngineApp>
