How to add net.tcp to the "Enabled protocols" by using a WIX 3.5 project/setup?
Asked Answered
S

4

11

We have a few MSI packages (generated by WIX) that install WCF services. Most of these services need net.tcp for their endpoint bindings.

I'd like to make our deployment life easier and automate the process of adding net.tcp. I already know the WixIisExtension.dll and make use of its useful functions (create web site, virt. directory, etc.).

Can I use the WixIisExtension to enable the net.tcp protocol? If not, how can I achieve that?

Stroud answered 29/6, 2010 at 12:40 Comment(1)
In the official Windows Installer XML Toolset 3.5 Documentation I could not find any topic that describes how to do that. I would have assumed that should be possible using the IIS elements (like WebDirProperties, WebVirtualDir or WebApplication) but there is nothing that could lead me into the right direction.Stroud
V
7

Add a new Project to your Setup Solution (Windows Installer XML -> C# Custom Action Project)

In this Project add a reference to the Assembly Microsoft.Web.Administration, which can be found here: C:\Windows\System32\inetsrv and is required to add the protocols.

My Custom Action looks like this:

using System;
using System.Linq;
using Microsoft.Deployment.WindowsInstaller;
using Microsoft.Web.Administration;

namespace Setup.CustomAction.EnableProtocols
{
    public class CustomActions
    {
        [CustomAction]
        public static ActionResult EnableProtocols(Session session)
        {
            session.Log("Begin EnableProtocols");

            var siteName = session["SITE"];
            if (string.IsNullOrEmpty(siteName))
            {
                session.Log("Property [SITE] missing");
                return ActionResult.NotExecuted;
            }

            var alias = session["VIRTUALDIRECTORYALIAS"];
            if (string.IsNullOrEmpty(alias))
            {
                session.Log("Property [VIRTUALDIRECTORYALIAS] missing");
                return ActionResult.NotExecuted;
            }

            var protocols = session["PROTOCOLS"];
            if (string.IsNullOrEmpty(protocols))
            {
                session.Log("Property [PROTOCOLS] missing");
                return ActionResult.NotExecuted;
            }

            try
            {
                var manager = new ServerManager();

                var site = manager.Sites.FirstOrDefault(x => x.Name.ToUpper() == siteName.ToUpper());
                if (site == null)
                {
                    session.Log("Site with name {0} not found", siteName);
                    return ActionResult.NotExecuted;
                }

                var application = site.Applications.FirstOrDefault(x => x.Path.ToUpper().Contains(alias.ToUpper()));
                if (application == null)
                {
                    session.Log("Application with path containing {0} not found", alias);
                    return ActionResult.NotExecuted;
                }

                application.EnabledProtocols = protocols;
                manager.CommitChanges();
                return ActionResult.Success;
            }
            catch (Exception exception)
            {
                session.Log("Error setting enabled protocols: {0}", exception.ToString());
                return ActionResult.Failure;
            }
        }
    }
}

Please note that I am assuming three properties here: SITE, VIRTUALDIRECTORYALIAS & PROTOCOLS

Build the solution now. In the background, WiX creates two assemblies %Project%.dll and %Project%.CA.dll. The CA.dll includes the depending Microsoft.Web.Administration automatically.

Then in your WiX Setup Project include a reference to the new Custom Action Project. The reference is required for referencing the %Projet%.CA.dll.

Edit the product.wxs

First add the properties somewhere inside the product element:

<!-- Properties -->
<Property Id="SITE" Value="MySite" />
<Property Id="VIRTUALDIRECTORYALIAS" Value="MyVirtDirectoryAlias" />
<Property Id="PROTOCOLS" Value="http,net.tcp" />

Below add the binary element:

<!-- Binaries -->
<Binary Id="CustomAction.EnableProtocols" SourceFile="$(var.Setup.CustomAction.EnableProtocols.TargetDir)Setup.CustomAction.EnableProtocols.CA.dll" />

Note that you have to add the CA.dll.

Below add the Custom Action:

<!-- Custom Actions -->
<CustomAction Id="EnableProtocols" BinaryKey="CustomAction.EnableProtocols" DllEntry="EnableProtocols" Execute="immediate" Return="check" />

And finally the Installation Sequence where you want the execution to take place.

<!-- Installation Sequence -->
<InstallExecuteSequence>
  <Custom Action="EnableProtocols" After="InstallFinalize">NOT Installed</Custom>
</InstallExecuteSequence>

that's all. Should work. Thanks to Darin Dimitrov for providing the links above.

Vietnamese answered 21/6, 2012 at 14:52 Comment(5)
Great mini tutorial. Thanks for filling in how things relate. Esp the ".CA.dll" voodoo.Recording
Thanks! I've added a "check for existing" logic here ::: Binding foundBinding = site.Bindings.FirstOrDefault(b => b.Protocol.Equals(bindingProtocol, StringComparison.OrdinalIgnoreCase) && b.BindingInformation.Equals(bindingInformation, StringComparison.OrdinalIgnoreCase));Recording
if (null == foundBinding) { //// add bindings session.Log("About add to Site.Bindings. SITE='{0}', BINDINGINFORMATION='{1}', BINDINGPROTOCOL='{2}'.", sitename, bindingInformation, bindingProtocol); site.Bindings.Add(bindingInformation, bindingProtocol);Recording
serverManager.CommitChanges(); session.Log("ServerManager.CommitChanges successsful for adding to Site.Bindings. SITE='{0}', BINDINGINFORMATION='{1}', BINDINGPROTOCOL='{2}'.", sitename, bindingInformation, bindingProtocol); result = true; }Recording
else { session.Log(string.Format("Binding already exists. (SiteName='{0}', bindingInformation='{1}', bindingProtocol='{2}')", sitename, bindingInformation, bindingProtocol)); result = true; /* do not fail if the binding already exists, the point is to have the binding */ }Recording
S
5

Here is the right way to do this in WIX (assuming you are installing on a 64-bit operating system - if not at a guess I'd say change CAQuietExec64 to CAQuietExec although this is untested):

Get a reference to appcmd.exe:

<Property Id="APPCMD">
  <DirectorySearch Id="FindAppCmd" Depth="1" Path="[WindowsFolder]\system32\inetsrv\">
    <FileSearch Name="appcmd.exe"/>
  </DirectorySearch>
</Property>

Define the following custom actions (the properties [WEB_SITE_NAME] and [WEB_APP_NAME] can be populated elsewhere in your installer; or to test you can hard-code them):

<CustomAction
  Id="SetEnableNetTCPCommmand"
  Property="EnableNetTCP"
  Value="&quot;[APPCMD]&quot; set app &quot;[WEB_SITE_NAME]/[WEB_APP_NAME]&quot; /enabledProtocols:http,net.tcp"/>

<CustomAction 
  Id="EnableNetTCP"
  BinaryKey="WixCA"
  DllEntry="CAQuietExec64"
  Execute="deferred"
  Return="ignore"
  Impersonate="no" />

Now in the InstallExecuteSequence add

<InstallExecuteSequence>
  ...
  <Custom Action="SetEnableNetTCPCommmand" After="InstallExecute">APPCMD AND NOT Installed</Custom>
  <Custom Action="EnableNetTCP" After="SetEnableNetTCPCommmand">APPCMD AND NOT Installed</Custom>
  ...
</InstallExecuteSequence>

And if all is well in the world that will now update the protocols.

Statecraft answered 5/12, 2013 at 9:49 Comment(1)
Well played. I was deploying a WCF service hosted in IIS over named pipes. With a few tweaks, I now have "http,net.pipe" in my enabled protocols. This not being in the default wix-installer was a let down.Recording
A
1

You may take a look at this article on MSDN. There's a section at the end which illustrates how to use the managed API to achieve configure a WAS enabled service. I am not familiar with Wix but you could probably use and plug this code into some custom deployment step.

Asteriated answered 22/11, 2010 at 12:27 Comment(0)
R
1

This can't be done using the standard WiXIIsExtension, as far as I know. Thus, the only option you have is a custom action.

You can also find this thread interesting - it gives a hint how to achieve the similar thing in MSBuild script, but you should be able to translate it to custom action easily.

Good luck!

Roadside answered 25/11, 2010 at 12:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.