如何:按更改类型筛选更改日志
上次修改时间: 2009年7月29日
适用范围: SharePoint Foundation 2010
该示例是一个在内容数据库范围内查询更改日志的控制台应用程序。该查询查找对 SPUser 和 SPGroup 对象所做的更改,其中涉及添加、更新或删除任一类型的对象;还查找会修改组成员资格的更改。
请注意,该示例尝试证明可独立于系统对象的安全性管理更改日志的安全性。当您编译并运行该示例时,您的特权可能允许您读取更改日志,并发现哪些类型的对象发生了更改以及对这些对象进行了哪些类型的更改,但可能不允许您访问对象本身。因此,代码可能会输出有关 SPUser 对象在特定日期被添加到网站集的信息,还可能会输出所添加对象的 GUID。但当它尝试检索该对象时,可能仍会引发 UnauthorizedAccessException。拥有访问更改日志的权限并不等于拥有访问所更改对象的权限。
示例
using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
namespace Test
{
class Program
{
static SPUserCollection m_users;
static SPGroupCollection m_groups;
static void Main(string[] args)
{
using (SPSite currentSite = new SPSite("https://localhost"))
{
SPTimeZone tz = currentSite.RootWeb.RegionalSettings.TimeZone;
SPContentDatabase db = currentSite.ContentDatabase;
m_users = currentSite.RootWeb.AllUsers;
m_groups = currentSite.RootWeb.Groups;
// Construct a query.
SPChangeQuery query = new SPChangeQuery(false, // Specify object types
false // Specify change types
);
// Specify object types.
query.User = true;
query.Group = true;
// Specify change types.
query.Add = true;
query.Delete = true;
query.Update = true;
query.GroupMembershipAdd = true;
query.GroupMembershipDelete = true;
long total = 0;
while (true)
{
SPChangeCollection changes = db.GetChanges(query);
total += changes.Count;
foreach (SPChange change in changes)
{
// Print the date of the change.
Console.WriteLine("\nDate: {0}",
tz.UTCToLocalTime(change.Time).ToString());
// Get the url, user collection, and group collection
// of the site where the change took place.
foreach (SPSite site in db.Sites)
{
if (site.ID == change.SiteId)
{
Console.WriteLine("Site Url: {0}", site.Url);
try
{
m_users = site.RootWeb.AllUsers;
m_groups = site.RootWeb.Groups;
}
catch (UnauthorizedAccessException)
{
// Do nothing. The failure is handled elsewhere in the code.
}
finally
{
site.Dispose();
}
break;
}
site.Dispose();
}
// Print the nature of the change.
Console.WriteLine("Type of object: {0}", change.GetType().ToString());
Console.WriteLine("Type of change: {0}", change.ChangeType.ToString());
// Get information about a user change.
if (change is SPChangeUser)
{
SPChangeUser userChange = (SPChangeUser)change;
// Print the user name.
string userName = GetPrincipalName(userChange.Id, true);
Console.WriteLine("User name: {0}", userName);
}
// Get information about a group change.
if (change is SPChangeGroup)
{
SPChangeGroup groupChange = (SPChangeGroup)change;
// Print the group name.
string groupName = GetPrincipalName(groupChange.Id, false);
Console.WriteLine("Group name: {0}", groupName);
if (groupChange.ChangeType == SPChangeType.MemberAdd ||
groupChange.ChangeType == SPChangeType.MemberDelete)
{
string userName = GetPrincipalName(groupChange.UserId, true);
Console.WriteLine("User name: {0}", userName);
}
}
}
if (changes.Count < query.FetchLimit)
break;
query.ChangeTokenStart = changes.LastChangeToken;
}
Console.WriteLine("\nTotal changes = {0:#,#}", total);
}
Console.Write("\nPress ENTER to continue...");
Console.Read();
}
static string GetPrincipalName(int id, bool isUser)
{
string name = string.Empty;
try
{
if (isUser)
{
SPUser user = m_users.GetByID(id);
name = user.LoginName;
}
else
{
SPGroup group = m_groups.GetByID(id);
name = group.Name;
}
}
catch (UnauthorizedAccessException)
{
name = "unknown (access not authorized)";
}
catch (SPException)
{
name = "unknown (not found)";
}
return name;
}
}
}
Imports System
Imports Microsoft.SharePoint
Imports Microsoft.SharePoint.Administration
Module ConsoleApp
Dim m_users As SPUserCollection
Dim m_groups As SPGroupCollection
Sub Main()
Using currentSite As SPSite = New SPSite("https://localhost")
Dim tz As SPTimeZone = currentSite.RootWeb.RegionalSettings.TimeZone
Dim db As SPContentDatabase = currentSite.ContentDatabase
m_users = currentSite.RootWeb.Users
m_groups = currentSite.RootWeb.Groups
' Construct a query.
Dim query As SPChangeQuery = New SPChangeQuery(False, False)
' Specify object types.
query.User = True
query.Group = True
' Specify change types.
query.Add = True
query.Delete = True
query.Update = True
query.GroupMembershipAdd = True
query.GroupMembershipDelete = True
Dim total As Long = 0
While True
Dim changes As SPChangeCollection = db.GetChanges(query)
total += changes.Count
Dim change As SPChange
For Each change In changes
' Print the date of the change.
Console.WriteLine(vbCrLf + "Date: {0}", _
tz.UTCToLocalTime(change.Time).ToString())
' Get the url, user collection, and group collection
' of the site where the change took place.
Dim site As SPSite
For Each site In db.Sites
If site.ID = change.SiteId Then
Console.WriteLine("Site Url: {0}", site.Url)
Try
m_users = site.RootWeb.AllUsers
m_groups = site.RootWeb.Groups
Catch
' Do nothing. The failure is handled elsewhere in the code.
Finally
site.Dispose()
End Try
Exit For
End If
site.Dispose()
Next
' Print the nature of the change.
Console.WriteLine("Type of object: {0}", change.GetType().ToString())
Console.WriteLine("Type of change: {0}", change.ChangeType.ToString())
' Get information about a user change.
If TypeOf change Is SPChangeUser Then
Dim userChange As SPChangeUser = CType(change, SPChangeUser)
' Print the user name.
Dim userName As String = GetPrincipalName(userChange.Id, True)
Console.WriteLine("User name: {0}", userName)
End If
' Get information about a group change.
If TypeOf change Is SPChangeGroup Then
Dim groupChange As SPChangeGroup = CType(change, SPChangeGroup)
' Print the group name.
Dim groupName As String = GetPrincipalName(groupChange.Id, False)
Console.WriteLine("Group name: {0}", groupName)
If (groupChange.ChangeType = SPChangeType.MemberAdd) Or _
(groupChange.ChangeType = SPChangeType.MemberDelete) Then
Dim userName As String = GetPrincipalName(groupChange.UserId, True)
Console.WriteLine("User name: {0}", userName)
End If
End If
Next
If changes.Count < changes.FetchLimit Then
Exit While
End If
query.ChangeTokenStart = changes.LastChangeToken
changes = db.GetChanges(query)
End While
Console.WriteLine(vbCrLf + "Total changes: {0}", total)
End Using
Console.Write(vbCrLf + "Press ENTER to continue...")
Console.Read()
End Sub
Function GetPrincipalName(ByVal id As Integer, ByVal isUser As Boolean) As String
Dim name As String = String.Empty
Try
If isUser Then
Dim user As SPUser = m_users.GetByID(id)
name = user.LoginName
Else
Dim group As SPGroup = m_groups.GetByID(id)
name = group.Name
End If
Catch secex As UnauthorizedAccessException
name = "unknown (access not authorized)"
Catch spex As SPException
name = "unknown (not found)"
End Try
Return name
End Function
End Module