views:

2633

answers:

3

I want to deploy a VSTO 3 Application Level Word 2007 addin that I've written with Visual Studio 2008. I see that WiX has an extension named WixOfficeExtension that looks like it might have this functionality, but I can't find any documentation for it, and I can't discern it's purpose from the source code.

Has anyone attempted this before, and were you able to pull it off successfully?

+3  A: 

I am surprised no one has answered this... I been researching Addins, so I will just dump a few links here. I am not sure you if you have already found the solution for what you were looking for but this can help others searching like me:

The answer is installing vsto 3.0 addins for office does work for wix, but I dont know anything about this WixOfficeExtension? For me to get it working was not a simple task and you need quite a bit of things to get this accomplished correctly:

Step 1. Do I really want to use a VSTO?

See here: http://social.msdn.microsoft.com/Forums/en-US/vsto/thread/3f97705a-6052-4296-a10a-bfa3a39ab4e7/#)http://social.msdn.microsoft.com/Forums/en-US/vsto/thread/3f97705a-6052-4296-a10a-bfa3a39ab4e7/#

Step 2. Ok VSTO is right read here:

From MS Misha Shneerson-- Deploying VSTO for 2007: http://blogs.msdn.com/mshneer/archive/2006/01/05/deployment-articles.aspx Microsoft Deployment info here: http://msdn.microsoft.com/en-us/library/bb386179.aspx#

Step 3. Do I need to install more than one addin at a time or want to use WIX cause I want it? Go to step 4.

If not use the installer in visual studio and make your life easy... Here is Microsofts setup installer, easiest way: http://msdn.microsoft.com/en-us/library/cc563937.aspx

Go here to find a a good summary of tips/ideas. I browse the forums for help as well here, very good site.(well summarized, geered for outlook but applicable to office): http://www.outlookcode.com/article.aspx?ID=42

Step 4. Wix

A)Get familiar with this you need it:Registry Entries for Application-Level Add-Ins http://msdn.microsoft.com/en-us/library/bb386106.aspx#

B)Use the setup object based from windows installer in visual studio to generate an MSI file.

C)Test that msi and make sure your addin works using the microsoft MSI. Trust me that many of the problems take you the most time here.

D)Run dark.exe (in wix bin) and take a look at the registry settings that were created for the output file.

E)Add these registry settings into your wix file.
--I did find this blog a little helpful, but it was for com addons for Excel: http://matthewrowan.spaces.live.com/blog/cns!CCB05A30BCA0FF01!143.entry

F)Run and deploy.

Note: I will add more here as I find more here. I am still learning Wix and what I can do with it in Terms of addins, etc. Wix is great, Office addins deployment is a royal pain.

Brian
I actually did succeed in getting this done, will post an answer as soon as time allows...
Jacob
Very nice. I hope this helps others as wix is not the easiest to get working with addins. I actually have been working alot on COM addins but tested VSTO also.
Brian
+8  A: 

This is the code I ended up using. I basically ported the examples from MSDN to use WiX.

Note: This specific solution is only for a Word 2007 addin, but the case for Excel is very similar. Simply modify the registry/component checks and keys/values according to the aforementioned MSDN Article.

Inclusion List Custom Action

In order to run addins with full trust, it must be added to the Inclusion List for the current user. The only way to do this reliably is with a custom action. This is a port of the custom action in the article to the new Deployment Tools Foundation included with WiX.

To use it, create a new DTF project called VSTOCustomAction and add CustomAction.cs.

CustomAction.cs
using System;
using System.Security;
using System.Security.Permissions;
using Microsoft.Deployment.WindowsInstaller;
using Microsoft.VisualStudio.Tools.Office.Runtime.Security;

namespace VSTOCustomActions
{
    public class CustomActions
    {
        private static string GetPublicKey(Session session)
        {
            return session["VSTOCustomAction_PublicKey"];
        }
        private static string GetManifestLocation(Session session)
        {
            return session["VSTOCustomAction_ManifestLocation"];
        }
        private static void ErrorMessage(string message, Session session)
        {
            using (Record r = new Record(message))
            {
                session.Message(InstallMessage.Error, r);
            }
        }

        [CustomAction]
        public static ActionResult AddToInclusionList(Session session)
        {
            try
            {
                SecurityPermission permission =
                    new SecurityPermission(PermissionState.Unrestricted);
                permission.Demand();
            }
            catch (SecurityException)
            {
                ErrorMessage("You have insufficient privileges to " +
                    "register a trust relationship. Start Excel " +
                    "and confirm the trust dialog to run the addin.", session);
                return ActionResult.Failure;
            }

            Uri deploymentManifestLocation = null;
            if (Uri.TryCreate(GetManifestLocation(session),
                UriKind.RelativeOrAbsolute, out deploymentManifestLocation) == false)
            {
                ErrorMessage("The location of the deployment manifest is missing or invalid.", session);
                return ActionResult.Failure;
            }

            AddInSecurityEntry entry = new AddInSecurityEntry(deploymentManifestLocation, GetPublicKey(session));
            UserInclusionList.Add(entry);

            session.CustomActionData.Add("VSTOCustomAction_ManifestLocation", deploymentManifestLocation.ToString());

            return ActionResult.Success;

        }

        [CustomAction]
        public static ActionResult RemoveFromInclusionList(Session session)
        {
            string uriString = session.CustomActionData["VSTOCustomAction_ManifestLocation"];
            if (!string.IsNullOrEmpty(uriString))
            {
                Uri deploymentManifestLocation = new Uri(uriString);
                UserInclusionList.Remove(deploymentManifestLocation);
            }
            return ActionResult.Success;
        }

    }
}

Wix Fragment

We obviously need the actual WiX file to install the addin. Reference it from your main .wcs file with

<FeatureRef Id="MyAddinComponent"/>
Addin.wcs
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"&gt;
    <Fragment Id="Word2007Fragment">

      <!-- Include the VSTO Custom action  -->
      <Binary Id="VSTOCustomAction" SourceFile="path\to\VSTOCustomAction.dll"/>
      <CustomAction Id="AddToInclusionList" BinaryKey="VSTOCustomAction" DllEntry="AddToInclusionList" Execute="immediate"/>
      <CustomAction Id="RemoveFromInclusionList" BinaryKey="VSTOCustomAction" DllEntry="RemoveFromInclusionList" Execute="immediate"/>

      <!-- Set the parameters read by the Custom action -->
      <!-- 
     The public key that you used to sign your dll, looks something like <RSAKeyValue><Modulus>...</Modulus><Exponent>...</Exponent></RSAKeyValue>
     Take note: There should be no whitespace in the key!
      -->
      <Property Id="VSTOCustomAction_PublicKey"><![CDATA[Paste you public key here]]></Property>
      <CustomAction Id="PropertyAssign_ManifestLocation" Property="VSTOCustomAction_ManifestLocation" Value="[INSTALLDIR]MyAddin.MyAddin.vsto" />

      <!-- Properties to check prerequisites -->
      <Property Id="VSTORUNTIME">
        <RegistrySearch Id="RegistrySearchVsto"
                        Root="HKLM"
                        Key="SOFTWARE\Microsoft\vsto runtime Setup\v9.0.30729"
                        Name="SP"
                        Type="raw"/>
      </Property>
      <Property Id="HASWORDPIA">
        <ComponentSearch Id="ComponentSearchWordPIA"
                         Guid="{816D4DFD-FF7B-4C16-8943-EEB07DF989CB}"/>
      </Property>
      <Property Id="HASSHAREDPIA">
        <ComponentSearch Id="ComponentSearchSharedPIA"
                         Guid="{FAB10E66-B22C-4274-8647-7CA1BA5EF30F}"/>
      </Property>


      <!-- Feature and component to include the necessary files -->
      <Feature Id="MyAddinComponent" Title ="Word 2007 Addin" Level="1" AllowAdvertise="no">
        <ComponentRef Id="MyAddinComponent"/>
        <Condition Level="0"><![CDATA[NOT ((VSTORUNTIME="#1") AND HASSHAREDPIA AND HASWORDPIA)]]></Condition>
      </Feature>

      <DirectoryRef Id="INSTALLDIR">
          <Component Id="MyAddinComponent" Guid="your component guid here">
              <File Name="MyAddin.dll" Source="path\to\MyAddin.dll" />
              <File Name="MyAddin.dll.manifest" Source="path\to\MyAddin.dll.manifest" />
              <File Name="MyAddin.vsto" Source="path\to\MyAddin.vsto" />
              <RegistryKey Root="HKCU"
                  Key="Software\Microsoft\Office\Word\Addins\MyAddin"
                  Action="createAndRemoveOnUninstall">
                <RegistryValue Type="string" Name="FriendlyName" Value="MyAddin Word 2007 Addin" />
                <RegistryValue Type="string" Name="Description" Value="MyAddin Word 2007 Addin" />
                <RegistryValue Type="string" Name="Manifest" Value="[INSTALLDIR]MyAddin.vsto|vstolocal" KeyPath="yes"/>
                <RegistryValue Type="integer" Name="LoadBehavior" Value="3"/>
              </RegistryKey>
          </Component>
      </DirectoryRef>

      <!-- Modify the install sequence to call our custom action -->
      <InstallExecuteSequence>
        <Custom Action="AddToInclusionList" After="InstallFinalize"><![CDATA[(&MyAddinComponent = 3) AND NOT (!MyAddinComponent = 3)]]></Custom>
        <Custom Action="PropertyAssign_ManifestLocation" Before="AddToInclusionList"><![CDATA[(&MyAddinComponent = 3) AND NOT (!MyAddinComponent = 3)]]></Custom>
        <Custom Action="RemoveFromInclusionList" After="InstallFinalize"><![CDATA[(&MyAddinComponent = 2) AND NOT (!MyAddinComponent = 2)]]></Custom>
      </InstallExecuteSequence>
    </Fragment>
</Wix>

Hope that this saves some time for someone out there.

Jacob
PropertyAssign_ManifestLocation should be evaluated before "RemoveFromInclusionList" as well, otherwise major upgrades will fail.
Rinat Abdullin
A: 

Jacob,

Did you get a chance to post a final solution anywhere?

Zi

Zi Makki
Yes, see the accepted answer. [Also note, answers are for answers, comments are for discussion. Welcome to stackoverflow ;)]
Jacob