Thursday, July 8, 2010

MOSS 2007: Get Shared Services User Profile without “Manage User Profile” permission

For a custom functionality I’m developing for my customer I needed to retrieve the user profile logged on the application. To accomplish this task SharePoint object model provides the class UserProfileManager which allows you to query user profile properties.

There is only a tip when you write your code to access the user profile properties, in fact you can use two different piece of code to accomplish that:

  1. if you instance a new UserProfileManager (see the commented code below on 7th row) you could have problem and receive the following error:

    “You must have manage user profiles administrator rights to use administrator mode.”

    This is due to the fact that to instance a UserProfileManager you need administration right on SharePoint Shared Service.
  2. Instead of the creation of a new instance of UserProfileManager class, you can get an already present instance using ProfileLoader class (see row 8, 9 and 10 below). In this way you can access to a read-only version of UserProfileManager class which permits you to query every properties of the user profile you have requested (see all the example below).
   1:  public UserProfile GetUserProfile(string loginName)
   2:  {
   3:      UserProfile userProfile;
   4:      using (var Site = new SPSite(SiteId))
   5:      {
   6:          var ctx = ServerContext.GetContext(Site);
   7:          //var upm = new UserProfileManager(ctx, true);
   8:          var profile = ProfileLoader.GetProfileLoader(ctx);
   9:          var upm = profile.GetUserProfileManager();
  10:          var spUserProfile = upm.GetUserProfile(loginName);
  11:   
  12:          userProfile = new UserProfile(spUserProfile.ID)
  13:            {
  14:                Login = loginName,
  15:                PreferredName = spUserProfile["PreferredName"] != null ? 
  16:                  spUserProfile["PreferredName"].Value as string : string.Empty,
  17:                  
  18:                Manager = spUserProfile["Manager"] != null ? 
  19:                  spUserProfile["Manager"].Value as string : string.Empty,
  20:                  
  21:                Name = spUserProfile["FirstName"] != null ? 
  22:                  spUserProfile["FirstName"].Value as string : string.Empty,
  23:                  
  24:                Surname = spUserProfile["LastName"] != null ? 
  25:                  spUserProfile["LastName"].Value as string : string.Empty
  26:            };
  27:   
  28:      }
  29:   
  30:      return userProfile;
  31:  }

 

Particular thanks to my friend Michele who supported and suggested me on how to resolve this problem.

kick it on DotNetKicks.com
Save to delicious 0 saves

TFS 2010: TF270015: 'MSTest.exe' returned an unexpected exit code. Expected '0'; actual '1'.

If you try to build an “old” Visual Studio 2008 solution with the new Team Foundation Server 2010 and after the build you try to execute automatic unit test project inserting the following directive inside your build project:

<MetaDataFile Include="$(BuildProjectFolderPath)/&lt;your vsmdi file>.vsmdi">
   <TestList>yourtestproject.UnitTest</TestList>
<MetaDataFile>

your build probably will fail with the following nice error:

TF270015: 'MSTest.exe' returned an unexpected exit code. Expected '0'; actual '1'.

After a Google search (see references below) I’ve found that the problem could be due to the fact that TFS 2010 can only build test project written in .NET 4.0.

For now there’s no fix available to resolve this problem (as you can see here) and there’s no timing about a Microsoft hotfix (QFE) release.

References:

kick it on DotNetKicks.com
Save to delicious 0 saves

Wednesday, July 7, 2010

MOSS 2007: “The evaluation version of Microsoft Office SharePoint Server 2007 for this server has expired”

If you receive this error when you try to access to SharePoint Shared Service on your machine, don't panic. It's a problem due to SP2 installation. You can find more detail and hotfix about this problem here.

SP_false_expired_Message

Reference:

kick it on DotNetKicks.com
Save to delicious 0 saves

Monday, April 19, 2010

Insert a Watermark with iTextSharp

iTextSharp is a very good open source library to manage file in pdf format. You can find many examples on how you can use this powerful library inside your application in this tutorial, but in this post I want to focus on a way to create a watermark and insert it inside in an existing pdf document.

This need come up from a project for my current customer who need to create a pdf document from a office file (Word, Excel and PowerPoint format) with a watermark reporting user name (user claiming the copy of the document). So, the approach I used to accomplish the requirement foresee the following steps:

  1. First, I create a bitmap with the text I want to render in the watermark;
  2. then, I insert the bitmap created inside my pdf document using iTextSharp library.

Bitmap creation is very easy using dot Net Framework classes. So, I developed the Watermark class with default constructor requiring the text to render:

   1:  public Watermark(string watermarkText)
   2:          {            
   3:              Text = watermarkText;
   4:              TextFont = new Font("Arial", 25, FontStyle.Bold);
   5:              Inizialize();
   6:          }

TextFont is an auto property that consumer can modify to change watermark font. In the constructor I also initialize the Watermark instance setting the resolution DPI, the scale factor and I calculate the bitmap size (width and height in pixel) using the following method:

   1:  private const int DEFAULT_SCALE_RATIO = 24;
   2:   
   3:  private void Inizialize()
   4:  {
   5:      ScaleFactor = DEFAULT_SCALE_RATIO;
   6:      Position = WatermarkPosition.Central;
   7:      BackGroundColor = Color.Transparent;
   8:      BrushColor = Color.LightGray;
   9:   
  10:      using (var bitmap = new Bitmap(1, 1))
  11:      {
  12:          bitmap.SetResolution(DPI, DPI);
  13:          using(var g = Graphics.FromImage(bitmap))
  14:          {
  15:              Height = Convert.ToInt32(g.MeasureString(Text, TextFont).Height);
  16:              Width = Convert.ToInt32(g.MeasureString(Text, TextFont).Width);
  17:          }
  18:      }
  19:  }

It is necessary to scale the bitmap because you could have resolution problems when you use it with iTextSharp library (see paragraph Impact on the resolution in iTextSharp tutorial).

To get the desired bitmap I created the following public methods:

  • one to get the image with original size
  • one to get scaled image
   1:  public Image GetImage()
   2:  {    
   3:      var bitmap = new Bitmap(Width, Height);
   4:      var image = CreateImage(bitmap, TextFont);
   5:      return image;
   6:   
   7:  }
   8:   
   9:  public Image GetScaledImage()
  10:  {
  11:      var bitmap = new Bitmap(ScaledWidth, ScaledHeight);
  12:      var image = CreateImage(bitmap, ScaledTextFont);
  13:      return image;
  14:  }

where ScaledWidth and ScaledHeight are:

   1:  public int ScaledWidth
   2:  {
   3:      get { return Width *100 / ScaleFactor; }
   4:  }
   5:   
   6:  public int ScaledHeight
   7:  {
   8:      get { return Height *100 / ScaleFactor; }
   9:  }

The last thing is the CreateImage method which really makes the work:

   1:  private const float DEFAULT_IMAGE_DPI = 72f;
   2:   
   3:  private Image CreateImage(Bitmap bitmap, Font font)
   4:  {
   5:      bitmap.SetResolution(DEFAULT_IMAGE_DPI, DEFAULT_IMAGE_DPI);
   6:      using(var g = Graphics.FromImage(bitmap))
   7:      {
   8:          SetGraphicsProperty(g);
   9:   
  10:          var sizef = g.MeasureString(Text, font);
  11:          g.Clear(BackGroundColor);
  12:   
  13:          var text = Text;
  14:          var width = bitmap.Width;
  15:   
  16:          if (Repeater)
  17:          {
  18:              while (width%sizef.Width > 0)
  19:              {
  20:                  text += " - " + Text;
  21:                  width -= Convert.ToInt32(sizef.Width);
  22:              }
  23:          }
  24:   
  25:          g.DrawString(text, font, new SolidBrush(BrushColor), 0, 0,
  26:                       new StringFormat(StringFormatFlags.FitBlackBox));
  27:          g.Flush();
  28:      }
  29:      return bitmap;
  30:  }

Repeater is an auto-property to create a bitmap with text repeated many times necessary to fill all the bitmap width.This is required, for example, when I want a watermark positioned along all document margins.

BackgroundColor and BrushColor are two auto-property which permit to customize watermark look & feel.

SetGraphicsProperty method just initializes some image properties (see here for more details):

private static void SetGraphicsProperty(Graphics g)
{
    // Set the System.Drawing.Graphics object property SmoothingMode to HighQuality 
    g.SmoothingMode = SmoothingMode.AntiAlias;
    // Set the System.Drawing.Graphics object property CompositingQuality to HighQuality
    g.CompositingQuality = CompositingQuality.HighQuality;
    // Set the System.Drawing.Graphics object property InterpolationMode to High
    g.InterpolationMode = InterpolationMode.High;
 
    g.PixelOffsetMode = PixelOffsetMode.HighQuality;
 
    g.TextRenderingHint = TextRenderingHint.AntiAlias;
}

Now that we have our watermark, we can work on PDF document where we want insert it. To accomplish this I create the PDFDocument class:

   1:  using iTextSharp.text;
   2:  using iTextSharp.text.pdf;
   3:   
   4:  public class PDFDocument
   5:  {
   6:   
   7:      private PDFDocument(Guid Id)
   8:      {
   9:          ID = Id;
  10:          Watermarks = new List<IWatermark>();
  11:      }
  12:   
  13:      public PDFDocument(Guid id, byte[] binaryFile, string fileName) : this(id)
  14:      {
  15:          binary = binaryFile;
  16:          var pdfReader = new PdfReader(binaryFile);
  17:          if(pdfReader.NumberOfPages == 0 ) 
  18:              throw new Exception("Document does not contain any page!");
  19:          var pageSize = pdfReader.GetPageSizeWithRotation(1);
  20:          PageWidth = Convert.ToInt32(pageSize.Width);
  21:          PageHeight = Convert.ToInt32(pageSize.Height);
  22:          PageRotationInDegree = pageSize.Rotation;
  23:          FileName = fileName;
  24:      }
  25:      
  26:  ...
  27:   
  28:  }

The constructor of my entity require the id, the binary data and the file name.
Note that here I’m using iTextSharp library and, in particular, the PDFReader class in iTextSharp.text.pdf namespace; in this way I can set some useful properties about document in question, such as page width, height and rotation. I also define an auto property to add desired watermarks to my pdf document:

    public IList<Watermark> Watermarks
    {
        get;
        set;
    }

And now the main point of the class. With GetDocumentWithWatermark method, I process the pdf document to insert the real watermark picture:

   1:  public byte[] GetDocumentWithWatermark(bool protect)
   2:  {
   3:      using (var outputStream = new MemoryStream())
   4:      {
   5:      var pdfReader = new PdfReader(binary);
   6:      var pdfStamper = new PdfStamper(pdfReader, outputStream);
   7:   
   8:      foreach (var watermark in Watermarks)
   9:      {
  10:          using (var bitmap = watermark.GetScaledImage())
  11:          {
  12:          var image = Image.GetInstance(bitmap, BaseColor.WHITE );
  13:          
  14:          var numberOfPages = pdfStamper.Reader.NumberOfPages;
  15:   
  16:          for (var i = 1; i <= numberOfPages; i++)
  17:          {
  18:              var pageSize = pdfStamper.Reader.GetPageSizeWithRotation(i);
  19:              PdfContentByte waterMarkContent = null;
  20:              switch (watermark.Position)
  21:              {
  22:                  case WatermarkPosition.Right:
  23:                      image.RotationDegrees = 90;
  24:                      image.Rotate();
  25:                      image.ScalePercent(watermark.ScaleFactor);
  26:                      image.SetAbsolutePosition(pageSize.Width - 
  27:                                                  image.ScaledWidth, 0);
  28:                      waterMarkContent = pdfStamper.GetOverContent(i);
  29:                      break;
  30:                  case WatermarkPosition.Central:
  31:                      image.RotationDegrees = WATERMARK_ANGLE;
  32:                      image.Rotate();
  33:                      image.ScalePercent(watermark.ScaleFactor);
  34:                      image.SetAbsolutePosition(pageSize.Width/2 - 
  35:                                                  image.ScaledWidth/2,
  36:                                                pageSize.Height/2 - 
  37:                                                  image.ScaledHeight/2);
  38:                      waterMarkContent = pdfStamper.GetUnderContent(i);
  39:                      break;
  40:                  case WatermarkPosition.Left:
  41:                      image.RotationDegrees = 90;
  42:                      image.Rotate();
  43:                      image.ScalePercent(watermark.ScaleFactor);
  44:                      image.SetAbsolutePosition(0, 0);
  45:                      waterMarkContent = pdfStamper.GetOverContent(i);
  46:                      break;
  47:              }
  48:   
  49:              if (waterMarkContent != null) 
  50:                  waterMarkContent.AddImage(image, true);
  51:          }
  52:          }
  53:      }
  54:      pdfStamper.Close();
  55:      pdfReader.Close();
  56:      return outputStream.ToArray();
  57:      }

 

as you can see I use iTextSharp class such as PdfReader and PdfStamper to manipulate the document and then, in the switch code segment, I create and position the image according to I want a central, left or right watermark. Note that I call two different method of pdfStamper instance:

  • GetUnderContent method: allow to put my watermark a level lower the current document layout. This is the best solution when I set central watermark and I want that document text and image are over the watermark
  • GetOverContent method: allow to set watermark upper all document content. Because left and right watermark stay on document margin, could be very useful put it over all content especially when you are manipulating pdf file coming from a PowerPoint document conversion which can have non-transparent background image.

Note that I have repeated the operation for all the page inside the pdf document because page layout could be change (horizontal or vertical page layout).

References:

  1. iTextSharp library
  2. iTextSharp tutorial
  3. http://www.codeproject.com/Articles/71961/Creating-a-Simple-Sheet-Designer-in-Csharp.aspx
kick it on DotNetKicks.com
Save to delicious 0 saves

Monday, March 1, 2010

VirtualBox: Shrink guest volume

Today, I tried to increase space on my working notebook. I usually work in virtual environment and in the last period I’ve found very cool VirtualBox virtualization product.

From a first analysis, I found that the logical space occupied by guest disk was less than the physical space on my hard disk (32 GB versus 37 GB). Unfortunately VirtualBox UI don’t provide any tools to shrink volume such as in MS Virtual PC. So, I had a short search on Google and I found out a couple of very interesting posts to  accomplish the task.

Here, summarized the steps:

  1. Defrag your guest disk using windows defrag,
  2. Download the following tool (SDelete) and copy and extract it in your virtual environment,
  3. Open a console in guest system, go to SDelete directory and type the following command:

    sdelete -c c:\

    where C:\ is the volume to shrink.
  4. Shutdown the virtual machine.
  5. In the host environment open a console, go to VirtualBox directory (in my case was: “C:\Program Files\Sun\VirtualBox”)
  6. Type the following command:

    VBoxManage.exe modifyvdi <your path to vdi file>\file.vdi compact

The last operation is the slowest and requires about 20 minutes (probably depends on machine and file size).

Assumptions:

VirtualBox version: 3.1.4

Host O.S.: Windows 7 x64

Guest O.S.: Windows 2008 x86

References:

kick it on DotNetKicks.com
Save to delicious 0 saves

Sunday, January 17, 2010

How to use Office 2007 Automation in Windows 2008 service

I’ve lost approximately 3 days about this topic. I read tens of posts by finally I’ve understood…

I’m working on a solution including a file conversion from a document in MS Office 2003 format (doc, xls, ppt) to PDF.

To do this I’ve seen several products base on a windows service which utilize MS Office 2007 or Open Office capabilities to export your documents in PDF format.

I’m not very satisfy to accomplish the requirements with a product, so I started to investigate different examples to create my custom solution.

I started with the following projects hosted on “The Code Project” portal.

While the first example is pretty easy to try (the only trouble is to find the correct version of Open Office to install :-)), the second hides unpredictable scenarios. In fact, after the test of the Office automation using the simple application form in the example, I try to export the code in a windows service process. The code is the same you can find in this MSDN article:

   1: try
   2: {
   3:     // Open the source document.
   4:     wordDocument = wordApplication.Documents.Open(
   5:         ref paramSourceDocPath, ref paramMissing, ref paramMissing,
   6:         ref paramMissing, ref paramMissing, ref paramMissing,
   7:         ref paramMissing, ref paramMissing, ref paramMissing,
   8:         ref paramMissing, ref paramMissing, ref paramMissing,
   9:         ref paramMissing, ref paramMissing, ref paramMissing,
  10:         ref paramMissing);
  11:  
  12:     // Export it in the specified format.
  13:     if (wordDocument != null)
  14:         wordDocument.ExportAsFixedFormat(paramExportFilePath,
  15:             paramExportFormat, paramOpenAfterExport, 
  16:             paramExportOptimizeFor, paramExportRange, paramStartPage,
  17:             paramEndPage, paramExportItem, paramIncludeDocProps, 
  18:             paramKeepIRM, paramCreateBookmarks, paramDocStructureTags, 
  19:             paramBitmapMissingFonts, paramUseISO19005_1,
  20:             ref paramMissing);
  21: }
  22: catch (Exception ex)
  23: {
  24:     // Respond to the error
  25: }
  26: finally
  27: {
  28:     // Close and release the Document object.
  29:     if (wordDocument != null)
  30:     {
  31:         wordDocument.Close(ref paramMissing, ref paramMissing,
  32:             ref paramMissing);
  33:         wordDocument = null;
  34:     }
  35:  
  36:     // Quit Word and release the ApplicationClass object.
  37:     if (wordApplication != null)
  38:     {
  39:         wordApplication.Quit(ref paramMissing, ref paramMissing,
  40:             ref paramMissing);
  41:         wordApplication = null;
  42:     }
  43:     
  44:     GC.Collect();
  45:     GC.WaitForPendingFinalizers();
  46:     GC.Collect();
  47:     GC.WaitForPendingFinalizers();
  48: }

I need to tell you that my dev environment is based on Windows Server 2008 (x86) with the latest SP. When I tried to convert the first doc file using the service, I receive the bitter newness. Despite the code were the same, convert process failed. Debugging, I found out that Word could not open the file and returned a null object (see row 13 in above code block).
Google searching response, further the “Microsoft does not support Office server side automation (for version till 2007 – see here)” notice, says that other guys experienced in same problem using Windows 2008 services (see this post). So, I tried the same custom service in a virtual machine with Windows Server 2003 and all went well. With an in deep search I’ve found other very usefully posts regarding Windows 2008 Server family lack about a particular folders. In detail:
  • for x64 system is necessary to create the following folder:
    C:\Windows\SysWOW64\config\systemprofile\Desktop
  • for x86 system:
    C:\Windows\System32\config\systemprofile\Desktop

After this little tip, also Windows Server 2008 service resumed to work well providing the Office automation desired.

References:
kick it on DotNetKicks.com
Save to delicious 0 saves

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