部署和使用 SPCopy:第二部分
访问第 1 部分中 SPCopy 的功能。
引言
本文是 SPCopy 的续篇,将展示不同的方法来暴露 SPCopy 的功能,以便在 SharePoint 中使用,可以直接从应用程序页面使用,或者通过 stsadm 或 PowerShell 等管理工具使用。
注意:除了 ISPStsadmCommand
之外,本文中的所有示例都是为 SharePoint 2010 创建的,并使用了 Visual Studio 2010。
ISPStsadmCommand
任何处理过 SharePoint 的人都知道,stsadm.exe 是一个命令行工具,允许管理员对 SharePoint 服务器执行操作。就像 SharePoint 本身非常可配置和可扩展以满足创建时无法预料的需求一样,stsadm.exe 也具有可配置性,允许根据需要添加命令。实现这一目标的方法是实现 Microsoft.SharePoint.StsAdmin
命名空间中的 ISPStsadmCommand
接口。
由于该接口已被许多其他资源深入介绍,其中一些我列在本文章的末尾,我将只展示一个基本实现。
public class HelloWorld : ISPStsadmCommand
{
#region ISPStsadmCommand Members
public string GetHelpMessage(string command)
{
return "Help World";
}
public int Run(string command,
System.Collections.Specialized.StringDictionary keyValues,
out string output)
{
output = "Hello, World";
return 0;
}
#endregion
}
编译后的程序集被放置在 GAC 中,并将一个 XML 文件添加到 ...\12\CONFIG 文件夹中。
<?xml version="1.0" encoding="utf-8" ?>
<commands>
<command name="hello"
class="HelloWorldCommand.HelloWorld,
HelloWorldCommand,
Version=1.1.1.1,
Culture=neutral,
PublicKeyToken=a9baec847ddb5ad1"/>
</commands?
同样,本文无意深入介绍 ISPStsadmCommand
接口的实现。附带的下载文件包含了 SPCopy
功能的完整实现。
PowerShell Cmdlets
不幸的是,在 SharePoint 2010 中,对 stsadm.exe 的扩展支持已被弃用,因此上述方法将不再有效。取而代之的是,SharePoint 2010 现在使用 Windows PowerShell 和 Cmdlet。这其中的一个好处是,它们可以像其他 SharePoint 项(如功能或网站定义)一样,作为 SharePoint 包(WSP)进行部署,并享有 Windows PowerShell 的其他优点,本文将不作介绍。
实现 SharePoint Cmdlet
在创建 SharePoint Cmdlet 时,首先要了解的是使用哪个类。有五个基类可供选择:SPNewCmdletBase
、SPSetCmdletBase
、SPGetCmdletBase
、SPRemoveCmdletBase
和 SPCmdlet
。所有这些类都位于 Microsoft.SharePoint.PowerShell
命名空间中。它们的区别如下:
SPNewCmdletbase<TCmdletObject>
:一个抽象基类,用于创建对象的新实例并将其保存到数据存储中。SPGetCmdletBase<TCmdletObject>
:抽象基类,允许派生类查找并返回TCmdletObject
类型对象集。SPSetCmdletBase<TCmdletObject>
:抽象基类,派生类可以使用它来更新数据存储中现有对象的属性。SPRemoveCmdletBase<TCmdletObjec>
:抽象基类,用于从数据存储中删除指定类型的数据对象的现有数据对象。SPCmdlet
:表示为 SharePoint 部署编写的所有自定义 Cmdlet 的抽象基类,为所有 SharePoint Cmdlet 提供统一的行为。
正如您所见,前四个基类基本上是 CRUD 操作:创建 = SPNewCmdletBase
,读取 = SPGetCmdletBase
,更新 = SPSetCmdletBase
,删除 = SPRemoveCmdletBase
。最后一个是用于派生自定义 Cmdlet 的通用基类。由于 SPSiteCopy
功能本身不涉及任何 CRUD 操作,因此我将使用 SPCmdlet
作为基类。
SPCmdlet
为了构建 SPCopyCmd
,我将首先在“新建项目”模板对话框中选择“空 SharePoint 项目”。
要创建 SPCmdlet
,需要引用 Microsoft.SharePoint.PowerShell.dll。但这会带来一个挑战。该程序集唯一出现的地方是 GAC,而不是其他 SharePoint 相关程序集所在的 14\ISAPI 文件夹。要找到此程序集,您需要使用以下命令进行搜索:
dir Microsoft.Sharepoint.Powershell.dll /s
找到程序集后,将其复制到另一个位置,以便在项目中引用。我建议将其与其他的 SharePoint 相关程序集一起复制到 14\ISAPI 文件夹中;这样,以后就可以轻松找到它。还必须将另一个程序集引用添加到项目中:System.Management.Automation.dll。虽然 System.Management
出现在“添加引用”对话框的“.NET”选项卡中,但我们需要的不是这个。我们需要的那个不会出现在“.NET”选项卡中,所以您必须在 C:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0 找到它。
现在已经引用了所有必需的程序集,就可以开始构建自定义 SPCmdlet
了。
[SPCmdlet(RequireLocalFarmExist = true, RequireUserFarmAdmin = false)]
public class SPCopyBase : SPCmdlet
{
protected override void InternalValidate()
{
if(string.IsNullOrEmpty(Source))
throw new ArgumentException("Source must be specified");
if(string.IsNullOrEmpty(Destination))
throw new ArgumentException("Destination must be specified");
}
protected override void InternalProcessRecord()
{
// Implementation goes here
}
#region Properties
[Parameter(Position = 0, Mandatory = true)]
public string Source { get; set; }
[Parameter(Position = 1, Mandatory = true)]
public string Destination { get; set; }
protected bool IsCopy { get; set; }
#endregion
}
如您所见,该类派生自 SPCmdlet
并实现了两个重写方法:InternalValidate
和 InternalProcessRecord
。如果该 Cmdlet
实现的是 Set 或 Get 功能,我们将分别重写 RetrieveDataObject
或 UpdateDataObject
。但是,由于此 Cmdlet
不是用于 CRUD 类型操作,我们只需要实现这两个方法。您还可以看到 SPCmdletAttribute
被应用于此。该属性提供的三个参数非常直观:RequireLocalFarmExists
、RequireUserFarmAdmin
和 RequireUserMachineAdmin
。
为了将 Cmdlet
暴露给 PowerShell,必须创建一个 XML 文件并将其放置在 14\CONFIG\POWERSHELL\Registration 文件夹中。在 VS2010 的 SharePoint 项目中,向项目中添加此文件夹非常容易。右键单击解决方案资源管理器中的项目,然后选择“添加”->“SharePoint 映射文件夹”。导航到正确的文件夹,然后单击“确定”。
创建文件夹后,添加一个 XML 文件。虽然您可以随意命名,但按照约定,应以项目名称来命名。SharePoint PowerShell 在启动时使用此 XML 文件将任何命令加载到环境中。
<ps:Config xmlns:ps="urn:Microsoft.SharePoint.PowerShell"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:Microsoft.SharePoint.PowerShell SPCmdletSchema.xsd">
<ps:Assembly Name="$SharePoint.Project.AssemblyFullName$">
<ps:Cmdlet>
<ps:VerbName>Copy-SPWeb</ps:VerbName>
<ps:ClassName>MANSoftDev.SharePoint.PowerShell.SPCopyCmd</ps:ClassName>
<ps:HelpFile>MANSoftDev.SharePoint.PowerShell.dll-help.xml</ps:HelpFile>
</ps:Cmdlet>
<ps:Cmdlet>
<ps:VerbName>Move-SPWeb</ps:VerbName>
<ps:ClassName>MANSoftDev.SharePoint.PowerShell.SPMoveCmd</ps:ClassName>
<ps:HelpFile>MANSoftDev.SharePoint.PowerShell.dll-help.xml</ps:HelpFile>
</ps:Cmdlet>
</ps:Assembly>
</ps:Config>
首先需要做的是将 Assembly
元素的 Name
属性设置为您正在构建的程序集的四部分名称。$SharePoint.Project.AssemblyFullName$
在编译时会自动包含此信息。接下来,您需要为程序集中的每个 Cmdlet
添加一个 Cmdlet
元素。VerbName
元素告诉 PowerShell 将哪个 Verb-Name 与 Cmdlet
相关联,而 ClassName
元素包含实现它的类的完全限定名。HelpFile
元素是必需的;但是,指定的实际文件不必存在。按照约定,您可以使用程序集的名称,这样如果您决定提供帮助文件,会更容易。本文不涉及实现帮助文件。
实现 Cmdlet
由于程序集包含复制和移动命令,PowerShell 需要一种方法来区分哪个类用于哪个命令。这正是 CmdletAttribute
的作用所在。这两个必需的参数分别用于指定与 Cmdlet
关联的动词和名词。VerbsCommon
枚举包含常用动词的值,如 Set、Get、Find 等等。如果其中一个不符合您的需求,也可以提供任何字符串。
[Cmdlet(VerbsCommon.Copy, "SPWeb")]
public class SPCopyCmd : SPCopyBase
{
public SPCopyCmd()
{
base.IsCopy = true;
}
}
[Cmdlet(VerbsCommon.Move, "SPWeb")]
public class SPMoveCmd : SPCopyBase
{
public SPMoveCmd()
{
base.IsCopy = false;
}
}
复制或移动 SPWeb
的所有工作已在 上一篇文章 中完成,因此实现 Cmdlet
非常简单。为简单起见,我将直接从上一个项目将 SPWeb
类复制到此项目中。有关此实现的详细信息,请参阅 上一篇文章。
protected override void InternalProcessRecord()
{
MANSoftDev.SharePoint.PowerShell.SPWeb copy =
new MANSoftDev.SharePoint.PowerShell.SPWeb();
copy.SourceURL = Source;
copy.DestinationURL = Destination;
if(IsCopy)
copy.Copy();
else
copy.Move();
}
编译完所有内容后,剩下要做的就是将文件部署到服务器。在解决方案资源管理器中,右键单击项目并选择“部署”。这将把 XML 文件复制到 Registration 文件夹,并将程序集安装到 GAC。当您打开 SharePoint 2010 管理 Shell 时,它将使用 PowerShell\Registration 文件夹中的 XML 文件加载所有 Cmdlet。
当然,本文并非 Cmdlet 开发的完整论述,还有许多其他方面可以实现,但目前为止,它涵盖了该主题。
应用程序页面
虽然创建 ISPStsadminCommand
或 SPCmdlet
来公开复制或移动网站的功能相对容易,但它们并不非常用户友好或易于访问。要使用它们,我们必须位于 SharePoint 服务器本身。要以更用户友好的方式公开该功能,可以创建一个应用程序页面,并通过“站点操作”菜单或“站点设置”页面访问它。
对于那些使用过 SharePoint 2007 的人来说,您会非常满意 Visual Studio 2010 中用于创建和部署解决方案包的工具。我将触及一些基本内容,但本文无意涵盖 Visual Studio 2010 SharePoint 工具。
要创建应用程序页面并将其添加到必要的菜单中,我将再次从创建“空 SharePoint 项目”开始。创建完成后,在解决方案资源管理器中右键单击项目,然后选择“添加”->“SharePoint 'Layouts' 映射文件夹”。与 SharePoint 2007 一样,最佳做法是在 layouts 下创建一个文件夹来包含您的自定义实现。现在,右键单击此文件夹,然后选择“添加”->“新建项”。
选择“应用程序页面”并为其命名(在这种情况下为 SPCopy.aspx),然后单击“添加”。项目结构现在看起来像这样:
现在,只需将适当的控件添加到 ASPX 文件,并将事件处理程序添加到代码隐藏文件即可。
protected void OnMove(object sender, EventArgs e)
{
if(Destination.Text.Length != 0)
{
web.SourceURL = SPContext.Current.Web.Url;
web.DestinationURL = Destination.Text;
web.Move();
Response.Redirect(Destination.Text);
}
}
protected void OnCopy(object sender, EventArgs e)
{
if(Destination.Text.Length != 0)
{
web.SourceURL = SPContext.Current.Web.Url;
web.DestinationURL = Destination.Text;
web.Move();
Response.Redirect(Destination.Text);
}
}
为了访问该页面,我将在“站点设置”页面和“站点操作”菜单中添加一个项。这可以通过向项目中添加一个 Element
来实现。同样,Visual Studio 2010 使此操作非常容易。在解决方案资源管理器中右键单击项目,然后选择“添加”->“新建项”。从“添加新项”对话框中选择“空元素”。将其添加到项目后,按照如下方式添加 XML。尽管“站点操作”组是该项的逻辑位置,但似乎没有它的 GroupId
,因此我将其添加到“站点管理”组中。
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint">
<CustomAction Id="SPCopy"
RequireSiteAdministrator="True"
Location="Microsoft.SharePoint.SiteSettings"
GroupId="SiteAdministration"
Title="Copy/Move Web"
Description="Copy or move web"
Sequence="1001">
<UrlAction Url="_layouts/mansoftdev/spcopy.aspx"/>
</CustomAction>\>
同样,本文并非关于 SharePoint CustomActions、Elements 或 Features,因此我不会深入探讨细节。我在“参考”部分提供了一些链接。
关注点
Visual Studio 2010 在 SharePoint 开发方面的改进非常出色,无疑使该平台的开发更加轻松,甚至有趣。
IStsadmCommand 参考
- http://sharepointsolutions.blogspot.com/2006/09/extending-stsadmexe-with-custom.html
- http://msdn.microsoft.com/en-us/library/bb417382.aspx
SPCmdlet 参考
CustomAction 参考
- http://msdn.microsoft.com/en-us/library/bb802730.aspxhttp://msdn.microsoft.com/en-us/library/bb802730.aspx
- http://msdn.microsoft.com/en-us/library/ms460194.aspxhttp://msdn.microsoft.com/en-us/library/ms460194.aspx
历史
- 10/4/27:首次发布。