Month: June 2015

Workflow Manager – Scripted Installation

Allrighty, I was sick and tired of NOT being able to install my Workflow Manager without the Web-platform Installer installation. Secondly I was tired of not being able to install Workflow Manager using my loved one, Powershell. So I called upon my good friend Mads Hjort Larsen and we started to work on it.
The script below will make use of offline msi files for the installation. So make sure you grab those before you run the script. They should be located in the same folder as the script before you run it.

The script

Set-Location (Split-Path -Parent -Path $MyInvocation.MyCommand.Definition)
Clear-Host

#region Variables
$SQLserver = '<SQL SERVER>' # Name of the database server.
$DBprefix = '<Database Pre-fix>' # All databases will be prefixed with this string.

$SBRunAsAccount = '<Service Bus service account>' # The account under which the service runs. This account must be a domain account.
$SBRunAsPasswordString = '<Service Bus service Account passwprd>' # Password for RunAs account (in cleartext).
$SBAdminGroup = '<Service Bus Administrator group>' # The admin group for Service Bus. (Default "BUILTIN\Administrators")
$SBCertificateAutoGenerationKey = '<Certificate passphrase>' # This passphrase is required for certificate auto generation. This parameter is mandatory if you want certificates to be auto generated.
$TcpPort = <Service Bus port> # The port that the Service Bus for Windows Server uses for TCP. (Default 9354) 
$MessageBrokerPort = <Message Broker port> 9356 # The port that the Service Bus for Windows Server uses for MessageBroker communication. (Default 9356)
$InternalPortRangeStart = <Port Range> # The start of the port range that Service Bus for Windows Server uses for internal communication purposes. (Default 9000) 

$WFRunAsAccount = '<Service Bus service account>' # The account under which the service will be running. This account must be a domain account.
$WFRunAsPasswordString = '<Service Bus service account password>' # Password for RunAs account (in cleartext).
$WFAdminGroup = '<Service Bus Administrator group>' # The set of users who are considered workflow administrators. (Default BUILTIN\Administrators)
$WFCertificateAutoGenerationKey = '<Certificate Passphrase>' # This passphrase is required for certificate auto generation. This is a mandatory parameter if you want certificates to be auto generated.
$HttpsPort = <Workflow HTTPS Port> # The port that will be used by the workflow for HTTPS communication. (Default 12290)
$HttpPort = <Workflow HTTP Port> # The port that will be used by the workflow for HTTP communication. (Default 12291)

$SBNamespace = '<Service Bus Namespace>' # Specifies the name for the new Service Bus for Windows Server service namespace.
$AddressingScheme = 'Path' # Specifies the addressing scheme used in the service namespace. The possible values for this parameter are Path (default value) and DNSRegistered. If the value DNSRegistered is specified, the -DnsEntry parameter is required.
$ManageUsers = '<Workflow Namespace Administrator01>','<Workflow Namespace Administrator02>' # Specifies user or group names that will be managers of the service namespace.

#Filelocations:
$WF  = "WindowsFabric.msi"
$SB  = "Service_Bus.msi"
$WMC = "WorkflowManagerClient_x64.msi"
$WM  = "Workflow_Manager.msi"

## Can't touch this... or anything below this line ;P

$Sleep = 90 # Sleep duration is set to 90 seconds because that what all the cool kids online are doing.

$ArgumentList = 'IACCEPTEULA=yes WEBPI=1 /QUIET /NORESTART' 
<# 
    "IACCEPTEULA=yes" is required for quiet install of Windows Fabric, 
    "WEBPI=1" is required for installation of Service Bus and Workflow Manager outside of the Web Platform Installer, 
    "/QUIET" = Quiet mode, no user interaction, 
    "/NORESTART" = Do not restart after the installation is complete.
#>

$fileNotFound = $null
#endregion

Write-Host "VERIFYING THAT FILES EXIST:"
$files = $WF,$SB,$WMC,$WM
foreach ($file in $files) {
    if (Test-Path -Path $file){
        Write-Host "✓ $file" -ForegroundColor Green
    }else{Write-Host "X $file" -ForegroundColor Red;$fileNotFound = $true}
}if ($fileNotFound -eq $true){Exit}
''
foreach ($file in $files) {
    Write-Host "Installing $file... " -NoNewline
    Start-Process $file -ArgumentList $ArgumentList -Wait
    Write-Host "Done"
}

[Environment]::SetEnvironmentVariable("PSModulePath", [Environment]::GetEnvironmentVariable("PSModulePath","Machine"))
Import-Module WorkflowManager

#region StringBuilding
# The strings are created like this to make it easier to put them on different SQL servers
function BuildString ($type, $dbName, $SQLserver) {
    New-Variable -Name $type'DBConnectionStringDataSource' -Value $SQLserver
    New-Variable -Name $type'DBConnectionStringInitialCatalog' -Value $DBprefix$dbName
    New-Variable -Name $type'DBConnectionString' -Scope Script -Value ("Data Source="+(Get-Variable -Name $type'DBConnectionStringDataSource' -ValueOnly)+";Initial Catalog="+(Get-Variable -Name $type'DBConnectionStringInitialCatalog' -ValueOnly)+";Integrated Security=True;Encrypt=False") -Force
}

# Example ConnectionString: Data Source=SQL01;Initial Catalog=Udv_service_SBManagement;Integrated Security=True;Encrypt=False
BuildString SBFarm SBManagement $SQLserver
BuildString GateWay SBGateway $SQLserver
BuildString MessageContainer SBMessageContainer $SQLserver
BuildString WFFarm WFManagement $SQLserver
BuildString Instance WFInstanceManagement $SQLserver
BuildString Resource WFResourceManagement $SQLserver
#endregion

$SBCertificateAutoGenerationKey = ConvertTo-SecureString -AsPlainText -Force -String $SBCertificateAutoGenerationKey -Verbose
New-SBFarm -SBFarmDBConnectionString $SBFarmDBConnectionString -InternalPortRangeStart $InternalPortRangeStart -TcpPort $TcpPort -MessageBrokerPort $MessageBrokerPort -RunAsAccount $SBRunAsAccount -AdminGroup $SBAdminGroup -GatewayDBConnectionString $GatewayDBConnectionString -CertificateAutoGenerationKey $SBCertificateAutoGenerationKey -MessageContainerDBConnectionString $MessageContainerDBConnectionString -Verbose
New-WFFarm -WFFarmDBConnectionString $WFFarmDBConnectionString -RunAsAccount $WFRunAsAccount -AdminGroup $WFAdminGroup -HttpsPort $HttpsPort -HttpPort $HttpPort -InstanceDBConnectionString $InstanceDBConnectionString -ResourceDBConnectionString $ResourceDBConnectionString -CertificateAutoGenerationKey $SBCertificateAutoGenerationKey -Verbose

$SBRunAsPassword = ConvertTo-SecureString -AsPlainText -Force -String $SBRunAsPasswordString -Verbose
Add-SBHost -SBFarmDBConnectionString $SBFarmDBConnectionString -RunAsPassword $SBRunAsPassword -EnableFirewallRules $true -CertificateAutoGenerationKey $SBCertificateAutoGenerationKey -Verbose

Try {
    New-SBNamespace -Name $SBNamespace -AddressingScheme $AddressingScheme -ManageUsers $ManageUsers -Verbose
    for ($i=$Sleep; $i -gt 1; $i--) {
        Write-Progress -Activity "Creating new SB Namespace" -Status "Sleeping" -SecondsRemaining $i
        Start-Sleep 1
    }
}
Catch [system.InvalidOperationException]{}

$SBClientConfiguration = Get-SBClientConfiguration -Namespaces $SBNamespace -Verbose
$WFRunAsPassword = ConvertTo-SecureString -AsPlainText -Force -String $WFRunAsPasswordString -Verbose
Add-WFHost -WFFarmDBConnectionString $WFFarmDBConnectionString -RunAsPassword $WFRunAsPassword -EnableFirewallRules $true -SBClientConfiguration $SBClientConfiguration -CertificateAutoGenerationKey (ConvertTo-SecureString $WFCertificateAutoGenerationKey -AsPlainText -Force) -Verbose

(The script is currently using a self-signed certificate.)

How to get MSI files
WebPICMD.exe /offline /products:”WindowsFabric,ServiceBus_1_1,WorkflowManager” /Path:c:\temp\

WindowsFabric.msi
WebPICMD.exe /offline /products:WindowsFabric /Path:c:\temp\

Service_Bus.msi
WebPICMD.exe /offline /Products:ServiceBus_1_1 /Path:c:\temp\

WorkflowManagerClient_x64.msi
WebPICMD.exe /offline /Products:WorkflowManager /Path:c:\temp\

Workflow_Manager.msi
WebPICMD.exe /offline /Products:WorkflowManager /Path:c:\temp\

Updated 17-June-2015: Incorporated Martin Sandersens comment into the script, removing the need for customized msi files.
Updated 07-August-2015: Updated script for fewer lines of code.

Advertisements