以编程方式记录到Sharepoint ULS
我想在Sharepoint Web部件中记录内容,但我希望它包含在ULS中。我发现的大多数示例都已登录到事件日志或者其他文件,但是我还没有真正找到用于登录ULS的示例。
令人讨厌的是,Microsoft.SharePoint.Diagnostics类都标记为Internal。我确实找到了一个无论如何通过反射来使用它们的示例,但是这看起来确实充满风险和不稳定,因为Microsoft可能会通过他们想要的任何修补程序来更改该类。
Sharepoint文档对有关什么是ULS以及如何配置它的许多管理员信息都没有真正帮助,但是我还没有找到一个支持的代码示例来实际记录我自己的事件。
有任何提示或者提示吗?
编辑:从这个问题的年代开始,我们可能会看到这是针对SharePoint 2007的。在SharePoint 2010中,可以使用SPDiagnosticsService.Local,然后使用WriteTrace。请参阅下面的Jrgen答案。
解决方案
是的,这是可能的,请参阅此MSDN文章:http://msdn2.microsoft.com/hi-in/library/aa979595(zh-cn).aspx
这是C#中的一些示例代码:
using System; using System.Runtime.InteropServices; using Microsoft.SharePoint.Administration; namespace ManagedTraceProvider { class Program { static void Main(string[] args) { TraceProvider.RegisterTraceProvider(); TraceProvider.WriteTrace(0, TraceProvider.TraceSeverity.High, Guid.Empty, "MyExeName", "Product Name", "Category Name", "Sample Message"); TraceProvider.WriteTrace(TraceProvider.TagFromString("abcd"), TraceProvider.TraceSeverity.Monitorable, Guid.NewGuid(), "MyExeName", "Product Name", "Category Name", "Sample Message"); TraceProvider.UnregisterTraceProvider(); } } static class TraceProvider { static UInt64 hTraceLog; static UInt64 hTraceReg; static class NativeMethods { internal const int TRACE_VERSION_CURRENT = 1; internal const int ERROR_SUCCESS = 0; internal const int ERROR_INVALID_PARAMETER = 87; internal const int WNODE_FLAG_TRACED_GUID = 0x00020000; internal enum TraceFlags { TRACE_FLAG_START = 1, TRACE_FLAG_END = 2, TRACE_FLAG_MIDDLE = 3, TRACE_FLAG_ID_AS_ASCII = 4 } // Copied from Win32 APIs [StructLayout(LayoutKind.Sequential)] internal struct EVENT_TRACE_HEADER_CLASS { internal byte Type; internal byte Level; internal ushort Version; } // Copied from Win32 APIs [StructLayout(LayoutKind.Sequential)] internal struct EVENT_TRACE_HEADER { internal ushort Size; internal ushort FieldTypeFlags; internal EVENT_TRACE_HEADER_CLASS Class; internal uint ThreadId; internal uint ProcessId; internal Int64 TimeStamp; internal Guid Guid; internal uint ClientContext; internal uint Flags; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct ULSTraceHeader { internal ushort Size; internal uint dwVersion; internal uint Id; internal Guid correlationID; internal TraceFlags dwFlags; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] internal string wzExeName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] internal string wzProduct; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] internal string wzCategory; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 800)] internal string wzMessage; } [StructLayout(LayoutKind.Sequential)] internal struct ULSTrace { internal EVENT_TRACE_HEADER Header; internal ULSTraceHeader ULSHeader; } // Copied from Win32 APIs internal enum WMIDPREQUESTCODE { WMI_GET_ALL_DATA = 0, WMI_GET_SINGLE_INSTANCE = 1, WMI_SET_SINGLE_INSTANCE = 2, WMI_SET_SINGLE_ITEM = 3, WMI_ENABLE_EVENTS = 4, WMI_DISABLE_EVENTS = 5, WMI_ENABLE_COLLECTION = 6, WMI_DISABLE_COLLECTION = 7, WMI_REGINFO = 8, WMI_EXECUTE_METHOD = 9 } // Copied from Win32 APIs internal unsafe delegate uint EtwProc(NativeMethods.WMIDPREQUESTCODE requestCode, IntPtr requestContext, uint* bufferSize, IntPtr buffer); // Copied from Win32 APIs [DllImport("advapi32.dll", CharSet = CharSet.Unicode)] internal static extern unsafe uint RegisterTraceGuids([In] EtwProc cbFunc, [In] void* context, [In] ref Guid controlGuid, [In] uint guidCount, IntPtr guidReg, [In] string mofImagePath, [In] string mofResourceName, out ulong regHandle); // Copied from Win32 APIs [DllImport("advapi32.dll", CharSet = CharSet.Unicode)] internal static extern uint UnregisterTraceGuids([In]ulong regHandle); // Copied from Win32 APIs [DllImport("advapi32.dll", CharSet = CharSet.Unicode)] internal static extern UInt64 GetTraceLoggerHandle([In]IntPtr Buffer); // Copied from Win32 APIs [DllImport("advapi32.dll", SetLastError = true)] internal static extern uint TraceEvent([In]UInt64 traceHandle, [In]ref ULSTrace evnt); } public enum TraceSeverity { Unassigned = 0, CriticalEvent = 1, WarningEvent = 2, InformationEvent = 3, Exception = 4, Assert = 7, Unexpected = 10, Monitorable = 15, High = 20, Medium = 50, Verbose = 100, } public static void WriteTrace(uint tag, TraceSeverity level, Guid correlationGuid, string exeName, string productName, string categoryName, string message) { const ushort sizeOfWCHAR = 2; NativeMethods.ULSTrace ulsTrace = new NativeMethods.ULSTrace(); // Pretty standard code needed to make things work ulsTrace.Header.Size = (ushort)Marshal.SizeOf(typeof(NativeMethods.ULSTrace)); ulsTrace.Header.Flags = NativeMethods.WNODE_FLAG_TRACED_GUID; ulsTrace.ULSHeader.dwVersion = NativeMethods.TRACE_VERSION_CURRENT; ulsTrace.ULSHeader.dwFlags = NativeMethods.TraceFlags.TRACE_FLAG_ID_AS_ASCII; ulsTrace.ULSHeader.Size = (ushort)Marshal.SizeOf(typeof(NativeMethods.ULSTraceHeader)); // Variables communicated to SPTrace ulsTrace.ULSHeader.Id = tag; ulsTrace.Header.Class.Level = (byte)level; ulsTrace.ULSHeader.wzExeName = exeName; ulsTrace.ULSHeader.wzProduct = productName; ulsTrace.ULSHeader.wzCategory = categoryName; ulsTrace.ULSHeader.wzMessage = message; ulsTrace.ULSHeader.correlationID = correlationGuid; // Pptionally, to improve performance by reducing the amount of data copied around, // the Size parameters can be reduced by the amount of unused buffer in the Message if (message.Length < 800) { ushort unusedBuffer = (ushort) ((800 - (message.Length + 1)) * sizeOfWCHAR); ulsTrace.Header.Size -= unusedBuffer; ulsTrace.ULSHeader.Size -= unusedBuffer; } if (hTraceLog != 0) NativeMethods.TraceEvent(hTraceLog, ref ulsTrace); } public static unsafe void RegisterTraceProvider() { SPFarm farm = SPFarm.Local; Guid traceGuid = farm.TraceSessionGuid; uint result = NativeMethods.RegisterTraceGuids(ControlCallback, null, ref traceGuid, 0, IntPtr.Zero, null, null, out hTraceReg); System.Diagnostics.Debug.Assert(result == NativeMethods.ERROR_SUCCESS); } public static void UnregisterTraceProvider() { uint result = NativeMethods.UnregisterTraceGuids(hTraceReg); System.Diagnostics.Debug.Assert(result == NativeMethods.ERROR_SUCCESS); } 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]); } static unsafe uint ControlCallback(NativeMethods.WMIDPREQUESTCODE RequestCode, IntPtr Context, uint* InOutBufferSize, IntPtr Buffer) { uint Status; switch (RequestCode) { case NativeMethods.WMIDPREQUESTCODE.WMI_ENABLE_EVENTS: hTraceLog = NativeMethods.GetTraceLoggerHandle(Buffer); Status = NativeMethods.ERROR_SUCCESS; break; case NativeMethods.WMIDPREQUESTCODE.WMI_DISABLE_EVENTS: hTraceLog = 0; Status = NativeMethods.ERROR_SUCCESS; break; default: Status = NativeMethods.ERROR_INVALID_PARAMETER; break; } *InOutBufferSize = 0; return Status; } }
}
此DID对我不起作用,并始终挂断我的Webpart。我让它工作了一秒钟,然后又没有了。而且,只有当我删除了Trace register / unregister / etc语句后,它才起作用。
因此,我推荐这篇对我有用的优秀文章:
http://sharepoint.namics.com/2008/05/logging_in_webparts.html
本质上,我们应该使用:
.NET的通用基础结构库。
我是从这里下载的:
http://netcommon.sourceforge.net/
我使用了gacutil(或者控制面板/管理工具/.net配置工具)将2.0 / release dll添加到了gac。
我将对我的代码的引用添加到了dll的文件中(从下载中下载)。一切编译完毕。
我必须创建一个目录和空的日志文件,然后bam!在第一个Web部件加载上它起作用了。我花了好几个小时尝试获取我的Web部件的日志记录,这一点效果很好,并且它是一个很好的标准,例如log4j。