工作流:将文件从一个站点复制到另一个服务器或站点





5.00/5 (1投票)
此工作流将把一个站点文档库中的文件复制到另一个服务器或 Web 应用程序。
免责声明
我不是一个经过正规培训的程序员。我正在上谷歌的计算机科学学院。请尽量不要嘲笑我的代码。对于因查看我的代码而引起的任何医疗问题,我不承担任何责任。
引言
本文提供的代码可用于创建一个自定义工作流操作,该操作会将一个文档从一个站点的文档库复制到另一个站点的库。在 SPD 中添加操作时,用户将能够提供目标网站 URL 和目标库。
此操作不会将文档元数据复制到目标站点。它只会复制项目。此操作不会将作者姓名复制到目标站点。它只会复制项目。此操作不会将项目版本号复制到目标站点。它只会复制项目。
背景
在互联网上搜索了一个现成的代码示例后,我不得不自己解决这个问题。因为我不是程序员,所以花了一段时间才把它拼凑起来。希望它能帮助像我这样需要一个好的入门程序来开始的人。
此代码已在我的开发环境和 SharePoint 2010 Enterprise 的小型安装上进行了测试。
使用代码
我不会详细介绍如何创建自定义工作流操作项目。有很多关于如何执行此操作的好文章。我在下面提供了一些参考。设置项目后,根据需要替换下面的代码。对于像我这样的新手,这意味着
- 确保此处列出的 usings 在您的项目中
- 替换命名空间声明后花括号内的代码
- 务必在 windows 程序集中注册您的项目,并将此处列出的公共令牌替换为您的公共令牌。
第一段代码是您的活动库中的 clsCopyItem.cs 项。在此代码中,定义了工作流上下文的变量以及目标 Web 和目标库。我还使用了 CreateHistoryEvent 类在多个位置添加工作流历史记录中的条目,用于跟踪和故障排除。随意添加或删除,根据需要。
我也没有在此代码中放置广泛的错误处理或释放方法,因为我仍在尝试弄清楚。当我了解这一点时,或者如果有人真的乐于助人并提供一些建议,我将更新代码。
using System;
using System.ComponentModel;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel;
using System.Workflow.Activities;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;
using Microsoft.SharePoint.WorkflowActions;
namespace ActivityLibrary
{
public partial class clsCopyItem : SequenceActivity
{
public clsCopyItem()
{
InitializeComponent();
}
#region Dependency Properties
public static DependencyProperty SiteUrlProperty = DependencyProperty.Register("SiteUrl",
typeof(string), typeof(clsCopyItem), new PropertyMetadata(""));
[DescriptionAttribute("Url of site where item is to be moved to")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[ValidationOption(ValidationOption.Optional)]
public string SiteUrl
{
get { return ((string)(base.GetValue(clsCopyItem.SiteUrlProperty))); }
set { base.SetValue(clsCopyItem.SiteUrlProperty, value); }
}
public static DependencyProperty LibraryNameProperty =
DependencyProperty.Register("LibraryName", typeof(string),
typeof(clsCopyItem), new PropertyMetadata(""));
[DescriptionAttribute("Name of library to move item to")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[ValidationOption(ValidationOption.Optional)]
public string LibraryName
{
get { return ((string)(base.GetValue(clsCopyItem.LibraryNameProperty))); }
set { base.SetValue(clsCopyItem.LibraryNameProperty, value); }
}
public static DependencyProperty __ContextProperty =
System.Workflow.ComponentModel.DependencyProperty.Register(
"__Context", typeof(WorkflowContext), typeof(clsCopyItem));
[Description("Context")]
[Category("Context")]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public WorkflowContext __Context
{
get { return ((WorkflowContext)(base.GetValue(clsCopyItem.__ContextProperty))); }
set { base.SetValue(clsCopyItem.__ContextProperty, value); }
}
public static DependencyProperty __ListIdProperty =
System.Workflow.ComponentModel.DependencyProperty.Register("__ListId", typeof(string), typeof(clsCopyItem));
[Description("List Id")]
[Category("List Id")]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public string __ListId
{
get { return ((string)(base.GetValue(clsCopyItem.__ListIdProperty))); }
set { base.SetValue(clsCopyItem.__ListIdProperty, value); }
}
public static DependencyProperty __ListItemProperty =
System.Workflow.ComponentModel.DependencyProperty.Register(
"__ListItem", typeof(int), typeof(clsCopyItem));
[Description("List Item")]
[Category("List Item")]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int __ListItem
{
get { return ((int)(base.GetValue(clsCopyItem.__ListItemProperty))); }
set { base.SetValue(clsCopyItem.__ListItemProperty, value); }
}
#endregion
public Guid workflowId = default(System.Guid);
public SPWorkflowActivationProperties workflowProperties = new SPWorkflowActivationProperties();
//private void codeCopyItem_ExecuteCode(object sender, EventArgs e)
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
ISharePointService wfService = executionContext.GetService<ISharePointService>();
SPListItem item = workflowProperties.Item;
string targetSiteUrl = SiteUrl;
string targetLib = LibraryName;
string LogMessage = "Message logged to workflow history: ";
//string targetSiteUrl = "http://testpublic.mwestling-lt/DocCenter";
//string targetLib = "Documents";
//Added to see if I can get the context items like file, etc.
SPWeb contextWeb = __Context.Web;
SPList contextList = contextWeb.Lists[new Guid(__ListId)];
SPListItem contextItem = contextList.GetItemById(__ListItem);
SPFile contextFile = contextItem.File;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite targetSite = new SPSite(targetSiteUrl))
{
using (SPWeb targetWeb = targetSite.OpenWeb())
{
try
{
if (contextFile != null)
{
//Setup variables
SPFolder targetFolder = targetWeb.RootFolder.SubFolders[targetLib];
string strfutureFilePath = targetFolder + "/" + contextFile.Name;
//First test to see if the file exists on the target
SPFile isItThere = targetWeb.GetFile(strfutureFilePath);
if (isItThere.Exists)
{
SPWorkflow.CreateHistoryEvent(targetWeb, __Context.WorkflowInstanceId, 0,
targetWeb.CurrentUser, TimeSpan.Zero, "Information", LogMessage +
"Target file exists, going to check it out if needed", string.Empty);
//Check to see if it is already checked out, if so, undo the checkout
if (isItThere.CheckOutType == SPFile.SPCheckOutType.None)
{
//If it exists, check it out
isItThere.CheckOut();
}
else
{
isItThere.UndoCheckOut();
isItThere.CheckOut();
}
}
//Check out the source file
SPWorkflow.CreateHistoryEvent(targetWeb, __Context.WorkflowInstanceId, 0,
targetWeb.CurrentUser, TimeSpan.Zero, "Information",
LogMessage + "Checking out source file", string.Empty);
if (contextFile.CheckOutType == SPFile.SPCheckOutType.None)
{ contextFile.CheckOut(); }
else
{ contextFile.UndoCheckOut(); contextFile.CheckOut(); }
//Try to overwrite, if not, then change code and add in the delete
SPWorkflow.CreateHistoryEvent(targetWeb, __Context.WorkflowInstanceId, 0, targetWeb.CurrentUser,
TimeSpan.Zero, "Information", LogMessage +
"Copying file to destination", string.Empty);
SPFile movedFile = targetFolder.Files.Add(contextItem.File.Name, contextItem.File.OpenBinary(), true);
//Check in destination file
string movedFileComment = "Copied from " + contextFile.DocumentLibrary.Title + ".";
movedFile.CheckIn(movedFileComment);
//Check in source file and publish
string checkInComment = "File has been copied to the " +
targetFolder.Name + " library on the " + targetWeb.Title + " site";
contextFile.CheckIn(checkInComment);
contextFile.Publish(checkInComment);
contextFile.Approve(checkInComment);
SPWorkflow.CreateHistoryEvent(targetWeb, __Context.WorkflowInstanceId, 0,
targetWeb.CurrentUser, TimeSpan.Zero, "Information",
LogMessage + "File copied and checked in", string.Empty);
}
}
catch (Exception ex)
{
string Message = ex.Message;
SPWorkflow.CreateHistoryEvent(targetWeb, __Context.WorkflowInstanceId, 0,
targetWeb.CurrentUser, TimeSpan.Zero, "Error",
"Message: " + Message, string.Empty);
throw ex;
}
}
}
});
return ActivityExecutionStatus.Closed;
}
}
}
下一段代码将用于您的 CopyItemToAnotherLibrary.actions 文件中。它定义了工作流操作需要的参数,例如目标 URL 和目标库。请记住,注册程序集时,您需要使用您的令牌更新 PublicKeyToken。
<?xml version="1.0" encoding="utf-8" ?>
<WorkflowInfo>
<Actions Sequential="then" Parallel="and">
<Action Name="Move Item to Another Library"
ClassName="ActivityLibrary.clsCopyItem"
Assembly="ActivityLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5cd1b18d3e72bd18"
Category="Custom Actions"
AppliesTo="all">
<RuleDesigner Sentence="Send Item to Library %2 at Site URL %1">
<FieldBind Field="SiteUrl" Text="Site URL" DesignerType="TextArea" Id="1"/>
<FieldBind Field="LibraryName" Text="Library Name" DesignerType="TextArea" Id="2"/>
</RuleDesigner>
<Parameters>
<Parameter Name="SiteUrl" Type="System.String, mscorlib" Direction="In" DesignerType="StringBuilder"
Description="URL of the destination site. Must be in the form of http://ServerName/(SiteName)" />
<Parameter Name="LibraryName" Type="System.String, mscorlib" Direction="In" DesignerType="StringBuilder"
Description="Name of the destination library." />
<Parameter Name="__Context"
Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext, Microsoft.SharePoint.WorkflowActions"
Direction="In" DesignerType="Hide"/>
<Parameter Name="__ListId" Type="System.String, mscorlib, mscorlib" Direction="In" DesignerType="Hide"/>
<Parameter Name="__ListItem" Type="System.Int32, mscorlib, mscorlib" Direction="In" DesignerType="Hide"/>
</Parameters>
</Action>
</Actions>
</WorkflowInfo>
关注点
由于这是我第一次尝试编写自定义操作,我发现有很多关于编写自定义操作的好文章,以及用于将它们组合在一起的好代码片段。我确信有人会看到他们的代码片段,感谢您发布它。我包括了我在下面找到的一些有用的链接。
参考文献
历史
初始发布 - 当提供建议等或我学到更多并创建更新时,将进行更新。