Friday, May 18, 2007

K2 Solution Installer

For a project I was doing I needed to create a custom installer to deploy a K2 Solution. The client wanted the solution to install the K2 project hands off.

We have four enviroments we had to deal with Dev, QA, Staging and production. Each has a string table and enviromental specific Process Data - Default values.

We use source safe to store the K2 solution and all of it's components. I wanted to have a seperate location were I stored the final solution from my working copy. I created a seperate folder/Project in source safe and linked all the files I wanted to use in my installation project. Now all I needed to do is checkin my code and get the latest version in my final project location. I could then go back and continue working on the solution without linking directly to my working copy.

For my needs I only had one process to export so I didn't deal with multi-process solution. I created a configuration file for each enviroment that looked something like this

     <Solution>K2 Solution\K2WorkFlow.ksn</Solution>
          <String Title="Title">Value</String>
     <DataField Title="Title">
     <Group Name="DOMAIN\GROUP">
     <User Name="DOMAIN\USERNAME">

After I had seperate configuration files I had the installer copy the correct configuration file over based on a set of radio button to select different enviroments. I Added all the solution files to the installer these would include .kpr, kcm, .dll, .k2n files in the same structure as they appear in my working solution.

Some of the user input questions we ask during the installation process were K2 Server Name, Process Name, Sql Server Name.

After the installer copies all the files we then launch an installer class to do the heavy lifting. I used the "using K2Studio" in my code and included references to Interop.K2Studio, K2ROM, K2SPUtilities .

Note: You must have k2studio installed on the machine running the installer. The installer uses k2studio.exe to compile and export the process.

Here is the main logic of the K2 installer:

  • We load and parse the Configuration file
  • These are the object I used during export process
    1. K2Studio.Application K2App = new K2Studio.Application();
    2. K2Studio.Project K2Project;
    3. K2Studio.ProcessFolder K2ProcessFolder;
    4. K2Studio.Process K2Process;
    5. K2Studio.Processes K2Processes;
  • K2App.Solution.Open(pathToSolutionFile) - This is defined in my configuration file

  • K2Project = K2App.Solution.Projects.Item(0); - I Select the first K2 Project. Since I only had one.

  • I remove all the servers being using the K2Project.ExporServers Object
  • " K2Project.ExportServers.Remove(0);"

  • I re-add the k2 export server "K2Project.ExportServers.Add(serverName);" - The servername is asked during the installation process.

  • I set the K2ProcessFolder to the object K2Project.ProcessFolder;

  • I then get K2Processes = K2ProcessFolder.Processes; and grab the first item out of there. "K2Processes.Item(0);"

  • I then export all the string entries. I check if each item exists already then update the string value if not then add the string - K2Project.ExportServers.Item(0).StringTable.Add(Title);

  • I export the datafields found in the configuration files
  • newDataField = K2Process.DataFields.Add(Title);
  • Set the Type "newDataField.Type= K2Studio.EnumDataType.TypeString;" we use a
    switch statement to determine what type we are using
  • Set the value "newDataField.Value=MyValue;"
  • set the MetaData "newDataField.MetaData=MetatData"

  • We set the Process Name "K2Process.Name = ProcessName". The process name is asked during the installation process.

  • Then we export the k2 process to the server "K2Process.Export(serverName, ref Result);" and then display the results in a MessageBox.

  • Use created a stored procedure the accepts XML anduses the OPENXML command to parser through my configuration file.
  • I select the latest Process ID "SELECT @PROCID=ID from k2.dbo._ProcSet WHERE Name=@PROCESSNAME"
  • I then delete the _Procuser and _ProcGroups there are related to the process ID
  • Iinsert the Groups into the _ProcGroup.
  • Insert the Users into the _ProcUser table

  • Note: At the end of the installation process I could not get K2Studio.exe to close down. So had to create a function that would shut down the process.

And thats all there is to creating an automated install kit for K2

Monday, September 18, 2006

One of the things I have been introduced to over the last few months at work is extreme programming. One of the key concepts in extreme programming is 10 minute deployments. So with this in mind I set out to automate most if not all of the deployment packages for each server.

One of the servers for this project has a number of web services and keeping these up to date used to take 15 minutes. If any typos were made during the installation process it would then take me another 5-10 minutes to figure out that indeed a typo caused the entire problem.

I created a batch file and decided to use the msiexec command line utility to uninstall and install my application. Here is a list of the command line commands for misexec. You can get these yourself by typing msiexec in a command window.

Windows ® Installer. V 3.01.4000.1823
msiexec /Option [Optional Parameter]
Install Options

Installs or configures a product
Administrative install - Installs a product on the network
/j [/t ] [/g ]
Advertises a product - m to all users, u to current user

Uninstalls the product
Display Options
Quiet mode, no user interaction
Unattended mode - progress bar only
Sets user interface level
n - No UI
b - Basic UI
r - Reduced UI
f - Full UI (default)
Help information
Restart Options
Do not restart after the installation is complete
Prompts the user for restart if necessary
Always restart the computer after installation
Logging Options
i - Status messages
w - Nonfatal warnings
e - All error messages
a - Start up of actions
r - Action-specific records
u - User requests
c - Initial UI parameters
m - Out-of-memory or fatal exit information
o - Out-of-disk-space messages
p - Terminal properties
v - Verbose output
x - Extra debugging information
+ - Append to existing log file
! - Flush each line to the log
* - Log all information, except for v and x options
Equivalent of /l*
Update Options
/update [;Update2.msp]
Applies update(s)
/uninstall [;Update2.msp] /package
Remove update(s) for a product
Repair Options
Repairs a product
p - only if file is missing
o - if file is missing or an older version is installed (default)
e - if file is missing or an equal or older version is installed
d - if file is missing or a different version is installed
c - if file is missing or checksum does not match the calculated value
a - forces all files to be reinstalled
u - all required user-specific registry entries (default)
m - all required computer-specific registry entries (default)
s - all existing shortcuts (default)
v - runs from source and recaches local package
Setting Public Properties
Consult the Windows ® Installer SDK for additional documentation on the
command line syntax.
Copyright © Microsoft Corporation. All rights reserved.
Portions of this software are based in part on the work of the Independent JPEG Group.

As you can see there are a number of parameters that can be used. I will discuss just the ones I used in my batch file you can experiment with the the rest yourself. The first thing I did was to uninstall the current packages using this command for each MSI.

msiexec /x {803D4FBB-E1C2-499A-8F9C-6FD5287229D0} /quiet /passive /log "c:\lInstall.txt"

  • /x uninstall the product. I decided to use the product key instead of the application name. I couldn't get the product name to work as a parameter.
  • When getting the product ID look at the properties for your installation project and you will see a Product Code property you can use this value.
  • /quiet - No user interaction
  • /Passive -Unattended mode - progress bar only
  • /log - I logged the installation just in case something happend and I could go back and look.
Installation your MSI.

msiexec ALLUSERS=1 SQL_LOCALHOST=ServerName DIR_ADDRESS="LDAP://OU=MyBusiness,DC=Company,DC=com" PROPERTY_LOCALHOST="Server Name" /i %CommonService% /quiet /passive

In order to get this to work you must configure your installation application to accept command line defaults. Otherwise the properties you pass from the batch file will never be used.

  • In your user interface screens were you define the UI to accept user input just add the [PROPERTY] to the value portion of the UI.\

Here is a an example of a text valuet that I wanted to default to the SQL_LOCALHOST from the batch command line.

Property Sheet in the Installation solution

  • Edit1Label - SQL Server - Title for the label
  • Edit1Property - SQL_LOCALHOST
  • Edit1value - [SQL_LOCALHOST] - Remeber the name must be in brackets.

  • ALLUSERS =1 . If this is set to one the the installation will be for all users instead of the current user.
  • SQL_LOCALHOST=ServerName - each parameter with default values.
  • /i - install - and then your path to the msi. I put mine in a varaible so different developers could change it qickly.
  • /quiet - No user interaction
    /Passive -Unattended mode - progress bar only

and thats all there is to it.

Tuesday, September 12, 2006

Welcome to my blog. Here you will find postings related to many development topics. Here is just a few topics coming up in the next little while.

  • One touch installation
  • Optimizing infopath
  • Web Service Caching techniques.