Freigeben über


Beispiel für ein Ablaufprotokoll

Letzte Änderung: Donnerstag, 15. April 2010

Gilt für: SharePoint Foundation 2010

Das folgende Codebeispiel zeigt, wie mithilfe der neuen API-Verbesserungen in SharePoint Foundation 2010 in das Ablaufprotokoll geschrieben wird.

Weitere Informationen zur Verwendung der SPDiagnosticsServiceBase-Klasse zum Schreiben in das ULS-Ablaufprotokoll (Unified Logging Service, vereinheitlichter Protokollierungsdienst) finden Sie unter Verwenden der Ablaufprotokollierungs-API.

Beispiel für ein Ablaufprotokoll

class SPTraceLogger : EventProvider
{
    private static string s_ExeName = System.Diagnostics.Process.GetCurrentProcess().ProcessName;
 
    private const uint TRACE_VERSION_CURRENT = 2;
    private const uint TRACE_FLUSH_TAG = 0xFFFFFFFFu;
    private const TraceSeverity TRACE_FLUSH_LEVEL = 0;
    private const string TRACE_FLUSH_EVENT_NAME = "Global\\Tracing_Service_Flush_Event";
 
    [Flags]
    enum TraceFlags
    {
        None = 0,
        TRACE_FLAG_START = 1,
        TRACE_FLAG_END = 2,
        TRACE_FLAG_MIDDLE = 3, // Notice middle==start+end, allows use as a bitmask.
        TRACE_FLAG_FLUSH = 8, // Ask trace manager to flush all file buffers.
    }
 
    public enum TraceSeverity : byte
    {
        CriticalEvent = 1,
        Exception = 4,
        Assert = 7,
        WarningEvent = 8,
        Unexpected = 10,
        Monitorable = 15,
        InformationEvent = 18,
        High = 20,
        Medium = 50,
        Verbose = 100,
        VerboseEx = 200
    }
 
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 4)]
    private struct Payload
    {
        public ushort Size;
        public uint dwVersion;
        public uint Id;
        public TraceFlags dwFlags;
        public long TimeStamp;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
        public string wzExeName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string wzProduct;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string wzCategory;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 801)]
        public string wzMessage;
    }
 
    // Wrapper class used to manually marshal data to unmanaged memory.
    // This lets us avoid using the "unsafe" keyword.
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    struct EVENT_DATA_DESCRIPTOR : IDisposable
    {
        IntPtr Ptr;      // Pointer to data.
        uint Size;       // Size of data in bytes.
        uint Reserved;
 
        public EVENT_DATA_DESCRIPTOR(Payload payload)
        {
            Ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Payload)));
            Marshal.StructureToPtr(payload, Ptr, false);
            Size = (uint)Marshal.SizeOf(typeof(Payload));
            Reserved = 0;
        }
 
        void IDisposable.Dispose()
        {
            Marshal.FreeHGlobal(Ptr);
        }
    }
 
    // Wrapper class used to manually marshal data to unmanaged memory.
    // This lets us avoid using the "unsafe" keyword.
    struct DataDescriptorWrapper : IDisposable
    {
        public IntPtr Ptr;     // Pointer to data
 
        public DataDescriptorWrapper(EVENT_DATA_DESCRIPTOR descriptor)
        {
            Ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(EVENT_DATA_DESCRIPTOR)));
            Marshal.StructureToPtr(descriptor, Ptr, false);
        }
 
        void IDisposable.Dispose()
        {
            Marshal.FreeHGlobal(Ptr);
        }
    }
 
    public SPTraceLogger()
        : base(SPFarm.Local.TraceSessionGuid)
    {
    }
 
    private void WriteImpl(TraceSeverity level, Payload payload)
    {
        EventDescriptor descriptor = new EventDescriptor(0, 0, 0, (byte)level, 0, 0, 0);
        using (EVENT_DATA_DESCRIPTOR data = new EVENT_DATA_DESCRIPTOR(payload))
        using (DataDescriptorWrapper wrapper = new DataDescriptorWrapper(data))
        {
            bool fResult = WriteEvent(ref descriptor, 1, wrapper.Ptr);
            if (!fResult)
                Console.WriteLine("Failed to call WriteEvent for real payload {0}", Marshal.GetLastWin32Error());
        }
    }
 
    private void Write(TraceFlags flags, uint id, TraceSeverity level, string exeName, string area, string category, string message)
    {
        Payload payload = new Payload();
        payload.Size = (ushort)Marshal.SizeOf(typeof(Payload));
        payload.dwVersion = TRACE_VERSION_CURRENT;
        payload.Id = id;
        payload.TimeStamp = DateTime.Now.ToFileTime();
        payload.wzExeName = exeName;
        payload.wzProduct = area;
        payload.wzCategory = category;
 
        // If the message is smaller than 800 characters, no need to break it up.
        if (message == null || message.Length <= 800)
        {
            payload.wzMessage = message;
            payload.dwFlags = flags;
            WriteImpl(level, payload);
            return;
        }
 
        // For larger messages, break it into 800 character chunks.
        for (int i = 0; i < message.Length; i += 800)
        {
            int cchRemaining = Math.Min(800, message.Length - i);
            payload.wzMessage = message.Substring(i, cchRemaining);
 
            if (i == 0)
                payload.dwFlags = TraceFlags.TRACE_FLAG_START | flags;
            else if (i + 800 < message.Length)
                payload.dwFlags = TraceFlags.TRACE_FLAG_MIDDLE | flags;
            else
                payload.dwFlags = TraceFlags.TRACE_FLAG_END | flags;
 
            WriteImpl(level, payload);
        }
    }
 
    public void Write(uint id, TraceSeverity level, string area, string category, string message)
    {
        Write(TraceFlags.None, id, level, s_ExeName, area, category, message);
    }
 
    public void Write(uint id, TraceSeverity level, string exeName, string area, string category, string message)
    {
        Write(TraceFlags.None, id, level, exeName, area, category, message);
    }
 
    private void FlushImpl()
    {
        Write(TraceFlags.TRACE_FLAG_FLUSH, TRACE_FLUSH_TAG, TRACE_FLUSH_LEVEL, "", "", "", " ");
    }
 
    public bool Flush(int timeout)
    {
        // Special case for timeout = 0; just send the request and immediately return.
        if (timeout == 0)
        {
            FlushImpl();
            return true;
        }
 
        // Create the wait handle with appropriate permissions.
        bool fCreatedNew;
        EventWaitHandleSecurity security = new EventWaitHandleSecurity();
        security.SetAccessRule(new EventWaitHandleAccessRule(new SecurityIdentifier(WellKnownSidType.ServiceSid, null), EventWaitHandleRights.Modify, AccessControlType.Allow));
 
        using (EventWaitHandle waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset, TRACE_FLUSH_EVENT_NAME, out fCreatedNew, security))
        {
            // Request the trace service to flush data, and wait for the service to signal completion.
            FlushImpl();
            return waitHandle.WaitOne(timeout);
        }
    }
 
    public bool Flush()
    {
        return Flush(5000);
    }
 
    public static uint TagFromString(string wzTag)
    {
        System.Diagnostics.Debug.Assert(wzTag.Length == 4);
        return (uint)(wzTag[0] << 24 | wzTag[1] << 16 | wzTag[2] << 8 | wzTag[3]);
    }
}

Siehe auch

Konzepte

Kategorien für Ablaufverfolgungsprotokolle

Schreiben in das Ablaufprotokoll aus benutzerdefiniertem Code

Weitere Ressourcen

Trace Logs