BSOne.SFC/Tocsg.Module/ContentSearch/EXE_ContentSearch/ThdSchFileScan.pas

979 lines
27 KiB
Plaintext

{*******************************************************}
{ }
{ ThdSchFileScan }
{ }
{ Copyright (C) 2022 Sunk }
{ }
{*******************************************************}
unit ThdSchFileScan;
interface
uses
{$IFDEF _HE_}
ManagerModel,
{$ENDIF}
Define,
System.SysUtils, System.Classes, Winapi.Windows, System.SyncObjs,
System.Generics.Collections, Winapi.Messages, Tocsg.Thread,
Tocsg.Files, CttSchDefine, Tocsg.Win32;
const
// ProcessSoftcampDRM.pas로 이동 25_0218 14:24:19 kku
// SIGN_SOFTCAMP_DRM: array [0..13] of Byte =
// ($53, $43, $44, $53, $41, $30, $30, $34, $00, $00, $52, $00, $20, $88); // SCDSA00 시작됨 // 수정 23_1221 11:02:43 kku
// ($53, $43, $44, $53, $41, $30, $30, $34, $00, $00, $52, $00, $20, $88, $F1, $53); // SCDSA004 시작됨
SIGN_FASOO_DRM: array [0..7] of Byte = ($9B, $20, $44, $52, $4D, $4F, $4E, $45); // > DRMONE 로 시작됨
type
TThdSchFileScan = class(TTgThread)
protected
sProcDir_,
sProcSchFile_: String;
FileScanOpt_: TFileScanOpt;
llTotalTgFile_,
llProcTgFile_,
llFound_,
llFoundFile_,
llTotalDir_,
llTotalFile_: LONGLONG;
TgDirList_,
TgNetDirList_,
ScanExtList_,
SvFileList_,
SvDirList_,
SvScanList_,
TestCompList_: TStringList;
sWorkDir_: String;
dtBegin_: TDateTime;
evScanSearchEnd_,
evScanSearchBegin_: TNotifyEvent;
sMtx_: String;
TaskMutex_: TTgMutex;
CttSchOpt_: TCttSchOpt;
hKvCttSch_: HWND;
KvProcInfo_,
NtProcInfo_: TProcessInformation;
dtRecentSch_: TDateTime;
qSchEnt_,
qSchNetEnt_: TQueue<String>;
bSendEvent_: Boolean;
bDoNetSch_, // 네트워크 위치 검색 확인
bIgrFasDrm_, // 파수 DRM 적용된 파일 무시 24_1023 15:28:49 kku
bIgrScDrm_, // 소캠 DRM 적용된 파일 무시 23_1206 16:53:12 kku
bIgrAipDrm_, // AIP DRM 적용된 파일 무시 24_0215 10:16:53 kku
bIgrSizeZero_: Boolean;// 사이즈 0인 파일 무시
{$IFDEF _HE_}
CttSchProg_: TCttSchProg;
dwProgTick_: DWORD;
sSchTitle_: String;
bIgrExcept_: Boolean;
MgCampExcept_: TManagerCampExcept;
{$ENDIF}
dtScan_: TDateTime;
bProcContinue_: Boolean;
procedure ScanSchFiles;
procedure ScanSchNetFiles;
procedure Execute; override;
public
Constructor Create(sTgDirs: String; aOpt: TFileScanOpt; dtScan: TDateTime; bSendEvent: Boolean = true);
Destructor Destroy; override;
procedure UpdateProgress(sStatus: String; bForce: Boolean = false; sResult: String = 'none');
procedure SetKvCttSchHandle(h: HWND);
function NextSchPath: String;
procedure AddNetFileEnt(sPath: String);
procedure IncFoundCount(nHits: Integer);
procedure IncFoundFileCount;
procedure IncEncFileCount;
procedure IncEncFailFileCount;
procedure IncDelFileCount;
procedure IncTotalDir(ll: LONGLONG);
procedure IncTotalFile(ll: LONGLONG);
property WorkState: TTgThreadState read GetWorkState;
property TotalDirCount: LONGLONG read llTotalDir_;
property TotalFileCount: LONGLONG read llTotalFile_;
property TotalTgFileCount: LONGLONG read llTotalTgFile_;
property TotalEncCount: LONGLONG read CttSchProg_.llEncFileCnt;
property TotalEncFailCount: LONGLONG read CttSchProg_.llEncFailFileCnt;
property TotalDelCount: LONGLONG read CttSchProg_.llDelFileCnt;
property ProcTgFileCount: LONGLONG read llProcTgFile_;
property FoundCount: LONGLONG read llFound_;
property FoundFileCount: LONGLONG read llFoundFile_;
property ProcDir: String read sProcDir_;
property ProcSchFile: String read sProcSchFile_;
property BeginDT: TDateTime read dtBegin_;
property OnScanSearchBegin: TNotifyEvent write evScanSearchBegin_;
property OnScanSearchEnd: TNotifyEvent write evScanSearchEnd_;
property KvCttSchWnd: HWND read hKvCttSch_;
property IsSendEvent: Boolean read bSendEvent_;
property ScanDate: TDateTime read dtScan_;
property IgrScDrm: Boolean write bIgrScDrm_;
property IgrFasDrm: Boolean write bIgrFasDrm_;
property IgrAipDrm: Boolean write bIgrAipDrm_;
property IgrSizeZero: Boolean write bIgrSizeZero_;
{$IFDEF _HE_}
property CttSchProg: TCttSchProg read CttSchProg_;
property SchTitle: String read sSchTitle_;
property IgrExcept: Boolean write bIgrExcept_;
{$ENDIF}
end;
implementation
uses
{$IFDEF _HE_}
ManagerService, GlobalDefine, Condition,
{$ENDIF}
Tocsg.PCRE, Tocsg.Trace, Tocsg.Exception,
Tocsg.Strings, Tocsg.Safe, Tocsg.Path, Tocsg.Process, System.DateUtils,
superobject, Tocsg.Json, Tocsg.WinInfo, Tocsg.DateTime, Tocsg.Convert, Tocsg.FileInfo, DefineHelper, Tocsg.AIP,
ProcessSoftcampDRM, Tocsg.Registry, Tocsg.Delete;
{ TThdSchFileScan }
Constructor TThdSchFileScan.Create(sTgDirs: String; aOpt: TFileScanOpt; dtScan: TDateTime; bSendEvent: Boolean = true);
var
i: Integer;
sTemp: String;
ThdDirWatchEnt: TThdDirWatchEnt;
begin
Inherited Create;
bSendEvent_ := bSendEvent;
hKvCttSch_ := 0;
bDoNetSch_ := false;
bIgrScDrm_ := false;
bIgrFasDrm_ := false;
bIgrAipDrm_ := false;
bIgrSizeZero_ := true;
WorkState_ := tsInit;
{$IFDEF _HE_}
bIgrExcept_ := false;
ZeroMemory(@CttSchProg_, SizeOf(CttSchProg_));
dwProgTick_ := 0;
if aOpt.bShowSchTitle then
sSchTitle_ := aOpt.sSchTitle
else
sSchTitle_ := '';
MgCampExcept_ := nil;
{$ENDIF}
if dtScan <> 0 then
dtScan_ := dtScan
else
dtScan_ := Now;
bProcContinue_ := false;
TgDirList_ := TStringList.Create;
SplitString(sTgDirs, '|', TgDirList_);
TgNetDirList_ := TStringList.Create;
for i := TgDirList_.Count - 1 downto 0 do
begin
sTemp := TgDirList_[i];
if TgDirList_[i].StartsWith('@') or TgDirList_[i].StartsWith('\\') then
begin
TgDirList_.Delete(i);
if sTemp[1] = '@' then
Delete(sTemp, 1, 1);
TgNetDirList_.Add(sTemp);
end;
end;
FileScanOpt_ := aOpt;
case FileScanOpt_.CttSchOpt.nWorkPriority of
0 : Priority := tpHighest;
1 : Priority := tpHigher;
// 2 : Priority := tpNormal;
3 : Priority := tpLower;
4 : Priority := tpLowest;
else Priority := tpNormal;
end;
llFound_ := 0;
llFoundFile_ := 0;
llTotalTgFile_ := 0;
llProcTgFile_ := 0;
llTotalDir_ := 0;
llTotalFile_ := 0;
sProcSchFile_ := '';
ScanExtList_ := TStringList.Create;
ScanExtList_.CaseSensitive := false;
SplitString(FileScanOpt_.sScanExt, '|', ScanExtList_);
@evScanSearchEnd_ := nil;
@evScanSearchBegin_ := nil;
SvFileList_ := nil;
SvDirList_ := nil;
SvScanList_ := nil;
if FileScanOpt_.bSaveFileList then
SvFileList_ := TStringList.Create;
if FileScanOpt_.bSaveDirList then
SvDirList_ := TStringList.Create;
if FileScanOpt_.bSaveScanList then
SvScanList_ := TStringList.Create;
TestCompList_ := TStringList.Create;
sMtx_ := 'Global\TaskKvCttSch@' + FormatDateTime('yyyymmddhhnnss', Now);
TaskMutex_ := TTgMutex.Create(sMtx_);
CttSchOpt_ := FileScanOpt_.CttSchOpt;
hKvCttSch_ := 0;
dtRecentSch_ := 0;
qSchEnt_ := TQueue<String>.Create;
qSchNetEnt_ := TQueue<String>.Create;
ZeroMemory(@KvProcInfo_, SizeOf(KvProcInfo_));
ZeroMemory(@NtProcInfo_, SizeOf(NtProcInfo_));
dtBegin_ := Now;
StartThread;
end;
Destructor TThdSchFileScan.Destroy;
begin
if KvProcInfo_.dwProcessId <> 0 then
begin
TerminateProcessByPid(KvProcInfo_.dwProcessId);
KvProcInfo_.dwProcessId := 0;
end;
if NtProcInfo_.dwProcessId <> 0 then
begin
TerminateProcessByPid(NtProcInfo_.dwProcessId);
NtProcInfo_.dwProcessId := 0;
end;
{$IFDEF _HE_}
if MgCampExcept_ <> nil then
FreeAndNil(MgCampExcept_);
{$ENDIF}
FreeAndNil(qSchNetEnt_);
FreeAndNIl(qSchEnt_);
FreeAndNil(ScanExtList_);
if SvFileList_ <> nil then
FreeAndNil(SvFileList_);
if SvDirList_ <> nil then
FreeAndNil(SvDirList_);
if SvScanList_ <> nil then
FreeAndNil(SvScanList_);
FreeAndNil(TestCompList_);
FreeAndNil(TgNetDirList_);
FreeAndNil(TgDirList_);
FreeAndNil(TaskMutex_);
Inherited;
end;
procedure TThdSchFileScan.ScanSchFiles;
var
sTgDir: String;
IgrWordPaths: TStringList;
i: Integer;
llLimitSize: LONGLONG;
procedure ExtractFiles(sDir: String);
var
wfd: TWin32FindData;
hSc: THandle;
sExt,
sFName,
sPath: String;
dtCreate,
dtModify: TDateTime;
llSize: LONGLONG;
begin
try
if not DirectoryExists(sDir) then
exit;
sDir := IncludeTrailingPathDelimiter(sDir);
if IgrWordPaths.Count > 0 then
begin
var i: Integer;
sPath := UpperCase(sDir);
for i := 0 to IgrWordPaths.Count - 1 do
begin
if Pos(IgrWordPaths[i], sPath) > 0 then
exit;
end;
end;
if SvDirList_ <> nil then
SvDirList_.Add(sDir);
sPath := sDir + '*.*';
hSc := FindFirstFile(PChar(sPath), wfd);
if hSc = INVALID_HANDLE_VALUE then
exit;
try
Repeat
if GetWorkStop or Terminated then
begin
SetWorkState(tsStop);
exit;
end;
if (String(wfd.cFileName) <> '.') and (String(wfd.cFileName) <> '..') then
begin
sFName := UpperCase(wfd.cFileName);
sPath := sDir + wfd.cFileName;
if ((wfd.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) <> 0) then
begin
Inc(llTotalDir_);
// \application data\ 등 junction 속성 경로가 있으면 무시해야함..
// 시스템 권한으로 돌리면 해당 경로로 정크된 경로까지 따라 들어감 24_0226 14:32:14 kku
if (wfd.dwFileAttributes and FILE_ATTRIBUTE_REPARSE_POINT) = 0 then
ExtractFiles(sPath);
end else begin
Inc(llTotalFile_);
if SvFileList_ <> nil then
SvFileList_.Add(sPath);
if Pos('~$', sFName) = 1 then
continue;
if Pos('POWERSHELL_TRANSCRIPT', sFName) = 1 then
continue;
sExt := GetFileExt(sPath).ToLower;
if (sExt <> '$KV') and (ScanExtList_.IndexOf(sExt) <> -1) then
begin
if FileScanOpt_.bPartScan and (FileScanOpt_.dtRecent <> 0) then
begin
dtCreate := ConvFileTimeToDateTime_Local(wfd.ftCreationTime);
dtModify := ConvFileTimeToDateTime_Local(wfd.ftLastWriteTime);
if (CompareDateTime(FileScanOpt_.dtRecent, dtCreate) <> -1) and
(CompareDateTime(FileScanOpt_.dtRecent, dtModify) <> -1) then
continue;
end;
llSize := GetFileSizeHiLow(wfd.nFileSizeHigh, wfd.nFileSizeLow);
if (llSize = 0) and bIgrSizeZero_ then
continue;
if (llLimitSize > 0) and (llSize >= llLimitSize) then
continue;
// 소캠 파일 거르기 23_1031 12:30:45 kku
if bIgrScDrm_ then
begin
if CheckSign(sPath, @SIGN_SOFTCAMP_DRM[0], Length(SIGN_SOFTCAMP_DRM)) then
begin
// Inc(CttSchProg_.llEncFileCnt);
continue;
end;
end;
// 파수 파일 거르기 24_1023 15:29:22 kku
if bIgrFasDrm_ then
begin
if CheckSign(sPath, @SIGN_FASOO_DRM[0], 8) then
begin
// Inc(CttSchProg_.llEncFileCnt);
continue;
end;
end;
if bIgrAipDrm_ then
begin
// if Pos('대외비', GetAipLabel(sPath)) > 0 then
if IsAipEncryted(sPath) then
continue;
end;
// 예외 거르기 23_1227 12:58:55 kku
if (MgCampExcept_ <> nil) and MgCampExcept_.IsExceptFile(sPath) then
continue;
qSchEnt_.Enqueue(sPath);
Inc(llTotalTgFile_);
if SvScanList_ <> nil then
SvScanList_.Add(sPath);
end;
end;
end;
Until not FindNextFile(hSc, wfd);
finally
WinApi.Windows.FindClose(hSc);
end;
except
// ..
end;
end;
begin
llLimitSize := LONGLONG(FileScanOpt_.nLimitSizeMB) * 1048576;
Guard(IgrWordPaths, TStringList.Create);
SplitString(UpperCase(FileScanOpt_.sIgrWordPath), '|', IgrWordPaths);
try
SetWorkState(tsWorking);
for i := 0 to TgDirList_.Count - 1 do
begin
if GetWorkStop or Terminated then
begin
SetWorkState(tsStop);
exit;
end;
sProcDir_ := '?:\';
sTgDir := TgDirList_[i];
if not DirectoryExists(sTgDir) then
continue;
sProcDir_ := sTgDir;
// 대상 파일 스캔
ExtractFiles(sTgDir);
end;
except
on E: Exception do
begin
ETgException.TraceException(Self, E, 'Fail .. ScanSchFiles()');
SetWorkState(tsFail);
end;
end;
end;
procedure TThdSchFileScan.ScanSchNetFiles;
var
sHpExe, sParam: String;
procedure CreateProcessNetScan;
var
hProcess: THandle;
O: ISuperObject;
begin
{$IFDEF _HE_}
if MutexExists(MUTEX_KILL) then
begin
SetWorkStop(true);
exit;
end;
{$ENDIF}
if not FileExists(sHpExe) then
exit;
try
if NtProcInfo_.dwProcessId <> 0 then
TerminateProcessByPid(NtProcInfo_.dwProcessId);
ZeroMemory(@NtProcInfo_, SizeOf(NtProcInfo_));
O := SO;
O.I['Cmd'] := HPCMD_REQ_NETDIR_SCAN;
O.S['Mtx'] := sMtx_;
O.I['Tasker'] := ULONGLONG(Self);
O.O['FOpt'] := TTgJson.ValueToJsonObject<TFileScanOpt>(FileScanOpt_);
O.I['CT'] := CUSTOMER_TYPE;
O.S['TgNDir'] := sProcDir_;
if SaveJsonObjToFile(O, sParam) then
begin
{$IFDEF DEBUG}
NtProcInfo_ := ExecuteApp(sHpExe, Format('/p "%s"', [sParam]), SW_SHOWNORMAL);
{$ELSE}
NtProcInfo_ := ExecuteAppAsUser('explorer.exe', sHpExe, Format('/p "%s"', [sParam]), SW_SHOWNORMAL);
{$ENDIF}
if NtProcInfo_.dwProcessId = 0 then
begin
{$IFDEF DEBUG}
ASSERT(false);
{$ELSE}
_Trace('Fail .. CreateProcessNetScan() .. ExecuteApp()');
{$ENDIF}
end;
end else
_Trace('Fail .. CreateProcessNetScan() .. SaveJsonObjToFile()');
except
on E: Exception do
ETgException.TraceException(Self, E, 'Fail .. CreateProcessNetScan()');
end;
end;
var
i: Integer;
dwRst: DWORD;
begin
if GetWorkState <> tsWorking then
exit;
try
sHpExe := GetRunExePathDir + DIR_CONF + EXE_HP;
if not FileExists(sHpExe) then
exit;
sParam := GetRunExePathDir + '$NetSchOpt.dat';
for i := TgNetDirList_.Count - 1 downto 0 do
begin
sProcDir_ := TgNetDirList_[i];
CreateProcessNetScan;
while not Terminated and not GetWorkStop do
begin
dwRst := WaitForSingleObject(NtProcInfo_.hProcess, 50);
if dwRst <> WAIT_TIMEOUT then
break;
// 타임아웃
// if (nTimeOutMilSec > 0) and ((GetTickCount - dwExecuteTick) > nTimeOutMilSec) then
// begin
// TerminateProcess(PI.hProcess, 999);
// exit;
// end;
end;
if Terminated or GetWorkStop then
begin
if NtProcInfo_.hProcess <> 0 then
TerminateProcess(NtProcInfo_.hProcess, 999);
exit;
end;
end;
DeleteFile(PChar(sParam));
except
on E: Exception do
begin
ETgException.TraceException(Self, E, 'Fail .. ScanSchNetFiles()');
SetWorkState(tsFail);
end;
end;
end;
procedure TThdSchFileScan.SetKvCttSchHandle(h: HWND);
begin
hKvCttSch_ := h;
end;
function TThdSchFileScan.NextSchPath: String;
begin
Lock;
try
if qSchEnt_.Count > 0 then
begin
if not bProcContinue_ then
begin
bProcContinue_ := true;
var sInfo: String := GetRegValueAsString(HKEY_LOCAL_MACHINE, REG_HE, 'cppn');
if sInfo <> '' then
begin
var InfoList: TStringList;
Guard(InfoList, TStringList.Create);
SplitString(sInfo, ':', InfoList, true);
if InfoList.Count > 4 then
begin
var nIdx: Integer := StrToIntDef(InfoList[0], 0);
llFoundFile_ := StrToIntDef(InfoList[1], 0);
CttSchProg_.llFound := llFoundFile_;
CttSchProg_.llEncFileCnt := StrToIntDef(InfoList[2], 0);
CttSchProg_.llEncFailFileCnt := StrToIntDef(InfoList[3], 0);
CttSchProg_.llDelFileCnt := StrToIntDef(InfoList[4], 0);
var nCnt: Integer := qSchEnt_.Count;
if nCnt > nIdx then
begin
while llProcTgFile_ < nIdx do
begin
Result := qSchEnt_.Dequeue;
sProcSchFile_ := Result;
dtRecentSch_ := Now;
Inc(llProcTgFile_);
end;
end;
end;
end;
end;
Result := qSchEnt_.Dequeue;
sProcSchFile_ := Result;
dtRecentSch_ := Now;
Inc(llProcTgFile_);
end else
if qSchNetEnt_.Count > 0 then
begin
if not bProcContinue_ then
begin
bProcContinue_ := true;
var sInfo: String := GetRegValueAsString(HKEY_LOCAL_MACHINE, REG_HE, 'cppn');
if sInfo <> '' then
begin
var InfoList: TStringList;
Guard(InfoList, TStringList.Create);
SplitString(sInfo, ':', InfoList, true);
if InfoList.Count > 4 then
begin
var nIdx: Integer := StrToIntDef(InfoList[0], 0);
llFoundFile_ := StrToIntDef(InfoList[1], 0);
CttSchProg_.llFound := llFoundFile_;
CttSchProg_.llEncFileCnt := StrToIntDef(InfoList[2], 0);
CttSchProg_.llEncFailFileCnt := StrToIntDef(InfoList[3], 0);
CttSchProg_.llDelFileCnt := StrToIntDef(InfoList[4], 0);
var nCnt: Integer := qSchNetEnt_.Count;
if nCnt > nIdx then
begin
while llProcTgFile_ < nIdx do
begin
Result := qSchNetEnt_.Dequeue;
sProcSchFile_ := Result;
dtRecentSch_ := Now;
Inc(llProcTgFile_);
end;
end;
end;
end;
end;
if not bDoNetSch_ then
begin
bDoNetSch_ := true;
if KvProcInfo_.dwProcessId <> 0 then
TerminateProcessByPid(KvProcInfo_.dwProcessId);
ZeroMemory(@KvProcInfo_, SizeOf(KvProcInfo_));
exit;
end;
Result := qSchNetEnt_.Dequeue;
sProcSchFile_ := Result;
dtRecentSch_ := Now;
Inc(llProcTgFile_);
// _Trace('NextSchPath - NetPath = %s', [Result], 1);
end else
Result := '';
finally
Unlock;
end;
{$IFDEF _HE_}
// 부하 때문에 전송하지 않도록 함 (HEC에서 부하 확인) 24_0919 14:39:34 kku
// if gMgSvc.IsNewApi then
// UpdateProgress('PROGRESS')
// else
// UpdateProgress('progress');
{$ENDIF}
if Result = '' then
begin
DelRegValue(HKEY_LOCAL_MACHINE, REG_HE, 'cppn');
DelRegValue(HKEY_LOCAL_MACHINE, REG_HE, 'cptd');
DelRegValue(HKEY_LOCAL_MACHINE, REG_HE, 'cpid');
SetWorkState(tsCompleted);
SetWorkStop(true);
end else
SetRegValueString(HKEY_LOCAL_MACHINE, REG_HE, 'cppn', Format('%d:%d:%d:%d:%d',
[llProcTgFile_, llFoundFile_, CttSchProg_.llEncFileCnt, CttSchProg_.llEncFailFileCnt, CttSchProg_.llDelFileCnt]), true);
end;
procedure TThdSchFileScan.AddNetFileEnt(sPath: String);
begin
if (MgCampExcept_ <> nil) and MgCampExcept_.IsExceptFile(sPath) then
exit;
qSchNetEnt_.Enqueue(sPath);
Inc(llTotalTgFile_);
end;
procedure TThdSchFileScan.IncFoundCount(nHits: Integer);
begin
Inc(llFound_, nHits);
end;
procedure TThdSchFileScan.IncFoundFileCount;
begin
Inc(llFoundFile_);
end;
procedure TThdSchFileScan.IncEncFileCount;
begin
{$IFDEF _HE_}
Inc(CttSchProg_.llEncFileCnt);
{$ENDIF}
end;
procedure TThdSchFileScan.IncEncFailFileCount;
begin
{$IFDEF _HE_}
Inc(CttSchProg_.llEncFailFileCnt);
{$ENDIF}
end;
procedure TThdSchFileScan.IncDelFileCount;
begin
{$IFDEF _HE_}
Inc(CttSchProg_.llDelFileCnt);
{$ENDIF}
end;
procedure TThdSchFileScan.IncTotalDir(ll: LONGLONG);
begin
Inc(llTotalDir_, ll);
end;
procedure TThdSchFileScan.IncTotalFile(ll: LONGLONG);
begin
Inc(llTotalFile_, ll);
end;
procedure TThdSchFileScan.UpdateProgress(sStatus: String; bForce: Boolean = false; sResult: String = 'none');
begin
{$IFDEF _HE_}
if CttSchProg_.sScanId <> '' then
begin
var dwTick: DWORD := GetTickCount;
if bForce or ((dwTick - dwProgTick_) > 10000) then
begin
dwProgTick_ := dwTick;
CttSchProg_.llProc := llProcTgFile_;
CttSchProg_.llTotal := llTotalTgFile_;
CttSchProg_.llFound := llFoundFile_;
CttSchProg_.sResult := sResult;
CttSchProg_.sStatus := sStatus;
if bSendEvent_ then
begin
if gMgSvc.IsNewApi then
gMgSvc.SendCampnProgInfo(CttSchProg_)
else
gMgSvc.SendCttSchProgInfo(CttSchProg_);
end;
end;
end;
{$ENDIF}
end;
procedure TThdSchFileScan.Execute;
var
sComName,
sKvCsPath: String;
procedure CreateProcessKV;
var
hProcess: THandle;
O: ISuperObject;
sParam: String;
begin
{$IFDEF _HE_}
if MutexExists(MUTEX_KILL) then
begin
SetWorkStop(true);
exit;
end;
{$ENDIF}
if not FileExists(sKvCsPath) then
exit;
try
if KvProcInfo_.dwProcessId <> 0 then
begin
TerminateProcessByPid(KvProcInfo_.dwProcessId);
DeleteDir(sWorkDir_);
end;
if not ForceDirectories(sWorkDir_) then
begin
_Trace('Fail .. CreateWorkDir()');
SetWorkState(tsFail);
exit;
end;
ZeroMemory(@KvProcInfo_, SizeOf(KvProcInfo_));
hKvCttSch_ := 0;
dtRecentSch_ := 0;
O := SO;
O.I['CSTT'] := Integer(csttSchMulti);
O.S['Mtx'] := sMtx_;
O.I['Tasker'] := ULONGLONG(Self);
if FileScanOpt_.nLangId <> 0 then
O.I['LangID'] := FileScanOpt_.nLangId;
if FileScanOpt_.sSchPtrns <> '' then
O.S['SchPtrns'] := FileScanOpt_.sSchPtrns;
if bDoNetSch_ then
CttSchOpt_.sTaskDir := sKvCsPath[1] + ':\ProgramData\HE\STask\';
O.O['Opt'] := TTgJson.ValueToJsonObject<TCttSchOpt>(CttSchOpt_);
O.I['CT'] := CUSTOMER_TYPE;
sParam := GetRunExePathDir + '$KvCttSchOpt.dat';
if SaveJsonObjToFile(O, sParam) then
begin
if bDoNetSch_ then
begin
{$IFDEF DEBUG}
KvProcInfo_ := ExecuteApp(sKvCsPath, Format('-p "%s"', [sParam]), SW_SHOWNORMAL);
{$ELSE}
KvProcInfo_ := ExecuteAppAsUser('explorer.exe', sKvCsPath, Format('-p "%s"', [sParam]), SW_SHOWNORMAL);
{$ENDIF}
end else
KvProcInfo_ := ExecuteApp(sKvCsPath, Format('-p "%s"', [sParam]), SW_SHOWNORMAL);
if KvProcInfo_.dwProcessId = 0 then
begin
{$IFDEF DEBUG}
ASSERT(false);
{$ELSE}
_Trace('Fail .. CreateProcessKV() .. ExecuteApp()');
{$ENDIF}
end;
end else
_Trace('Fail .. CreateProcessKV() .. SaveJsonObjToFile()');
except
on E: Exception do
ETgException.TraceException(Self, E, 'Fail .. CreateProcessKV()');
end;
end;
var
nTmSec,
nTaskLenMax: Integer;
bNewStart: Boolean;
begin
sWorkDir_ := GetRunExePathDir + 'STask\';
DeleteDir(sWorkDir_);
if not ForceDirectories(sWorkDir_) then
begin
_Trace('Fail .. CreateWorkDir()');
SetWorkState(tsFail);
exit;
end;
CttSchOpt_.sTaskDir := sWorkDir_;
nTmSec := FileScanOpt_.nSchTimeoutSec;
if nTmSec <= 0 then
nTmSec := DEF_TIMEOUT_SEC;
_Trace('TThdSchFileScan .. Init .. TmSec=%d', [nTmSec], 5);
{$IFDEF _HE_}
if gMgSvc.IsNewApi then
begin
if IsCampaignTaskIdLong then
nTaskLenMax := 64
else
nTaskLenMax := 32;
end else
nTaskLenMax := 24;
CttSchProg_.dtStart := dtBegin_;
CttSchProg_.sScanId := FileScanOpt_.sScanId;
sComName := GetComName;
bNewStart := GetRegValueAsString(HKEY_LOCAL_MACHINE, REG_HE, 'cpid') <> CttSchProg_.sScanId;
if bNewStart then
begin
DelRegValue(HKEY_LOCAL_MACHINE, REG_HE, 'cppn');
DelRegValue(HKEY_LOCAL_MACHINE, REG_HE, 'cptd');
end;
if not bNewStart then
CttSchProg_.sTaskId := GetRegValueAsString(HKEY_LOCAL_MACHINE, REG_HE, 'cptd');
if CttSchProg_.sTaskId = '' then
begin
if IsCampaignTaskIdLong then
CttSchProg_.sTaskId := sComName + '\' + FormatDateTime('yymmddhhnnss', dtBegin_)
else
CttSchProg_.sTaskId := sComName + '\' + FormatDateTime('hhnnss', dtBegin_);
if Length(CttSchProg_.sTaskId) > nTaskLenMax then
begin
SetLength(sComName, Length(sComName) - (Length(CttSchProg_.sTaskId) - nTaskLenMax));
if IsCampaignTaskIdLong then
CttSchProg_.sTaskId := sComName + '\' + FormatDateTime('yymmddhhnnss', dtBegin_)
else
CttSchProg_.sTaskId := sComName + '\' + FormatDateTime('hhnnss', dtBegin_);
end;
SetRegValueString(HKEY_LOCAL_MACHINE, REG_HE, 'cptd', CttSchProg_.sTaskId, true);
SetRegValueString(HKEY_LOCAL_MACHINE, REG_HE, 'cpid', CttSchProg_.sScanId, true);
end;
if bIgrExcept_ then
MgCampExcept_ := TManagerCampExcept.Create;
{$ENDIF}
if Assigned(evScanSearchBegin_) then
evScanSearchBegin_(Self);
{$IFDEF _HE_}
if bNewStart then
begin
if gMgSvc.IsNewApi then
UpdateProgress('PENDING')
else
UpdateProgress('scan');
end;
{$ENDIF}
// 로컬 드라이브 스캔
ScanSchFiles;
// 공유폴더, 네트워크 드라이브 스캔
ScanSchNetFiles;
if SvFileList_ <> nil then
SvFileList_.SaveToFile(FileScanOpt_.sSvFilePath, TEncoding.UTF8);
if SvDirList_ <> nil then
SvDirList_.SaveToFile(FileScanOpt_.sSvDirPath, TEncoding.UTF8);
if SvScanList_ <> nil then
SvScanList_.SaveToFile(FileScanOpt_.sSvScanPath, TEncoding.UTF8);
sKvCsPath := GetRunExePathDir + EXE_KVCTTSCH;
while not Terminated and not GetWorkStop do
begin
try
if (KvProcInfo_.dwProcessId = 0) or
(GetProcessNameByPid(KvProcInfo_.dwProcessId) = '') or
( (dtRecentSch_ > 0) and
(SecondsBetween(dtRecentSch_, Now) >
(nTmSec + BooleanToInt(Pos(GetFileExt(sProcSchFile_).ToUpper, COMPRESS_EXTS) > 0, 60, 0))) ) then // 압축파일은 시간을 더 준다
CreateProcessKV;
Sleep(1000);
except
on E: Exception do
ETgException.TraceException(Self, E, 'Fail .. Execute()');
end;
end;
if KvProcInfo_.dwProcessId <> 0 then
begin
TerminateProcessByPid(KvProcInfo_.dwProcessId);
KvProcInfo_.dwProcessId := 0;
end;
{$IFDEF _HE_}
if gMgSvc.IsNewApi then
UpdateProgress('DONE', true);
// kv에서 임시 파일을 사용하고 비정상 종료 시 삭제를 못하는 경우가 있다.
// 사용자 임시 폴더 초기화 25_0903 09:11:59 kku
ClearUserTempFolder;
{$ENDIF}
// DeleteDir(sWorkDir_);
if Assigned(evScanSearchEnd_) then
evScanSearchEnd_(Self);
end;
end.