/mcs/class/referencesource/System.IdentityModel.Selectors/infocard/Diagnostics/Managed/Microsoft/InfoCards/Diagnostics/InfocardTrace.cs
C# | 886 lines | 540 code | 104 blank | 242 comment | 54 complexity | da0a5b5257435d9bae829811297e9a4a MD5 | raw file
Possible License(s): LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace Microsoft.InfoCards.Diagnostics
- {
- using System;
- using System.Xml;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Globalization;
- using System.ComponentModel; //win32exception
- using System.Runtime.InteropServices;
- using System.Runtime.CompilerServices;
- using System.Runtime.ConstrainedExecution;
- using Microsoft.Win32.SafeHandles;
- using System.Security;
- using System.Security.Principal;
- using System.Runtime;
- using System.ServiceModel.Diagnostics;
- using System.Threading;
- //
- // For InfoCardBaseException
- //
- using System.IdentityModel.Selectors;
- // Summary
- // InfoCardTrace is the main driver class for the managed tracing infrastructure.
- // Essentially it is a wrapper over the Indigo DiagnosticsAndTracing classes.
- // Externally a facade of simple TraceXXXX calls is provided which
- // internally thunk across to the indigo classes to perform the work.
- //
- // The trace class also provides support for flowing of correlation ids allowing
- // tracing of requests across process and managed / unmanaged boundaries
- // See the Infocard Tracing documentation at http://team/sites/infocard for
- // detail on configuration and usage.
- //
- // Remarks
- // All functions are thread safe
- //
- // Example usage looks like:
- // using IDT=Microsoft.InfoCards.Diagnostics.InfoCardTrace
- // IDT.TraceVerbose( InfoCardTraceCode.StoreInvalidKey, myKey );
- // IDT.TraceDebug( "Got an infocard {0} with name {1}", card, card.Name );
- //
- //
- static class InfoCardTrace
- {
- static class TraceCode
- {
- public const int IdentityModelSelectors = 0xD0000;
- public const int GeneralInformation = TraceCode.IdentityModelSelectors | 0X0001;
- public const int StoreLoading = TraceCode.IdentityModelSelectors | 0X0002;
- public const int StoreBeginTransaction = TraceCode.IdentityModelSelectors | 0X0003;
- public const int StoreCommitTransaction = TraceCode.IdentityModelSelectors | 0X0004;
- public const int StoreRollbackTransaction = TraceCode.IdentityModelSelectors | 0X0005;
- public const int StoreClosing = TraceCode.IdentityModelSelectors | 0X0006;
- public const int StoreFailedToOpenStore = TraceCode.IdentityModelSelectors | 0X0007;
- public const int StoreSignatureNotValid = TraceCode.IdentityModelSelectors | 0X0008;
- public const int StoreDeleting = TraceCode.IdentityModelSelectors | 0X0009;
- }
- static Dictionary<int, string> traceCodes = new Dictionary<int, string>(9)
- {
- { TraceCode.GeneralInformation, "GeneralInformation" },
- { TraceCode.StoreLoading, "StoreLoading" },
- { TraceCode.StoreBeginTransaction, "StoreBeginTransaction" },
- { TraceCode.StoreCommitTransaction, "StoreCommitTransaction" },
- { TraceCode.StoreRollbackTransaction, "StoreRollbackTransaction" },
- { TraceCode.StoreClosing, "StoreClosing" },
- { TraceCode.StoreFailedToOpenStore, "StoreFailedToOpenStore" },
- { TraceCode.StoreSignatureNotValid, "StoreSignatureNotValid" },
- { TraceCode.StoreDeleting, "StoreDeleting" },
- };
- static string GetTraceString(int traceCode)
- {
- return traceCodes[traceCode];
- }
- static string GetMsdnTraceCode(int traceCode)
- {
- return LegacyDiagnosticTrace.GenerateMsdnTraceCode("System.IdentityModel.Selectors", GetTraceString(traceCode));
- }
- [DllImport("advapi32",
- CharSet = CharSet.Unicode,
- EntryPoint = "ReportEventW",
- ExactSpelling = true,
- SetLastError = true)]
- private static extern bool ReportEvent([In] SafeHandle hEventLog,
- [In] short type,
- [In] ushort category,
- [In] uint eventID,
- [In] byte[] userSID,
- [In] short numStrings,
- [In] int dataLen,
- [In] HandleRef strings,
- [In] byte[] rawData);
- //
- // Summary:
- // Provides a wrapper over a handle retrieved by RegisterEventSource
- //
- internal class SafeEventLogHandle : SafeHandle
- {
- [DllImport("advapi32",
- CharSet = CharSet.Unicode,
- EntryPoint = "RegisterEventSourceW",
- ExactSpelling = true,
- SetLastError = true)]
- private static extern SafeEventLogHandle RegisterEventSource(string uncServerName, string sourceName);
- [DllImport("advapi32",
- CharSet = CharSet.Unicode,
- EntryPoint = "DeregisterEventSource",
- ExactSpelling = true,
- SetLastError = true)]
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
- private static extern bool DeregisterEventSource(IntPtr eventLog);
- public static SafeEventLogHandle Construct()
- {
- SafeEventLogHandle h = RegisterEventSource(null, InfoCardTrace.InfoCardEventSource);
- if (null == h || h.IsInvalid)
- {
- int error = Marshal.GetLastWin32Error();
- TraceDebug("failed to registereventsource with error {0}", error);
- }
- return h;
- }
- //
- // Summary:
- // Manages the lifetime of a native handle retrieved by register event source.
- // Parameters:
- // handle - the handle to wrap.
- //
- private SafeEventLogHandle()
- : base(IntPtr.Zero, true)
- {
- }
- public override bool IsInvalid
- {
- get
- {
- return (IntPtr.Zero == base.handle);
- }
- }
- //
- // Summary:
- // Releases the eventlog handle.
- //
- protected override bool ReleaseHandle()
- {
- #pragma warning suppress 56523
- return DeregisterEventSource(base.handle);
- }
- }
- //
- // Summary:
- // Returns whether the current exception is fatal.
- // Notes:
- // Currently this delegates to the code in ExceptionUtility.cs
- //
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
- public static bool IsFatal(Exception e)
- {
- return Fx.IsFatal(e);
- }
- public static TimerCallback ThunkCallback(TimerCallback callback)
- {
- return Fx.ThunkCallback(callback);
- }
- public static WaitCallback ThunkCallback(WaitCallback callback)
- {
- return Fx.ThunkCallback(callback);
- }
- public static void CloseInvalidOutSafeHandle(SafeHandle handle)
- {
- Utility.CloseInvalidOutSafeHandle(handle);
- }
- //
- // The event source we log against. May need to be updated should our name change before rtm
- //
- const string InfoCardEventSource = "CardSpace 4.0.0.0";
- //
- // Summary:
- // Writes an audit message to the application's event log
- //
- public static void Audit(EventCode code)
- {
- LogEvent(code, null, EventLogEntryType.Information);
- }
- public static void Audit(EventCode code, string message)
- {
- LogEvent(code, message, EventLogEntryType.Information);
- }
- public static void Assert(bool condition, string format, params object[] parameters)
- {
- if (condition)
- {
- return;
- }
- string message = format;
- if (null != parameters && 0 != parameters.Length)
- {
- message = String.Format(CultureInfo.InvariantCulture, format, parameters);
- }
- TraceDebug("An assertion fired: {0}", message);
- #if DEBUG
- //
- // Let DebugAssert handle this for us....
- // If not in debugger, Assertion Failed: Abort=Quit, Retry=Debug, Ignore=Continue
- // If in debugger, will hit a DebugBreak()
- //
- DiagnosticUtility.DebugAssert( false, message );
- #else
- //
- // Retail assert failfasts service
- //
- FailFast(message);
- #endif
- }
- [Conditional("DEBUG")]
- public static void DebugAssert(bool condition, string format, params object[] parameters)
- {
- #if DEBUG
- if (condition)
- {
- return;
- }
- string message = format;
- if (null != parameters && 0 != parameters.Length)
- {
- message = String.Format( CultureInfo.InvariantCulture, format, parameters );
- }
- TraceDebug( "An assertion fired: {0}", message );
- if (Debugger.IsAttached)
- {
- Debugger.Launch();
- Debugger.Break();
- }
- DiagnosticUtility.DebugAssert( false, message );
- FailFast( message );
- #endif
- }
- //
- // Facade functions to allow simple call semantics.
- //
- public static void FailFast(string message)
- {
- DiagnosticUtility.FailFast(message);
- }
- [Conditional("DEBUG")]
- public static void TraceVerbose(int traceCode)
- {
- TraceInternal(TraceEventType.Verbose, traceCode, null);
- }
- [Conditional("DEBUG")]
- public static void TraceVerbose(int traceCode, params object[] parameters)
- {
- TraceInternal(TraceEventType.Verbose, traceCode, parameters);
- }
- [Conditional("DEBUG")]
- public static void TraceInfo(int traceCode)
- {
- TraceInternal(TraceEventType.Information, traceCode, null);
- }
- [Conditional("DEBUG")]
- public static void TraceInfo(int traceCode, params object[] parameters)
- {
- TraceInternal(TraceEventType.Information, traceCode, parameters);
- }
- [Conditional("DEBUG")]
- public static void TraceWarning(int traceCode)
- {
- TraceInternal(TraceEventType.Warning, traceCode, null);
- }
- [Conditional("DEBUG")]
- public static void TraceWarning(int traceCode, params object[] parameters)
- {
- TraceInternal(TraceEventType.Warning, traceCode, parameters);
- }
- [Conditional("DEBUG")]
- public static void TraceError(int traceCode)
- {
- TraceInternal(TraceEventType.Error, traceCode, null);
- }
- [Conditional("DEBUG")]
- public static void TraceError(int traceCode, params object[] parameters)
- {
- TraceInternal(TraceEventType.Error, traceCode, parameters);
- }
- [Conditional("DEBUG")]
- public static void TraceCritical(int traceCode)
- {
- TraceInternal(TraceEventType.Critical, traceCode, null);
- }
- [Conditional("DEBUG")]
- public static void TraceCritical(int traceCode, params object[] parameters)
- {
- TraceInternal(TraceEventType.Critical, traceCode, parameters);
- }
- //
- // Enable the setting of level explicitly.
- //
- [Conditional("DEBUG")]
- public static void Trace(TraceEventType level, int traceCode)
- {
- TraceInternal(level, traceCode, null);
- }
- [Conditional("DEBUG")]
- public static void Trace(TraceEventType level, int traceCode, params object[] parameters)
- {
- TraceInternal(level, traceCode, parameters);
- }
- //
- // Summary
- // DebugTrace is an additional level of tracing, intended for
- // use by the devleopment team during the product development cycle.
- // The trace funcitons need no localization and can be fed arbitrary strings as
- // the format specifier.
- //
- // Remarks
- // Will be turned off in RETAIL builds.
- // All tracing is done at the VERBOSE level.
- //
- // Parameters
- // format - a format string using the standard .net string format specifier syntax
- // parameters - optional parmaters to be embedded in the format string.
- //
- [Conditional("DEBUG")]
- public static void TraceDebug(string format, params object[] parameters)
- {
- #if DEBUG
- if (DiagnosticUtility.ShouldTraceVerbose)
- {
- // Retrieve the string from resources and build the message.
- //
- string message = format;
- if (null != parameters && 0 != parameters.Length)
- {
- message = String.Format( CultureInfo.InvariantCulture, format, parameters );
- }
- //
- // If we were passed a null message, at least flag it
- //
- if (String.IsNullOrEmpty(message))
- {
- message = "NULL DEBUG TRACE MESSAGE!";
- }
- //
- // Build a trace message conforming to the ETL trace schema and
- // call down through the diagnostic support classes to trace the call.
- //
- InfoCardTraceRecord tr = new InfoCardTraceRecord(
- GetTraceString(TraceCode.GeneralInformation),
- message );
- DiagnosticUtility.DiagnosticTrace.TraceEvent(
- TraceEventType.Verbose,
- TraceCode.GeneralInformation,
- SR.GetString(GetTraceString(TraceCode.GeneralInformation)),
- GetMsdnTraceCode(TraceCode.GeneralInformation),
- tr, null, message);
- }
- #endif
- }
- [Conditional("DEBUG")]
- public static void TraceDebug(string message)
- {
- #if DEBUG
- if (DiagnosticUtility.ShouldTraceVerbose)
- {
- //
- // If we were passed a null message, at least flag it
- //
- if (String.IsNullOrEmpty(message))
- {
- message = "NULL DEBUG TRACE MESSAGE!";
- }
- //
- // Build a trace message conforming to the ETL trace schema and
- // call down through the diagnostic support classes to trace the call.
- //
- InfoCardTraceRecord tr = new InfoCardTraceRecord(
- GetTraceString(TraceCode.GeneralInformation),
- message );
- DiagnosticUtility.DiagnosticTrace.TraceEvent(
- TraceEventType.Verbose,
- TraceCode.GeneralInformation,
- SR.GetString(GetTraceString(TraceCode.GeneralInformation)),
- GetMsdnTraceCode(TraceCode.GeneralInformation),
- tr, null, message);
- }
- #endif
- }
- //
- // Summary:
- // Logs the event for the appropriate infocard error code. This code should
- // match the entries in messages,mc
- // Parameters:
- // code - the event code to log
- // Notes:
- // This code may need to be extended to support an array of string parameters. We will do this if our event
- // log messages require it.
- //
- private static void LogEvent(EventCode code, string message, EventLogEntryType type)
- {
- using (SafeEventLogHandle handle = SafeEventLogHandle.Construct())
- {
- string parameter = message;
- if (null != handle)
- {
- if (String.IsNullOrEmpty(parameter))
- {
- parameter = SR.GetString(SR.GeneralExceptionMessage);
- }
- //
- // Report event expects a LPCTSTR* lpStrings. Use GCHandle, instead
- // of writing code with unsafe because InfoCard client uses this
- // and our client cannot contain any unsafe code.
- //
- //
- // This is the array of LPCTSTRs
- //
- IntPtr[] stringRoots = new IntPtr[1];
- //
- // This is to pin the parameter string itself. Use an array here if you want more than 1 string
- //
- GCHandle stringParamHandle = new GCHandle();
- //
- // This is to pin the pointer to the array of LPCTSTRs
- //
- GCHandle stringsRootHandle = new GCHandle();
- try
- {
- //
- // Pin the IntPtrs (ie array of LPCTSTRs)
- //
- stringsRootHandle = GCHandle.Alloc(stringRoots, GCHandleType.Pinned);
- //
- // Pin the parameter string itself
- //
- stringParamHandle = GCHandle.Alloc(parameter, GCHandleType.Pinned);
- //
- // Give the intptr address of the pinned string
- //
- stringRoots[0] = stringParamHandle.AddrOfPinnedObject();
- //
- // From msdn: The interop marshaler passes only the handle [2nd arg to constructor in our case]
- // to unmanaged code, and guarantees that the wrapper (passed as the first parameter
- // to the constructor of the HandleRef) remains alive for the duration of the [PInvoke] call.
- //
- HandleRef data = new HandleRef(handle, stringsRootHandle.AddrOfPinnedObject());
- SecurityIdentifier sid = WindowsIdentity.GetCurrent().User;
- byte[] sidBA = new byte[sid.BinaryLength];
- sid.GetBinaryForm(sidBA, 0);
- if (!ReportEvent(
- handle,
- (short)type,
- (ushort)InfoCardEventCategory.General,
- (uint)code,
- sidBA,
- 1,
- 0,
- data,
- null))
- {
- //
- // Errors in the eventlog API should be ignored by applications
- //
- int error = Marshal.GetLastWin32Error();
- TraceDebug("Failed to report the event with error {0}", error);
- }
- }
- finally
- {
- if (stringsRootHandle.IsAllocated)
- {
- stringsRootHandle.Free();
- }
- if (stringParamHandle.IsAllocated)
- {
- stringParamHandle.Free();
- }
- }
- }
- }
- }
- public static void TraceAndLogException(Exception e)
- {
- bool shouldLog = false;
- bool isInformational = false;
- InfoCardBaseException ie = e as InfoCardBaseException;
- //
- // We only log if this is an infocard exception that hasnt been previous logged,
- // and isnt the user cancelled exception.
- //
- if (null != ie && !(ie is UserCancelledException) && !ie.Logged)
- {
- shouldLog = true;
- }
- if (shouldLog)
- {
- //
- // If this is the parent of a previously logged exception then log as
- // informational.
- // If one of the children is UserCancelled, don't log at all
- //
- Exception current = ie.InnerException;
- while (null != current)
- {
- if (current is UserCancelledException)
- {
- shouldLog = false;
- break;
- }
- else if (current is InfoCardBaseException)
- {
- if ((current as InfoCardBaseException).Logged)
- {
- isInformational = true;
- }
- }
- current = current.InnerException;
- }
- }
- if (shouldLog)
- {
- EventLogEntryType logType = isInformational ? EventLogEntryType.Information : EventLogEntryType.Error;
- string message = ie.Message;
- if (!isInformational)
- {
- message = BuildMessage(ie);
- }
- LogEvent((EventCode)ie.NativeHResult, message, logType);
- }
- TraceException(e);
- }
- private static string BuildMessage(InfoCardBaseException ie)
- {
- Exception ex = ie;
- String errString = ex.Message + "\n";
- if (null != ex.InnerException)
- {
- while (null != ex.InnerException)
- {
- errString += String.Format(System.Globalization.CultureInfo.CurrentUICulture,
- SR.GetString(SR.InnerExceptionTraceFormat),
- ex.InnerException.Message);
- ex = ex.InnerException;
- }
- errString += String.Format(System.Globalization.CultureInfo.CurrentUICulture,
- SR.GetString(SR.CallStackTraceFormat),
- ie.ToString());
- }
- else
- {
- if (!String.IsNullOrEmpty(Environment.StackTrace))
- {
- errString += String.Format(System.Globalization.CultureInfo.CurrentUICulture,
- SR.GetString(SR.CallStackTraceFormat),
- Environment.StackTrace);
- }
- }
- return errString;
- }
- //
- // Summary:
- // Logs a general exception in the event log
- // Parameters:
- // e - the exception to log.
- //
- [Conditional("DEBUG")]
- public static void TraceException(Exception e)
- {
- Exception current = e;
- int indent = 0;
- while (null != current)
- {
- TraceDebug("{0}Exception: message={1}\n stack trace={2}",
- new string(' ', indent * 2),
- e.Message,
- e.StackTrace);
- current = current.InnerException;
- indent++;
- }
- }
- //
- // Summary
- // Throw an exception and log an error in the event log
- //
- public static Exception ThrowHelperError(Exception e)
- {
- TraceAndLogException(e);
- return DiagnosticUtility.ExceptionUtility.ThrowHelperError(e);
- }
- //
- // Summary
- // Throw an exception but don't log in the event log
- //
- public static Exception ThrowHelperErrorWithNoLogging(Exception e)
- {
- return DiagnosticUtility.ExceptionUtility.ThrowHelperError(e);
- }
- //
- // Summary
- // Throw an exception and log a warning in the event log
- //
- public static Exception ThrowHelperWarning(Exception e)
- {
- TraceAndLogException(e);
- return DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(e);
- }
- //
- // Summary
- // Throw an exception and log a critical event in the event log
- //
- public static Exception ThrowHelperCritical(Exception e)
- {
- TraceAndLogException(e);
- return DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(e);
- }
- //
- // Summary:
- // Throws an infocard argument exception. Currently mapped to a communication exception,
- //
- public static void ThrowInvalidArgumentConditional(bool condition, string argument)
- {
- if (condition)
- {
- string message = string.Format(
- System.Globalization.CultureInfo.CurrentUICulture,
- SR.GetString(SR.ServiceInvalidArgument),
- argument);
- throw ThrowHelperError(new InfoCardArgumentException(message));
- }
- }
- //
- // Summary
- // Throw an ArgumentNullException and log an error in the event log
- //
- public static Exception ThrowHelperArgumentNull(string err)
- {
- return DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(err);
- }
- //
- // Summary
- // Throw an ArgumentException and log an error in the event log
- //
- public static Exception ThrowHelperArgument(string message)
- {
- return DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(message);
- }
- //
- // Summary
- // Throw an ArgumentNullException and log an error in the event log
- //
- public static Exception ThrowHelperArgumentNull(string err, string message)
- {
- return DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(err, message);
- }
- //
- // Summary
- // The following series of calls enable finer grained control over tracing in the client
- // All calls simply delegate down to the indigo DiagnosticTrace implementation which
- // triggers it's behaviour based on the currently configured listeners.
- //
- // Remarks
- // Typical usage is
- // if( IDT.ShouldTraceVerbose() )
- // {
- // string toTrace = this.SafeDumpState();
- // IDT.TraceVerbose( InfocardTraceCode.InfoCardCreated, toTrace );
- // }
- //
- public static bool ShouldTrace(TraceEventType type)
- {
- return DiagnosticUtility.ShouldTrace(type);
- }
- public static bool ShouldTraceCritical
- {
- get { return DiagnosticUtility.ShouldTraceCritical; }
- }
- public static bool ShouldTraceError
- {
- get { return DiagnosticUtility.ShouldTraceError; }
- }
- public static bool ShouldTraceWarning
- {
- get { return DiagnosticUtility.ShouldTraceWarning; }
- }
- public static bool ShouldTraceInformation
- {
- get { return DiagnosticUtility.ShouldTraceInformation; }
- }
- public static bool ShouldTraceVerbose
- {
- get { return DiagnosticUtility.ShouldTraceVerbose; }
- }
- //
- // Summary
- // Expose the activity ids associated with the current flow of activity.
- // ActivityIDs allow the correlation of events across process and managed / unmanaged bounda
- // Normally they are managed implicitly. The .net runtime will ensure they flow across thread
- // intra-process ( appdomain ) boundaries, and the indigo runtime will ensure they
- // flow across indigo interactions ( cross process and cross machine ).
- // We have a couple of responsibilities:
- // When transitioning from mananged to unmanaged code:
- // grab the activity id
- // pass it across to native code through the activityID rpc parameter.
- // When transitioning from unmanaged code
- // call SetActivityId passing in the received id.
- //
- // Remarks
- // Trace calls automatically attach the activityID on all calls.
- //
- public static Guid GetActivityId()
- {
- return System.Runtime.Diagnostics.DiagnosticTraceBase.ActivityId;
- }
- public static void SetActivityId(Guid activityId)
- {
- //
- // This will trace by default at level verbose.
- //
- System.Runtime.Diagnostics.DiagnosticTraceBase.ActivityId = activityId;
- }
- //
- // Summary
- // The main trace function. Responsible for extracting the appropriate string
- // from the application's resource file, formatting the string with the set of paramters
- // if appropriate,
- // and passing the request down to the IndigoDiagnostics classes.
- //
- // Parameters
- // level - the level to trace at. verbose <= level <= critical
- // code - the infocard trace code - a unique numeric / string identifier.
- // parameters - an optional set of parameters used to supply additional diagnostic information
- //
- // Remarks
- // Trace calls automatically attach the activityID on all calls.
- //
- [Conditional("DEBUG")]
- private static void TraceInternal(
- TraceEventType level,
- int traceCode,
- params object[] parameters)
- {
- #if DEBUG
- if (DiagnosticUtility.ShouldTrace(level))
- {
- //
- // Retrieve the string from resources and build the message.
- //
- #if INFOCARD_CLIENT
- string message = SR.GetString(GetTraceString(traceCode));
- #else
- string message = SR.GetString(traceCode);
- #endif
- Assert( !String.IsNullOrEmpty( message ), "resource string lookup failed!!!" );
- if (!String.IsNullOrEmpty( message ) && null != parameters)
- {
- try
- {
- message = String.Format(
- System.Globalization.CultureInfo.CurrentUICulture,
- message,
- parameters );
- }
- catch (FormatException f)
- {
- Assert( false, "Invalid format: " + traceCode );
- TraceException( f );
- message = SR.GetString( SR.GeneralTraceMessage, traceCode );
- }
- }
- //
- // Build a trace message conforming to the ETL trace schema and
- // call down through the diagnostic support classes to trace the call.
- //
- DiagnosticUtility.DiagnosticTrace.TraceEvent( level,
- traceCode,
- SR.GetString(GetTraceString(traceCode)),
- GetMsdnTraceCode(TraceCode.GeneralInformation),
- new InfoCardTraceRecord( GetTraceString(traceCode), message ), null, message);
- }
- #endif
- }
- }
- }