{*******************************************************} { } { 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; 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.Create; qSchNetEnt_ := TQueue.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(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(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.