ServiceApplikation stopper
Hej Eksperter,Er der nogen der kan hjælpe mig med hvorfor min Service Apllikation stopper. Min service gør det at den overvåger et blibliotek for nogle bestemte filer. Når de filer er tilgænglige, dvs, ikke er låst skal den åbne dem og læse indholdet og smide det ind i SQL DB. I starten spiller det helt fint, men det stopper. Jeg ved ikke hvorfor, det håber jeg at nogen kan ortælle mig. Og hvis nogen kunne hjælpe mig med at optimere koden ville det bare være helt perfekt. I den kode jeg har lavet er det nok muligt at genbruge noget af det, til de andre rutiner som tager hånd om de forskellige filer, men jeg ved ikke liiiige hvordan det gøres. Flere point kan gives.
unit ServerUnit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
Registry, DirWatchU, DB, ADODB, ExtCtrls, ShellApi;
type
TComputerInfoCheck = class(TService)
DirWatch1: TDirWatch;
ADOQuery1: TADOQuery;
ADOConnection1: TADOConnection;
Timer1: TTimer;
ADOTable1: TADOTable;
procedure Timer1Timer(Sender: TObject);
procedure ADOQuery1DeleteError(DataSet: TDataSet; E: EDatabaseError;
var Action: TDataAction);
procedure ADOQuery1PostError(DataSet: TDataSet; E: EDatabaseError;
var Action: TDataAction);
procedure ServiceAfterUninstall(Sender: TService);
procedure DirWatch1NewFileCreated(Sender: TObject; const FileName: string);
procedure ServiceStop(Sender: TService; var Stopped: Boolean);
procedure ServiceStart(Sender: TService; var Started: Boolean);
procedure ServiceAfterInstall(Sender: TService);
private
{ Private declarations }
var StringList : TStringList; Debug : Boolean;
procedure ProcessCmdLineParameters;
procedure StartDirWatch;
procedure StopDirWatch;
public
function GetServiceController: TServiceController; override;
{ Public declarations }
end;
var
ComputerInfoCheck: TComputerInfoCheck;
implementation
{$R *.DFM}
{$R MsgResource.RES}
procedure ServiceController(CtrlCode: DWord); stdcall;
begin
ComputerInfoCheck.Controller(CtrlCode);
end;
function FileInUse(FileName: TFileName): Boolean;
var
HFileRes: HFILE;
begin
Result := False;
if not FileExists(FileName) then
Exit;
HFileRes := CreateFile(PChar(FileName),GENERIC_READ or GENERIC_WRITE,0,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
Result := (HFileRes = INVALID_HANDLE_VALUE);
if not Result then
CloseHandle(HFileRes);
end;
procedure TComputerInfoCheck.ADOQuery1DeleteError(DataSet: TDataSet;
E: EDatabaseError; var Action: TDataAction);
begin
LogMessage(E.Message,EVENTLOG_ERROR_TYPE, 0, 4);
end;
procedure TComputerInfoCheck.ADOQuery1PostError(DataSet: TDataSet;
E: EDatabaseError; var Action: TDataAction);
begin
LogMessage(E.Message,EVENTLOG_ERROR_TYPE, 0, 4);
end;
procedure TComputerInfoCheck.DirWatch1NewFileCreated(Sender: TObject;
const FileName: string);
var strTmp, strTmp1, strTmp2, strName, strComputerName, strFilNavn : string;
count : integer; F: TStream; UnicodeString: WideString; UnicodeSign: Word;
FileSize: Cardinal;
begin
if (pos('SW.kvk',Filename) <> 0) or (pos('BIOS.kvk',Filename) <> 0) or
(pos('DISK.kvk',Filename) <> 0) or (pos('CPU.kvk',Filename) <> 0) or
(pos('RAM.kvk',Filename) <> 0) then
begin
LogMessage('File created: ' + Filename,EVENTLOG_INFORMATION_TYPE, 0, 2);
try
repeat
Sleep(100);
until not FileInUse(Filename);
F := TFileStream.Create(FileName, fmOpenRead);
StringList := TStringList.Create;
try
FileSize := F.Size;
if FileSize >= SizeOf(UnicodeSign) then
begin
F.ReadBuffer(UnicodeSign, SizeOf(UnicodeSign));
if UnicodeSign = $FEFF then
begin
Dec(FileSize, SizeOf(UnicodeSign));
SetLength(UnicodeString, FileSize div SizeOf(WideChar));
F.ReadBuffer(UnicodeString[1], FileSize);
// now UnicodeString contains Unicode string read from stream
StringList.Text := UnicodeString;
end
else
try
// not a Unicode format;
StringList.LoadFromFile(FileName);
except
on EFopenError do
begin
LogMessage('Cannot open file: ' + filename,EVENTLOG_ERROR_TYPE, 0, 4);
end;
end;
end;
finally
F.Free;
DeleteFile(FileName);
end;
finally
if Debug then
LogMessage(filename + ' open.',EVENTLOG_SUCCESS, 0, 1);
strFilNavn := Copy(Extractfilename(Filename),1,10);
ADOTable1.Active := true;
if not ADOTable1.Locate('COMPUTERNAME',strFilNavn,[]) then
begin
ADOQuery1.SQL.Text := 'Insert Into BIOSINFO (COMPUTERNAME) Values(:PCOMPUTERNAME)';
ADOQuery1.Connection.BeginTrans;
try
ADOQuery1.Parameters.ParamByName('PCOMPUTERNAME').Value := strFilNavn;
ADOQuery1.ExecSQL;
ADOQuery1.Connection.CommitTrans;
except
ADOQuery1.Connection.RollbackTrans;
Raise;
end;
end;
ADOTable1.Active := false;
// if Debug then
LogMessage(strFilNavn,EVENTLOG_SUCCESS, 0, 1);
if (StringList[1] <> '') then
begin
// VIDEO
if (pos('Node,Description',StringList[1]) <> 0) then
begin
strTmp := StringList[2];
strComputerName := copy(strTmp,1,pos(',',strTmp)-1);
if Debug then
LogMessage(strComputerName,EVENTLOG_INFORMATION_TYPE, 0, 2);
Delete(strTmp,1,pos(',',strTmp));
ADOTable1.Active := true;
if ADOTable1.Locate('COMPUTERNAME',strComputerName,[]) then
begin
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Text := 'Update BIOSINFO SET VIDEOCARD = :pVIDEO WHERE COMPUTERNAME = ' + quotedstr(strComputername);
ADOQuery1.Connection.BeginTrans;
try
ADOQuery1.Parameters.ParamByName('pVIDEO').Value := strTmp;
ADOQuery1.ExecSQL;
ADOQuery1.Connection.CommitTrans;
except
ADOQuery1.Connection.RollbackTrans;
Raise;
end;
end
else
begin
ADOQuery1.SQL.Text := 'Insert Into BIOSINFO (COMPUTERNAME, VIDEOCARD) Values(:pCOMPUTERNAME,:pVIDEO)';
ADOQuery1.Connection.BeginTrans;
try
ADOQuery1.Parameters.ParamByName('pCOMPUTERNAME').Value := strComputerName;
ADOQuery1.Parameters.ParamByName('pVIDEO').Value := strTmp;
ADOQuery1.ExecSQL;
ADOQuery1.Connection.CommitTrans;
except
ADOQuery1.Connection.RollbackTrans;
Raise;
end;
ADOTAble1.Active := false
end;
end;
// RAM
if (pos('Node,MaxCapacity',StringList[1]) <> 0) then
begin
strTmp := StringList[2];
strComputerName := copy(strTmp,1,pos(',',strTmp)-1);
if Debug then
LogMessage(strComputerName,EVENTLOG_INFORMATION_TYPE, 0, 2);
Delete(strTmp,1,pos(',',strTmp));
ADOTable1.Active := true;
if ADOTable1.Locate('COMPUTERNAME',strComputerName,[]) then
begin
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Text := 'Update BIOSINFO SET RAM = :pRAM WHERE COMPUTERNAME = ' + quotedstr(strComputername);
ADOQuery1.Connection.BeginTrans;
try
ADOQuery1.Parameters.ParamByName('pRAM').Value := strTmp;
ADOQuery1.ExecSQL;
ADOQuery1.Connection.CommitTrans;
except
ADOQuery1.Connection.RollbackTrans;
Raise;
end;
end
else
begin
ADOQuery1.SQL.Text := 'Insert Into BIOSINFO (COMPUTERNAME, RAM) Values(:pCOMPUTERNAME,:pRAM)';
ADOQuery1.Connection.BeginTrans;
try
ADOQuery1.Parameters.ParamByName('pCOMPUTERNAME').Value := strComputerName;
ADOQuery1.Parameters.ParamByName('pRAM').Value := strTmp;
ADOQuery1.ExecSQL;
ADOQuery1.Connection.CommitTrans;
except
ADOQuery1.Connection.RollbackTrans;
Raise;
end;
ADOTAble1.Active := false
end;
end;
// CPU
if (pos('Node,MaxClockSpeed,Name',StringList[1]) <> 0) then
begin
strTmp := StringList[2];
strComputerName := copy(strTmp,1,pos(',',strTmp)-1);
if Debug then
LogMessage(strComputerName,EVENTLOG_INFORMATION_TYPE, 0, 2);
Delete(strTmp,1,pos(',',strTmp));
strTmp1 := copy(strTmp,1,pos(',',strTmp)-1);
if Debug then
LogMessage(strTmp1,EVENTLOG_INFORMATION_TYPE, 0, 2);
Delete(strTmp,1,pos(',',strTmp));
while pos(#32#32,strTmp) <> 0 do
delete(strTmp,pos(#32#32,strTmp),1);
// delete(strTmp,1,1);
if Debug then
LogMessage(strTmp1,EVENTLOG_INFORMATION_TYPE, 0, 2);
Delete(strTmp,1,pos(',',strTmp));
ADOTable1.Active := true;
if ADOTable1.Locate('COMPUTERNAME',strComputerName,[]) then
begin
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Text := 'Update BIOSINFO SET CPU = :PCPU WHERE COMPUTERNAME = ' + quotedstr(strComputername);
ADOQuery1.Connection.BeginTrans;
try
ADOQuery1.Parameters.ParamByName('PCPU').Value := strTmp;
ADOQuery1.ExecSQL;
ADOQuery1.Connection.CommitTrans;
except
ADOQuery1.Connection.RollbackTrans;
Raise;
end;
end
else
begin
ADOQuery1.SQL.Text := 'Insert Into BIOSINFO (COMPUTERNAME, CPU) Values(:PCOMPUTERNAME,:PCPU)';
ADOQuery1.Connection.BeginTrans;
try
ADOQuery1.Parameters.ParamByName('pCOMPUTERNAME').Value := strComputerName;
ADOQuery1.Parameters.ParamByName('pCPU').Value := strTmp;
ADOQuery1.ExecSQL;
ADOQuery1.Connection.CommitTrans;
except
ADOQuery1.Connection.RollbackTrans;
Raise;
end;
ADOTAble1.Active := false
end;
end;
// DISK
if (pos('Node,Caption,Size',StringList[1]) <> 0) then
begin
for count := 2 to StringList.Count-1 do
begin
strTmp := StringList[count];
strComputerName := copy(strTmp,1,pos(',',strTmp)-1);
if Debug then
LogMessage(strComputerName,EVENTLOG_INFORMATION_TYPE, 0, 2);
Delete(strTmp,1,pos(',',strTmp));
strTmp1 := copy(strTmp,1,pos(',',strTmp)-1);
if Debug then
LogMessage(strTmp,EVENTLOG_INFORMATION_TYPE, 0, 2);
Delete(strTmp,1,pos(',',strTmp));
strTmp2 := strTmp;
if Debug then
LogMessage(strTmp1,EVENTLOG_INFORMATION_TYPE, 0, 2);
ADOTable1.Active := true;
if ADOTable1.Locate('COMPUTERNAME',strComputerName,[]) then
begin
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Text := 'Update BIOSINFO SET DISKSIZE = :PDISKSIZE, DISKMODEL = :PDISKMODEL WHERE COMPUTERNAME = ' + quotedstr(strComputername);
ADOQuery1.Connection.BeginTrans;
try
ADOQuery1.Parameters.ParamByName('PDISKMODEL').Value := strTmp1;
ADOQuery1.Parameters.ParamByName('PDISKSIZE').Value := strTmp2;
ADOQuery1.ExecSQL;
ADOQuery1.Connection.CommitTrans;
except
ADOQuery1.Connection.RollbackTrans;
Raise;
end;
end
else
begin
ADOQuery1.SQL.Text := 'Insert Into BIOSINFO (COMPUTERNAME, DISKSIZE, DISKMODEL) Values(:PCOMPUTERNAME,:PDISKSIZE,:PDISKMODEL)';
ADOQuery1.Connection.BeginTrans;
try
ADOQuery1.Parameters.ParamByName('PCOMPUTERNAME').Value := strComputerName;
ADOQuery1.Parameters.ParamByName('PDISKSIZE').Value := strTmp1;
ADOQuery1.Parameters.ParamByName('PDISKMODEL').Value := strTmp2;
ADOQuery1.ExecSQL;
ADOQuery1.Connection.CommitTrans;
except
ADOQuery1.Connection.RollbackTrans;
Raise;
end;
ADOTAble1.Active := false
end;
end;
end;
// BIOS
if (pos('Node,IdentifyingNumber,Name',StringList[1]) <> 0) then
begin
for count := 2 to StringList.Count-1 do
begin
strTmp := StringList[count];
strComputerName := copy(strTmp,1,pos(',',strTmp)-1);
if Debug then
LogMessage(strComputerName,EVENTLOG_INFORMATION_TYPE, 0, 2);
Delete(strTmp,1,pos(',',strTmp));
strTmp1 := copy(strTmp,1,pos(',',strTmp)-1);
if Debug then
LogMessage(strTmp1,EVENTLOG_INFORMATION_TYPE, 0, 2);
Delete(strTmp,1,pos(',',strTmp));
strTmp2 := strTmp;
if Debug then
LogMessage(strTmp1,EVENTLOG_INFORMATION_TYPE, 0, 2);
ADOTable1.Active := true;
if ADOTable1.Locate('COMPUTERNAME',strComputerName,[]) then
begin
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Text := 'Update BIOSINFO SET SERVICETAG = :pSERVICETAG, MODEL = :pMODEL WHERE COMPUTERNAME = ' + quotedstr(strComputername);
ADOQuery1.Connection.BeginTrans;
try
ADOQuery1.Parameters.ParamByName('PSERVICETAG').Value := strTmp1;
ADOQuery1.Parameters.ParamByName('PMODEL').Value := strTmp2;
ADOQuery1.ExecSQL;
ADOQuery1.Connection.CommitTrans;
except
ADOQuery1.Connection.RollbackTrans;
Raise;
end;
end
else
begin
ADOQuery1.SQL.Text := 'Insert Into BIOSINFO (COMPUTERNAME, SERVICETAG, MODEL) Values(:PCOMPUTERNAME,:PSERVICETAG,:PMODEL)';
ADOQuery1.Connection.BeginTrans;
try
ADOQuery1.Parameters.ParamByName('PCOMPUTERNAME').Value := strComputerName;
ADOQuery1.Parameters.ParamByName('PSERVICETAG').Value := strTmp1;
ADOQuery1.Parameters.ParamByName('PMODEL').Value := strTmp2;
ADOQuery1.ExecSQL;
ADOQuery1.Connection.CommitTrans;
except
ADOQuery1.Connection.RollbackTrans;
Raise;
end;
end;
end;
end;
// SOFTWARE
if (pos('Node,Name,Version',StringList[1]) <> 0) then
begin
with ADOQuery1 do
begin
close;
SQL.Clear;
SQL.Add('DELETE FROM SWINFO WHERE COMPUTERNAME = ' + QuotedStr(strFilNavn));
ExecSQL;
end;
for count := 2 to StringList.Count-1 do
begin
strTmp := StringList[count];
strComputerName := copy(strTmp,1,pos(',',strTmp)-1);
if Debug then
LogMessage(strComputerName,EVENTLOG_INFORMATION_TYPE, 0, 2);
Delete(strTmp,1,pos(',',strTmp));
// strName := copy(strTmp,1,pos(',',strTmp)-1);
strTmp1 := copy(strTmp,1,pos(',',strTmp)-1);
if Debug then
LogMessage(strName,EVENTLOG_INFORMATION_TYPE, 0, 2);
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Text := 'Insert Into SWINFO (COMPUTERNAME, NAME) Values(:PCOMPUTERNAME,:PNAME)';
ADOQuery1.Connection.BeginTrans;
try
ADOQuery1.Parameters.ParamByName('PCOMPUTERNAME').Value := strComputerName;
ADOQuery1.Parameters.ParamByName('PNAME').Value := strTmp1;
ADOQuery1.ExecSQL;
ADOQuery1.Connection.CommitTrans;
except
ADOQuery1.Connection.RollbackTrans;
Raise;
end;
end;
end;
end;
end;
StringList.Free;
end
else
LogMessage('Another file was created.' + Filename,EVENTLOG_INFORMATION_TYPE, 0, 2);
end;
function TComputerInfoCheck.GetServiceController: TServiceController;
begin
Result := ServiceController;
end;
procedure TComputerInfoCheck.ServiceAfterInstall(Sender: TService);
var
Reg : TRegistry;
Key : string;
begin
Reg := TRegistry.Create(KEY_READ or KEY_WRITE);
try
Reg.RootKey := HKEY_LOCAL_MACHINE;
if Reg.OpenKey('\SYSTEM\CurrentControlSet\Services\' + Name, false) then
begin
Reg.WriteString('Description', 'This is a description for my fine Service Application.');
Reg.CloseKey;
end;
finally
Reg.Free;
end;
// Create registry entries so that the event viewer show messages properly when we use the LogMessage method.
Key := '\SYSTEM\CurrentControlSet\Services\Eventlog\Application\' + Self.Name;
Reg := TRegistry.Create(KEY_READ or KEY_WRITE);
try
Reg.RootKey := HKEY_LOCAL_MACHINE;
if Reg.OpenKey(Key, True) then
begin
Reg.WriteString('EventMessageFile', ParamStr(0));
Reg.WriteInteger('TypesSupported', 7);
Reg.CloseKey;
end;
finally
Reg.Free;
end;
end;
procedure TComputerInfoCheck.ServiceAfterUninstall(Sender: TService);
var
Reg: TRegistry;
Key: string;
begin
// Delete registry entries for event viewer.
Key := '\SYSTEM\CurrentControlSet\Services\Eventlog\Application\' + Self.Name;
Reg := TRegistry.Create(KEY_READ or KEY_WRITE);
try
Reg.RootKey := HKEY_LOCAL_MACHINE;
if Reg.KeyExists(Key) then
Reg.DeleteKey(Key);
finally
Reg.Free;
end;
end;
procedure TComputerInfoCheck.ServiceStart(Sender: TService;
var Started: Boolean);
begin
LogMessage('Alfa Laval Computer Check started.',EVENTLOG_SUCCESS, 0, 1);
StartDirWatch;
end;
procedure TComputerInfoCheck.ServiceStop(Sender: TService;
var Stopped: Boolean);
begin
LogMessage('Alfa Laval Computer Check stopped.',EVENTLOG_SUCCESS, 0, 1);
StopDirWatch;
end;
procedure TComputerInfoCheck.StartDirWatch();
begin
try
ProcessCmdLineParameters;
DirWatch1.Start;
except
on E: Exception do begin
LogMessage(E.Message,EVENTLOG_ERROR_TYPE, 0, 4);
StopDirWatch;
end;
end;
end;
procedure TComputerInfoCheck.StopDirWatch;
begin
DirWatch1.Stop;
end;
procedure RunAndWait(App: string; show: word);
var
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
w: DWORD;
begin
ZeroMemory(@StartupInfo, Sizeof(StartupInfo)); //zaplni nulami
ZeroMemory(@ProcessInfo, Sizeof(ProcessInfo));
StartupInfo.cb := Sizeof(StartupInfo);
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow := SHOW;
if not CreateProcess(nil,
PChar(App),
nil,
nil,
False,
NORMAL_PRIORITY_CLASS,
nil,
nil,
StartupInfo,
ProcessInfo) then
begin
exit;
end;
w:=STILL_ACTIVE;
while (GetExitCodeProcess(ProcessInfo.hProcess, w)) and (w=STILL_ACTIVE) do
Application.Initialize;
end;
procedure TComputerInfoCheck.Timer1Timer(Sender: TObject);
var StrList : TStringList; strFilNavn : string; count : integer;
begin
RunAndWait('cmd /c "%systemroot%\system32\dsquery.exe" computer -name dkso* -o rdn -limit 0 -disabled > c:\comdis.txt', SW_HIDE);
StrList := TStringList.Create;
StrList.LoadFromFile('c:\comdis.txt');
if not DeleteFile('c:\comdis.txt') then
LogMessage('Delete not ok',EVENTLOG_ERROR_TYPE, 0, 4);
for count := 0 to StrList.Count - 1 do
begin
if strList[count] <> '' then
begin
strFilNavn := strList[count];
Delete(strFilNavn,1,1);
Delete(strFilNavn,length(strFilNavn),1);
with ADOQuery1 do
begin
close;
SQL.Clear;
SQL.Add('DELETE FROM SWINFO WHERE COMPUTERNAME = ' + QuotedStr(strFilNavn));
ExecSQL;
end;
end;
end;
end;
procedure TComputerInfoCheck.ProcessCmdLineParameters;
var Count : Byte;
Reg : TRegistry;
Parameter : string;
begin
Parameter := '';
Reg := TRegistry.Create(KEY_READ or KEY_WRITE);
if ParamCount > 1 then
begin
For count := 0 to ParamCount-1 do
Begin
Case Param[Count][2] Of
'P','p' : begin
DirWatch1.DirectoryToWatch := Copy(Param[Count], 4, Length(Param[Count]) - 3);
Parameter := Parameter + Param[Count] + ' ';
LogMessage('Path: ' + DirWatch1.DirectoryToWatch,EVENTLOG_INFORMATION_TYPE, 0, 2);
end;
'F','f' : begin
DirWatch1.WatchSubDirectories := true;
Parameter := Parameter + Param[Count] + ' ';
LogMessage('WatchSubDirectories',EVENTLOG_INFORMATION_TYPE, 0, 2);
end;
'D','d' : begin
Debug := true;
end;
end;
End;
try
Reg.RootKey := HKEY_LOCAL_MACHINE;
if Reg.OpenKey('\SYSTEM\CurrentControlSet\Services\' + Name, false) then
begin
Reg.WriteString('Parameters', Parameter);
Reg.CloseKey;
end;
finally
Reg.Free;
end;
end
else
begin
try
Reg.RootKey := HKEY_LOCAL_MACHINE;
if Reg.OpenKey('\SYSTEM\CurrentControlSet\Services\' + Name, false) then
begin
Parameter := Reg.ReadString('Parameters');
Reg.CloseKey;
end;
finally
Reg.Free;
end;
for Count := 0 to length(Parameter) do
begin
if pos('-',parameter) <> 0 then
begin
case Parameter[2] of
'P','p' : begin
DirWatch1.DirectoryToWatch := Copy(Parameter, 4, pos(' ',Parameter)-4);
Delete(Parameter, 1, pos(' ',Parameter));
LogMessage('Path:' + DirWatch1.DirectoryToWatch,EVENTLOG_INFORMATION_TYPE, 0, 2);
end;
'F','f' : begin
DirWatch1.WatchSubDirectories := true;
Delete(Parameter, 1, pos(' ', Parameter));
LogMessage('WatchSubDirectories',EVENTLOG_INFORMATION_TYPE, 0, 2);
end;
end;
end;
end;
end;
end;
end.
