none
Deploying Outlook Add-In (after following tutorial Part 2)

    Question

  • First off, it's worth saying that VSTO 2005 is excellent both as a product and as supported by all of the great articles and samples. Office has become a very important Hosting environment for enterprise applications and VSTO (and the community) is exactly what we need.

    I just finally got my Outlook Add-In to work with one-click deployment, but I needed to customize the SetSecurity project referenced in the Part 2 Walk-thru.

    I added a "trustTargetDir" parameter and when "trustTargetDir" is true, then the AddSecurityPolicy method uses "FullTrust" o the targetDir.

    In my case, I'm using Redemption.dll because I need to manipulate MAPI Extended Headers, and even though I set the Interop.Redemption.dll also as a target of a Custom Action in my Setup project to mark it as FullTrust, my Outlook Add-In project would not work on the client until the targetDir was set to FullTrust.

    Any insights on this?

    Kevin Farley, MCSD, MCDBA, Principal Solutions Architect
    EMC Microsoft Practice

    Friday, February 24, 2006 2:35 PM

Answers

  • Thanks.

    Meanwhile, I had another approach because I am not sure your method is 100% safe.

    I reused the parameter assemvbly name to be a list of DLLs wth coma separator. Example :
    /assemblyName="foo.dll,bar.dll"

    Modified code in SetSecurity.cs:

    After string assemblyName = this.Context.Parameters["assemblyName"]; add :
    string[] assemblyNames = assemblyName.Split(new Char[] { ',' });

    Replace :
                    CaspolSecurityPolicyCreator.AddSecurityPolicy(
                        allUsers,
                        solutionCodeGroupName,
                        solutionCodeGroupDescription,
                        assemblyPath,
                        assemblyCodeGroupName,
                        assemblyCodeGroupDescription);
            
    With :
     foreach (string name in assemblyNames)
                    {
                        string path = Path.Combine(targetDir, name);

                        CaspolSecurityPolicyCreator.AddSecurityPolicy(
                        allUsers,
                        solutionCodeGroupName,
                        solutionCodeGroupDescription,
                        path,
                        assemblyCodeGroupName,
                        assemblyCodeGroupDescription);
                    }

    That's it !
    • Marked as answer by Tim Li Thursday, April 2, 2009 7:48 AM
    Wednesday, May 24, 2006 1:11 PM
  • I fixed this issue. It was a "feature" of the SetSecurity process which was not designed to handle multiple assemblies passed in for the same Assembly Group.

    Each time you pass an Assembly in to the SetSecurity process it first Deletes the Security Policy for the Assembly Group, then it adds a Nothing Security Policy for the -url and then a FullTrust for the Assembly only.

    I updated SetSecurity to provide the following 2 additional features:

    /trustTargetDir - this parameter allows you to create the Policy Group as Full Trust on the entire -url

    /groupExists - this parameter bypasses the Remove Group option and the Create Group option and simply adds the Assembly to the AssemblyGroup Policy

    Now everything is working fine, and now I don't do a FullTrust on the -url.

    I recommend the Tutorial Part 2 sample code be updated to something along the lines above and documented on how to handle multiple assemblies.

    I'm leaving this marked open until someone can review the suggestions above.

    Kevin Farley, MCSD, MCDBA, Principal Solutions Architect
    EMC Microsoft Practice

    Monday, February 27, 2006 9:30 PM
  • Hi Kevin,

    You are correct - the SetSecurity code sample demonstrates adding security settings for a single assembly only.

    There are several ways to extend the sample to handle multiple assemblies:

    - if the custom action is invoked once, all assemblies can be passed at once to the custom action and security policy can be added for each of them in a loop in the custom action code

    - if the custom action is invoked separately for each assembly, the code can be extended to something along the lines you pointed in your solution

     

    Thank you for your feedback. We will consider extending the sample to cover multiple assemblies as well.

     

    Lubo

    Tuesday, February 28, 2006 6:13 PM

All replies

  • Kevin,

    Thanks for you enthusiastic endorsement of Visual Studio Tools for Office. I forwarded your comment to the team. Again, thanks.

    A couple of things:

    1) We do not support redemption, so I will not speak to that product specifically.

    2) What evidence are you using to grant the full trust? Is it a signed assembly? Or, are you determining fulltrust by location of the assembly? If it is the latter, then it would make sense that the assembly would not run until you designate the directory where the assembly is located as being a trusted location.

    I'll sort it out with you, and I look forward to your response.

    John.

    Friday, February 24, 2006 5:04 PM
  • No problem not endorsing Redemption on your part. For my part, its fair to say that Redemption rocks when you need Safe Extended MAPI support.

    Regarding VSTO and this community, frankly the support and available information is amazing and hopefully your bonuses (and stock) will reflect all of this. I have the Eric duo book as well, which is required reading as far as I can tell.

    Regarding Security Policy, ah..that is an interesting topic. I can say that Office as a Secure Hosting environment is excellent and the attention to detail in this area is a great demonstration of how secure Windows and Office are becoming.

    I followed the Tutorial instructions and added the name and url as evidence for each assembly. This worked because each time I did this (first one assembly, then the other), it solved the Security Exception thrown by Office.

    But even after having a Security Policy for the Assemblies (by name) the solution now was in the mysterious "COM object could not load" error that befuddles all of us. I had Exception handling in place so I wasn't handing any Exceptions back to the Office run-time.

    I eliminate the problem when I use a Security Policy for the entire TargetDir using the targetDir as evidence.

    If there is some trace logging I can set for the Office run-time to figure out what specific error (or assembly/COM object) is causing the silent issue, then I'll be glad to try it out. In my case, the solution requires the non-endorsed Redemption.dll, an Interop.Redemption.dll and my Solution.dll. It also refers to AzROLES.dll, and CDO (for CdoPropTags). So it uses Interop.AzROLES.dll and Interop.MAPI.dll. The solution is strong-named. Since I don't get Security Exceptions on any other Assemblies I haven't added them as Custom Actions for SetSecurity.

    Are other assemblies loading in the Office secure AppDomain that I should add as Custom Actions by name to solve this problem?

    As an aside to the product team (who genuinely have done a great job), the whole Deployment Pre-req issue, and SecurityPolicy issue, which I have now solved for myself by referring to Mads Blog on Pre-Req building, and Part 2 Tutorial (plus my change), would be something to add to the VSTO Wizard.

    The Wizard could add the SetSecurity Project, the Custom Actions, and the Pre-Req elements at some appropriate point in a future Svc Pak (much like the InfoPath Svc Pak 1). This way, every developer using VSTO doesn't have to solve this issue independently.

    Another aside, I had to spend a lot of time solving InfoPath Trusted Forms in a similar fashion as this was also imperfectly documented and buried in numerous technical articles. The Security Policy is good, having each Developer have to figure it all out with numerous web searches, white papers, blogs, experiments is not.

    regards,

    Kevin Farley, MCSD, MCDBA, Principal Solutions Architect
    EMC Microsoft Practice

    Friday, February 24, 2006 9:02 PM
  • Kevin,

    It is interesting that trusting the entire folder solves the problem. What other files do you place into the target directory? Remember that not just assemblies can cause other code to be loaded so not just assemblies need to be trusted.

    For example - if you have a .config file that causes some objects to be loaded through reflection then the .config file should be trusted as well. (this is the actual problem we ran into before with WSE 3.0 used with VSTO - I wish I could find the post but google turns up nothing).

    Saturday, February 25, 2006 4:05 AM
  • These are the assemblies in the install dir:

    Interop.AZROLESLib.dll
    Interop.MAPI.dll
    Interop.Redemption.dll
    SendMailRulesCheck.dll
    SendMailRulesCheck.dll.manifest
    SetSecurity.dll
    SetSecurity.InstallState
    VSTOStorageWrapper.Interop.dll

    Works like a charm when the full-path is trusted, and this happens in the Custom Action now with my added /trustTargetDir="true" parameter on the SetSecurity project.

    Monday, February 27, 2006 4:21 PM
  • I fixed this issue. It was a "feature" of the SetSecurity process which was not designed to handle multiple assemblies passed in for the same Assembly Group.

    Each time you pass an Assembly in to the SetSecurity process it first Deletes the Security Policy for the Assembly Group, then it adds a Nothing Security Policy for the -url and then a FullTrust for the Assembly only.

    I updated SetSecurity to provide the following 2 additional features:

    /trustTargetDir - this parameter allows you to create the Policy Group as Full Trust on the entire -url

    /groupExists - this parameter bypasses the Remove Group option and the Create Group option and simply adds the Assembly to the AssemblyGroup Policy

    Now everything is working fine, and now I don't do a FullTrust on the -url.

    I recommend the Tutorial Part 2 sample code be updated to something along the lines above and documented on how to handle multiple assemblies.

    I'm leaving this marked open until someone can review the suggestions above.

    Kevin Farley, MCSD, MCDBA, Principal Solutions Architect
    EMC Microsoft Practice

    Monday, February 27, 2006 9:30 PM
  • Thanks for pointing this out. I can pass your comments regarding the tutorials on.
    Tuesday, February 28, 2006 9:06 AM
  • Hi Kevin,

    You are correct - the SetSecurity code sample demonstrates adding security settings for a single assembly only.

    There are several ways to extend the sample to handle multiple assemblies:

    - if the custom action is invoked once, all assemblies can be passed at once to the custom action and security policy can be added for each of them in a loop in the custom action code

    - if the custom action is invoked separately for each assembly, the code can be extended to something along the lines you pointed in your solution

     

    Thank you for your feedback. We will consider extending the sample to cover multiple assemblies as well.

     

    Lubo

    Tuesday, February 28, 2006 6:13 PM
  • Hello Kevin

    I'm facing the same problem as you did but I can't figure out how did you gave a Full Trust to the entire directory and what did you mean with: /trustTargetDir=true.

    in other words, what do I have to change in the SetSecurity Project?

    Thanks a lot, Yoav

    Wednesday, April 12, 2006 2:35 PM
  • Hi,

    I'd be very interested in that too. Thanks.
    Wednesday, May 24, 2006 12:17 PM
  • Sorry I didn't see this for a while....

    I changed the SetSecurity project to allow for 2 more parameters....1 to Trust the Entire TargetDirectory and 1 to signify that the SolutionCodeGroup already exists.

    Note that the default behavior is to delete the SolutionCodeGroup prior to re-adding it.

    So now, using the same Command-line switch approach I can either choose to trust the entire targetDir (not the very best recommendation, but sometimes neccessary) or specifically add Assemblies to an existing SolutionCodeGroup and signify not to delete this CodeGroup prior to adding the new assembly to it.

    I could give you the code (not too many lines actually) ... but I learned a  lot by doing this myself and recommend the same to others as an exercise in CASPOL policy deployment. Here is an outline of steps to follow:

    1. Add 2 more parameter switches "groupExists" and "trustTargetDir"

    2. Add code to default these to false etc.

    3. Add the IF statement prior to the delete on the codeGroup if the groupExists is set to true

    4. Add the 2 parameters to the AddSecurityPolicy method and handle the trustTargetDir and groupExists functionality there. Not too hard really, and good to solve yourself for future issues like this.

    regards,

    kjf

    Wednesday, May 24, 2006 12:28 PM
  • Hi - I posted a response to the prior thread...give it a try!

    kjf

    Wednesday, May 24, 2006 12:29 PM
  • Thanks.

    Meanwhile, I had another approach because I am not sure your method is 100% safe.

    I reused the parameter assemvbly name to be a list of DLLs wth coma separator. Example :
    /assemblyName="foo.dll,bar.dll"

    Modified code in SetSecurity.cs:

    After string assemblyName = this.Context.Parameters["assemblyName"]; add :
    string[] assemblyNames = assemblyName.Split(new Char[] { ',' });

    Replace :
                    CaspolSecurityPolicyCreator.AddSecurityPolicy(
                        allUsers,
                        solutionCodeGroupName,
                        solutionCodeGroupDescription,
                        assemblyPath,
                        assemblyCodeGroupName,
                        assemblyCodeGroupDescription);
            
    With :
     foreach (string name in assemblyNames)
                    {
                        string path = Path.Combine(targetDir, name);

                        CaspolSecurityPolicyCreator.AddSecurityPolicy(
                        allUsers,
                        solutionCodeGroupName,
                        solutionCodeGroupDescription,
                        path,
                        assemblyCodeGroupName,
                        assemblyCodeGroupDescription);
                    }

    That's it !
    • Marked as answer by Tim Li Thursday, April 2, 2009 7:48 AM
    Wednesday, May 24, 2006 1:11 PM
  • Lex007,

    That is just what I'm looking for!  I'm going to try it, it looks like it should work.

    Ours, like most companies use an n-tier framework, so have more than one assembly for any given application (including Office Add-ins). 

     

    Wednesday, September 27, 2006 9:57 PM
  • I was looking at the original thread that was posted in Feb 2006 and today the date is May 18, 2007. It's been more than a year but no one at MS has updated the MSDN article. I wasted one whole day to figure out the problem. I was getting the "runtime error: addin can not be loaded" error and it was solved only when I gave permissions to the whole folder, not only the single DLL. Thanks Lex007 for sharing your code, it saved some of my time!

     

    Suggestion for MS: The article in question should be updated with this new information as soon as possible so that new users don't have to face these problems.

     

    Thanks,

     

    S.S. Ahmed

     

    --

    Friday, May 18, 2007 3:00 PM
  • Fantastic!  This sorted me out after two days of despair!

     

    Five start post!.

     

    Someone in the development team MUST put a note at least in the tutorials about multiple assemblies and this solution. Anyone writing an Outlook add-in for 2003 is almost certain to need Redemption.  It took me a long time to find this solution. Someone like me new to VSTO and new to .NET and Outlook programming has a mountain to climb to write even the simplest add-in.

     

    thanks Lex.

     

    Thursday, April 10, 2008 7:05 AM
  • Hi, I've tried following the solution at the forum without luck Sad

     

    The SetSecurity project I'm using is the one available to download from the deployment tutorial, the name of the installed folder is Microsoft Visual Studio 2005 Tools for Office SE Resources. I applied what Lex007 said, using a loop for and putting all assemblies separated by comas.

     

    Then with those changes I've added the primary output from SetSecurity Project to my setup project and in the custom actions part added one custom action referenced to primary output set security.


    That adds the custom action for all operations: install, commit, rollback, uninstall.

    Then selecting the install custom action in the CustomActionData property i wrote: /assemblyName="UrbeMap.dll,age2005dll.dll,Wizard.dll" /targetDir="[TARGETDIR]\" /solutionCodeGroupName="UrbeMap" /solutionCodeGroupDescription="Maps for Office" /assemblyCodeGroupName="UrbeMap" /assemblyCodeGroupDescription="Maps for Office" /allUsers=[ALLUSERS]

    (UrbeMap it's my main project).

    On the other 3 operations i wrote in the CustomActionData property: /solutionCodeGroupName="UrbeMap"

     

    When i tried to install i got the error:

     

    Cannot set the security policy ---> Cannot create the security code group 'UrbeMap' ---> The module must have and assembly manifest (Exception HRESULT: 0x80131018).

     

    I read the original solution by Kevin Farley but I couldn't reproduce it. I've read through the code but didn't find where and how to put to trust the entire dir or to make it not delete the previous group name.

     

    I hope you can give me further advice

    Thanks a lot for your help

    Martin

    Tuesday, May 6, 2008 7:56 PM
  • I agree with you benjaxed - Lex created a five start post. This removed a great headeck of mine :0)

    Thursday, June 19, 2008 8:49 PM
  • 2 years gone since the first message was posted. And for today I've got the same error, because article was not updated
    Tuesday, July 15, 2008 2:34 PM
  • 3 years.. Tuturial still not updated.. I went through the same thing and I solved it by following this link:
    http://blogs.msdn.com/akashb/archive/2008/10/10/8994631.aspx

    Lex's code didn't work for me. I received an error message saying that user already exists..
    Thursday, July 9, 2009 3:43 PM
  • My Outlook add-in works OK on development machine, I built it and tried installing on another machine. Installation works OK, but when the outlook is opened, the add-in isn't "there".
    I tried to follow instructions from MSDN: http://msdn.microsoft.com/en-us/library/ms406084.aspx ...I can follow them until the "Adding a Custom Action to Grant Trust to the Assembly"- I don't have sample project "SetSecurity" on my machine. I installed VS2k8 + SDK.

    where can I get SetSecurity demo project?
    Tuesday, August 4, 2009 5:12 PM
  • Hi everybody, 

    I have Two client vista machines with the same security configuration.
    I build my project on my developpement machine then copy ".exe" and try to install it on the first client machine.
    I have got a weird 2869 error message and installation process stopped.
    In the second machine , I installed my plug in with no problem but, when I start Outlook, I see my plugin in the incactive plugin list and doesnt  load.?
    Its surely due to grating trust security level ? In my solution I added also à Security project that give all assemblies the good trust level.

    I Have followed many tutorials in the net but withour any good result as this one :

    Office 2K7, Windows Vista ( same problem encoutred on windows XP ) and VS 2005.

    I will appreciate very much any of your help !
    Monday, August 10, 2009 12:13 PM
  • Worked for me too :) thanks
    Wednesday, April 14, 2010 9:42 AM