Tag Archives: Workflow

SharePoint 2013 List Item Save Timeout

I received a report from a colleague today that he was getting timeout errors after clicking the save button on a list item edit form. Initial testing of web head performance showed no issues and the ULS log only reported timing out during the save.

Taking a deeper look, we established that the list in question had a custom 2013 workflow attached – aha! At the same time, OOTB publish workflows were taking longer than usual to complete.

Next step, we checked on the Workflow Manager log in the event view on each of the machines in our Workflow Manager farm. Lo and behold, we found a critical issue with connecting to the Service Bus on one of the servers. Turned out that all three service bus services were stopped. In checking the other two servers in the Workflow Manager quorum, they too showed stopped SB services.

My guess is that IT had rolled out a patch for Service Bus and not checked to see if the services restarted on each affected server. I believe Microsoft recently released a patch for Service Bus, which may or may not require a server reboot, which could account for the services having stopped and not restarted (expected after a reboot).

So, there you have it, if you come across these symptoms, check your workflow.

Install Workflow Manager with PowerShell

By default, SharePoint 2013 on-premises installation includes the legacy SharePoint 2010 workflow engine only. To take advantage of Workflow 2013 you must install Workflow Manager. You can achieve this by installing Workflow Manager with the Web Platform Installer and then configure with the Workflow Manager Configuration Wizard. I have recently cobbled together my own SharePoint 2013 configuration scripts to setup SharePoint 2013 on-prem – soup to nuts – with Powershell. In keeping with this same theme, this blog post details the script required to install and configure Workflow Manager.

First things first, Workflow Manager is a separate installation from SharePoint, available on the web. I used the latest version of the Web Platform Installer to pull down the files. I had to install WPI first.

With WPI installed, open an elevated console and run the following command:

webpicmd /offline /Products:WorkflowManagerRefresh /Path:c:WorkflowManagerFiles

We now have the Workflow Manager installation files in c:WorkflowManagerFiles. Installing WFM is a simple case of running the following command:

WebpiCmd.exe /Install /Products:WorkflowManagerRefresh /XML:c:/WorkflowManagerFiles/feeds/latest/webproductlist.xml

Note: Make sure you install the ‘Refresh’ of WFM if installing on Windows Server 2012 R2. Installing the original 1.0 version causes issues when registering WFM with SharePoint 2013. I strongly recommend patching SharePoint 2013 to SP1.

After completing the installation, Workflow Manager launches the configuration wizard. You can use the wizard WFM if you like and need do no more, but if you want to see the juicy script that the wizard generates, then read on.

The following is my complete script to configure a WFM farm – it’s a simple configuration. For those interested, Spencer Harbar has a series of good posts on configuring load balanced WFM: http://www.harbar.net/articles/wfm2.aspx.

function WFM-Configure {
    # Create new SB Farm
    $SBCertificateAutoGenerationKey = ConvertTo-SecureString -AsPlainText  -Force  -String $passphrase;
    $WFCertAutoGenerationKey = ConvertTo-SecureString -AsPlainText  -Force  -String $passphrase;
    $managementCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFMSB_Management;Integrated Security=True;Encrypt=False';
    $gatewayCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFMSB_Gateway;Integrated Security=True;Encrypt=False';
    $messageContCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFMSB_MessageContainer;Integrated Security=True;Encrypt=False';
    Write-Host -ForegroundColor White ' - Creating new Service Bus farm...' -NoNewline;
    try {
        $sbFarm = Get-SBFarm -SBFarmDBConnectionString $managementCS;
        Write-Host -ForegroundColor White 'Already Exists';
    }
    catch {
        New-SBFarm -SBFarmDBConnectionString $managementCS -InternalPortRangeStart 9000 -TcpPort 9354 -MessageBrokerPort 9356 -RunAsAccount $spServiceAcctName `
            -AdminGroup 'BUILTINAdministrators' -GatewayDBConnectionString $gatewayCS -CertificateAutoGenerationKey $SBCertificateAutoGenerationKey `
            -MessageContainerDBConnectionString $messageContCS;
        Write-Host -ForegroundColor White 'Done';
    }
    # Create new WF Farm
    Write-Host -ForegroundColor white " - Creating new Workflow Farm..." -NoNewline;
    $wfManagementCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFM_Management;Integrated Security=True;Encrypt=False';
    $wfInstanceCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFM_InstanceManagement;Integrated Security=True;Encrypt=False';
    $wfResourceCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFM_ResourceManagement;Integrated Security=True;Encrypt=False';
    try {
        $wfFarm = Get-WFFarm -WFFarmDBConnectionString $wfManagementCS;
        Write-Host -ForegroundColor White 'Already Exists';
    }
    catch {
        New-WFFarm -WFFarmDBConnectionString $wfManagementCS -RunAsAccount $spServiceAcctName -AdminGroup 'BUILTINAdministrators' -HttpsPort 12290 -HttpPort 12291 `
            -InstanceDBConnectionString $wfInstanceCS -ResourceDBConnectionString $wfResourceCS -CertificateAutoGenerationKey $WFCertAutoGenerationKey;
        Write-Host -ForegroundColor white 'Done';
    }
    # Add SB Host
    Write-Host -ForegroundColor white ' - Adding Service Bus host...' -NoNewline;
    try {
        $SBRunAsPassword = ConvertTo-SecureString -AsPlainText  -Force  -String $spServiceAcctPwd;
        Add-SBHost -SBFarmDBConnectionString $managementCS -RunAsPassword $SBRunAsPassword -EnableHttpPort `
            -EnableFirewallRules $true -CertificateAutoGenerationKey $SBCertificateAutoGenerationKey;
        Write-Host -ForegroundColor white 'Done';
    } 
    catch {
        Write-Host -ForegroundColor white 'Already Exists';
    }
    Write-Host -ForegroundColor white ' - Creating Workflow Default Namespace...' -NoNewline;
    $sbNamespace = $dbPrefix + '-WorkflowNamespace';
    try {
        $defaultNS = Get-SBNamespace -Name $sbNamespace -ErrorAction SilentlyContinue;
        Write-Host -ForegroundColor white 'Already Exists';
    }
    catch {
        try {
            # Create new SB Namespace
            $currentUser = $env:userdomain + '' + $env:username;
            New-SBNamespace -Name $sbNamespace -AddressingScheme 'Path' -ManageUsers $spServiceAcctName,$spAdminAcctName,$currentUser;
            Start-Sleep -s 90
            Write-Host -ForegroundColor white 'Done';
        }
        catch [system.InvalidOperationException] {
            throw;
        }
    }
    # Get SB Client Configuration
    $SBClientConfiguration = Get-SBClientConfiguration -Namespaces $sbNamespace;
    # Add WF Host
    try {
        $WFRunAsPassword = ConvertTo-SecureString -AsPlainText  -Force  -String $spServiceAcctPwd;
        Write-Host -ForegroundColor White ' - Adding Workflow Host...' -NoNewline;
        Add-WFHost -WFFarmDBConnectionString $wfManagementCS `
        -RunAsPassword $WFRunAsPassword -EnableFirewallRules $true `
        -SBClientConfiguration $SBClientConfiguration -CertificateAutoGenerationKey $WFCertAutoGenerationKey;
        Write-Host -ForegroundColor White 'Done';
    }
    catch {
        Write-Host -ForegroundColor white "Already Exists";
    }
}

Let’s break the script down a little. I should mention that cutting and pasting my script into your Powershell window won’t work to start because the script assumes the existence of a few predefined variables, as follows:

  • $dbServer – SQL Alias for my SQL server (best to use an alias not the server name)
  • $dbPrefix – Prefix for all my database names
  • $spServiceAcctName – Name of my service account (used for workflow manager)
  • $spServiceAcctPWD – Password for my service account
  • $spAdminAcct – Admin account for SharePoint
  • $passphrase – Passphrase used by WFM when joining new hosts to the farm

WFM consists of two parts – the Service Bus and the Workflow Engine. To start with, my script creates a new Service Bus Farm…

$SBCertificateAutoGenerationKey = ConvertTo-SecureString -AsPlainText  -Force  -String $passphrase;
    $WFCertAutoGenerationKey = ConvertTo-SecureString -AsPlainText  -Force  -String $passphrase;
    $managementCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFMSB_Management;Integrated Security=True;Encrypt=False';
    $gatewayCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFMSB_Gateway;Integrated Security=True;Encrypt=False';
    $messageContCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFMSB_MessageContainer;Integrated Security=True;Encrypt=False';
    Write-Host -ForegroundColor White ' - Creating new Service Bus farm...' -NoNewline;
    try {
        $sbFarm = Get-SBFarm -SBFarmDBConnectionString $managementCS;
        Write-Host -ForegroundColor White 'Already Exists';
    }
    catch {
        New-SBFarm -SBFarmDBConnectionString $managementCS -InternalPortRangeStart 9000 -TcpPort 9354 -MessageBrokerPort 9356 -RunAsAccount $spServiceAcctName `
            -AdminGroup 'BUILTINAdministrators' -GatewayDBConnectionString $gatewayCS -CertificateAutoGenerationKey $SBCertificateAutoGenerationKey `
            -MessageContainerDBConnectionString $messageContCS;
        Write-Host -ForegroundColor White 'Done';
    }

Notice that my script does some checking and error control so that I can run this script multiple times without it causing error because of pre-configuration. OK, now to the Workflow Farm…

Write-Host -ForegroundColor white " - Creating new Workflow Farm..." -NoNewline;
    $wfManagementCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFM_Management;Integrated Security=True;Encrypt=False';
    $wfInstanceCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFM_InstanceManagement;Integrated Security=True;Encrypt=False';
    $wfResourceCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFM_ResourceManagement;Integrated Security=True;Encrypt=False';
    try {
        $wfFarm = Get-WFFarm -WFFarmDBConnectionString $wfManagementCS;
        Write-Host -ForegroundColor White 'Already Exists';
    }
    catch {
        New-WFFarm -WFFarmDBConnectionString $wfManagementCS -RunAsAccount $spServiceAcctName -AdminGroup 'BUILTINAdministrators' -HttpsPort 12290 -HttpPort 12291 `
            -InstanceDBConnectionString $wfInstanceCS -ResourceDBConnectionString $wfResourceCS -CertificateAutoGenerationKey $WFCertAutoGenerationKey;
        Write-Host -ForegroundColor white 'Done';
    }

With both Service Bus and Workflow farms created, it’s time to create a Service Bus host and a Workflow Management Host. WFM adopts a similar architecture to ADFS and SharePoint in that a farm consists of one or many hosts. The more hosts the better availability of service with network load balancing.

Here’s the part script to create a new Service Bus Host…

Write-Host -ForegroundColor white ' - Adding Service Bus host...' -NoNewline;
    try {
        $SBRunAsPassword = ConvertTo-SecureString -AsPlainText  -Force  -String $spServiceAcctPwd;
        Add-SBHost -SBFarmDBConnectionString $managementCS -RunAsPassword $SBRunAsPassword `
            -EnableFirewallRules $true -CertificateAutoGenerationKey $SBCertificateAutoGenerationKey;
        Write-Host -ForegroundColor white 'Done';
    } 
    catch {
        Write-Host -ForegroundColor white 'Already Exists';
    }
    Write-Host -ForegroundColor white ' - Creating Workflow Default Namespace...' -NoNewline;
    $sbNamespace = $dbPrefix + '-WorkflowNamespace';
    try {
        $defaultNS = Get-SBNamespace -Name $sbNamespace -ErrorAction SilentlyContinue;
        Write-Host -ForegroundColor white 'Already Exists';
    }
    catch {
        try {
            # Create new SB Namespace
            $currentUser = $env:userdomain + '' + $env:username;
            New-SBNamespace -Name $sbNamespace -AddressingScheme 'Path' -ManageUsers $spServiceAcctName,$spAdminAcctName,$currentUser;
            Start-Sleep -s 90
            Write-Host -ForegroundColor white 'Done';
        }
        catch [system.InvalidOperationException] {
            throw;
        }
    }

…and finally, we create the Workflow Manager host…

$SBClientConfiguration = Get-SBClientConfiguration -Namespaces $sbNamespace;
    # Add WF Host
    try {
        $WFRunAsPassword = ConvertTo-SecureString -AsPlainText  -Force  -String $spServiceAcctPwd;
        Write-Host -ForegroundColor White ' - Adding Workflow Host...' -NoNewline;
        Add-WFHost -WFFarmDBConnectionString $wfManagementCS `
        -RunAsPassword $WFRunAsPassword -EnableFirewallRules $true -EnableHttpPort `
        -SBClientConfiguration $SBClientConfiguration -CertificateAutoGenerationKey $WFCertAutoGenerationKey;
        Write-Host -ForegroundColor White 'Done';
    }
    catch {
        Write-Host -ForegroundColor white "Already Exists";
    }

At this point, we’ve completed configuration of Workflow Manager, but we’re not quite finished with configuration yet. We need to tell SharePoint about the existence of the WFM farm, which involves installing WFM client on each SharePoint server (you don’t need to install the client if you have installed the WFM on a SharePoint server). Ideally, your WFM farm is independent of SharePoint (servers and databases), but for test purposes you can install the whole lot on one server.

Let’s make sure WFM is working before we configure SharePoint. Open a browser to the following location…

http://WFM-server-name:12291

You should see some XML returned from the service (you may need to run IE as admin for this to work).

<ScopeInfo xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/workflow/2012/xaml/activities">
  <DefaultWorkflowConfiguration /> 
  <Description>Root Scope</Description> 
  <LastModified>2014-05-12T23:17:49.47</LastModified> 
  <LastRevised>2014-05-12T23:17:49.47</LastRevised> 
  <Path>/</Path> 
 <SecurityConfigurations>
 <ScopedSecurityConfiguration i:type="WindowsSecurityConfiguration">
  <Name>Microsoft.Workflow.Management.Security.WindowsSecurityConfiguration</Name> 
  <WorkflowAdminGroupName>BUILTINAdministrators</WorkflowAdminGroupName> 
  </ScopedSecurityConfiguration>
  </SecurityConfigurations>
  <Status>Active</Status> 
 </ScopeInfo>

Our last task is to tell SharePoint 2013 about our new Workflow farm, which we accomplish with the following cmdlet (run this on each SharePoint server):

Register-SPWorkflow -spsite 'http://web-application-url' -WorkflowHostUri 'http://WFM-server-FQDN:12291' -AllowOAuthHttp;

All being well, you should have a Workflow Manager Proxy listed under Manage Service Applications in Central Administration. Note: This proxy gets created whether the Register-SPWorkflow cmdlet succeeds or fails, so remember to remove this proxy after an error. Selecting the proxy and clicking the Manage icon in the ribbon should give you a page that indicates SharePoint is connected to the WFM. You’re good to go and create 2013 workflows.

Some things to note…

My configuration uses HTTP between SharePoint and WFM. In a production scenario, I recommend using HTTPS. In which case, you need to export the auto-generated certificate (from https://WFM-server-FQDN:12290) and import it into SharePoint Central Admin under Security -> Manage Trust. When using SSL, run the same Register-SPWorkflow cmdlet, but change the WFM location to https://WFM-server-FQDN:12290 and drop the -AllowOAuthHttp switch.

Some organizations rely heavily on workflow. Not unlike SharePoint, ADFS, and other farm based services, it’s a good idea to configure WFM with multiple hosts when high availability is important.

Configuring SharePoint 2013 for Windows Azure Workflow

SharePoint 2013 now abstracts workflow processing to the cloud – using Windows Azure Workflow (WAW). SharePoint still maintains the legacy workflow engine, as part of the .NET Framework 3.5.1, to enable execution of SharePoint 2010 workflows. However, SharePoint 2013 does not install WAW by default. The following steps detail additional configuration.

1. Ensure you are not installing on a domain controller – WAW integration does not work with SharePoint 2013 running on a single server domain controller

2. Create an account in your domain for WAW

3. Add this account to the local administrators group on the SharePoint server and grant log on locally permissions

4. Ensure the SQL server accepts connections via TCP/IP – use the SQL Server Configuration Manager tool

5. Provide the WAW account access to SQL Server, include create database permissions (or you could grant administrative permissions if you are brave)

6. Log onto the SharePoint server as that account

7. Install Workflow Beta 1.0 (http://technet.microsoft.com/en-us/library/jj193478), using the Web Platform Installer

8. After installation, you should see the WAW Configuration Wizard

9. Click to create a new farm, using custom settings

10. Configure databases and click the Test Connection button for each

11. Make sure the WAW service account is correct – use the fully qualified domain name (FQDN), by default it prepopulates the textbox with a non-FQDN

12. Provide certificate generation keys

13. Leave the ports as default

14. Check the checkbox to allow management over HTTP (if you choose to use HTTPS you will need to establish trust between SharePoint and WAW using a trusted certificate)

15. Click the next button to move onto configuring the service bus

16. Complete similar steps for database, service account, and certificates settings as you did above

17. Again, leave the ports as default

18. Review the summary page, then click the tick button to complete the configuration

19. Wait for the configuration to complete – this might take a little time

20. After WAW configuration completes, run the following PowerShell command:

Register-SPWorkflowService –SPSite "http://{sitecollectionurl}" –WorkflowHostUri "http://{workflowserve}:12291" –AllowOAuthHttp

21. Assuming no errors, you have now configured WAW in SharePoint 2013 for your site collection

More information on installing and configuring WAW is available at the following URL: http://technet.microsoft.com/en-us/library/jj658588%28v=office.15%29