BSOne.SFC/eCrmHE/EXE_eCrmHomeEdition/Process/ProcessRecentDoc.pas

254 lines
7.1 KiB
Plaintext

{*******************************************************}
{ }
{ RecoverService }
{ }
{ Copyright (C) 2022 kku }
{ }
{*******************************************************}
// 문서 열람하면 감지하는 용도로 사용하려고 했는데,
// 최근 열었던 문서를 닫고 바로 열때는 감지하지 못하는 문제가 있다.
// 그래서 사용안함.
// 그래도 나중에 비슷한 기능 구현을 위해 뼈대 남겨놓음 25_1106 10:32:24 kku
unit ProcessRecentDoc;
interface
uses
System.SysUtils, System.Classes, Winapi.Windows,
Vcl.Graphics, Tocsg.Thread, ManagerPattern, Tocsg.Files,
System.Generics.Collections;
const
DEF_DOC_EXTS = 'TXT|LOG|DOC|WPS|PDF|XLS|PPT|HWP|DOCX|DOTX|XLSX|XLTX|PPTX|POTX';
type
TRecentDocWatch = class(TTgDirWatchBase)
private
bIsWorking_: Boolean;
sDocExts_,
sLastOpenFile_: String;
ullLastTick_: ULONGLONG;
DocExtList_: TStringList;
procedure UpdateTargetExts(sExts: String);
procedure ProcessDirWatchEnt(Sender: TObject; pInfo: PDirWatchEnt); override;
public
Constructor Create;
Destructor Destroy; override;
procedure StartService;
procedure StopService;
property IsWorking: Boolean read bIsWorking_;
end;
implementation
uses
Tocsg.Safe, Tocsg.Strings, Tocsg.Path, superobject, Tocsg.Exception,
GlobalDefine, AbUnzper, AbArcTyp, ManagerService,
ManagerModel, Condition, Tocsg.Packet, Tocsg.Shell, Tocsg.Process, Tocsg.Driver;
{ TRecentDocWatch }
Constructor TRecentDocWatch.Create;
begin
Inherited Create(true, false);
ullLastTick_ := 0;
sLastOpenFile_ := '';
DocExtList_ := TStringList.Create;
DocExtList_.CaseSensitive := false;
// sDocExts_ := DEF_DOC_EXTS;
// SplitString(sDocExts_, '|', DocExtList_, false, true);
bIsWorking_ := false;
SetFilter(FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME or
FILE_NOTIFY_CHANGE_SIZE or FILE_NOTIFY_CHANGE_LAST_WRITE);
end;
Destructor TRecentDocWatch.Destroy;
begin
StopService;
Inherited;
FreeAndNil(DocExtList_);
end;
procedure TRecentDocWatch.UpdateTargetExts(sExts: String);
begin
if (sExts <> '') and (sExts <> sDocExts_) then
begin
sDocExts_ := sExts;
SplitString(sDocExts_, '|', DocExtList_, false, true);
end;
end;
procedure TRecentDocWatch.StartService;
var
sDir, sUserDir: String;
DList: TStringList;
i: Integer;
begin
if not bIsWorking_ then
begin
sDir := GetWindowsDir;
if sDir = '' then
begin
_Trace('Fail .. Not found windowsDir', 1);
exit;
end;
sUserDir := UpperCase(sDir[1]) + ':\Users\';
Guard(DList, TStringList.Create);
ExtrDirFromDir(sUserDir, DList);
for i := 0 to DList.Count - 1 do
begin
AddDirWatch(sUserDir + DList[i] + '\AppData\Roaming\Microsoft\Windows\Recent\', true);
end;
bIsWorking_ := true;
Processor_.StartThread;
end;
end;
procedure TRecentDocWatch.StopService;
begin
if bIsWorking_ then
begin
bIsWorking_ := false;
Processor_.Clear;
Processor_.PauseThread;
try
ClearDirWatch;
except
on E: Exception do
ETgException.TraceException(Self, E, 'Fail .. StopService()');
end;
end;
end;
procedure TRecentDocWatch.ProcessDirWatchEnt(Sender: TObject; pInfo: PDirWatchEnt);
var
sExt, sDocPath,
sFName, sPName: String;
i: Integer;
PO: TPrefModel;
MonKind: TFileMonKind;
LogInfo: TLogInfo;
DriveInfo: TDriveInfo;
begin
try
case pInfo.dwAction of
1, 3 : // Add, Modify
begin
sDocPath := '';
sExt := GetFileExt(pInfo.sPath).ToUpper;
if sExt = 'AUTOMATICDESTINATIONS-MS' then
sDocPath := GetLastOpenFileFromJumpListAuto(pInfo.sPath);
if sDocPath = '' then
begin
if sExt <> 'LNK' then
exit;
sDocPath := GetTargetExeFromLink(pInfo.sPath);
if sDocPath = '' then
exit;
end;
// 간혹 사용자 폴더가 이상하게(?) 표시되는 경우가 있다.. 보정 24_0514 10:09:24 kku
if (sDocPath <> '') and (Pos('windows\system32\config\systemprofile', sDocPath.ToLower) > 0) then
begin
_Trace('Replace path = "%s"', [sDocPath], 3);
sFName := ExtractFileName(sDocPath);
sDocPath := StringReplace(sDocPath, 'windows\system32\config\systemprofile',
Format('Users\%s', [sFName]), [rfReplaceAll, rfIgnoreCase]);
_Trace('Replace Path done = "%s"', [sDocPath], 3);
end;
// _Trace('Found RecentFile = "%s"', [sDocPath], 3);
if not FileExists(sDocPath) then
exit;
if sDocPath <> sLastOpenFile_ then
begin
sLastOpenFile_ := sDocPath;
ullLastTick_ := GetTickCount64;
end else
if (GetTickCount64 - ullLastTick_) < 1200 then // 1.2초간 중복 감지 걸름 25_1216 14:53:17 kku
exit;
sExt := GetFileExt(sDocPath);
sPName := GetProcessNameFromWndHandle(GetForegroundWindow);
if sExt.ToUpper.Contains('DOC') and (CompareText('winword.exe', sPName) <> 0) then
begin
// 워드는 종료할때도 점프리스트가 업데이트 된다... 25_1216 15:02:57 kku
// sLastOpenFile_ := '';
// ullLastTick_ := 0;
exit;
end;
_Trace('파일 열람 감지 .. PName=%s, Path=%s', [sPName, sDocPath], 5);
PO := gMgSvc.ModePolicy;
MonKind := PO.FileMon.Kind;
if sDocExts_ <> PO.FileMon.sExts then
UpdateTargetExts(PO.FileMon.sExts);
case MonKind of
fmkNone : exit;
fmkAll : ;
fmkIncExt :
begin
if DocExtList_.IndexOf(sExt) = -1 then
exit;
end;
fmkIgrExt :
begin
if DocExtList_.IndexOf(sExt) <> -1 then
exit;
end;
end;
if PO.FileMon.OnlyUSB then
begin
GetDriveDetail(ExtractFileDrive(sDocPath), @DriveInfo);
if Pos('USB', UpperCase(DriveInfo.sSerial)) <> 1 then
exit;
end;
ZeroMemory(@LogInfo, SizeOf(LogInfo));
LogInfo.sCode := LOGCODE_PREVENT_FILEMONITOR;
if PO.FileMon.OnlyUSB then
begin
LogInfo.sDevName := DriveInfo.sFriendlyName;
LogInfo.sDevSerial := DriveInfo.sSerial;
LogInfo.sDevClassId := DriveInfo.sClassGuid;
end;
LogInfo.sSummary := Format('[Open] %s', [sDocPath]);
LogInfo.sAppName := sPName;
LogInfo.sPath := sDocPath;
if gMgSvc.IsNewApi then
gMgSvc.SendEventLogEx(@LogInfo, false);
if gMgSvc.ModePolicy.FileMon.IsNoti then
gMgSvc.PopupMessage(TYPE_MSG_PREVENT_FILECHANGE, LogInfo.sSummary);
end;
2 : ; // Delete
// 3 : ; // Modify
4 : ; // Rename
5 : ; // New name
end;
except
on E: Exception do
ETgException.TraceException(Self, E, 'Fail .. ProcessDirWatchEntry()')
end;
end;
end.