• QuickFlow教程(15)常见问题释疑


    本文将针对QuickFlow开发人员经常碰到的问题做一个集中的解释。

    1)QuickFlow是什么

    QuickFlow是基于SharePoint(2007,2010)的一个工作流设计工具,它包含一个核心的Flowchart流程模型和一个无代码设计器。基于QuickFlow开发SharePoint工作流和直接在SharePoint上开发工作流很类似,使用Quickflow前最好了解下默认的SharePoint工作流是如何开发和运行的。

    更多细节,参见:http://cid-7f5a25cdf47d03e6.office.live.com/view.aspx/QuickFlow/Docs/QuickFlow2.0%E7%99%BD%E7%9A%AE%E4%B9%A6.docx

    2)QuickFlow如何安装

    QuickFlow的安装包含两部分:一部分是一个wsp的解决方案,这个解决方案中,包括所有dll文件和页面文件,这个wsp分两个版本:一个用于SharePoint2007,一个用户SharePoint2010。另外一部分是设计器,设计器无需安装,直接解压后即可打开exe文件,需要指出的是,当前版本的设计器只能在SharePoint服务器上运行。

    详细见:http://cid-7f5a25cdf47d03e6.office.live.com/view.aspx/QuickFlow/Docs/QuickFlow%E5%AE%89%E8%A3%85%E6%8C%87%E5%8D%97.docx

    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

     3- 参考:http://www.dev4side.com/community/blog/2010/12/1/bug-using-delay-activity-on-sharepoint-2010-workflow.aspx

     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功能

  • 相关阅读:
    大数据下的质量体系建设
    快速打造属于你的接口自动化测试框架
    测试环境问题排查的那些事儿
    100个任务,用多机实现
    shell 在一个文件中查找数字
    shell中的awk使用
    shell怎么实现多进程
    删除字符串S1中的子串S2
    C++11的新特性
    C++里面普通指针怎么转换成智能指针
  • 原文地址:https://www.cnblogs.com/jianyi0115/p/2078774.html
Copyright © 2020-2023  润新知