Board logo

Subject: [建议]TCnDebugger [Print This Page]

Author: jAmEs_    Time: 2009-12-24 12:30     Subject: [建议]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;

[ 本帖最后由 jAmEs_ 于 2009-12-24 16:30 编辑 ]
Author: Passion    Time: 2009-12-24 15:31

本来就有输出到文件的功能哇。
Author: jAmEs_    Time: 2009-12-24 16:29

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

我回去看了一下,好像必须打开查看器,才会输出文件吧?
Author: Passion    Time: 2009-12-24 18:02

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

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

你的意思是不要启动查看器而直接输出到文件?
Author: jAmEs_    Time: 2009-12-26 11:15

对啊。。
Author: Passion    Time: 2009-12-26 19:39

明白你的需求了。我改了一下,晚上回去提交。
Author: jAmEs_    Time: 2009-12-27 13:36


Author: Passion    Time: 2009-12-28 13:27

先试一试我改的内容?在附件里。

Attachment: CnDebug.pas (2009-12-28 13:27, 78.73 K) / Download count 577
http://bbs.cnpack.org/attachment.php?aid=713
Author: jAmEs_    Time: 2009-12-28 18:57

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

好的。命名上局部变量似乎是不太合适用F,F都是表示Field,一般是类的成员变量。
Author: jAmEs_    Time: 2009-12-30 10:31

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

好的,接受。
Author: jAmEs_    Time: 2010-2-11 11:38

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;
Author: jAmEs_    Time: 2010-2-11 11:40

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

没有人回应一下?
Author: 艳漫虹    Time: 2010-7-11 11:32

新人报到,怎么好像很冷清的。。。。。。




Welcome to CnPack Forum (http://bbs.cnpack.org/) Powered by Discuz! 5.0.0