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?
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.
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=""[APPCMD]" set app "[WEB_SITE_NAME]/[WEB_APP_NAME]" /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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With