2010年10月17日 星期日

使用WindDBG附加程序除錯Silverlight應用程式

 

使用的程式碼如下:

  1: private void MyButton_Click(object sender, RoutedEventArgs e)
  2: {
  3:     try
  4:     {
  5: 	    throw new Exception("Test exception");
  6:     }
  7:     catch
  8:     {
  9:     }
 10:     Thread.Sleep(25000);
 11:     MyButton.Content = "Pushed";
 12: } 

1. 首先要知道正在執行的應用程式ProcessID,這邊我使用Process Explorer這一套軟體來抓。


image


image 


2. 進入WinDBG,打開[File]->[Attach to a Process…],選取剛剛找到的ProcessID。


image


3. 載入正確的WinDBG Extension DLL – SOS.dll,讓我們可以看到.NET Framework的Managed 程式碼。


(據測試的結果,本步驟可省略,但用!eeversion.chain確認一下較好)


可以用Everything來看一下有哪些SOS.dll


image


看一下目前的執行期環境,我們要挑一個和目前執行期環境相同版本的SOS.dll。


0:022> lm v m *clr*  <== List Loaded Modules(v = verbose;m Pattern )
start    end        module name
63450000 637b9000   coreclr    (deferred)            
    Image path: c:\Program Files\Microsoft Silverlight\4.0.50917.0\coreclr.dll
    Image name: coreclr.dll
    Timestamp:        Fri Sep 17 12:06:19 2010 (4C92E93B)
    CheckSum:         00361079
    ImageSize:        00369000
    File version:     4.0.50917.0
    Product version:  4.0.50917.0
    File flags:       0 (Mask 3F)
    File OS:          4 Unknown Win32
    File type:        2.0 Dll
    File date:        00000000.00000000
    Translations:     0409.04b0
    CompanyName:      Microsoft Corporation
    ProductName:      Microsoft® Silverlight
    InternalName:     coreclr.dll
    OriginalFilename: coreclr.dll
    ProductVersion:   4.0.50917.0
    FileVersion:      4.0.50917.0 (SL_V4_SVC.050917-0000)
    FileDescription:  Microsoft .NET Runtime Common Language Runtime - WorkStation
    LegalCopyright:   © Microsoft Corporation.  All rights reserved.
    Comments:         Flavor=Retail


也可以使用!eeversion指令。


0:028> !eeversion ==> (顯示 Common Language Runtime 版本)
4.0.50917.0 retail
Workstation mode
SOS Version: 4.0.50917.0 retail build


0:011> .reload ==> (Reload Module)
Reloading current modules
................................................................
............................................................
0:011> .load C:\Program Files\Microsoft Silverlight\4.0.50917.0\sos.dll ==>(Load Extension DLL)


檢查Extension DLL是否已經正確載入


0:011> .chain ==>(List Debugger Extensions)
Extension DLL search Path:
    C:\Program Files\Debugging Tools for Windows (x86)\WINXP;C:\Program Files\Debugging Tools for Windows (x86)\winext;C:\Program Files\Debugging Tools for Windows (x86)\winext\arcade;C:\Program Files\Debugging Tools for Windows (x86)\pri;C:\Program Files\Debugging Tools for Windows (x86);C:\Program Files\Debugging Tools for Windows (x86)\winext\arcade(...省略)
Extension DLL chain:
    C:\Program Files\Microsoft Silverlight\4.0.50917.0\sos: image 4.0.50917.0, API 1.0.0, built Fri Sep 17 12:08:16 2010
        [path: C:\Program Files\Microsoft Silverlight\4.0.50917.0\sos.dll]
    C:\Program Files\Microsoft Silverlight\4.0.50917.0\sos.dll: image 4.0.50917.0, API 1.0.0, built Fri Sep 17 12:08:16 2010
        [path: C:\Program Files\Microsoft Silverlight\4.0.50917.0\sos.dll]
    dbghelp: image 6.12.0002.633, API 6.1.6, built Tue Feb 02 04:08:26 2010
        [path: C:\Program Files\Debugging Tools for Windows (x86)\dbghelp.dll]
    ext: image 6.12.0002.633, API 1.0.0, built Tue Feb 02 04:08:31 2010
        [path: C:\Program Files\Debugging Tools for Windows (x86)\winext\ext.dll]
    exts: image 6.12.0002.633, API 1.0.0, built Tue Feb 02 04:08:24 2010
        [path: C:\Program Files\Debugging Tools for Windows (x86)\WINXP\exts.dll]
    uext: image 6.12.0002.633, API 1.0.0, built Tue Feb 02 04:08:23 2010
        [path: C:\Program Files\Debugging Tools for Windows (x86)\winext\uext.dll]
    ntsdexts: image 6.1.7650.0, API 1.0.0, built Tue Feb 02 04:08:08 2010
        [path: C:\Program Files\Debugging Tools for Windows (x86)\WINXP\ntsdexts.dll]


4. 列出Internet Explorer裡面的執行序,找出應用程式使用的ThreadID和他的內容。


0:011> ~* e !clrstack ==>(~ = 執行序; * = 全部; e = 執行; !clrstack = 提供 Managed 程式碼的堆疊追蹤)
OS Thread Id: 0x7ac (0)
Unable to walk the managed stack. The current thread is likely not a
managed thread. You can run !threads to get a list of managed threads in
the process
(...省略)
OS Thread Id: 0x163c (4)
Child SP IP       Call Site
020ed848 77b164f4 [HelperMethodFrame: 020ed848] System.Threading.Thread.SleepInternal(Int32)
020ed888 62a68e05 System.Threading.Thread.Sleep(Int32)
020ed88c 041e042d
SilverlightApplication1.MainPage.MyButton_Click(System.Object, System.Windows.RoutedEventArgs)
020ed8c4 632a0b81 System.Windows.Controls.Primitives.ButtonBase.OnClick()
020ed8d8 632f9d24 System.Windows.Controls.Button.OnClick()
020ed8e4 632a058e System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(System.Windows.Input.MouseButtonEventArgs)
020ed8f4 63262e01 System.Windows.Controls.Control.OnMouseLeftButtonUp(System.Windows.Controls.Control, System.EventArgs)
020ed904 63260f44 MS.Internal.JoltHelper.FireEvent(IntPtr, IntPtr, Int32, Int32, System.String)
020ed948 632e702f DomainNeutralILStubClass.IL_STUB_ReversePInvoke(Int32, Int32, Int32, Int32, IntPtr)
020eda24 071c6dbc [ContextTransitionFrame: 020eda24]
OS Thread Id: 0xe10 (5)
Unable to walk the managed stack. The current thread is likely not a
managed thread. You can run !threads to get a list of managed threads in
the process
(...省略)


5. 列出Exception的記憶體回收堆積 (Heap) 資訊,取得最近的Method Table物件(這裡是指Exception物件)。


0:011> !dumpheap -type Exception ==>(列出記憶體回收堆積; –type 只會列出相同型別與子型別的物件)
Address       MT     Size
078e1024 62c52b94       80    
078e1074 62c5b580       80    
078e10c4 62c5b5c8       80    
078e1114 62c5b658       80    
078e1164 62c5da48       80    
078e11b4 62c5da48       80    
078e4c24 62c33358       32    
078eb200 633533ac       32    
078eb220 633782a0       32    
078fac6c 6334a330       32    
0791f8b4 62c52b94       80    
total 0 objects
Statistics:
      MT    Count    TotalSize Class Name
633782a0        1           32 MS.Internal.Error+GetExceptionTextDelegate
633533ac        1           32 MS.Internal.Error+ClearExceptionDelegate
6334a330        1           32 System.EventHandler`1[[System.Windows.ApplicationUnhandledExceptionEventArgs, System.Windows]]
62c33358        1           32 System.UnhandledExceptionEventHandler
62c5b658        1           80 System.ExecutionEngineException
62c5b5c8        1           80 System.StackOverflowException
62c5b580        1           80 System.OutOfMemoryException
62c5da48        2          160 System.Threading.ThreadAbortException
62c52b94        2          160 System.Exception
Total 11 objects


6. 列出參考到這個Method Table物件(這裡是指Exception物件)的位址


0:011> !dumpheap -mt 62c52b94 ==> (列出記憶體回收堆積; –mt 列出對應到 MethodTable 結構之物件)       
Address       MT     Size
078e1024 62c52b94       80    
0791f8b4 62c52b94       80    
total 0 objects
Statistics:
      MT    Count    TotalSize Class Name
62c52b94        2          160 System.Exception
Total 2 objects


7. 列出物件內容,這邊是Exception,所以使用!pe指令。


0:011> !pe 0791f8b4 ==>(print exception)
Exception object: 0791f8b4
Exception type:   System.Exception
Message:          Test exception
InnerException:   <none>
StackTrace (generated):
    SP       IP       Function
    020ED88C 041E0417 UNKNOWN!SilverlightApplication1.MainPage.MyButton_Click(System.Object, System.Windows.RoutedEventArgs)+0x57


StackTraceString: <none>
HResult: 80131500
The current thread is unmanaged


結論:


這個例子體現了尋找錯誤必須要由大往小,由粗往細的過程。


由Process到Thread: ProcessID => ~* e !clrstack


由物件到函式表:!dumpheap –type xxx => !dumpheap –mt xxx


參考資料:


2010年10月14日 星期四

讓Visio 2007支援Robustness Diagram(穩健圖、魯棒圖)的三種元素

  1. http://www.softwarestencils.com/uml/index.html#Visio2007下載範本
  2. 設定Vision的檔案路徑
    1. 選擇[工具]=>[選項]=>[進階]=>[檔案路徑] image
    2. 設定[我的圖形(M)][和範本(T)]image
  3. 將下載的檔案放在"C:\Users\<使用者名稱>\我的圖形\軟體與資料庫"下image
  4. 在[檔案]=>[新增]=>[快速入門]中可以見到新增的範本了。

image

2010年10月9日 星期六

Web 測試中的奇怪網址

在Vistual Studio 的Web 測試,錄製時產生了大量的奇怪網址:

https://urs.microsoft.com/urs.asmx?MSURS-Client-Key=...&MSURS-Patented-Lock=...

經過一番網路上的搜尋與自己的測試後,發現原來這個網址是微軟的"Smart Screen篩選"所使用。

在Web 測試中當然要把它關閉,不然除了增加管理與使用的困難,也增加了不必要的網路流量。

怎麼樣關閉Smart Screen篩選功能呢? 有以下三種方法(IE8):

  • (全域)[工具]—>[Smart Screen 篩選] –>[關閉Smart Screen 篩選...]—>選擇 關閉Smart Screen 篩選

image

  • (全域)[工具]—>[網際網路選項]—>[進階]—>關閉 啟用記憶體保護以協助避免網路攻擊

image

  • (區域)[工具]—>[安全性]—>[信任的網站/自訂等級]—>停用 Smart Screen 篩選

(記得要選擇可以信任的網站嘿~~)

image

安全性設定 - 信任的網站區域

參考資料:

ICONIX 開發方法

核心方法很簡單,也符合一般的流程,最重要的是,個人認為可以補足UML開發過程中的不足。

bridgingthechasm-sm

請注意其中的Robustness Diagram。

iconixprocess-lg

較詳細的圖片解說:

iconixprocessroadmap-lg

登入 Robustness Diagram(台:穩健圖、陸:魯棒圖)

登入頁魯棒圖

註冊 Robustness Diagram

註冊魯棒圖

 

參考資料:

深入偵錯程式碼

在程式碼偵錯時,可以顯示.Net Framework的原始程式碼,不但可以了解控制項或其他程序的流程,也可以對錯誤的原因有更進一步的認識,何樂而不為。

1. [啟用.NET Framework 來源步進]時,會取消Just My Code,請讓它取消。Just My Code的意思是偵錯只限定於自己寫的程式碼,現在我們要深入MS所提供的程式碼,所以要取消他。

0001-747x456_thumb1

2. 設定[符號檔(.pdf)位置(F):]與[從符號伺服器將符號快去至此目錄(C):]。本機位置請設定為相同。遠端位置請設定為 http://msdl.microsoft.com/download/symbols

 0003-747x456_thumb1

3. 按[確定]之後,會從遠端下載專案所需要的符號檔。符號檔以命名空間為一個單位,除非專案使用到的命名空間不同,否則這個步驟只會執行一次。

0002-747x456_thumb1

參考資料:

  1. 使用 Microsoft 符號伺服器取得偵錯符號檔
  2. Download Windows Symbol Packages

ASP.NET 狀態管理優缺點比較與建議事項

用戶端狀態管理選項

 

優點

缺點

檢視狀態 不需要伺服器資源
實作簡單
增強安全性功能
效能考量
裝置限制
潛在安全性風險
控制項狀態 不需要伺服器資源
可靠性
全面性
需要部分程式設計工作
隱藏欄位 不需要伺服器資源
廣泛支援
簡單實作
潛在安全性風險
簡單的儲存架構
效能考量
儲存限制
Cookie 可設定的到期規則
不需要伺服器資源
簡化
資料保存性
大小限制
使用者設定的拒絕
潛在安全性風險
查詢字串 不需要伺服器資源
廣泛支援
簡單實作
潛在安全性風險
容量限制

 

用戶端方法狀態管理摘要

狀態管理選項

建議的使用方式

檢視狀態 當您需要儲存網頁將回傳本身的少量資訊時使用。使用 ViewState 屬性會提供基本安全性功能。
控制項狀態 當您需要儲存伺服器來回往返之間控制的少量狀態資訊時使用。
隱藏欄位 您需要儲存網頁將回傳本身或其他網頁的少量資訊,而且不考量安全性的問題時使用。
(注意事項:您只能在送至伺服器的網頁上使用隱藏欄位。)
Cookie 當您需要在用戶端上儲存少量資訊,而且不考量安全性的問題時使用。
查詢字串 當您要將少量資訊從一網頁傳輸至另一網頁,而且不考量安全性的問題時使用。
(注意事項:只有在要求相同網頁,或透過連結要求另一網頁時,才能使用查詢字串。)

 

伺服器端狀態管理選項

  優點 缺點
應用程式狀態 實作簡單
應用程式範圍
應用程式範圍
有限的資料耐久性
資源需求
工作階段狀態 實作簡單
工作階段特定事件
資料保存性
平台延展性
Cookieless 支援
擴充性
效能考量
設定檔屬性 資料保存性
平台延展性
擴充性
效能考量
額外設定的需求
資料維護
資料庫支援 安全性
儲存空間
資料保存性
強固性和資料完整性
協助工具
廣泛支援
複雜度
效能考量

 

伺服器端方法狀態管理摘要

狀態管理選項

建議的使用方式

應用程式狀態 當您正在儲存變更頻率低、由許多使用者使用的全域資訊、而且不考量安全性的問題時使用。
請勿在應用程式狀態中儲存大量資訊。
工作階段狀態 當您要儲存個別工作階段專用且存留期短暫的資訊,同時必須顧慮安全性時使用。
請勿在工作階段狀態中儲存大量資訊。
請注意,工作階段狀態物件會在您應用程式中每個工作階段的存留期期間建立並維護。
在擁有許多使用者的應用程式中,這可能會佔用大量的伺服器資源並且影響延展性。
設定檔屬性 當您儲存在工作階段過期後需要保存的使用者特定資訊,並且在後續造訪應用程式需要再度擷取時使用。
資料庫支援 當您儲存大量資訊、管理交易、或是資料必須不受應用程式和工作階段重新啟動的影響時使用。
資料採擷是重要的,而且也必須顧慮安全性。

 

參考資料: ASP.NET 狀態管理建議事項

伺服器控制項與子屬性的視圖狀態比較

















public class BookNew : WebControl
public class StateManagedAuthor : IStateManager
     
private StateManagedAuthor authorValue;

[DesignerSerializationVisibility(
DesignerSerializationVisibility.Content),
PersistenceMode(PersistenceMode.InnerProperty)]
public virtual StateManagedAuthor Author
{
get
{
if (authorValue == null)
{
authorValue = new StateManagedAuthor();

if (IsTrackingViewState)
{
((IStateManager)authorValue).TrackViewState();
}
}
return authorValue;
}
}
private bool _isTrackingViewState;
private StateBag _viewState;

protected virtual StateBag ViewState
{
get
{
if (_viewState == null)
{
_viewState = new StateBag(false);

if (_isTrackingViewState)
{
((IStateManager)_viewState).TrackViewState();
}
}
return _viewState;
}
}
bool IStateManager.IsTrackingViewState
{
get
{
return _isTrackingViewState;
}
}
internal void SetDirty()
{
_viewState.SetDirty(true);
}
protected override void LoadViewState(object savedState)
{
Pair p = savedState as Pair;
if (p != null)
{
base.LoadViewState(p.First);
((IStateManager)Author).LoadViewState(p.Second);
return;
}
base.LoadViewState(savedState);
}
void IStateManager.LoadViewState(object savedState)
{
if (savedState != null)
{
((IStateManager)ViewState).LoadViewState(savedState);
}
}

protected override object SaveViewState()
{
object baseState = base.SaveViewState();
object thisState = null;

if (authorValue != null)
{
thisState = ((IStateManager)authorValue).SaveViewState();
}

if (thisState != null)
{
return new Pair(baseState, thisState);
}
else
{
return baseState;
}
}
object IStateManager.SaveViewState()
{
object savedState = null;

if (_viewState != null)
{
savedState =((IStateManager)_viewState).SaveViewState();
}
return savedState;
}
protected override void TrackViewState()
{
if (authorValue != null)
{
((IStateManager)authorValue).TrackViewState();
}
base.TrackViewState();
}
void IStateManager.TrackViewState()
{
_isTrackingViewState = true;

if (_viewState != null)
{
((IStateManager)_viewState).TrackViewState();
}
}
public override string ToString()
{
return ToString(CultureInfo.InvariantCulture);
}
public string ToString(CultureInfo culture)
{
return TypeDescriptor.GetConverter(
GetType()).ConvertToString(null, culture, this);
}

參考資料:


資料繫結(數據綁定、DataBind)概略流程

DataBind_thumb3

補充:DataSourceControl 類別

您可以把資料來源控制項想像成 DataSourceControl 物件及其相關資料清單 (稱為資料來源檢視) 的組合。每份資料清單都由 DataSourceView 物件表示。因為基礎資料儲存區包含一個或多個資料清單,所以 DataSourceControl 永遠與一個或多個具名 DataSourceView 物件產生關聯。IDataSource 介面會定義所有資料來源控制項與資料來源檢視互動時使用的方法:GetViewNames 方法是用來列舉目前與資料來源控制項關聯的資料來源檢視,而 GetView 方法則是用來依名稱擷取特定資料來源檢視執行個體。

您也可以把資料來源控制項想像成呼叫端用來存取資料的兩個不同介面。當頁面開發人員在開發 Web Form 網頁時,會直接與 DataSourceControl 類別這個介面互動,而資料繫結控制項和資料繫結控制項作者則會與 DataSourceView 類別這個介面互動。因為只有在執行階段才可使用 DataSourceView 物件,所以資料來源控制項或資料來源檢視的任何保存狀態,都必須由資料來源控制項直接公開。