亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Delphi > 正文

Delphi深度探索-CodeSite應用指南

2019-11-18 18:41:34
字體:
來源:轉載
供稿:網友

Delphi深度探索-CodeSite應用指南

   Delphi雖然為我們提供極其強大的調試功能,查找Bug仍然是一項艱巨的工作,通常我們寫代碼和調試代碼的所消耗的時間是大致相同的,甚至有可能更多。為了減少無謂的時間和精力的浪費,有時我們還是需要專業調試工具的幫助來提高鎖定Bug的效率。本文中我們將介紹著名的調試工具CodeSite PRo 2.0(它獲得了2000年度Delphi Informant讀者選擇的最佳調試工具獎的第二名)。它的官方網址是www.raize.com。
    CodeSite的主要功能是可以讓開發者使用代碼來發送運行時的詳細信息到特殊的接收器,以便于進一步分析。更精確的說通過CodeSite實現的TCodeSite類,我們可以打包并發送運行時的信息給CodeSite Dispatcher(CodeSite的消息分發器),它可以路由這些消息到一個或多個接收器來察看。缺省的信息接收器是CodeSite Viewer(消息察看器)。
    CodeSite的效率體現在它不同于簡單的顯示消息的對話框或設定斷點來檢查變量,它更類似于Delphi自帶的事件日志功能(Event Log),當然毫無疑問它要比Event Log強大的多,它的消息是可持續的,也就是可以保存的,便于回溯分析。
    在介紹CodeSite的具體使用前,我們先來看一下它的三個組成部分。
    CodeSite對象
    正如前面提到的,從運行的應用程序中向外發送CodeSite消息是通過使用TCodeSite類(定義在CSIntf單元中)的一個實例來完成的,我們只要簡單的調用TCodeSite類的方法就可以 把消息發送給CodeSite Dispatcher。比如,可以使用對象的SendMsg方法來發送一個簡單的字符串消息。TCodeSite 對象實現了大量的方法來支持各種類型的信息發送而無須任何數據轉換,比如對象的SendObject方法有兩個參數:一個是消息字符串,一個是對對象實例的引用,這個方法會獲取對象所有published的屬性,然后把這些屬性的信息打包進CodeSite的消息中。 
    CodeSite Dispatcher
    大多數情況下,CodeSite Dispatcher會安靜的運行在系統的托盤區。它的唯一功能是路由從各個TCodeSite對象發來的CodeSite的消息到它們的目的地。缺省時,CodeSite消息都會發給CodeSite Viewer。我們甚至不需要啟動CodeSite Dispatcher,因為它會被TCodeSite等對象自動啟動?!?/DIV>
    TCodeSite 類定義了一個DestinationDetails屬性,它允許開發者設定發送的CodeSite消息是如何被CodeSite Dispatcher路由到不同目的地,比如日志文件。但通常沒有必要修改這個屬性。
    CodeSite Viewer
    雖然CodeSite 支持發送消息到不同的目標,但決大多數情況下CodeSite Viewer是主要的發送目標。即使是發送到其他目標,比如日志文件或另外一臺機器,CodeSite Viewer仍然是察看分析消息的主要工具?!?/DIV>
    CodeSite Viewer由下面四個面板構成:消息列表,消息察看器,調用堆棧和Scratch面板。CodeSite Viewer的主要工作區是Message列表,它用來顯示發送給Viewer的全部消息或是從日志文件中加載的消息。
    消息察看器用來察看同消息關聯的額外信息。比如如果當前的消息是由SendObject方法發送的話,消息察看器就會顯示對象全部的publised屬性當前值?!?/DIV>
    調用堆棧面板會根據csmEnterMethod消息顯示一個堆棧視圖?!?/DIV>
    Scratch面板則是用來顯示非可持續的信息的。當我們想跟蹤某些信息,但又不想在消息日志中記錄它們的時候,比如當我們想察看象鼠標當前位置這類大量的并重復的消息時,Scratch面板是非常有用的。這時我們可以可以使用TCodeSite對象的WritePoint方法,并指定Line ID參數以便指定用來容納鼠標信息的scratch面板行數。 
    下面就讓我們用一個簡單的例子來演示一下如何從程序中發送消息給CodeSite Viewer:
    (1)創建一個新的項目,然后切換組件面板到CodeSite頁面(CodeSite安裝后會在系統中安裝兩個組件TCSGlobalObject和TCSObject)。選擇TCSGlobalObject組件然后放到窗體上。TCSGlobalObject組件提供了設計時對全局TCodeSite對象的交互(全局TCodeSite是在CSInft單元中被初始化的)。
    (2)添加一個按鈕,然后在它的OnClick事件中寫下如下代碼:
    //CodeSite就是全局的TCodeSite對象
    CodeSite.SendMsg(‘CodeSite的第一條消息’);
    (3)編譯并運行這個簡單的程序。運行后點擊按鈕,CodeSite Dispatcher和CodeSite Viewer將會運行。同時在CodeSite Viewer的消息列表中將會看到程序發出的消息(注意:我們沒有必要在程序運行前啟動CodeSite Dispatcher和CodeSite Viewer,因為TCodeSite 對象在需要發送消息的時候會自動啟動它們的)。運行結果如下圖4.38所示:

圖4.38
 

 
 
 
 
 
 
 
 
 
 

    (4)接下來,停止程序,在OnClick事件處理過程中添加下面代碼:
    CodeSite.SendObject('Form1', Form1 );
    (5)重新編譯運行程序,再點按鈕一次,這回你會在CodeSite Viewer中看到兩條消息。其中Form1對應的消息包括Form1的對象信息。
    (6)為了看到Form1的相關聯的對象信息,選擇CodeSite Viewer的菜單命令View|Inspector會在消息列表右側顯示一個新的面板,Form1的published屬性都被顯示在其中,如下圖4.39所示:

圖4.39
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

    (7)再次停止程序,然后修改OnClick過程中代碼如下:
    CodeSite.EnterMethod('Button1Click');
    CodeSite.SendMsg('CodeSite的第一條消息');
    CodeSite.SendObject('Form1', Form1 );
    CodeSite.ExitMethod('Button1Click' );
    (8)這次我們再運行程序點擊按鈕后,就會看到“CodeSite的第一條消息”和“Form1”的消息被縮進在“Button1Click”消息之間,如下圖4.40所示:

圖4.40
 

 
 
 
 
 
 
 
 
 
 

    通過添加EnterMethod和ExitMethod方法的調用,我們可以生成一個日志來記錄方法何時被調用。
    看過例子之后,我們就會發現CodeSite的功能是非常強大的,我們只要簡單的在程序中添加幾條語句就可以生成非常詳細的信息,并通過CodeSite Viewer以生動的圖表表現出來。接下來,我們再來談談CodeSite的高級應用技術。
    發送消息到日志文件
    每個程序或多或少都會有Bug,不在這時發生,也會在那時發生,短時間內不發生,很長時間就可能發作,有時反復出現,有時非常偶然的才能被發現。如果一個人告訴你他寫的程序在任何時候都沒有任何問題,他一定是在撒謊。正是由于Bug的偶然性和隱蔽性,就使得我們往往很難重復用戶提交的Bug,這就給我們調試程序并找到問題的原因產生了極大的障礙,而CodeSite能夠發送消息到日志文件的特性就使得用戶報告Bug變得更容易,他們只要把運行時生成的信息文件提交就可以了。相應的我們調試程序的工作也會變得更輕松,我們可以使用CodeSite Viewer來直觀的分析錯誤發生的原因和位置。
    要想改變消息發送的目標,我們可以通過設定TCodeSite 對象的DestinationDetails屬性來實現。這項功能要求客戶的機器上必須安裝了CodeSite Dispatcher,它屬于CodeSite中可自由分發的部分。下面的要講具體過程仍然是基于前面講過的例子:
    (1)在窗體的OnCreate事件中添加下面代碼:
    CodeSite.DestinationDetails := 'File[Path=C:/FirstLog.csl]';
    (2)編譯并余興程序,這回我們在點擊按鈕后,消息就不再被發送給CodeSite Viewer而是發送到C盤的FirstLog.csl文件中。
    (3)使用CodeSite Viewer加載FirstLog.csl文件,這回我們就象先前一樣察看被保存的CodeSite消息了。
    (4)如果我們想把消息同時發送到CodeSite Viewer和日志文件的話,只修改前面的代碼為:
    CodeSite.DestinationDetails := 'Viewer,File[Path=C:/FirstLog.csl]';
    發送用戶定制的數據
    雖然TCodeSite 類提供了大量的處理不同數據類型的方法,但有時我們可能會需要發送某種自定義格式的數據信息。為此,TCodeSite 類定義了SendCustomData 方法,它支持發送任意的數據類型,并會根據一個自定義的格式器來格式化數據以便CodeSite Viewer可以正確的顯示數據。
    首先我們需要創建一個TCSFormatter 對象的子類,然后重載對象的FormatData,InspectorType和TypeName方法。然后調用CodeSite對象管理器對象CSObjectManager的來注冊新的TCSFormatter子類。此外,我們還需要調用RegisterCustomFormat方法來注冊一個新的消息類型。
    下面是一個實際應用的例子,單元CSEmployee.pas中實現了一個TCSEmployeeRecord記錄類型的定制格式器:
    unit CSEmployee;
    interface
    uses
      Windows, Graphics, CSIntf;
    const
      csmEmployeeSummary = csmUser + 1;
      csmEmployeeDetails = csmUser + 2;
    首先在Uses部分添加對CSIntf 單元的引用。第二步是為每一個格式器定義新的CodeSite消息類型常數,上面我們定義了兩個常數,注意常數應該大于csmUser,但不能大過32,000。 
    type
      TCSEmployee = record
        LastName: string;
        FirstName: string;
        Address: string;
        City: string;
        State: string;
        ZipCode: string;
        PhoneNumber: string;
        HireDate: TDateTime;
        Salary: Currency;
        VacationDays: Integer;
        SickDays: Integer;
        Manager: Boolean;
      end;
    上面的記錄就是我們要發送的自定義的數據類型?!?/DIV>
      TCSEmployeeSummaryFormatter = class( TCSFormatter )
      public
        function InspectorType: TCSInspectorType; override;
        procedure FormatData( var Data ); override;
        function TypeName: string; override;
      end;
      TCSEmployeeDetailsFormatter = class( TCSFormatter )
      public
        function InspectorType: TCSInspectorType; override;
        procedure FormatData( var Data ); override;
        function TypeName: string; override;
      end;
    上面是兩個定制的格式器類的定義。第一個格式器將把TCSEmployee 記錄格式化為一個文本格式,第二個格式化器將把TCSEmployee 記錄格式化為網格樣式。
    implementation
    uses
      SysUtils;
    {=========================================}
    {== TCSEmployeeSummaryFormatter Methods ==}
    {=========================================}
    function TCSEmployeeSummaryFormatter.InspectorType: TCSInspectorType;
    begin
      Result := itStockStringList;
    end;
    實現一個自定義的格式化器的第一步是確定哪種類型的內置察看器將被用來察看格式化后的數據,這里使用的是字符串列表察看器。察看器類型將被FormatData方法所使用。 
    procedure TCSEmployeeSummaryFormatter.FormatData( var Data );
    var
      EmpRec: TCSEmployee;
    begin
      EmpRec := TCSEmployee( Data );
      AddLine( EmpRec.FirstName + ' ' + EmpRec.LastName );
      AddLine( EmpRec.Address );
      AddLine( EmpRec.City + ', ' + EmpRec.State + '  ' + EmpRec.ZipCode );
      AddLine( '' );
      AddLine( 'Phone: ' + EmpRec.PhoneNumber );
      AddLine( 'Hire Date: ' + DateToStr( EmpRec.HireDate ) );
      AddLine( 'Salary: ' + Format( '%m', [ EmpRec.Salary ] ) );
      AddLine( '' );
      AddLine( 'Vacation Days: ' + IntToStr( EmpRec.VacationDays ) );
      AddLine( 'Sick Days: ' + IntToStr( EmpRec.SickDays ) );
      if EmpRec.Manager then
        AddLine( 'Manager: Yes' )
      else
        AddLine( 'Manager: No' );
    end;
    FormatData 方法是核心部分,注意傳遞給FormatData方法的Data參數是一個無類型的可變參數。這就意味著這個參數可以是任何數據類型的,通過格式注冊過程,我們可以確保強制類型映射為自定義的數據記錄,而不會發生轉換錯誤。
    轉換數據類型后,我們就可以對數據進行格式化了,這里使用TCSFormatter 基類的 AddLine方法在字符串間添加分割線來進行格式化。 
    function TCSEmployeeSummaryFormatter.TypeName: string;
    begin
      Result := 'TCSEmployee';
    end;
    TypeName方法的重載是可任選的,但通常我們可以用它來返回顯示在消息列表中的字符串。
    {=========================================}
    {== TCSEmployeeDetailsFormatter Methods ==}
    {=========================================}
    function TCSEmployeeDetailsFormatter.InspectorType: TCSInspectorType;
    begin
      Result := itStockGrid;
    end;
    對于employeedetails格式器來說,命名網格察看器將被用來察看數據信息:
    procedure TCSEmployeeDetailsFormatter.FormatData( var Data );
    var
      EmpRec: TCSEmployee;
    begin
      EmpRec := TCSEmployee( Data );
      AddNameValuePair( 'LastName', EmpRec.LastName );
      AddNameValuePair( 'FirstName', EmpRec.FirstName );
      AddNameValuePair( 'Address', EmpRec.Address );
      AddNameValuePair( 'City', EmpRec.City );
      AddNameValuePair( 'State', EmpRec.State );
      AddNameValuePair( 'ZipCode', EmpRec.ZipCode );
      AddNameValuePair( 'PhoneNumber', EmpRec.PhoneNumber );
      AddNameValuePair( 'HireDate', EmpRec.HireDate );
      AddNameValuePair( 'Salary', Format( '%m', [ EmpRec.Salary ] ) );
      AddNameValuePair( 'VacationDays', EmpRec.VacationDays );
      AddNameValuePair( 'SickDays', EmpRec.SickDays );
      AddNameValuePair( 'Manager', EmpRec.Manager );
    end;
    這里為了在網格察看器中格式化數據,我們使用AddNameValuePair方法來實現?!?/DIV>
    function TCSEmployeeDetailsFormatter.TypeName: string;
    begin
      Result := 'TCSEmployee';
    end;
    下面兩個過程是用來封裝對SendCustomData方法的調用的,這里對全局的TCodeSite對象實例CodeSite進行了調用:
    {=====================}
    {== Support Methods ==}
    {=====================}
    procedure CSSendEmployeeSummary( const Msg: string; EmpRec: TCSEmployee );
    begin
      CodeSite.SendCustomData( csmEmployeeSummary, Msg, EmpRec );
    end;
    procedure CSSendEmployeeDetails( const Msg: string; EmpRec: TCSEmployee );
    begin
      CodeSite.SendCustomData( csmEmployeeDetails, Msg, EmpRec );
    end;
    最后,不要忘了調用CSObjectManager.RegisterCustomFormatter方法把格式器注冊到CodeSite對象管理器中。
    initialization
      CSObjectManager.RegisterCustomFormatter( csmEmployeeSummary,
                      TCSEmployeeSummaryFormatter );
      CSObjectManager.RegisterCustomFormatter( csmEmployeeDetails,
                       TCSEmployeeDetailsFormatter );
    end.

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲天天在线日亚洲洲精| 国产精品一二区| 国产69精品久久久久久| 一区二区三区视频观看| 欧美成人免费在线视频| 成人综合国产精品| 国产亚洲一级高清| 亚洲毛片在线观看| 精品二区三区线观看| 亚洲精品一区二区在线| 亚洲精品永久免费精品| 久久香蕉精品香蕉| 亚洲美女精品成人在线视频| 日韩精品视频在线| 最近2019中文字幕在线高清| 国产精品第100页| 久久久久国产一区二区三区| 日韩欧美视频一区二区三区| 久久亚洲精品一区| 国产在线98福利播放视频| 亚洲天堂精品在线| 精品国产91乱高清在线观看| 国产精品偷伦视频免费观看国产| 亚洲aa在线观看| 国产日韩在线亚洲字幕中文| 国产小视频91| 亚洲美女福利视频网站| 精品久久久久久国产| 最新国产成人av网站网址麻豆| 欧美成人午夜激情| 亚洲aⅴ日韩av电影在线观看| 国产在线日韩在线| 日韩美女av在线免费观看| 国产欧美精品一区二区三区介绍| 欧美小视频在线观看| 久久久久久久久国产| 亚洲成年人在线| 91亚洲国产精品| 一区二区三区四区在线观看视频| 福利一区福利二区微拍刺激| 亚洲成人av在线播放| 欧美黄色成人网| 91老司机精品视频| 久久97精品久久久久久久不卡| 亚洲精品国偷自产在线99热| 亚洲美女喷白浆| 国产日本欧美一区二区三区在线| 日韩精品在线观看一区| www高清在线视频日韩欧美| 国产婷婷97碰碰久久人人蜜臀| 最近2019年好看中文字幕视频| 国产不卡在线观看| 亚洲精品理论电影| 国产精品扒开腿爽爽爽视频| 色www亚洲国产张柏芝| 国产日韩在线视频| 91精品国产高清自在线看超| 国产精品日韩一区| 久久久久久国产三级电影| 国产精自产拍久久久久久| 欧美日本高清一区| 在线日韩av观看| 亚洲第一页在线| 午夜精品久久久久久99热软件| 亚洲偷欧美偷国内偷| 欧美精品激情在线| 国产一区二区视频在线观看| 精品一区二区三区电影| 欧美成人精品xxx| 不用播放器成人网| 欧美一级电影在线| 亚洲成人免费在线视频| 欧美性猛交99久久久久99按摩| 欧美wwwwww| 91在线播放国产| 亚洲成色999久久网站| 欧美最猛黑人xxxx黑人猛叫黄| 中文字幕日韩欧美在线视频| 68精品国产免费久久久久久婷婷| 亚洲色图13p| 中日韩午夜理伦电影免费| 久久这里只有精品99| 久久精品影视伊人网| 亚洲美女激情视频| 国产精品久久久久久搜索| 97视频免费在线看| 亚洲网站视频福利| 美女av一区二区三区| 午夜精品久久久99热福利| 久久夜精品香蕉| 97碰在线观看| 亚洲美女又黄又爽在线观看| 4k岛国日韩精品**专区| 精品国产乱码久久久久久虫虫漫画| 亚洲欧美国产视频| 欧美中文在线字幕| 国内精品免费午夜毛片| 国产精品高精视频免费| 欧美老少做受xxxx高潮| 久久久久五月天| 久久久久久亚洲精品不卡| 久久影院资源站| 久久色精品视频| 日韩av在线看| 欧美午夜精品久久久久久浪潮| 亚洲高清一二三区| 亚洲色图色老头| 羞羞色国产精品| 久久久久日韩精品久久久男男| 欧美午夜精品久久久久久浪潮| 亚洲视频777| 国产精品久久久久久久天堂| 欧美成人剧情片在线观看| 欧美电影在线免费观看网站| 亚洲理论片在线观看| 97人人爽人人喊人人模波多| 国产精品男女猛烈高潮激情| 欧美日韩国产成人高清视频| 久久噜噜噜精品国产亚洲综合| 欧洲日本亚洲国产区| 日韩欧美亚洲综合| 久久99精品久久久久久琪琪| 国产欧美日韩丝袜精品一区| 国产精品一区二区av影院萌芽| 亚洲一区二区三区视频| 57pao成人国产永久免费| 久久免费高清视频| 日韩中文字幕在线精品| 久久久久久久久久久91| 91高清免费视频| 在线观看日韩专区| 91在线中文字幕| 欧美日韩视频在线| 国产一区二区欧美日韩| 日韩在线观看网站| 久久天天躁狠狠躁夜夜av| 国产丝袜视频一区| 日本久久91av| 91免费视频网站| 爽爽爽爽爽爽爽成人免费观看| 日日狠狠久久偷偷四色综合免费| 久久久成人的性感天堂| 最近中文字幕mv在线一区二区三区四区| 亚洲精品女av网站| 国产精品pans私拍| 色视频www在线播放国产成人| 日韩中文字幕不卡视频| 亚洲国产小视频| 欧美精品久久久久久久| 亚洲乱码国产乱码精品精| 一本色道久久综合亚洲精品小说| 国产视频一区在线| 成人在线激情视频| 中文字幕欧美在线| 国产精品福利网站| 91九色国产社区在线观看| 亚洲激情视频在线观看| 最近中文字幕mv在线一区二区三区四区| 久久久精品久久久| 96精品视频在线| 日本国产一区二区三区| 日韩高清电影免费观看完整| 中文字幕一区二区精品| 欧美激情综合色|