Wednesday, 29 August 2007

Deploying an Outlook 2007 application written with VSTO 2005 SE

I've just spent a ridiculously long time trying to deploy an add-in for Outlook 2007 running on Windows Vista, written in C# with Visual Studio 2005 Tools for Office Second Edition. There's a pretty good walkthrough on MSDN, but it's got way too much information that's irrelevant (ie for Word and Excel document add-ins) and the print is just so small when it's printed...!

Anyway, after scouring a few blogs, I managed to get it to work, so for the convenience of anyone else attempting this, here are the steps I took, along with the pitfalls I encountered. For the purposes of this, I'm making the same assumptions as in the MSDN Walkthrough, ie:
  • There is only one customization assembly; there are no other referenced or satellite assemblies deployed with the solution.

  • Deployment is to a local file folder and not to some other location, such as a Web server or network file share.

  • Your solution does not use the optional deployment manifest.

------------------------------------------------------------------------------------------------------------
You will need:

The MSI included with the MSDN walkthrough
(http://go.microsoft.com/fwlink/?linkid=83721)

Windows SDK Components for Windows Installer Developers
(You only really need WiRunSQL.vbs, which can be found in C:\Program Files\Microsoft SDKs\Windows\v6.0\Samples\SysMgmt\MSI\scripts after you install this in the default directory)
(http://www.microsoft.com/downloads/details.aspx?familyid=C2B1E300-F358-4523-B479-F53D234CDCCF&displaylang=en)

Aaron Stebner's script for setting the NoImpersonate flag
(http://blogs.msdn.com/astebner/archive/2006/10/23/mailbag-how-to-set-the-noimpersonate-flag-for-a-custom-action-in-visual-studio-2005.aspx)

Office 2007 Primary Interop Assemblies
(http://www.microsoft.com/downloads/details.aspx?familyid=59daebaa-bed4-4282-a28c-b864d8bfa513)

Office 2003 Primary Interop Assemblies (optional, but I put them in anyway)
(http://www.microsoft.com/downloads/details.aspx?familyid=3c9a983a-ac14-4125-8ba0-d36d67e0f4ad)

VSTO Runtime Redistributable
(http://go.microsoft.com/fwlink/?linkid=49612)

------------------------------------------------------------------------------------------------------------
As a reference, the walkthrough is still good reading for background, so here you go:
Part 1: http://msdn2.microsoft.com/en-us/library/bb332051.aspx
Part 2: http://msdn2.microsoft.com/en-us/library/bb332052.aspx


Okay, now for the steps:
  1. Create your project, sign the assemblies and add the prerequisites to the setup project - all this is well-documented in the walkthrough. Don't forget to compile and copy the ComponentCheck. Relevant sections of the walkthroughs include:

    Part 1: "Adding the Visual Studio Tools for Office Packages to the Bootstrapper", through to "To copy the packages into the bootstrapper"

  2. Sign the assembly, add the prerequisites, and add the SetSecurity project to the solution. Relevant sections of the walkthroughs include:

    Part 2: "Signing the Assembly" through to "To add the custom action data for the Uninstall Method"

    Important note: The custom action data needs to be entered all in one line, and a space before every / kept. What I did was to copy the entire thing to notepad, edit it till it looked like this (I know it looks cut-off, but if you click on the start of the line and press shift + end, you should be able to highlight all of it for copying - putting it on separate lines would have made things ambiguous):

    /assemblyName="OutlookAddin.dll" /targetDir="[TARGETDIR]\" /solutionCodeGroupName="MyCompanyName.OutlookAddin" /solutionCodeGroupDescription="Code group for OutlookAddin" /assemblyCodeGroupName="OutlookAddin" /assemblyCodeGroupDescription="Code group for OutlookAddin" /allUsers=[ALLUSERS]

    and then pasted it into the CustomActionData field for the Install method. Ensure that the solutionCodeGroupName is the same for all three fields you modify. For those of you getting the "The specified solution code group name is not valid" error: this is probably the cause of it - make sure it's all in one line as above and you should be fine.

  3. There is an excellent guide on how to do this bit at http://www.shahine.com/omar/VSTOAddinsAndVista.aspx
    and given that I simply copied his steps, I really think you should take the trouble to head there and check it out.
And - that's it, really. Build the setup file, and if you followed the walkthrough sections I pointed out as well as that little pitfall there, and step number 3...your application should be installed! Hope this helps.

Thursday, 26 July 2007

Gridview

Was looking for a way to populate a Gridview with a simple array of strings, and everybody and their dog seems to be posting tutorials about doing it with SQL data sources, etc (Or maybe I'm just really hopeless at Googling information I need). And then I found this gem of a guide on Gridview by Mike Pope. Turns out the feature I needed is apparently undocumented (go figure), and if you go over to his site here, you'll find, in his words:

"Sometimes your life is even simpler -- you have an array with simple values in it, and you want to display those. It's easy enough to bind the grid to the array. But how do you bind a BoundField to the contents of the array element? Turns out that if you set the DataField property of a BoundField to !, it tells the field (column) to get the ToString() version of whatever's in the array. (I'm pretty sure this is undocumented, though perhaps not unknown.)"

Isn't life great when it's simple?

New lines!

I thought it would be appropriate to start a new blog with a post about new lines. We've been trying to get a label in ASP.Net's Gridview to display multilines for text that a user has entered in a textbox. Basically, the user would post a message in a textbox, and the page would refresh to show the message. For some reason, new lines weren't being displayed properly. It might be just me, but I drove myself mental trying to find a solution for this online, and while string.Replace(System.Environment.NewLine, "
") worked well for hardcoded new lines, new lines which were being entered by the user just weren't rendering right.

So after much tinkering involving displaying the ascii values of all non-alphabetic and numeric characters, I found that when a user hits Enter in a text box, it's stored as ascii value (10). System.Environment.NewLine for Windows systems is (13)(10) . And so this ugly line was born:

text = text.Replace(((char)10).ToString(), (((char)13).ToString()) + (((char)10).ToString()));

Surely someone can come up with a better way than that! Please enlighten me if you do, and I hope this helps someone else who has this problem.