A few newbie questions

Apr 15, 2015 at 11:47 AM
Hi Oleg,

First off, great job with Wix#.

I'm completely new to Wix/Wix#, and trying to have my first MSI package built and ready. And I've got a few stumbles on my road. Maybe you or somebody else here can help me with those?

This is an example of the project:
var featureHostSvc = new Feature(
    "Service Host (Win Service)",
    "The host implemented as a Windows service",
    true)
{
    Attributes = new Dictionary<string, string> { { "AllowAdvertise", "no" } },
    ConfigurableDir = "SERVICEHOSTDIR"
};

File featureHostSvcInstaller;

var project =
    new Project(
        "My Product",
        new Dir(
            new Id("ROOTDIR"),
            defaultInstallDir,
            new Dir(
                new Id("SERVICEHOSTDIR"),
                "ServiceHost",
                new Files(featureHostSvc, @"Files\ServiceHost\*.*", new[] { "Service.Host.exe", "*.config" }),
                // avoid overwriting the existing config files
                new File(featureHostSvc, @"Files\ServiceHost\DB.config") { Condition = Condition.NOT_Installed },
                new File(featureHostSvc, @"Files\ServiceHost\Service.Host.exe.config") { Condition = Condition.NOT_Installed },
                featureHostSvcInstaller = new File(featureHostSvc, @"Files\ServiceHost\Service.Host.exe")),
            ...
        )
    )
{
    GUID =...,
    //UI = WUI.WixUI_Mondo,
    UI = WUI.WixUI_FeatureTree,
    Encoding = System.Text.Encoding.UTF8,
    Version = new Version(GetProductVersion()),
    MajorUpgradeStrategy = MajorUpgradeStrategy.Default
};

featureHostSvcInstaller.ServiceInstaller = new ServiceInstaller
{
    Name = "ServerHost",
    StartOn = SvcEvent.Install,
    StopOn = SvcEvent.InstallUninstall_Wait,
    RemoveOn = SvcEvent.Uninstall_Wait
};
1). When I build the project, I have LGHT0204/ICE30 errors regarding duplicated components. When taking a look into the produced WXS file, I can see 2 separate entries for "Service.Host.exe": one with a relative path to the source file (this is for the entry with the service installer in it), and another one with an absolute path to the source file.
<Component Id="Component.Service.Host.exe" Guid="...">
    <File Id="File.Service.Host.exe" Source="Files\ServiceHost\Service.Host.exe" />

    <ServiceInstall Id="ServerHost" Name="ServerHost" DisplayName="ServerHost" Description="..." Type="ownProcess" Start="auto" ErrorControl="normal" />

    <ServiceControl Id="StartServerHost" Name="ServerHost" Start="install" Wait="no" />
    <ServiceControl Id="StopServerHost" Name="ServerHost" Stop="both" Wait="yes" />
    <ServiceControl Id="RemoveServerHost" Name="ServerHost" Remove="uninstall" Wait="yes" />
</Component>

<Component Id="Component.Service.Host.exe.1" Guid="...">
    <File Id="File.Service.Host.exe.1" Source="C:\...\Files\ServiceHost\Service.Host.exe" />
</Component>
Is it as expected? Or is it a bug?

2). Regarding the way to avoid overwriting existing/installed *.config files. Is my approach with using conditions looks ok? Or should I be doing something else?

3). For my Win services I need to add some dependencies on other Win services. Is it doable in Wix? If yes, what would be the best approach?

Thanks in advance.

Cheers,
Pavel
Apr 15, 2015 at 1:08 PM
Hi Pavel,

It isn't a bug. I have modified your code a little so I can run it. I also added the output to verify that the wildcard path works OK:
project.ResolveWildCards()
       .AllFiles
       .ForEach(f =>Console.WriteLine(f.Name));
An this is the output:
Files\ServiceHost\DB.config
Files\ServiceHost\Service.Host.exe.config
Files\ServiceHost\Service.Host.exe
E:\...\Support\Services\Files\ServiceHost\readme.txt
E:\...\Support\Services\Files\ServiceHost\Service.Host.exe
Clearly the wildcard exclusions didn't work as expected. This is because the exclusion masks are applied for the whole file path not just name name. Thus the following small change fixes the problem:
new Files(svcFeature, @"Files\ServiceHost\*.*", new[] { "*Service.Host.exe", "*.config" })
The test also revealed that ResolveWildCards creates the mixture of absolute and relative paths. There is nothing wrong with this but I will change it for the next release to produce consistent file set.

BTW the the use of exclusion mask has been marked as obsolete, however I just missed the constructor that you used. Otherwise you would get a nice warning and advice to use predicate instead. Which is more intuitive comparing to the mask:
new Files(svcFeature, @"Files\ServiceHost\*.*", f => !f.EndsWith("Service.Host.exe") && 
                                                     !f.EndsWith(".config")),
You can find the whole adjusted solution here.

As for the service dependencies WiX allows expressing dependency via ServiceDependency element. Wix# does not support it directly so you will need to inject it as in the InjectXML sample. But... I think it is a useful feature and I am going to add it to the next release (in a day or two).
Apr 15, 2015 at 2:20 PM
Lovely, thanks a lot for the very quick reply.
What about the implementation for the NeverOverwrite Wix option? Is it expected to work for *.config files in my example in combination with Condition.NOT_Installed? Or is there another [better] approach to that in Wix#?
Apr 16, 2015 at 8:14 AM
Edited Apr 16, 2015 at 10:57 AM
I think Condition.NOT_Installed alone does what you want. If the file exist it doesn't overwrite it. Tough I am not sure about the MajorUpgrade scenario.

NeverOverwrite will come in the next release anyway.