CnPack Forum » CnVCL 组件包 » [建议]TCnDebugger


2009-12-24 12:30 jAmEs_
[建议]TCnDebugger

我处对TCnDebugger.InternalOutputMsg做以下调整,这样可以在没有安装查看器的情况下,输入到文件,这样可以在普通用户使用时,作为跟踪器使用,强烈希望管理员能调整。:)或者有更好方法也行。。。

procedure TCnDebugger.InternalOutputMsg(const AMsg: AnsiString; Size: Integer;
  const ATag: AnsiString; ALevel, AIndent: Integer; AType: TCnMsgType;
  ThreadID: DWORD; CPUPeriod: Int64);
var
  TagLen, MsgLen: Integer;
  MsgDesc: TCnMsgDesc;
  FChannelReady: Boolean;

  procedure GenerateMsgDesc;
  begin
    // 进行具体的组装工作
    MsgLen := Size;
    if MsgLen > CnMaxMsgLength then
      MsgLen := CnMaxMsgLength;
    TagLen := Length(ATag);
    if TagLen > CnMaxTagLength then
      TagLen := CnMaxTagLength;

    FillChar(MsgDesc, SizeOf(MsgDesc), 0);
    MsgDesc.Annex.Level := ALevel;
    MsgDesc.Annex.Indent := AIndent;
    MsgDesc.Annex.ProcessId := GetCurrentProcessId;
    MsgDesc.Annex.ThreadId := ThreadID;
    MsgDesc.Annex.MsgType := Ord(AType);
    MsgDesc.Annex.TimeStampType := Ord(TimeStampType);

    case TimeStampType of
      ttDateTime: MsgDesc.Annex.MsgDateTime := Date + Time;
      ttTickCount: MsgDesc.Annex.MsgTickCount := GetTickCount;
      ttCPUPeriod: MsgDesc.Annex.MsgCPUPeriod := GetCPUPeriod;
    else
      MsgDesc.Annex.MsgCPUPeriod := 0; // 设为全 0
    end;

    // TimeMarkStop 时所耗 CPU 时钟周期数
    MsgDesc.Annex.MsgCPInterval := CPUPeriod;

    CopyMemory(@(MsgDesc.Annex.Tag), Pointer(ATag), TagLen);
    CopyMemory(@(MsgDesc.Msg), Pointer(AMsg), MsgLen);

    MsgLen := MsgLen + SizeOf(MsgDesc.Annex) + SizeOf(DWORD);
    MsgDesc.Length := MsgLen;
  end;
begin
  if FAutoStart and not FIgnoreViewer and not FViewerAutoStartCalled then
  begin
    StartDebugViewer;
    FViewerAutoStartCalled := True;
  end;

  Inc(FMessageCount);
  if not CheckEnabled then Exit;
  FChannelReady := FChannel.CheckReady;

  if (not FChannelReady) and (not FDumpToFile) then Exit;

  GenerateMsgDesc;

  if FChannelReady then
  begin
    if FChannel.CheckFilterChanged then
      FChannel.RefreshFilter(FFilter);

    if CheckFiltered(string(ATag), ALevel, AType) then
      InternalOutput(MsgDesc, MsgLen);
  end;

  // 同时 DumpToFile
  if FDumpToFile and not FIgnoreViewer and (FDumpFile <> nil) then
  begin
    if not FAfterFirstWrite then // 第一回写时需要判断是否重写
    begin
      if FUseAppend then
        FDumpFile.Seek(0, soFromEnd)
      else
      begin
        FDumpFile.Size := 0;
        FDumpFile.Seek(0, soFromBeginning);
      end;
      FAfterFirstWrite := True; // 后续写就无需判断了
    end;
   
    FDumpFile.Write(MsgDesc, MsgLen);
  end;
end;

[[i] 本帖最后由 jAmEs_ 于 2009-12-24 16:30 编辑 [/i]]

2009-12-24 15:31 Passion
本来就有输出到文件的功能哇。

2009-12-24 16:29 jAmEs_
怎么搞?我意思是直接由这个类输出哦,没有查看器的情况下~~麻烦告诉一下,呵呵

2009-12-24 16:52 jAmEs_
我回去看了一下,好像必须打开查看器,才会输出文件吧?

2009-12-24 18:02 Passion
打开查看器是输出到查看器,然后查看器可以另存文件。
我记得定义DUMP_TO_FILE的编译条件就行了,可以看看CnDebugger.pas头上的编译指令。

2009-12-24 23:25 jAmEs_
:lol 我感觉你忘记了,能否再去看看?DUMP_TO_FILE是启动输出文件,但是如果查看器没有启动,输出时,检查到就会跳出来。
因为输出时,用到MapFile,而MapFile是查看器创建的,没有创建就不会输出了。

2009-12-25 11:13 Passion
你的意思是不要启动查看器而直接输出到文件?

2009-12-26 11:15 jAmEs_
对啊。。

2009-12-26 19:39 Passion
明白你的需求了。我改了一下,晚上回去提交。

2009-12-27 13:36 jAmEs_
:lol :victory: :handshake

2009-12-28 13:27 Passion
先试一试我改的内容?在附件里。

2009-12-28 18:57 jAmEs_
好像跟我的差不多吧,我加FChannelReady(最好改为ChannelReady...)是为了不多次执行FChannel.CheckReady,因为里面好像有一些代码,避免效能问题,不过有需要我迟点看看。

2009-12-28 20:19 Passion
好的。命名上局部变量似乎是不太合适用F,F都是表示Field,一般是类的成员变量。

2009-12-30 10:31 jAmEs_
FChannelReady当时是从FChannel.CheckReady变来的,当时忘了删除F:lol
测试OK,你处看看是否需要按我说的用变量来保存FChannel.CheckReady结果,这样可以避免好几次判断。。。:D

2009-12-30 17:05 Passion
好的,接受。

2010-2-11 11:38 jAmEs_
procedure TCnDebugger.InternalOutputMsg(const AMsg: AnsiString; Size: Integer;
  const ATag: AnsiString; ALevel, AIndent: Integer; AType: TCnMsgType;
  ThreadID: DWORD; CPUPeriod: Int64);
var
  TagLen, MsgLen: Integer;
  MsgDesc: TCnMsgDesc;
  LeftMsg: AnsiString;
  LeftSize: Integer;

  procedure GenerateMsgDesc;
  begin
    // 进行具体的组装工作
    MsgLen := LeftSize;
    if MsgLen > CnMaxMsgLength then
      MsgLen := CnMaxMsgLength;
    TagLen := Length(ATag);
    if TagLen > CnMaxTagLength then
      TagLen := CnMaxTagLength;
   
    FillChar(MsgDesc, SizeOf(MsgDesc), 0);
    MsgDesc.Annex.Level := ALevel;
    MsgDesc.Annex.Indent := AIndent;
    MsgDesc.Annex.ProcessId := GetCurrentProcessId;
    MsgDesc.Annex.ThreadId := ThreadID;
    MsgDesc.Annex.MsgType := Ord(AType);
    MsgDesc.Annex.TimeStampType := Ord(TimeStampType);
   
    case TimeStampType of
      ttDateTime: MsgDesc.Annex.MsgDateTime := Date + Time;
      ttTickCount: MsgDesc.Annex.MsgTickCount := GetTickCount;
      ttCPUPeriod: MsgDesc.Annex.MsgCPUPeriod := GetCPUPeriod;
    else
      MsgDesc.Annex.MsgCPUPeriod := 0; // 设为全 0
    end;

    // TimeMarkStop 时所耗 CPU 时钟周期数
    MsgDesc.Annex.MsgCPInterval := CPUPeriod;

    CopyMemory(@(MsgDesc.Annex.Tag), Pointer(ATag), TagLen);
    CopyMemory(@(MsgDesc.Msg), Pointer(LeftMsg), MsgLen);

    if LeftSize > CnMaxMsgLength then
    begin
      LeftMsg := Copy(LeftMsg, CnMaxMsgLength + 1, LeftSize);
      LeftSize := LeftSize - CnMaxMsgLength;
    end
    else
      LeftSize := 0;

    MsgLen := MsgLen + SizeOf(MsgDesc.Annex) + SizeOf(DWORD);
    MsgDesc.Length := MsgLen;
  end;

  procedure DoInternalOutputMsg;
  begin
    if FAutoStart and not FIgnoreViewer and not FViewerAutoStartCalled then
    begin
      StartDebugViewer;
      FViewerAutoStartCalled := True;
    end;

    Inc(FMessageCount);
    if not CheckEnabled then
      Exit;
    if not FChannel.CheckReady and not FDumpToFile then
      Exit;

    while LeftSize > 0 do
    begin
      GenerateMsgDesc;

      if FChannel.CheckReady then
      begin
        if FChannel.CheckFilterChanged then
          FChannel.RefreshFilter(FFilter);

        if CheckFiltered(string(ATag), ALevel, AType) then
          InternalOutput(MsgDesc, MsgLen);
      end;

      // 同时 DumpToFile
      if FDumpToFile and not FIgnoreViewer and (FDumpFile <> nil) then
      begin
        if not FAfterFirstWrite then // 第一回写时需要判断是否重写
        begin
          if FUseAppend then
            FDumpFile.Seek(0, soFromEnd)
          else
          begin
            FDumpFile.Size := 0;
            FDumpFile.Seek(0, soFromBeginning);
          end;
          FAfterFirstWrite := True; // 后续写就无需判断了
        end;

        FDumpFile.Write(MsgDesc, MsgLen);
      end;
    end;
  end;
begin
  LeftMsg := AMsg;
  LeftSize := Size;
  DoInternalOutputMsg;
end;

2010-2-11 11:40 jAmEs_
我处对CnDebug做再次改动,当信息长度大于4096时,自动分割信息,希望接纳。或可考虑增加选项控制。
代码可适当调整。

2010-2-26 10:32 jAmEs_
没有人回应一下?:L

2010-7-11 11:32 艳漫虹
新人报到,怎么好像很冷清的。。。。。。

页: [1]
查看完整版本: [建议]TCnDebugger


Powered by Discuz! Archiver 5.0.0  © 2001-2006 Comsenz Inc.