Assert 是一種可以在程式碼存取使用權限類別和 PermissionSet 類別上呼叫的方法。您可以使用 Assert 使您的程式碼 (和下層呼叫端) 執行需擁有使用權限才可執行的動作,而程式碼的呼叫端可能沒有擁有執行所需的使用權限。安全性判斷提示可以變更 Runtime 在安全性檢查期間所執行的一般程序。當您判斷提示一個使用權限時,它可以讓安全性系統對已判斷提示的使用權限不檢查其程式碼的呼叫端。警告   使用判斷提示必須謹慎,因為它們會暴露安全性漏洞並破壞 Runtime 使用安全性條件限制的機制。
當類別庫呼叫進入 Unmanaged 程式碼內,或執行其使用權限明顯地和類別庫的用途不相關的呼叫時,判斷提示是非常有用的。例如,所有呼叫進入 Unmanaged 程式碼的 Managed 程式碼都必須有已指定了 UnmanagedCode 旗標的 SecurityPermission。不是由本機電腦產生的程式碼,如從本機 Intranet 下載的程式碼,依預設不會被授與這個使用權限。因此,為了要讓從本機 Intranet 下載的程式碼可以呼叫使用 Unmanaged 程式碼的程式庫,它必須要有由程式庫判斷提示的使用權限。此外,某些類別庫也可以執行呼叫端看不到且需要特殊使用權限的呼叫。當您的程式碼存取完全由呼叫端隱藏的資源時也可以使用判斷提示。例如,假設您的類別庫要取得資料庫中的資訊,但在取得的過程中仍可讀取電腦登錄中的資訊。因為使用您類別庫的開發人員沒有存取您的原始碼,所以他們無法知道他們的程式碼需要 RegistryPermission 以使用您的程式碼。在這種情形下,如果您決定不必要求您程式碼的呼叫端必須擁有存取登錄的使用權限,您可以判斷提示讀取登錄的使用權限。類別庫在這種狀態下即適合判斷提示使用權限,使呼叫端不需 RegistryPermission 即可使用該類別庫。當已判斷提示的使用權限和下層呼叫端所需求的使用權限屬於相同類型,且需求的使用權限是已判斷提示的使用權限子集時,判斷提示才會影響堆疊查核行程。例如,如果您使用 FileIOPermission 以讀取 C 磁碟機上的所有檔案,且執行 FileIOPermission 的下層需求以讀取 C:\Temp 中的檔案時,判斷提示將會影響堆疊查核行程;然而,當 FileIOPermission 的需求是寫入 C 磁碟機,判斷提示將不會產生任何的影響。若要執行判斷提示,您的程式碼必須同時被授與您正在判斷提示的使用權限,以及表示執行判斷提示權限的 SecurityPermission。雖然您可以判斷提示您程式碼尚未被授與的使用權限,但判斷提示將不具任何意義,因為安全性檢查在成功判斷提示之前將會失敗。下圖將說明當使用 Assert 時所產生的影響。假設以下有關組件 A、B、C、E 和 F 以及使用權限 P1 和 P1A 的陳述式 (Statement) 為 True: P1A 表示讀取 C 磁碟機上 .txt 檔的權限。 
P1 表示讀取 C 磁碟機上所有檔案的權限。 
P1A 和 P1 都屬於 FileIOPermissions,而 P1A 為 P1 的子集。 
組件 E 和 F 已被授與 P1A 使用權限。 
組件 C 已被授與 P1 使用權限。 
組件 A 和 B 不被授與 P1 或 P1A 使用權限。 
方法 A 包含於組件 A、方法 B 包含於組件 B 等等。 
使用判斷提示這個案例中,方法 A 呼叫 B、B 呼叫 C、C 呼叫 E 以及 E 呼叫 F。方法 C 判斷提示讀取 C 磁碟機上檔案的使用權限 (使用權限 P1),而方法 E 則要求讀取 C 磁碟機上 .txt 檔的使用權限 (使用權限 P1A)。當在 Run Time 發現 F 中的需求時,即會執行一個堆疊查核行程 (Stack Walk) 從 E 開始檢查所有 F 呼叫端的使用權限。因為 E 已被授與 P1A 使用權限,因此堆疊查核行程將會進行檢查 C 的使用權限,而找到 C 的判斷提示。因為需求的使用權限 (P1A) 是已判斷提示的使用權限 (P1) 子集,所以堆疊查核行程將停止並自動繼續進行安全性檢查。它並不需注意到組件 A 和 B 未被授與使用權限 P1A。利用判斷提示 P1,方法 C 可以確保它的呼叫端可以存取受 P1 保護的資源,即使呼叫端尚未被授與存取該資源的使用權限。當您設計一個類別庫且類別可以存取受保護的資源時,在大部份的情況下,您都應該產生安全性要求以要求類別的呼叫端需擁有適當的使用權限。如果您知道類別稍後將執行的作業其大部份的呼叫端都不擁有使用權限,而您要讓這些呼叫端呼叫您的程式碼時,您可以在代表程式碼將執行的使用權限物件上呼叫 Assert 方法,以判斷提示使用權限。以這種方式使用 Assert 可以讓一般情形下無法執行的呼叫端可以呼叫您的程式碼。因此,當您在判斷提示一個使用權限時,您應該事先執行適當的安全性檢查以防止您的元件被誤用。例如,假設一個高度受信任的程式庫類別擁有一個刪除檔案的方法。它會呼叫一個 Unmanaged Win32 函式來存取檔案。叫用您程式碼 Delete 方法的呼叫端會傳遞要刪除檔案的名稱 C:\Test.txt。在 Delete 方法內,您的程式碼會建立一個表示寫入存取至 C:\Test.txt 的 FileIOPermission 物件 (刪除檔案所需的寫入存取)。然後您的程式碼會呼叫 FileIOPermission 物件的 Demand 方法,以叫用命令式安全性檢查。如果呼叫堆疊中的其中一個呼叫端沒有擁有這個使用權限,則擲回一個 SecurityException。如果沒有擲回例外狀況,即表示所有的呼叫端都擁有存取 C:\Test.txt 的權限。因為您知道大部份的呼叫端都沒有擁有存取 Umanaged 程式碼的使用權限,所以稍後您的程式碼會建立一個表示呼叫 Unmanaged 程式碼和呼叫該物件 Assert 方法權限的 SecurityPermission 物件。最後,它會呼叫 Unmanaged Win32 函式以刪除 C:\Text.txt 並將控制權交回呼叫端。警告   當您的程式碼可以由其他程式碼用來存取您正在判斷提示的使用權限所保護的資源時,您必須確定您的程式碼並沒有使用判斷提示。例如,用來寫入檔案的程式碼,其檔案名稱是由呼叫端指定為參數時,您不可以判斷提示 FileIOPermission 以寫入檔案,因為協力廠商會開啟而誤用您的程式碼.
當您在同一個方法的多個使用權限上呼叫 Assert 方法,將會產生不可預期和無法預料的行為。相反地,您應該建立一個 PermissionSet 物件,將它傳遞給您要叫用的每一個使用權限,然後呼叫 PermissionSet 物件上的 Assert 方法。以下的範例將說明使用 Assert 方法以覆寫安全性檢查的宣告式語法。請注意,FileIOPermissionAttribute 語法採用兩個值:SecurityAction 列舉型別和要授與使用權限的檔案或目錄的位置。呼叫 Assert 將使存取 C:\Log.txt 的需求繼續進行,即使尚未檢查呼叫端存取該檔案的使用權限。[Visual Basic]
Option Explicit
Option StrictImports System
Imports System.IO
Imports System.Security.PermissionsNamespace LogUtil
   Public Class Log
      Public Sub New()      End Sub     <FileIOPermission(SecurityAction.Assert, All := "C:\Log.txt")> Public Sub 
      MakeLog()
         Dim TextStream As New StreamWriter("C:\Log.txt")
         TextStream.WriteLine("This  Log was created on {0}", DateTime.Now) '
         TextStream.Close()
      End Sub
   End Class
End Namespace[C#]
namespace LogUtil
{
   using System;
   using System.IO;
   using System.Security.Permissions;   public class Log
   {
      public Log()
      {    
      }   
      [FileIOPermission(SecurityAction.Assert, All = @"C:\Log.txt")]
      public void MakeLog()
      {   
         StreamWriter TextStream = new StreamWriter(@"C:\Log.txt");
         TextStream.WriteLine("This  Log was created on {0}", DateTime.Now);
         TextStream.Close();
      }
   }
}以下的程式碼片段將說明使用 Assert 方法以覆寫安全性檢查的命令式語法。在這個範例中,將會宣告一個 FileIOPermission 物件的執行個體。它的建構函式會通過 FileIOPermissionAccess.Read 的檢查,以定義允許存取的型別,其後接著一個描述檔案位置的字串。定義過 FileIOPermission 物件之後,您只需呼叫它的 Assert 方法以覆寫安全性檢查即可。[Visual Basic]
Option Explicit
Option Strict
Imports System
Imports System.IO
Imports System.Security.Permissions
Namespace LogUtil
   Public Class Log
      Public Sub New()
      End Sub 'New
      
      Public Sub MakeLog()
         Dim FilePermission As New FileIOPermission(FileIOPermissionAccess.AllAccess, "C:\Log.txt")
         FilePermission.Assert()
         Dim TextStream As New StreamWriter("C:\Log.txt")
         TextStream.WriteLine("This  Log was created on {0}", DateTime.Now)
         TextStream.Close()
      End Sub
   End Class
End Namespace[C#]
namespace LogUtil
{
   using System;
   using System.IO;
   using System.Security.Permissions;   public class Log
   {
      public Log()
      {    
      }   
      public void MakeLog()
      {
         FileIOPermission FilePermission = new FileIOPermission(FileIOPermissionAccess.AllAccess,@"C:\Log.txt"); 
         FilePermission.Assert();
         StreamWriter TextStream = new StreamWriter(@"C:\Log.txt");
         TextStream.WriteLine("This  Log was created on {0}", DateTime.Now);
         TextStream.Close();
      }
   }
}

解决方案 »

  1.   

    幸好,您不必逐行執行應用程式,就能知道發生了什麼。Systems.Diagnostics 命名空間中有 Trace 和 Debug 類別。這兩個類別 (基本上是相同的) 中有一些靜態 (Static) 方法,能讓程式碼收集程式碼執行路徑、程式碼涵蓋範圍甚至於效能設定檔等資訊。這二個類別提供的 Assert 方法,可以檢查條件並且能在條件為 false 時顯示訊息。若要使用 Trace 和 Debug 類別,請執行下列三個步驟。 定義 TRACE 或 DEBUG 符號。 
    為對應的 Listener 建立新的執行個體。 
    為程式碼的 Trace 或 Debug 類別,加入呼叫。 
    定義 - 您必須先定義對應符號,才能啟用偵錯或追蹤。您可以在編譯時,使用 Visual C# (以及 Managed Extensions for C++) 或 Visual Basic .NET 的 /d(efine) 條件式編譯參數,請參閱下面:csc /target:library /debug+ /d:TRACE math.cs
    vbc /target:library /debug+ /d:TRACE=True math.vb
    原始程式碼本身也可以定義符號,請參閱下面:#define TRACE     // for C# or the Managed Extensions for C++
    #Const TRACE=1    ' for Visual Basic .NET
    建立 - TraceListener可以擷取 Debug 和 Trace 輸出。就預設值而言,輸出會自動傳送到 DefaultTraceListener,再由它使用 OutputDebugString Windows API 將輸出傳送到 Windows 系統偵錯工具,以及使用 Debugger.Log 方法傳送到偵錯工具。如果沒有附加偵錯工具,Debugger.Log 傳送的訊息無效。果您在 Windows 架構偵錯工具中作業,[輸出] 視窗會顯示 Debug 和 Trace 訊息。不過,如果您在偵錯工具外作業 - 例如,在測試的電腦上 - 或是想將偵錯資訊存入文字架構記錄檔中,您必須建立新的 Listener ,並且加入到 Listeners 集合中。System.Diagnostic 命名空間提供 EventLogTraceListener 和 TextWriterTraceListener。若要建立文字檔來處理偵錯訊息,您只需要下列一行程式碼。 Trace.Listeners.Add(new 
       TextWriterTraceListener(File.Create("output.txt")));
    加入 - 最後,您可以加入各種 Trace.Write 方法呼叫,在 Run Time 時產生偵錯顯示,請參閱下面:Trace.WriteLine("");
    Trace.WriteLine("Starting tracing...");
    輸出檔的前幾個位元組中有無法讀取的有關這個檔案的文字編碼資訊,您也許想先執行空的 WriteLine 方法,從新行開始記錄。另一個值得注意的是呼叫 Trace.Indent,就預設值而言,它會用四個空格來縮排輸出:Trace.Indent();
    後續呼叫 Trace.Unindent,可以向左調整輸出。某個條件不符時,這個範例程式會使用 Trace 的 WriteLineIf 方法,產生記錄訊息。在此特殊狀況下,程式碼預期第一個數值項目是以非零的數字開頭。如果測試失敗,則會寫下一則訊息,請參閱下行。Trace.WriteLineIf(test == "0", "Oops: Leading zero"); // C#
    Trace.WriteLineIf(test = "0", "Oops: Leading zero")   ' VB
    將這些全部集合起來,執行範例程式,會建立下列的 Output.txt 檔案。Starting Tracing...
        InitializeComponent()
            Creating controls
            Setting up Label and TextBox
            Setting up numeric buttons
            Setting up operations buttons
            Adding Clear and Calculate
            Adding to Controls collection
        9 Clicked
        - Clicked
        6 Clicked
        Calculate Clicked
    Dispose()
    Assert 方法的操作方式類似,除了它輸出的是詳細的錯誤對話方塊,而且測試失敗。對應的 Assert 方法,類似下列程式碼。Trace.Assert(test != "0", "Oops", "Leading zero"); // C#
    Trace.Assert(test <> "0", "Oops", "Leading zero")  ' Visual Basic .NET
    Calc.exe 開始執行而且使用者輸入的前置字元為零時,會產生下列對話方塊。注意   如果程式無法執行完成,會產生 0 個位元組的 Output.txt 檔案。
      

  2.   

    多谢楼上详细的回答,不知道VC中的vector这个问题谁知道?