unit DBs1Log; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, VirtualTrees, Vcl.ExtCtrls, Tocsg.Trace, Vcl.Menus; type TDlgBs1Log = class(TTgTraceForm) vtList: TVirtualStringTree; popFun: TPopupMenu; miCopyToCB: TMenuItem; MainMenu: TMainMenu; miControl: TMenuItem; miView: TMenuItem; miAlwaysTop: TMenuItem; miExit: TMenuItem; N1: TMenuItem; miRunAsAgent: TMenuItem; miTerminateAgent: TMenuItem; OpenDialog: TOpenDialog; miRestartExplorer: TMenuItem; N2: TMenuItem; tState: TTimer; miAgreeInfoClear: TMenuItem; procedure vtListGetHint(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle; var HintText: string); procedure vtListGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer); procedure vtListGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure vtListFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); procedure vtListHeaderClick(Sender: TVTHeader; HitInfo: TVTHeaderHitInfo); procedure vtListCompareNodes(Sender: TBaseVirtualTree; Node1, Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer); procedure miCopyToCBClick(Sender: TObject); procedure vtListContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean); procedure miExitClick(Sender: TObject); procedure miViewClick(Sender: TObject); procedure miAlwaysTopClick(Sender: TObject); procedure miRunAsAgentClick(Sender: TObject); procedure miRestartExplorerClick(Sender: TObject); procedure miTerminateAgentClick(Sender: TObject); procedure vtListAfterCellPaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; CellRect: TRect); procedure FormCreate(Sender: TObject); procedure tStateTimer(Sender: TObject); procedure miAgreeInfoClearClick(Sender: TObject); private { Private declarations } // procedure WriteLog(dt: TDateTime; nLevel: Integer; sMsg: String); override; sCaption_, sDestIPort_: String; public { Public declarations } procedure CreateParams(var Params: TCreateParams); override; // 작업표시줄에 표시 procedure process_WM_WRITE_LOG(var msg: TMessage); Message WM_WRITE_LOG; procedure process_WM_SYSCOMMAND(var msg: TWMSysCommand); Message WM_SYSCOMMAND; end; var DlgBs1Log: TDlgBs1Log; implementation uses Tocsg.VTUtil, VirtualTrees.Types, System.Math, System.DateUtils, Vcl.Clipbrd, Tocsg.Strings, Tocsg.Shell, Tocsg.Process, Vcl.Themes, Condition, ManagerService, BuildInfo, Define; {$R *.dfm} procedure TDlgBs1Log.FormCreate(Sender: TObject); begin sCaption_ := Caption; sDestIPort_ := ''; end; procedure TDlgBs1Log.CreateParams(var Params: TCreateParams); begin Inherited CreateParams(Params); Params.ExStyle := WS_EX_APPWINDOW; Params.WndParent := GetDesktopWindow; end; procedure TDlgBs1Log.miRunAsAgentClick(Sender: TObject); begin OpenDialog.Filter := 'EXE files|*.exe'; OpenDialog.FileName := ''; if OpenDialog.Execute(Handle) then begin ExecutePath(OpenDialog.FileName); end; end; procedure TDlgBs1Log.miTerminateAgentClick(Sender: TObject); begin if MessageBox(Handle, PChar('Agent를 강제 종료 하시겠습니까?'), PChar(Caption), MB_ICONQUESTION or MB_YESNO) = IDNO then exit; TerminateProcess(GetCurrentProcess, 999); end; procedure TDlgBs1Log.miAgreeInfoClearClick(Sender: TObject); begin if MessageBox(Handle, PChar('보안 서약서 동의를 초기화 하시겠습니까?'), PChar(APP_TITLE), MB_ICONQUESTION or MB_YESNO) = IDNO then exit; gMgSvc.AgentModel.EulaDT := 0; gMgSvc.AgentModel.Save; end; procedure TDlgBs1Log.miAlwaysTopClick(Sender: TObject); begin if FormStyle = fsStayOnTop then FormStyle := fsNormal else FormStyle := fsStayOnTop; end; procedure TDlgBs1Log.miCopyToCBClick(Sender: TObject); var pNode: PVirtualNode; pData: PLogEnt; sLogs: String; cb: TClipboard; begin sLogs := ''; vtList.BeginUpdate; try pNode := vtList.GetFirstSelected; if pNode = nil then begin MessageBox(Handle, PChar('클립보드에 복사할 로그를 선택해 주십시오.'), PChar(Caption), MB_ICONWARNING or MB_OK); exit; end; while pNode <> nil do begin pData := vtList.GetNodeData(pNode); if pData.nLevel > 0 then SumString(sLogs, Format('[%s] [L%d] %s', [DateTimeToStr(pData.dt), pData.nLevel, pData.sMsg]), #13#10) else SumString(sLogs, Format('[%s] %s', [DateTimeToStr(pData.dt), pData.sMsg]), #13#10); pNode := vtList.GetNextSelected(pNode); end; if sLogs <> '' then begin Clipboard.AsText := sLogs; MessageBox(Handle, PChar('클립보드에 복사 되었습니다.'), PChar(Caption), MB_ICONINFORMATION or MB_OK); end; finally vtList.EndUpdate; end; end; procedure TDlgBs1Log.miExitClick(Sender: TObject); begin if MessageBox(Handle, PChar('디버그 모드를 종료하시겠습니까?'), PChar(Caption), MB_ICONQUESTION or MB_YESNO) = IDNO then exit; Close; end; procedure TDlgBs1Log.miViewClick(Sender: TObject); begin miAlwaysTop.Checked := FormStyle = fsStayOnTop; end; procedure TDlgBs1Log.miRestartExplorerClick(Sender: TObject); begin if MessageBox(Handle, PChar('explorer.exe를 재시작하시겠습니까?'), PChar(Caption), MB_ICONQUESTION or MB_YESNO) = IDNO then exit; TerminateProcessByName('explorer.exe'); Sleep(500); ExecuteAppAsUser('msedge.exe', 'explorer.exe', '', SW_HIDE); // ExecutePath_runAs('explorer.exe'); end; procedure TDlgBs1Log.FormClose(Sender: TObject; var Action: TCloseAction); begin Action := TCloseAction.caFree; end; procedure DrawColoredText(VT: TVirtualStringTree; Canvas: TCanvas; const R: TRect; const Text, Highlight: string); var P: Integer; LeftPart, HighlightPart, RightPart: string; X, Y: Integer; begin P := Pos(Highlight, Text); if P > 0 then begin LeftPart := Copy(Text, 1, P-1); HighlightPart := Copy(Text, P, Length(Highlight)); RightPart := Copy(Text, P + Length(Highlight), MaxInt); X := R.Left + VT.TextMargin + 6; Y := R.Top + ((R.Height - Canvas.TextHeight('H')) div 2); // Left Canvas.Font.Color := clNone; //clBlack; Canvas.TextOut(X, Y, LeftPart); Inc(X, Canvas.TextWidth(LeftPart)); // Highlight Canvas.Font.Color := clRed; Canvas.TextOut(X, Y, HighlightPart); Inc(X, Canvas.TextWidth(HighlightPart)); // Right Canvas.Font.Color := clNone; //clBlack; Canvas.TextOut(X, Y, RightPart); end else begin // 하이라이트 문자열 없으면 그냥 전체 출력 Canvas.TextOut(R.Left + 2, R.Top + 2, Text); end; end; procedure TDlgBs1Log.vtListAfterCellPaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; CellRect: TRect); var pData: PLogEnt; begin // if Column = 2 then // begin // pData := Sender.GetNodeData(Node); // if Pos('보안', pData.sMsg) > 0 then // DrawColoredText(vtList, TargetCanvas, CellRect, pData.sMsg, '보안'); // end; end; procedure TDlgBs1Log.vtListCompareNodes(Sender: TBaseVirtualTree; Node1, Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer); var pData1, pData2: PLogEnt; begin pData1 := Sender.GetNodeData(Node1); pData2 := Sender.GetNodeData(Node2); case Column of 0 : Result := CompareDateTime(pData1.dt, pData2.dt); 1 : Result := CompareValue(pData1.nLevel, pData2.nLevel); 2 : Result := CompareText(pData1.sMsg, pData2.sMsg); end; end; procedure TDlgBs1Log.vtListContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean); var pSelNode: PVirtualNode; begin pSelNode := vtList.GetNodeAt(MousePos); miCopyToCB.Visible := pSelNode <> nil; end; procedure TDlgBs1Log.vtListFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); var pData: PLogEnt; begin pData := Sender.GetNodeData(Node); Finalize(pData^); end; procedure TDlgBs1Log.vtListGetHint(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle; var HintText: string); var pData: PLogEnt; begin // if Column = 2 then // begin // if Node = nil then // exit; // pData := Sender.GetNodeData(Node); // HintText := pData.sMsg; // end else HintText := vtList.Text[Node, Column]; end; procedure TDlgBs1Log.vtListGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer); begin NodeDataSize := SizeOf(TLogEnt); end; procedure TDlgBs1Log.vtListGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string); var pData: PLogEnt; begin pData := Sender.GetNodeData(Node); case Column of 0 : CellText := DateTimeToStr(pData.dt); 1 : CellText := IntToStr(pData.nLevel); 2 : CellText := pData.sMsg; // begin // if Pos('보안', pData.sMsg) = 0 then // CellText := pData.sMsg; // end; end; end; procedure TDlgBs1Log.vtListHeaderClick(Sender: TVTHeader; HitInfo: TVTHeaderHitInfo); begin if HitInfo.Button = mbLeft then begin if HitInfo.Column = -1 then exit; with Sender, Treeview do begin if SortColumn > NoColumn then Columns[SortColumn].Options := Columns[SortColumn].Options + [coParentColor]; if (SortColumn = NoColumn) or (SortColumn <> HitInfo.Column) then begin SortColumn := HitInfo.Column; SortDirection := sdAscending; end else if SortDirection = sdAscending then SortDirection := sdDescending else SortDirection := sdAscending; Columns[SortColumn].Color := $00EFEFEF; vtList.BeginUpdate; try vtList.SortTree(SortColumn, SortDirection, False); finally vtList.EndUpdate; end; end; end; end; //procedure TDlgBs1Log.WriteLog(dt: TDateTime; nLevel: Integer; sMsg: String); //var // pData: PLogEnt; //begin // vtList.BeginUpdate; // try // pData := VT_AddChildData(vtList); // pData.dt := dt; // pData.nLevel := nLevel; // pData.sMsg := sMsg; // finally // vtList.EndUpdate; // end; //end; procedure TDlgBs1Log.process_WM_WRITE_LOG(var msg: TMessage); var pData: PLogEnt; begin vtList.BeginUpdate; try if vtList.RootNodeCount > 2000 then vtList.DeleteNode(vtList.GetFirst); pData := VT_AddChildData(vtList); pData^ := PLogEnt(msg.LParam)^; vtList.ScrollIntoView(vtList.GetLast, false); finally vtList.EndUpdate; end; end; procedure TDlgBs1Log.tStateTimer(Sender: TObject); begin if (gMgSvc <> nil) and (sDestIPort_ <> gMgSvc.DestIPort) then begin sDestIPort_ := gMgSvc.DestIPort; Caption := sCaption_ + Format(' - %s | %s | %s', [GetCustomerName, StrsReplace(sDestIPort_, ['https:', 'http:', '/'], ''), BUILD_DT]); end; end; procedure TDlgBs1Log.process_WM_SYSCOMMAND(var msg: TWMSysCommand); begin if msg.CmdType = SC_CLOSE then begin miExit.Click; exit end; Inherited; end; end.