254 lines
7.1 KiB
Plaintext
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.
|