Friday, May 29, 2009

K2 Blackpearl: Useful posts to configure ditribuited environment

This week I have been involved in the K2 Blackpearl environment setup. When you install it on a single machine the setup is very easy and fluent thanks to the installer provided by SourceCode. The activity began more difficult when you have to install various components on different machine in a distributed environment. In fact to allow multiple components communication it's required Kerberos Delegation. Here I posts some very handy reference to accomplish this tricky activity:
kick it on DotNetKicks.com
Save to delicious 0 saves

Wednesday, May 13, 2009

K2 Blackpearl: Set Sharepoint Task List Item Permission by code

Again on Sharepoint Workflow Integration Process... In the same process used in this post, I had to set particultar permissions to two custom sharepoint groups on the Tasks item created in Sharepoint Workflow Integration Client [SWIC]. In particular my goal was to set "View Only" permission to the following groups:
  • Approvator Box Push
  • Collaborator Box Push

where Box Push is my Sharepoint List with my K2 integrated workflow. Because I want to set this permissions when the task item is generated, in this case I cannot use "Sharepoint User Management" [SUM] event because I have the task item ID only when the item is created (see again this post). If you think to use SUM after the SWIC event, you haven't the desired behavior because process instance waits a user action to go on and permissions are set too late. So, to achieve my purpose I needed to write custom code in SWIC event after I get task item ID. In "ExecuteForUser" method body I call a K2 sharepoint web service (installed by K2 on MOSS) used to set permission on generic item (site, list or item list) hosted on MOSS solution. The code to call this service is the follow:

SourceCode.SharePoint.WebServices.K2SPPermissions K2SPPermissionsPRx =
  new SourceCode.SharePoint.WebServices.K2SPPermissions();
K2SPPermissionsPRx.Url = new K2Uri(MyUrl).FormatURI(true) +
     "_vti_bin/K2SPPermissions.ASMX";

ADCredentials directoryCredential = new ADCredentials();

K2SPPermissionsPRx.Credentials =
  directoryCredential.GetCredentials(K2SPPermissionsPRx.Url);

K2SPPermissionsPRx.SetSiteWidePermissionsFromXml(XML_FOR_PERMISSION);
where MyUrl is the Sharepoint site url. This service gets in input a xml string describing the permissions to assign. An example could be this:
<Group>
  <Filter> YOUR MOSS SITE </Filter>
  <SharePointPeopleAndGroupsItem>
    <Url>
      <SharePointSite> YOUR MOSS SITE </SharePointSite>
      <SharePointList>Tasks</SharePointList>
      <SharePointFolder></SharePointFolder>
      <SharePointListItem> YOUR ITEM ID </SharePointListItem>
      <SharePointGroup></SharePointGroup>
    </Url>
    <SharePointItemType>SHAREPOINTLISTITEM</SharePointItemType>
    <UserOrGroupCollection>
      <UserOrGroup>
        <LoginName>Approvers Box Push</LoginName>
        <Type>Group</Type>
      </UserOrGroup>
    </UserOrGroupCollection>
    <K2SharePointItemCollection></K2SharePointItemCollection>
    <K2UserOrGroupCollection></K2UserOrGroupCollection>
    <BreakRoleInheritance>True</BreakRoleInheritance>
    <CopyRoleAssignments>False</CopyRoleAssignments>
    <RevokeDefinitions>False</RevokeDefinitions>
    <AssignSiteMemberPermission>False</AssignSiteMemberPermission>
    <SharePointPermissionCollection>
      <SharePointPermission>
        <Name>Full Control</Name>
        <Type>REVOKE</Type>
      </SharePointPermission>
      <SharePointPermission>
        <Name>Design</Name>
        <Type>REVOKE</Type>
      </SharePointPermission>
      <SharePointPermission>
        <Name>Manage Hierarchy</Name>
        <Type>REVOKE</Type>
      </SharePointPermission>
      <SharePointPermission>
        <Name>Approve</Name>
        <Type>REVOKE</Type>
      </SharePointPermission>
      <SharePointPermission>
        <Name>Contribute</Name>
        <Type>REVOKE</Type>
      </SharePointPermission>
      <SharePointPermission>
        <Name>Read</Name>
        <Type>REVOKE</Type>
      </SharePointPermission>
<SharePointPermission>
 <Name>Restricted Read</Name>
<Type>REVOKE</Type>
</SharePointPermission>
<SharePointPermission>
<Name>View Only</Name>
<Type>ASSIGN</Type>
</SharePointPermission>
</SharePointPermissionCollection>
</SharePointPeopleAndGroupsItem>
</Group>
in my particular case I set "View Only" to "Approvers Box Push" group but you can set your desire permissions substituting ASSIGN to REVOKE label. In this way I achieve my purpose, in fact when a user member of Approvers Box Push open a task Item he or she could only view it (see the picture below). These permissions are set only to the item; on the Tasks list, users can add new task item as they want (as showed in the follow picture):
kick it on DotNetKicks.com
Save to delicious 0 saves

K2 Blackpearl - Get Task List Item in Sharepoint Workflow Integration

Using K2 Blackpearl features like Sharepoint events can be very usefull and easy to develop a workflow in few minutes. Althought, sometimes there are pitfalls that frustrate your initial purpose. For example, one of this day, I run against Sharepoint Workflow Integration features. I create my simple approval process in figure but, initially, I can't to get the task item ID created during Sharepoint Workflow Integration Client [SWIC]. I needed this ID because in my final activity I set a Sharepoint List Items event to delete the Task List Item created during the previous activity (SWIC, see Delete Task Activity in the figure above). To accomplish to this necessity, I had to create a new process DataField which I called "TaskId" Then I had to go inside the code generated by SWIC event and I modified the ExecuteForUser method body in the follow manner:
string taskIDstring = service.ModifyWorkflowAndGetTaskID(listId, listItemId,

                          workflowInstanceId, modificationID, contextData, "");



// Put task item id into process data field "TaskID"

string taskID = taskIDstring.Split(new string[] { "?ID=" },

                        StringSplitOptions.None)[1];

K2.ProcessInstance.DataFields["TaskID"].Value = taskID;
"service.ModifyWorkflowAndGetTaskID" calls a K2 web service who return a string contain the url of the task. A string like this: http://your MOSS server/Lists/Tasks/DispForm.aspx?ID=3.
Thank to this code I'm been able to delete Task List Item at the end of my process:
kick it on DotNetKicks.com
Save to delicious 0 saves

Friday, April 3, 2009

Disable Virtual Machine Time Bomb

Deactivate virtual PC time bomb If you have whatever needs to deactivate your virtual machine time synchronization (e.g. if there are software installed in your vm expiring), you could cut and paste the following XML code snippet in vmc file:
<integration>
   <microsoft>
       <components>
           <host_time_sync>
               <enabled type="boolean">false</enabled>
           </host_time_sync>
       </components>
   </microsoft>
</integration>
Obviously, you should open vmc file with editor like notepade...
kick it on DotNetKicks.com
Save to delicious 0 saves

Monday, March 2, 2009

Update Vitual Machine Additions issue

Last week I try to attach an old virtual machine (realized in Virtual PC 2004) to my Virtual PC 2007 sp1. When I try ti update the Virtual Machine Additions to the new release I recevice the following error: "Error 1714: the older version of Virtual Machine Additions cannot be removed. Contact your support group" The same error is raised up if you try to uninstall the component from "Add or Remove Program" (Panel Control -> Add or Remove Program). So, after a long googling, I succeeded in my purpose following this steps:
  • Download Windows Installer CleanUp Utility from Microsoft site,
  • Install the utility,
  • Launch "Windows Installer CleanUp Utility" (Start -> All program -> Windows Installer CleanUp Utility),
  • "Windows Installer..." shows a list of all your programs installed on your virtual system,
  • Select item "(All user) Virtual Machine Additions [your version]" like in the figure,
  • Click "Remove",
  • Click "Ok",
  • Re-run Virtual Machine Additions program installation
Now, you are able to complete successfully the setup. Note: If you install VMA from last version of Virtual PC (VirtualPC 2007 sp1), you should have this version number: 13.820. Reference: Windows Installer CleanUp Utility
kick it on DotNetKicks.com
Save to delicious 0 saves

Monday, February 9, 2009

Declarative Workflow

Today, I began to experiment on MS WF. I find very useful the possibility to load at runtime a xaml file of my personal workflow. To reach my goal I create two project with VS 2008 to test my solution:
  • A console project which is the entry point of my application;
  • A workflow library where put my custom activity and sequence workflow.
In my workflow library I add a xaml file where I put only my custom simple sequence with only one custom activity that print a "Hello world" (see the figure below). Remember that the custom activity must be tagged as [Serializable]. My xaml file hasn't the code behind because I built my workflow in declarative manner. If you take look at xml you could see:
<SequentialWorkflowActivity x:Name="Workflow1"
     xmlns:ns0="clr-namespace:MyWorkflowLibrary.Task;
Assembly=MyWorkflowLibrary, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow">
<ns0:HelloWorldTask x:Name="helloWorldTask1" />
</SequentialWorkflowActivity>
Note that I remove the x:Class attribute in SequentialWorkflowActivity. I do that because I haven't the compiled class in the code behind. In namespace attribute I add the reference to the assembly container of my activity, because this will be resolved at runtime. The console application "Main" looks something like this:
 static void Main(string[] args)
{
// Here, I read my xaml file containing my declarative workflow
var xmlReader =
    new XmlTextReader(
        new StringReader(
            File.ReadAllText(
                @"C:\Users\simonem\Documents\Visual Studio 2008\Projects\
                  TestWorkflow\MyWorkflowLibrary\HelloWorld.xoml")));

var runtime = new WorkflowRuntime();

runtime.StartRuntime();
runtime.WorkflowCompleted += delegate
                                 {
                                     Console.WriteLine("WorkFlow completed");
                                     Console.Read();
                                 };
try
{
    var instance = runtime.CreateWorkflow(xmlReader);
    instance.Start();

}
// Here I manage potential workflow validation exceptions
catch(WorkflowValidationFailedException wfve)
{
    var errorValidation = string.Empty;
    foreach (var error in wfve.Errors)
    {
        // StringBuilder is better...
        errorValidation += Environment.NewLine + error.ErrorText;
    }
    Console.WriteLine(errorValidation);
}
// General exceptions
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}
Console.Read();

}
Troubleshooting:
  • If during the program execution you receive an error such as "Could not deserialize object. The type 'clr-namespace:MyWorkflowLibrary.Task;.HelloWorldTask' could not be resolved. startIndex cannot be larger than length of string.Parameter name: startIndex" remember to specify the assembly reference in workflow xml code (see below):
     <SequentialWorkflowActivity x:Name="Workflow1"
     xmlns:ns0="clr-namespace:MyWorkflowLibrary.Task;
Assembly=MyWorkflowLibrary, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow">
  • If you couldn't compile your solution and you receive the following error "Cannot compile a markup file which does not contain declaration of the new workflow type." you must change the build action on your xaml file from "Content" to "None".
References:
kick it on DotNetKicks.com
Save to delicious 0 saves

Wednesday, February 4, 2009

TFS 2008: TF31002 error workaround...

After the setup of my new TFS server (see Install TFS 2008. The final attempt!!!), I start using TFS to share my project with other colleagues. So I follow Microsoft directives here To accomplish this goal, but when my friend trys to connect to my TFS server receive the infamous windows below:After a long and exhausting research on Google (I see that many other guys run against the same problem) I find the follow workaround:
  • Open IIS console,
  • Go to "Team Foundation Server" site, and open Authentication feature
  • Open context menu from ASP.NET Impersonation:
  • Set "Specific user" property to the account used to install your TFS server (in many other post is named TFSSetup)
Repeate the steps above also for the WSS site (in my case is the "Default Web Sites"). Remember that new TFS users must have also the permission in WSS site and in Reporting Service. To accomplish this requirement take a look to the screenshot below (IMHO is very usefull create a users group in your machine named TFS_Users and use it...):
Have a nice TFS experience ;-)
kick it on DotNetKicks.com
Save to delicious 0 saves

Sunday, February 1, 2009

Installing TFS 2008. The final attempt!!!

  • Goal:
Scope of this post is the installation of TFS 2008 on Windows Server 2008 and SQL Server 2008. To accomplish this target, I explored varied posts in other blog. Here I put together all the know how as result of my personal experience...
  • Before you begin, create your custom TFS iso:
From http://geekswithblogs.net/etiennetremblay/archive/2008/08/11/sql-2008--tfs-2008-sp1-the-lowdownhellip.aspx

[...I used Windows 2008 because this is going to be the prevalent OS to install on when people are going to start fresh or it most likely will. There was a little issue with that install when Windows 2008 RTM’ed back in February and I talked about it in this post. I wanted to see if the WSS issue was resolved in SP1. Well the good news is yes. When installing TFS, the experience is now the same for Windows 2003 and Windows 2008 and to boot, the SP1 now updates the WSS bits on the RTM DVD to WSS 3.0 SP1. Cool.

The problem is SQL 2008 now. You can’t use TFS 2008 RTM to install with SQL 2008. You need to slipstream (or Integrate) the SP on top of the RTM bits. The new install instruction covers this but here is a step by step.

a) Copy the original Media to a folder on any machine say d:\tfs\RTM

b) Extract the SP to a folder say d:\tfs\SPExtract

C:\SP1Download\TFS90SP1-KB949786-ENU /extract:d:\tfs\SP1Extract

c) Create a directory to put the result of the integration in say d:\tfs\ATIntegrated

d) Integrate (slipstream) the SP to the AT install by using this command line (note if you are in Windows 2008 make sure you start you console window as an Administrator or you’ll get prompted by UAC when executing the command).

msiexec /a C:\TFS\RTM\AT\vs_setup.msi /p C:\TFS\SP1Extract\TFS90sp1-KB949786.msp TARGETDIR=C:\TFS\ATIntegrated

e) Once you have done this make sure you copy back the ATIntegrated content to the original AT in the d:\TFS\RTM\AT overriding the original content.

Now you might be tempted to do the same integration with the Build and Proxy directory since they both have a vs_setup.msi file I know I was and actually did. You can’t. I works (well it looks like it does) but when you run the setup, it fails miserably. This is documented by Microsoft to NOT do that for Build and Proxy. You need to install the RTM version and then run the SP on top of it. It would have been nice to have a new DVD with all component SP’ed but it’s not to be.

f) After you have copied back the content to the original RTM directory, just burn a new ISO or DVD and you’re ready to install it.

NOT QUITE…

If you want to have Team Explorer (TE) on your server to create new project like I do, you need to install it BEFORE you install SQL 2008 and apply the TE SP1 also before IF you want to install the client tools as part of the SQL 2008 install which you most likely will to manage backups and verify tables, etc. This problem is fully explained in this KB, Visual Studio 2008 SP1 may be required for SQL Server 2008 installations. If you want to create an all in one server with Studio and Build for example you need to follow the same procedure. ...]

  • Account for the Setup:
From http://blogs.devleap.com/rob/archive/2006/03/29/7048.aspx [Sorry, in Italian]
[...Create 3 account (the account name can be as you prefer...). If the installation server is in a domain the account must be domain account and obviously of the same domain:

TFSSetup - used to do the TFS setup Administrators Group TFSService - used by the services (code coverage, TFSScheduler, SharePoint Timer), and by application pool Lon On Locally - da Local Security Settings - Local Policies - User Rights Assignment -> Allow log on locally Not in Administrators group for security reason If you are creating a domain account enable "Account is sensitive and cannot be delegated" for security reason TFSReports - used by Reporting Services Lon On Locally - da Local Security Settings - Local Policies - User Rights Assignment -> Allow log on locally Not in Administrators group for security reason By default the created users are in Users group, so they have "Log On Locally" property set. ...]

  • Be a man, now you are ready to start
Always from http://geekswithblogs.net/etiennetremblay/archive/2008/08/11/sql-2008--tfs-2008-sp1-the-lowdownhellip.aspx proceed as follows:

[...

i) Windows (2003/2008) + IIS

ii) VSTS and/or TE 2008

iii) SP1 of VSTS and/or TE (it’s the same one that installs for all version of VS/VS Core, you need to run it once for anything component you have installed)

iv) SQL 2008 + Component like DB, RS, AS, Client Tools, etc (follow the install guide instructions, i'll try to post an unattended install file when I have one)

Integration: Set automatic startup ed start SQL Server Agent and SQL Server Browser

v) TFS SP1 (integrated), this will now install WSS properly for both Windows 2003 and Windows 2008 so no need to install it before.

vi) TFS Build + TFS SP1 (which is a different SP then the VS one)

vii) TFS Proxy + TFS SP1 ...]

viii) From http://blogs.msdn.com/dstfs/archive/2008/10/23/my-experience-setting-up-tfs-windows-sever-sql-server-2008.aspx

[...Add NT AUTHORITY\NETWORK SERVICE as a user to the TfsWarehouse database in the SQL Data Engine, and add it to the TfsWarehouseDataReader database role. You can do that manually, or through a SQL script like this (run it from a SQL Management Studio query when connected to the SQL Data Engine):

USE TfsWarehouse CREATE USER [NT AUTHORITY\NETWORK SERVICE] FOR LOGIN [NT AUTHORITY\NETWORK SERVICE] EXEC sp_addrolemember N'TfsWarehouseDataReader', N'NT AUTHORITY\NETWORK SERVICE' ...] ix) Reinstall the VSTS2008 SP1 again...
  • Troubleshotting
If during the TFS Setup you have problem with reporting service, check in Reporting Service Configuration that https mode is not set (Web Service URL and Report Manager URL sections).
kick it on DotNetKicks.com
Save to delicious 0 saves