本文将针对QuickFlow开发人员经常碰到的问题做一个集中的解释。
1)QuickFlow是什么
QuickFlow是基于SharePoint(2007,2010)的一个工作流设计工具,它包含一个核心的Flowchart流程模型和一个无代码设计器。基于QuickFlow开发SharePoint工作流和直接在SharePoint上开发工作流很类似,使用Quickflow前最好了解下默认的SharePoint工作流是如何开发和运行的。
2)QuickFlow如何安装
QuickFlow的安装包含两部分:一部分是一个wsp的解决方案,这个解决方案中,包括所有dll文件和页面文件,这个wsp分两个版本:一个用于SharePoint2007,一个用户SharePoint2010。另外一部分是设计器,设计器无需安装,直接解压后即可打开exe文件,需要指出的是,当前版本的设计器只能在SharePoint服务器上运行。
3)Quickflow使用中碰到错误如何解决
有几种类型的错误:
发布流程时:这个时候出错,一般是web.config配置错误,重新激活下QuickFlow feature即可。在SP07下,在网站集功能管理中操作,在SP10下,需要到管理中心激活QuickFlow App Configuration feature,详见安装文档。
工作流运行时:有很多种可能性,首先要找到日志信息,日志有两个地方可以看,一个是工作流状态页面--在列表页面,点击工作流链接进入。在这个页面可以看到QuickFlow内部输出的日志。不仅仅是碰到错误,如果工作流没错误,但是运行结果跟预期的不一致,也可以到这个页面查看信息。比如设置了发送邮件,但是测试时却没有收到,那么状态页面会记录邮件发现情况。
另一个查看日志的地方是12/Logs or 14/Logs目录,这是SP自带的日志文件。打开最新的日志文件,在里面搜索Workflow Infrastructure ,可以搜到跟工作流有关的日志信息。
注:日志目录[C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\LOGS]
在页面提交的时出错: 这个时候,如果发现页面上没有详细的错误信息,那么首先要让SP显示出详细错误,这个操作是SP开发第一步就要做的。详细:google SharePoint 详细错误。 需要指出的是:Layouts下的web.config也是需要修改的(set customError mode=’off’)
4)关于工作流变量(workflow variable)
工作流变量是当使用QuickFlow Designer时,允许在流程级别添加一些特定类型的字段,各个活动的属性可以跟工作流变量绑定,UI代码可以直接控制工作流变量的值。
如果您是用VisualStudio+QuickFlow开发,那么是没必要用工作流变量的,工作流变量其实是模拟添加类字段(field)。用vs时,可以很方便的在工作流中添加字段,为什么还要用工作流变量呢?
当然,vs中工作流变量还是可以使用的,那么一般会碰到两个问题:
a)如何在UI代码中控制工作流字段的值:跟控制工作流变量的值是一样的,用QuickFlow.Core.WorkflowContext.Current.UpdateWorkflowVariable("NextApprovors", nextUsers);
b)如何在WF代码中控制工作流变量的值:直接设置字段的值即可,或者,用base.UpdateVariable("NextApprovors", nextUsers);如:
public QuickFlow.NameCollection nextUsers ;
//nexUsers bind to multiTask.Users
private void task_init(object sender, EventArgs e)
{
this.nextUsers = ...;
//or base.UpdateVariable("nextUsers", nextUsers);
}
记住:
在用VS+QF时,工作流变量跟普通的字段是一样的。
永远不要在VS的WF代码中调用WorkflowContext.Current。
如果要在UI代码中传递变量值,只能在几个固定的事件方法中才可行:
1-StartWorkflowButton.Executing事件中,
2-ActionsButton.ActionExecuting事件中,
3-TaskReassignButton.Executing事件中,
4-在启动页面或任务页面的Page_Load事件中,Page_Load中给工作流变量赋值后,必须在以下的操作中启动工作流或提交任务才会有效
无论在哪个方法中,都需要使用QuickFlow.Core.WorkflowContext.Current.UpdateWorkflowVariable来更新变量
注意:在UI代码中,只能设置工作流变量的值而不能获取工作流变量值,如果碰到必须获取工作流变量的情况,那么可以用列表字段传值来实现。
5)关于WorkflowContext.Current
这个类用于在工作流页面中跟工作流交互。非工作流页面不能使用。
6)如果不用QuickFlow提供的控件来开发工作流页面,如何启动流程,提交任务呢?
有两种方式:
a)直接用SharePoint的对象模型来操作。这样做会有些复杂性。
跟Workflow有关的方法有:SPSite.WorkflowManager.StartWorkflow, SPWorkflow.AlterTask,详细见SharePoint SDK.
b)用QuickFlow提供的API操作: WorkflowContext.Current.
用WorkflowContext.Current必须在特定的上下文下运行,包括列表的新建页面,任务的提交页面。
常用WorkflowContext方法如下:
WorkflowContext.Current | 获取到当前的工作流上下文 |
WorkflowContext.CreateContext(SPList dataList) | 基于某个列表创建一个上下文, 这样创建的context,自动工作流的时候,会自动在列表中新建一个列表项,用于非NewForm页面上启动工作流 |
.DataFields[] | 获取或设置列表字段值。 |
.UpdateWorkflowVariable(string name, object value) | 工作流启动前或任务提交前更新工作流变量 |
.StartWorkflow(string wfName) | 启动工作流 |
.CommitTask( string outcome ) |
完成任务,指定任务的结果(通过,拒绝) |
.ReAssignTask(string to) | 转发任务 |
WorkflowContext.Current.Task | 获取当前的WorkflowTask(只能获取到上次的数据) |
WorkflowContext.Current.TaskFields["field name"] | 获取当前的任务字段属性,可以获取到最新数据 |
提交任务需要用WorkflowTask类
WorkflowTask一般通过WorkflowContext.Current.Task(任务页面代码)或者WorkflowTask.FromListItem(任何地方)获取
常用WorkflowTask方法如下:
WorkflowTask.FromListItem | 将任务Item转换成WorkflowTask类 |
.Actions | 获取到任务的动作集合(TaskActions) |
bool CanCommit() | 当前用户是否可以提交工作流(只有网站集管理员或者任务操作人才能提交任务) |
CommitTask(string outcome) | 提交任务 |
示例:
在列表的Newform页面启动工作流:
WorkflowContext.Current.StartWorkflow(“My Workflow”)
无论是启动工作流还是提交任务前,都可以传递工作流变量
WorkflowContext.Current.UpdateWorkflowVariable(“vabiableName”,value)
在一个普通的aspx页面启动流程(非NewForm页面):
var wflist = SPContext.Current.Web.Lists[“List1”];
WorkflowContext wfCtx = WorkflowContext.CreateContext(wflist);
wfCtx.DataFields["Title"] = proj.ProjectName; //设置列表项字段
wfCtx.DataFields["ReferenceNo"] = proj.ReferenceNo;
wfCtx.DataFields[ProjectID_FieldName] = proj.ID;
wfCtx.UpdateWorkflowVariable("sendToPCController", true);//设置工作流变量
wfCtx.UpdateWorkflowVariable("PCController", new NameCollection(pcController));
wfCtx.UpdateWorkflowVariable("PM", new NameCollection(proj.ProductManager));
wfCtx.StartWorkflow(Config.WorkflowName);
在任务页面获取任务动作:
TaskActionCollection actons = WorkflowContext.Current.Task.Actions;
在任务页面完成任务:
WorkflowContext.Current.CommitTask(“Approved”); //Approved is a taskAction
在非任务页,如控制台或TimerJob代码中完成任务:
var taskItem = taskList.GetItemById(100);
var task = WorkflowTask.FromListItem(taskItem);
if(task.Actoins.Count>0) task.Commit(task.Actions[0]);
else taks.Commit();
7)CommentTaskField这个富文本框能否去掉其样式呢,就是不希望用户在审批意见里添加各种样式,只要输入文字意见好了
在网站内容类型管理中,找到任务内容类型,设置其 描述字段 不使用富文本
8)在Initialized事件中设置了活动的属性,为什么不起作用?
因为QF中的活动可以无限次执行,所以实际执行的活动只是设计器上的活动的副本
如果在活动已经开始执行了,再设置设计器上的活动的属性,可能就无效了。
有两个方法解决这个问题:
1--事件参数sender始终是执行中的活动,直接给sender赋值,如: ((Task)sender).User = "someUserAccount";
2--如果要让一个属性可以在活动执行时可以被修改,那么可以把这个属性绑定到一个全局变量,这样--就始终可以修改了.
3--在这个活动前面一个活动的Completed事件中给这个活动的字段赋值。
9)设置了规则引擎(BeforeRule or AfterRule),发现工作流长时间不结束
原因:规则的计算,改变了规则的条件,造成规则引擎重新运行规则(造成无限循环)
解决:把 重新计算 选项改成 永不(Never) , 了解WF规则引擎:http://msdn.microsoft.com/zh-cn/library/aa480193.aspx
10)任务被锁定,即使更正了代码错误,任务依然无法重新提交
解决:需要先把任务解锁,然后重新提交即可:
ServerModel code:
using (SPSite site = new SPSite("http://localhost")) { using (SPWeb web = site.OpenWeb()) { SPList taskList = web.Lists["Tasks"]; var item = taskList.GetItemById(188); //change 188 to the task id web.AllowUnsafeUpdates = true; item[SPBuiltInFieldId.WorkflowVersion] = 1; try { item.SystemUpdate(); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } }
ClientModel code:
try
{
using (ClientContext clientContext =new ClientContext("http://localhost"))
{
Web site = clientContext.Web;
var list = site.Lists.GetByTitle("Tasks");
ListItem item = list.GetItemById(188);
clientContext.Load(item);
clientContext.ExecuteQuery();
Console.WriteLine("WorkflowVersion: "+ item["WorkflowVersion"]);
item["WorkflowVersion"] =1;
item.Update();
clientContext.ExecuteQuery();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("done");
Console.ReadKey();
注:最新版本任务被锁定后,默认任务页面上会显示一个解锁的链接,如果是自定义的页面,则在页面上加上UnLockTaskLink控件即可。
若解锁后依然无法提交,则重新启动SharePoint Timer服务和数据库服务,然后再次解锁提交.若依然不行,则只能重启工作流。
ref:http://connect.nintex.com/forums/thread/6503.aspx
11)不用QuickFlow的API启动流程,而直接用纯MOSS接口启动,如何传递工作流变量呢?
代码入下:
//using QukckFlow.Core;
WorkflowVariableValues vs = new WorkflowVariableValues();
vs["variableName1"] = "value1";
vs["variableName2"] = "value2";
var eventData = SerializeUtil.Serialize(vs);
SPSite site = SPControl.GetContextSite(HttpContext.Current);
var wfName = "some workflow name";
var wfAss = list.WorkflowAssociations.GetAssociationByName(wfName, System.Globalization.CultureInfo.CurrentCulture);
wf = site.WorkflowManager.StartWorkflow(listItem, wfAss, eventData);
如果要异步启动工作流,可以调用:
site.WorkflowManager.StartWorkflow(object context, SPWorkflowAssociation association, string eventData, SPWorkflowRunOptions runOptions)
此异步方法只有SP2010支持。
12)如果工作流设置成自动启动(Auto), 用StartWorkflowButton启动工作流时会报错。
首先搞清楚MOSS默认的工作流机制:工作流启动分3种模式:
1)手工启动--就是通过下拉菜单进入工作流启动页面启动
2)自动启动--创建一条Item后自动自动
3)当Item的某个字段值改变后启动
用了StartWorkflowButton时,StartWorkflowButton会调用moss api启动工作流,实际上是模拟手工启动
如果配置成自动自动,那么moss会自动启动一个工作流, StartWorkflowButton会再次启动一个工作流
而一个工作里是不能启动2次的,所以,StartWorkflowButton启动工作流的时候就出错了
所以,用了StartWorkflowButton,或用其他方式调用MOSS API启动工作流,工作流必须设置成手工启动(Manual)
13)SP10任务表单上的任务历史记录列表会显示一个复选框,如何取消?
修改任务列表的默认视图设置,取消:Allow individual item checkboxes 复选框
14)在QFD中新建了一个工作流变量,但是在活动属性绑定窗口或规则编辑窗口无法找到这个变量
点下保存按钮,将工作流保存下即可。
15)重新发布流程后,流程名称后面出现 (1)
问题原因:是因为老版本的QFD发布流程时流程配置文件的BaseID会变造成的
解决方法:升级到最新版本的QFD,然后用SharePoint Designer打开工作流文件夹,把.xoml.wfconfig.xml的除1.0版本和当前版本外的版本删除,
然后将最新版本.xoml.wfconfig.xml中的BaseID修改成和1.0版本一致),用QFD重新发布流程即可
16)如何控制WorkflowHistory/TaskList显示的字段
如果是在自定义任务表单中,可以通过WorkflowHistory控件的ViewFields控制,如:
<QFL:WorkflowHistory runat="server" ID="hisList" ShowTaskOfCurrentWorkflow="true"
ViewFields=""Title,AssignedTo, Status, Body, StartDate, WorkflowOutcome, DelegateFrom"/>
如果是想控制QF自带的TaskList页面,则到网站设置->网站栏管理,将需要显示的字段添加到QuickFlow组中即可。
17)RuleDriven/TaskWizard设置了超时规则,不起作用
1-重启iis,重启SharePoint Timer服务,重启服务器
2-设置定时job扫描间隔: stsadm -o setproperty -propertyname "job-workflow" -propertyvalue "every 2 minutes between 0 and 59" -url http://dc
18)采用VS+QF开发工作流时,若已经在生产环境部署,如何更新,才能保证老流程正常运行下去?
若只是修改了方法内部的代码,则正常更新dll或wsp即可。
若增删了活动或变量,则必须先手工备份老程序集,然后将程序集版本升版,更新新程序集或wsp,然后重新部署老程序集,确保新老程序集在gac中同时存在
see: http://spmat.blogspot.com/2010/11/assembly-versioning-for-sharepoint.html
19)若发布流程时报QuickFlow or SystemXXX没有授权
认真阅读安装指南,重新激活QuickFlow App Configuration功能