- Update workflow definition XAMLs (for example from version 1 to version 2).
- Allow currently running instances of workflow to finish running the version 1 of the workflow.
- New instances of workflow will run version 2 of the workflow. Version 1 of the workflow shouldn't be allowed to run any more.
There are some examples on how to update Workflow Manager workflows on MSDN but these examples are strictly tied to Workflow Manager platform, not Workflow Manager in combination with SharePoint 2013. My solution is based on aforementioned MSDN article but it is adapted to SharePoint 2013.
Prerequisite for my solution is at least one deploy of the workflow using either Visual Studio deploy or using PowerShell scripts. Workflow needs to be deployed as a part of the feature only first time.
For part 1 of this post I will demonstrate how to publish new versions of workflow using console application. I also presume you are developing on development box with Visual Studio installed. In part 2 I will focus on packaging the deployment in feature receiver.
- Create new console application (.NET 4.5) project
- Add the following references to the project (not all are needed, but I didn't filter out unneeded references):
- Add WorkflowManagementClientExtensions class to the project:
//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------ using Microsoft.Activities; using Microsoft.Activities.Messaging; using Microsoft.Workflow.Client; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading; namespace Microsoft.Workflow.Samples.Common { public static class WorkflowManagementClientExtensions { public static void PublishActivity(this WorkflowManagementClient client, string name, string xamlFilePath) { client.Activities.Publish( new ActivityDescription(WorkflowUtils.Translate(xamlFilePath)) { Name = name }); } public static void PublishWorkflow(this WorkflowManagementClient client, string workflowName, string xamlFilePath, SubscriptionFilter activationFilter = null) { PublishWorkflow(client, workflowName, xamlFilePath, null, null, activationFilter); } public static void PublishWorkflow(this WorkflowManagementClient client, string workflowName, string xamlFilePath, Collection<ExternalVariable> externalVariables, SubscriptionFilter activationFilter = null) { PublishWorkflow(client, workflowName, xamlFilePath, externalVariables, null, activationFilter); } public static void PublishWorkflow(this WorkflowManagementClient client, string workflowName, string xamlFilePath, IDictionary<string, string> configValues, SubscriptionFilter activationFilter = null) { PublishWorkflow(client, workflowName, xamlFilePath, null, configValues, activationFilter); } public static void PublishWorkflow(this WorkflowManagementClient client, string workflowName, string xamlFilePath, Collection<ExternalVariable> externalVariables, IDictionary<string, string> configValues, SubscriptionFilter activationFilter = null) { // publish the activity description related with the workflow client.Activities.Publish( new ActivityDescription(WorkflowUtils.Translate(xamlFilePath)) { Name = workflowName }); // now, publish the workflow description WorkflowDescription description = new WorkflowDescription { Name = workflowName, ActivityPath = workflowName, }; // add external variables if (externalVariables != null) { externalVariables .ToList() .ForEach(ev => description.ExternalVariables.Add(ev)); } // add config if (configValues != null) { description.Configuration = new WorkflowConfiguration(); configValues .ToList() .ForEach(c => description.Configuration.AppSettings.Add(c)); } // add activation filter if (activationFilter != null) { description.ActivationDescription = new SubscriptionActivationDescription { Filter = activationFilter }; } // publish! client.Workflows.Publish(description); } public static void CleanUp(this WorkflowManagementClient client) { client.CurrentScope.Delete(); } public static string WaitForWorkflowCompletion(this WorkflowManagementClient client, string workflowName, string instanceId, int pollingInterval = 0) { string currentStatus = string.Empty; string lastStatus = string.Empty; WorkflowInstanceInfo instanceInfo = client.Instances.Get(workflowName, instanceId); while (true) { instanceInfo = client.Instances.Get(workflowName, instanceId); currentStatus = instanceInfo.UserStatus; if (currentStatus != lastStatus && !string.IsNullOrWhiteSpace(currentStatus)) { Console.Write(" Current Status: "); WorkflowUtils.Print(currentStatus, ConsoleColor.Cyan); lastStatus = currentStatus; } if (instanceInfo.WorkflowStatus == WorkflowInstanceStatus.Started || instanceInfo.WorkflowStatus == WorkflowInstanceStatus.NotStarted) { Thread.Sleep(pollingInterval); continue; } if (instanceInfo.WorkflowStatus == WorkflowInstanceStatus.Completed) { Console.WriteLine("\nWorkflow instance completed"); } break; } return instanceInfo.UserStatus; } } }
- Add WorkflowUtils class to the project. Notice that Translate method is loading assembly from Visual Studio PublicAssemblies folder:
//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------ using System; using System.Text; using System.Xaml; using System.Xml; using System.Xml.Linq; using Microsoft.Activities.Design.ExpressionTranslation; using Microsoft.Workflow.Client; using System.Reflection; namespace Microsoft.Workflow.Samples.Common { public class WorkflowUtils { public static WorkflowManagementClient CreateForSample(string rootScope, string scopeName) { var rootClient = new WorkflowManagementClient(new Uri(rootScope)); return rootClient.CurrentScope.PublishChildScope(scopeName, new ScopeDescription() { UserComments = string.Format("For {0} sample only", scopeName) }); } public static XElement Translate(string xamlFile) { string translatedWorkflowString = null; Assembly wfAssembly = Assembly.LoadFile(@"C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\PublicAssemblies\Microsoft.SharePoint.DesignTime.Activities.dll"); XamlXmlReaderSettings settings = new XamlXmlReaderSettings(); settings.LocalAssembly = wfAssembly; using (XamlReader xamlReader = new XamlXmlReader(xamlFile, settings)) { TranslationResults result = ExpressionTranslator.Translate(xamlReader); if (result.Errors.Count == 0) { StringBuilder sb = new StringBuilder(); using (XmlWriter xmlWriter = XmlWriter.Create(sb, new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true })) { using (XamlXmlWriter writer = new XamlXmlWriter(xmlWriter, result.Output.SchemaContext)) { XamlServices.Transform(result.Output, writer); } } translatedWorkflowString = sb.ToString(); } else { throw new InvalidOperationException("Translation errors"); } } return XElement.Parse(translatedWorkflowString); } public static void PrintDone() { Print("[Done]", ConsoleColor.Green); } public static void Print(string message, ConsoleColor color) { ConsoleColor currentColor = Console.ForegroundColor; Console.ForegroundColor = color; Console.WriteLine(message); Console.ForegroundColor = currentColor; } } }
- Now you need to find out the GUID of the module which was used in deploying workflow (prerequisite). This GUID is located in the Module element, Url attribute in Elements.xml file in workflow folder. For example, in Elements.xml file:
<?xml version="1.0" encoding="utf-8" ?> <Elements xmlns="http://schemas.microsoft.com/sharepoint/"> <Module Name="Workflow1" Url="wfsvc/86c7e42d4fe14b839d55fcbb6dde7b9c"> <File Url="Workflow.xaml" Type="GhostableInLibrary" Path="Workflow1\Workflow.xaml" DoGUIDFixUp="TRUE"> <Property Name="ContentType" Value="WorkflowServiceDefinition" /> <Property Name="isReusable" Value="true" /> <Property Name="RequiresInitiationForm" Value="False" /> <Property Name="RequiresAssociationForm" Value="False" /> <Property Name="WSPublishState" Value="3" /> <Property Name="WSDisplayName" Value="Workflow1" /> <Property Name="WSDescription" Value="My 'Workflow1' Workflow" /> <!-- If you change the name or Url of your custom initiation or association form, remember to update the corresponding property value (InitiationUrl or AssociationUrl) to match the new web relative url. --> <Property Name="RestrictToType" Value="List" /> <Property Name="RestrictToScope" Value="{$ListId:Shared Documents;}" /> </File> <File Url="WorkflowStartAssociation" Path="Workflow1\WorkflowStartAssociation" Type="GhostableInLibrary"> <Property Name="WSDisplayName" Value="Workflow1 - Workflow Start" /> <Property Name="ContentType" Value="WorkflowServiceSubscription" /> <Property Name="WSPublishState" Value="3" /> <Property Name="WSEventType" Value="WorkflowStart" /> <Property Name="WSEnabled" Value="true" /> <Property Name="WSGUID" Value="19cbf8a6-4af8-462c-b014-c8d7c0e327c1" /> <Property Name="WSEventSourceGUID" Value="{$ListId:Shared Documents;}" /> <Property Name="Microsoft.SharePoint.ActivationProperties.ListId" Value="{$ListId:Shared Documents;}" /> <Property Name="HistoryListId" Value="{$ListId:Lists/WorkflowHistoryList;}" /> <Property Name="TaskListId" Value="{$ListId:Lists/WorkflowTaskList;}" /> </File> </Module> <ListInstance FeatureId="{2c63df2b-ceab-42c6-aeff-b3968162d4b1}" TemplateType="4501" Title="wfsvc" Description="This list instance is used by SharePoint to keep track of workflows. Do not modify." Url="wfsvc" RootWebOnly="FALSE" /> </Elements>
this GUID is 86c7e42d4fe14b839d55fcbb6dde7b9c. Remember this GUID, you will need it in the following step. - Now you need to query workflow resource management database to find out the scope path of your workflow. If you left database name with default value during configuration of workflow farm, this query should get you the scope path (replace the GUID in query with GUID from the previous step):
SELECT [Path]
FROM [WFResourceManagementDB].[dbo].[Scopes] s
join [WFResourceManagementDB].[dbo].[Activities] a on s.ScopeId = a.ScopeId
where a.Name = 'WorkflowXaml_86c7e42d_4fe1_4b83_9d55_fcbb6dde7b9c' - Now it's time to change x:Class attribute in the workflow.xaml file. Last token in the attribute should contain GUID from step 5. For example: x:Class="In2.Ilas.Sp.Ecase.PukWf.WorkflowXaml_ed00d3bd_4796_41ba_b288_35ce2226f89a"
- Finally, console application should have the following code (replace the path from step 6 and workflow name from step 5):
using Microsoft.SharePoint; using Microsoft.SharePoint.Client; using Microsoft.SharePoint.Client.WorkflowServices; using Microsoft.Workflow.Client; using Microsoft.Workflow.Samples.Common; using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; using System.Net; using System.Text; using System.Threading.Tasks; using System.Linq; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { WorkflowManagementClient client = new WorkflowManagementClient("http://zg-sp2013-02:12291/SharePoint/default/030e8465-c66c-4f9f-83af-e64d5a4a799b/61aa1fff-103e-49c8-bc56-395c27ca7f81"); client.Activities.Publish(new ActivityDescription(WorkflowUtils.Translate("Workflow.xaml")) { Name = "WorkflowXaml_ed00d3bd_4796_41ba_b288_35ce2226f89a" }); } } }
- Copy Workflow.xaml file to console application's folder.
- Run the application.
Complete solution is available for download.
List of types in C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\PublicAssemblies\Microsoft.SharePoint.DesignTime.Activities.dll assembly:
namespace Microsoft.SharePoint.DesignTime.Activities { [ComVisible(false)] public class AppOnlySequence : Activity, ISupportInitialize [ComVisible(false)] public class AtomicTaskItemUpdatedHelper : Activity, ISupportInitialize [ComVisible(false)] public class BuildSPListItemWebLink : Activity<string>, ISupportInitialize [ComVisible(false)] public class BuildSPUri : Activity<string>, ISupportInitialize [ComVisible(false)] public class Calc : Activity, ISupportInitialize [ComVisible(false)] public class CallHTTPWebService : Activity, ISupportInitialize [ComVisible(false)] public class CheckInItem : Activity, ISupportInitialize [ComVisible(false)] public class CheckOutItem : Activity, ISupportInitialize [ComVisible(false)] public class Comment : Activity, ISupportInitialize [ComVisible(false)] public class CompositeTask : Activity, ISupportInitialize [ComVisible(false)] public class CompositeTaskHelper : Activity<bool>, ISupportInitialize [ComVisible(false)] public class ConvertPropertiesForSPListItem : Activity, ISupportInitialize [ComVisible(false)] public class ConvertTimeZoneFromSPLocalToUtc : Activity<DateTime>, ISupportInitialize [ComVisible(false)] public class ConvertTimeZoneFromUtcToSPLocal : Activity<DateTime>, ISupportInitialize [ComVisible(false)] public class CopyItem : Activity, ISupportInitialize [ComVisible(false)] public class CreatedBy : Activity<bool>, ISupportInitialize [ComVisible(false)] public class CreatedInRange : Activity<bool>, ISupportInitialize [ComVisible(false)] public class CreateListItem : Activity<Guid>, ISupportInitialize [ComVisible(false)] public class DateInterval : Activity<double>, ISupportInitialize [ComVisible(false)] public class DefaultRetryPolicy : Activity, ISupportInitialize [ComVisible(false)] public class DelayFor : Activity, ISupportInitialize [ComVisible(false)] public class DelayUntil : Activity, ISupportInitialize [ComVisible(false)] public class DeleteListItem : Activity, ISupportInitialize [ComVisible(false)] public class Email : Activity, ISupportInitialize [ComVisible(false)] public class ExpandGroupToUsers : Activity<Collection<string>>, ISupportInitialize [ComVisible(false)] public class ExpandInitFormUsers : Activity<Collection<string>>, ISupportInitialize [ComVisible(false)] public class ExtractSubstringFromEnd : Activity<string>, ISupportInitialize [ComVisible(false)] public class ExtractSubstringFromIndex : Activity<string>, ISupportInitialize [ComVisible(false)] public class ExtractSubstringFromIndexLength : Activity<string>, ISupportInitialize [ComVisible(false)] public class ExtractSubstringFromStart : Activity<string>, ISupportInitialize [ComVisible(false)] public class GenerateEmailDynamicValue : Activity<DynamicValue>, ISupportInitialize [ComVisible(false)] public class GetCurrentItemGuid : Activity<Guid>, ISupportInitialize [ComVisible(false)] public class GetCurrentItemId : Activity<int>, ISupportInitialize [ComVisible(false)] public class GetCurrentListId : Activity<Guid>, ISupportInitialize [ComVisible(false)] public class GetHistoryListId : Activity<Guid>, ISupportInitialize [ComVisible(false)] public class GetItemIdInCache : Activity<bool>, ISupportInitialize [ComVisible(false)] public class GetTaskListId : Activity<Guid>, ISupportInitialize [ComVisible(false)] public class IsNull : Activity<bool>, ISupportInitialize [ComVisible(false)] public class IsSPListItemPropertyLookupToDocsField : Activity<bool>, ISupportInitialize [ComVisible(false)] public class IsValidUser : Activity<bool>, ISupportInitialize [ComVisible(false)] public class JoinChoicesFromSPFieldMultiChoice : Activity<string>, ISupportInitialize [ComVisible(false)] public class JoinIdOrValueFromSPFieldLookupMulti : Activity<string>, ISupportInitialize [ComVisible(false)] public class JoinSiteUserInfoListPropertyFromSPFieldUserMulti : Activity<string>, ISupportInitialize [ComVisible(false)] public class JoinSPPrincipalPropertyFromInitFormParamUserMulti : Activity<string>, ISupportInitialize [ComVisible(false)] public class LookupSPChoiceFieldIndex : Activity<int>, ISupportInitialize [ComVisible(false)] public class LookupSPField : Activity<DynamicValue>, ISupportInitialize [ComVisible(false)] public class LookupSPFields : Activity<DynamicValue>, ISupportInitialize [ComVisible(false)] public class LookupSPGroup : Activity<DynamicValue>, ISupportInitialize [ComVisible(false)] public class LookupSPGroupMembers : Activity<DynamicValue>, ISupportInitialize [ComVisible(false)] public class LookupSPList : Activity<DynamicValue>, ISupportInitialize [ComVisible(false)] public class LookupSPListItem : Activity<DynamicValue>, ISupportInitialize [ComVisible(false)] public class LookupSPListItemBooleanProperty : Activity<bool>, ISupportInitialize [ComVisible(false)] public class LookupSPListItemDateTimeProperty : Activity<DateTime>, ISupportInitialize [ComVisible(false)] public class LookupSPListItemDoubleProperty : Activity<double>, ISupportInitialize [ComVisible(false)] public class LookupSPListItemDynamicValueProperty : Activity<DynamicValue>, ISupportInitialize [ComVisible(false)] public class LookupSPListItemGuid : Activity<Guid>, ISupportInitialize [ComVisible(false)] public class LookupSPListItemId : Activity<int>, ISupportInitialize [ComVisible(false)] public class LookupSPListItemInt32Property : Activity<int>, ISupportInitialize [ComVisible(false)] public class LookupSPListItemProperty : Activity<DynamicValue>, ISupportInitialize [ComVisible(false)] public class LookupSPListItemPropertyNameInREST : Activity<string>, ISupportInitialize [ComVisible(false)] public class LookupSPListItemSPFieldLookupMultiProperty : Activity<DynamicValue>, ISupportInitialize [ComVisible(false)] public class LookupSPListItemSPFieldLookupProperty : Activity<DynamicValue>, ISupportInitialize [ComVisible(false)] public class LookupSPListItemStringProperty : Activity<string>, ISupportInitialize [ComVisible(false)] public class LookupSPListProperty : Activity<DynamicValue>, ISupportInitialize [ComVisible(false)] public class LookupSPPrincipal : Activity<DynamicValue>, ISupportInitialize [ComVisible(false)] public class LookupSPPrincipalId : Activity<int>, ISupportInitialize [ComVisible(false)] public class LookupSPPrincipalProperty : Activity<string>, ISupportInitialize [ComVisible(false)] public class LookupSPTaskAssignedToDisplayName : Activity<string>, ISupportInitialize [ComVisible(false)] public class LookupSPTaskListItemAssignedTo : Activity<Collection<string>>, ISupportInitialize [ComVisible(false)] public class LookupSPUser : Activity<DynamicValue>, ISupportInitialize [ComVisible(false)] public class LookupSPUserProperty : Activity<string>, ISupportInitialize [ComVisible(false)] public class LookupWorkflowContextProperty : Activity<string>, ISupportInitialize [ComVisible(false)] public class LoopNTimes : Activity, ISupportInitialize [ComVisible(false)] public class ModifiedBy : Activity<bool>, ISupportInitialize [ComVisible(false)] public class ModifiedInRange : Activity<bool>, ISupportInitialize [ComVisible(false)] public class RegisterForSharePointEvent : Activity, ISupportInitialize [ComVisible(false)] public class ReplaceEmailTokens : Activity<string>, ISupportInitialize [ComVisible(false)] public class RetryForDurationPolicy : Activity, ISupportInitialize [ComVisible(false)] public class SetField : Activity, ISupportInitialize [ComVisible(false)] public class SetItemIdInCache : Activity, ISupportInitialize [ComVisible(false)] public class SetRelatedItem : Activity, ISupportInitialize [ComVisible(false)] public class SetTimeField : Activity<DateTime>, ISupportInitialize [ComVisible(false)] public class SetWorkflowStatus : Activity, ISupportInitialize [ComVisible(false)] public class SingleTask : Activity, ISupportInitialize [ComVisible(false)] public class TranslateDocument : Activity, ISupportInitialize [ComVisible(false)] public class UndoCheckOutItem : Activity, ISupportInitialize [ComVisible(false)] public class UpdateListItem : Activity, ISupportInitialize [ComVisible(false)] public class WaitForCustomEvent : Activity<string>, ISupportInitialize [ComVisible(false)] public class WaitForFieldChange : Activity, ISupportInitialize [ComVisible(false)] public class WaitForItemEvent : Activity, ISupportInitialize [ComVisible(false)] public class WebUri : Activity<string>, ISupportInitialize [ComVisible(false)] public class WordsInTitle : Activity<bool>, ISupportInitialize [ComVisible(false)] public class WorkflowInterop : Activity<Guid>, ISupportInitialize [ComVisible(false)] public class WriteToHistory : Activity, ISupportInitialize } namespace Microsoft.SharePoint.DesignTime.Activities.Expressions { [ComVisible(false)] public class ContainsStringIgnoreCase : Activity<bool>, ISupportInitialize [ComVisible(false)] public class IsEqualDate : Activity<bool>, ISupportInitialize [ComVisible(false)] public class IsEqualDateTime : Activity<bool>, ISupportInitialize [ComVisible(false)] public class IsEqualDynamicValue : Activity<bool>, ISupportInitialize [ComVisible(false)] public class IsEqualStringIgnoreCase : Activity<bool>, ISupportInitialize [ComVisible(false)] public class IsEqualUser : Activity<bool>, ISupportInitialize [ComVisible(false)] public class IsGreaterThanDateTime : Activity<bool>, ISupportInitialize [ComVisible(false)] public class IsGreaterThanOrEqualDateTime : Activity<bool>, ISupportInitialize [ComVisible(false)] public class IsLessThanDateTime : Activity<bool>, ISupportInitialize [ComVisible(false)] public class IsLessThanOrEqualDateTime : Activity<bool>, ISupportInitialize [ComVisible(false)] public class MatchesString : Activity<bool>, ISupportInitialize } namespace XamlStaticHelperNamespace { [GeneratedCode("XamlBuildTask", "4.0.0.0")] internal class _XamlStaticHelper }
In step 7 you write about GUID from step 4, but there is no GUID in step 4. Or do you mean step 5 (which means that in step 6 and 7 you use the same GUID)?
ReplyDeleteAnd what if my x:Class attributes in xaml files do not contain GUIDs, but are just type names (I have 4 workflows in a project, none has GUID in x:class)?
oh wait, or do you mean that I should add GUID to the name?
DeleteYou're right, I've updated the post accordingly.
DeleteYes, you should add GUID to the name.
Also, in step 6 when executing this SELECT I get 8 rows, 4 with first path, and another 4 with a second path. By selecting also date modified, I see that they were created in 2 different times, months apart. So, which Path should I choose? The most recent one?
ReplyDeleteThis probably means that you have your workflow deployed to multiple site collections. Modify the SELECT query to include all columns (SELECT * ...) and try to figure out in which workflow scope you need an update.
DeleteIndeed, in the Scopes table there is DefaultWorkflowConfiguration column which contains XML having all settings specific to site, for example:
DeleteMicrosoft.SharePoint.ActivationProperties.WebUrl
http://xxxxxx:99/
one can easily filter by this column. Thanks alot!
I am running into exception during XAML translate, do you know what that may be? So the type is unknown, but I am at loss how to fix this. I have references to all mentioned .Activities dlls.
ReplyDeleteUnhandled Exception: System.Xaml.XamlObjectWriterException: Cannot create unknown type '{http://schemas.microsoft.com/netfx/2009/xaml/activities}Variable({http://schemas.microsoft.com/workflow/2012/07/xaml/activities}DynamicValue)'.
at System.Xaml.XamlObjectWriter.WriteStartObject(XamlType xamlType)
at System.Xaml.XamlWriter.WriteNode(XamlReader reader)
at System.Xaml.XamlServices.Transform(XamlReader xamlReader, XamlWriter xamlW
riter, Boolean closeWriter)
at System.Xaml.XamlServices.Load(XamlReader xamlReader)
at Microsoft.Activities.Design.ExpressionTranslation.ExpressionTranslator.Get
RootObject(XamlReader reader, Boolean useInvariantCulture)
at Microsoft.Activities.Design.ExpressionTranslation.ExpressionTranslator.Try
GetActivitySourceInfoAndExpressionLanguage(XamlReader inputXamlReader, Object& r
ootObject, Activity& rootActivity, String& expressionLanguage, Dictionary`2& act
ivitySourceInformation, List`1& translationErrors)
at Microsoft.Activities.Design.ExpressionTranslation.ExpressionTranslator.Tra
nslateInternal(XamlReader inputXamlReader, String localAssemblyPath, String comp
iledExpressionRootTypeName)
at Microsoft.Activities.Design.ExpressionTranslation.ExpressionTranslator.Tra
nslate(XamlReader input)
at Microsoft.Workflow.Samples.Common.WorkflowUtils.Translate(String xamlFile)
Yes, I had the same error. That's why I added a line:
DeleteAssembly wfAssembly = Assembly.LoadFile(@"C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\PublicAssemblies\Microsoft.SharePoint.DesignTime.Activities.dll");
Are you sure you didn't modify the original code?
Yes I did, since I have VS2013 I have modified the path to '\Microsoft Visual Studio 12.0\', the dll (version 12.0.40814.0) is in the new path.
DeleteOr perhaps there is some other difference between versions?
I have added list of types in aforementioned assembly at the end of the post so you can compare it with VS 2013 assemply.
Deletethe types are exactle the same here and there.
Deletethere must be something else.
perhaps you could share your VS project, so I could dig into the differences?
DeleteSure. I've added the link for download in the post.
DeleteI have updated guids and paths from your project to mine, copied in my workflow.xaml, updated path to DLL from VS 11.0 to 12.0, and it worked.
DeleteI have no clue what the difference is, but it works.
Unfortunately now I get the following exception:
DeleteAn unhandled exception of type 'Microsoft.Workflow.Client.WorkflowManagementException' occurred in Microsoft.Workflow.Client.dll
Additional information: The name 'Workflow_9afb150d_0d85_4a1e_9887_9580f0038c90' of the x:Class attribute does not match the activity name 'WorkflowXaml_9afb150d_0d85_4a1e_9887_9580f0038c90'. Either specify the activity name or use the overwriteXClass argument to overwrite the value of the x:Class attribute for the XAML content. HTTP headers received from the server - ActivityId: 6bdf4237-c474-45d8-915d-84498aa83e8e. NodeId: SHP1D. Scope: /SharePoint/default/4a00fd73-dc0c-4e9c-940c-1a160197646a/7cedcde7-9265-442d-b156-eacbdb58c7e6. Client ActivityId : d6a2554d-622f-40e7-af9b-b234f7923aa2.
OK, so I have used this overload:
Deleteclient.Activities.Publish(new ActivityDescription(WorkflowUtils.Translate("Workflow1.xaml")) { Name = "WorkflowXaml_9afb150d_0d85_4a1e_9887_9580f0038c90" }, true, false);
and it worked.
..and another problem. during execution workflow gets suspended with the following exception:
DeleteSystem.FormatException: Expected hex 0x in '{0}'. at System.Guid.GuidResult.SetFailure(ParseFailureKind failure, String failureMessageID, Object failureMessageFormatArgument) at System.Guid.TryParseGuidWithHexPrefix(String guidString, GuidResult& result) at System.Guid.TryParseGuid(String g, GuidStyles flags, GuidResult& result) at System.Guid.Parse(String input) at System.Activities.CodeActivity`1.InternalExecute(ActivityInstance instance, ActivityExecutor executor, BookmarkManager bookmarkManager) at System.Activities.Runtime.ActivityExecutor.ExecuteActivityWorkItem.ExecuteBody(ActivityExecutor executor, BookmarkManager bookmarkManager, Location resultLocation)
OK, I have updated all $ListId tokens to static GUIDs, and now it works fine.
DeleteThanks for all the help!
Glad everything worked for you.
DeleteThis comment has been removed by the author.
ReplyDeletewhat do you think about this approach:
ReplyDeletehttp://sp2013workflows.blogspot.ru/2014/06/update-workflow-definition-in.html
It's interesting, but I think all workflow instances will be terminated if you use that approach. My goal was to allow currently running instances to finish using 'old' WF definition.
DeleteThis approach seems to be working. Old instances continue to run. I'll evaluate it a little bit more, but it seems to be working.
DeleteIn the end it has turned out to be a disaster. I have prepared the package to be run on production environment, but missed some needed dlls. The app crashed with the FileNotFoundException when trying to access Microsoft.Activities.Design.dll. Short time later workflow manager crashed with error:
ReplyDeleteFaulting application name: Microsoft.Workflow.ServiceHost.exe, version: 1.0.40131.0, time stamp: 0x52ef34e1
Faulting module name: KERNELBASE.dll, version: 6.3.9600.18007, time stamp: 0x55c4c341
Exception code: 0xe0434352
Fault offset: 0x000000000000871c
Faulting process id: 0xca8
Faulting application start time: 0x01d12d3cf0cd0f82
Faulting application path: C:\Program Files\Workflow Manager\1.0\Workflow\Artifacts\Microsoft.Workflow.ServiceHost.exe
Faulting module path: C:\Windows\system32\KERNELBASE.dll
Report Id: f761b77d-9930-11e5-80c6-0050568c1167
Faulting package full name:
Faulting package-relative application ID:
Then something else crashed (not sure yet what and why), it seems that it's the DB server (?), because now I'm flooded with errors of no connection to SQL Server. Workflow manager now crashes repeatedly.
I have no clue what to do, everything went fine on dev environment, and now this is a disaster.
Sorry to hear that, I suppose you don't have staging (UAT) environment?
DeleteTry to reregister SpWorkflowService: Register-SPWorkflowService -SPSite "http:// SP2013DEV01/" -WorkflowHostUri "http:// SP2013DEV01:12291/" - AllowOAuthHttp -Force -ScopeName "SharePoint"
Unfortunately no. It turns out that after getting the database up and services running, all started to work fine. Weird.
DeleteThanks for all the help but yet another problem, perhaps you can help: I have added custom activity (declarative) to the workflow, now I am getting 'System.Xaml.XamlObjectWriterException'. Additional information: Cannot create unknown type XXXXXXXXX.
ReplyDeleteOK so the type is declared in another xaml. I could use the assembly generated during project build and specify it, but the LocalAssembly property can have only assembly, and that's Microsoft.SharePoint.DesignTime.Activities.dll. How to specify another one?
I don't have custom activities in my project so I cannot say what the issue might be. Just by googling I stumbled upon this:
DeleteOpen source code of the activity. Change "xmlns:local="clr-namespace:DeclarativeServiceLibrary1" to xmlns:local="clr-namespace:DeclarativeServiceLibrary1;assembly=DeclarativeServiceLibrary1".
Source: http://stackoverflow.com/questions/2330762/wf4-rc-cannot-create-unknown-type-when-loading-wf-service-from-loose-xaml-with
thanks for googling this for me, unfortunately after adding this i'm still left with the same error
DeleteI'm sorry, I didn't have such a scenario.
DeleteI used custom activities as well in the past but have found that web service calls are much more flexible.
Web service calls won't help me. I am having problems with WaitForFieldChange activity - it doesn't detect changes on some lists&fields. Custom activity was a replacement, based upon WaitForItemEvent it would detect change and return new field value.
ReplyDeleteBut in the end I can simply add the code from the activity into main WF, it will mess it up a bit, but not much.
It is ok as long as you have a valid workaround :)
DeleteThank you for your solution. I can't find part 2
ReplyDeletePart 2 was supposed to be integration into feature receiver so that definitions update automatically during feature activation but in the end we stuck with setting ReplaceContent="TRUE" attribute on File element in workflow's Elements.xml file.
Delete