1

I'm learning how to use WiX to create an installer for my projects, and would like to be able to reference my VS2019 C# project's assembly information as populated from the project's Properties > Application > Assembly Information button in my .wxs file.

I understand I can use add the project as a reference and then use a $(var.MyProject.???) declaration, but I have no idea where to find the list of viable dot notation properties for the project. Alternatly I know I can use '' with <Package Manufacturer="$(var.CompanyName)" .../> to save having to typing the data multiple times, but i'd still prefer to pull it from the project and have it in one place.

Image for Clarity

Thank you

SEO terms: wix assembly version. wix assembly information

Reahreic
  • 596
  • 2
  • 7
  • 26
  • Did you check the WiX mailing list? https://wixtoolset.org/documentation/mailinglist/ - [old searchable archive here](http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/). – Stein Åsmul Feb 12 '21 at 13:34
  • I've perused through a bunch of those with varying degrees of insight. The closest I've gotten is with an Inline task in my .wixproj file that uses C# to extract the data and puts it into a task output parameter. I believe I just need to get the output variable to be accessible from the .wxs file as a preprocessor variable and I'll have it. – Reahreic Feb 12 '21 at 14:16
  • What if a solution has multiple projects whose OutputType is WinExe? – Tu deschizi eu inchid Feb 12 '21 at 14:31
  • Being able to specify multiple assemblies and their data depending on the selected UI options and display their specific data as would be a +1. But for now just getting one to work will allow me to expand the capability as needed. – Reahreic Feb 12 '21 at 14:37

2 Answers2

1

Light.exe: See the WiX light.exe documentation here: https://wixtoolset.org/documentation/manual/v3/overview/light.html#standard-binder-variables

If you want to run with the version of your main assembly as the setup's ProductVersion you should be able to just do:

<Product Id="*" Name="MyProject" Version="!(bind.fileVersion.MyMain.exe)"
         Manufacturer="MyCorp" Language="1033" UpgradeCode="PUT-GUID-HERE">

 <..>

  <Component Feature="Main">
    <File Id="MyMain.exe" Source="MyMain.exe"></File>
  </Component>

WiX Sample: Complete Github.com sample here.

The fileLanguage and fileVersion are available for all versioned binaries. Dot NET assemblies support a number of further variables - see documentation (same link as at the top of the answer).

Rob Mensching: WiX creator Mensching has an answer here. Essence: "You can drive your product version off of an assembly's version using "!(bind.assemblyVersion.FileId)". ... You can only specify binder variables in .wxs files. It's a binder (in light.exe) concept not an MSBuild (in MSBuild.exe reading .wixproj files) concept"

Heath Stewart: Please check this blog for some information on .NET assembly values: https://devblogs.microsoft.com/setup/get-binder-variables-for-assemblies-without-installing-into-the-gac/ - Essence: "...to get binder variables for assemblies without installing into the GAC set File/@Assembly to “.net” or “win32”, then for the same file set File/@AssemblyApplication to the value for File/@Id"


Links:

Stein Åsmul
  • 39,960
  • 25
  • 91
  • 164
  • I'm using visual studio and not the command line directly and am unable to get the installer to build using any combination of bind's at all. The system just isn't able to resolve the bind-time variables no matter what I type. – Reahreic Feb 11 '21 at 18:08
  • So after hours of fighting, I've only been able to get `bind.assemblyName..ABC`, `bind.fileVersion.ABC` and `bind.property.ProductVersion.ABC` to work. None of the "Package" properties will resolve no matter what I try. – Reahreic Feb 11 '21 at 19:42
  • Sorry to hear that. I just added a Visual Studio sample. I am not sure about those "Package" properties - are they perhaps only for Bundle projects and not WiX projects? (Bundle projects create setup.exe launchers, regular WiX projects create MSI files). – Stein Åsmul Feb 11 '21 at 21:15
  • It looks to me like those properties are for Bundles to refer to values inside MSI files. [See this random example found on github.com](https://github.com/ChangemakerStudios/Papercut-SMTP/blob/58e08eca4f59052c102a4e1d364bf7687a2b82cc/src/Papercut.Bootstrapper/Bundle.wxs). – Stein Åsmul Feb 11 '21 at 21:44
  • I've not yet started the wix bundle project, I plan to leverage one (If I understand correctly) to create a nicely designed custom UI but haven't started with that yet. I've determined that I'll most likely need to add a BeforeBuild action to the wix project that runs some C# to extract the `FileVersionInfo` class from the designated file and place it in some custom preprocessor variables, but I'm not having much luck there either. (Who'd have thought that not having to hard-code all of the application information would be this much of a seemingly impossible task...) – Reahreic Feb 12 '21 at 12:40
  • What information do you need beyond the file version? A quick description might help to think of alternative solutions? [Hello Burn example](https://stackoverflow.com/a/52071758/129130). Some links there to advanced GUI too. [More here](https://stackoverflow.com/a/52349744/129130) and [dated by now, but looks good](https://bryanpjohnston.com/2012/09/28/custom-wix-managed-bootstrapper-application/comment-page-1/). and [Neil Sleightholm's Burn tips and tricks](http://neilsleightholm.blogspot.com/2012/05/wix-burn-tipstricks.html) – Stein Åsmul Feb 12 '21 at 12:47
  • I'd like to use each of the fields populated in the target project's Properties > Application > AssemblyInformation dialog without having to hard code them into each wix installer that I have to create. (Title, Description, Company, Product, Copyright, Trademark, AssemblyVersion, FileVersion) The annoying thing is VS has a publish tab built in, it just doesn't create standalone installer and drives you to deploy via the store which in my field is impossible. – Reahreic Feb 12 '21 at 13:02
1

For those who run into this in the future here's what it took to gain access to the assembly information from wix.

Note at the time of posting I hadn't managed to return the entire data object as a single struct, but can at least output the values as strings.

To make it easy to define the targeted assembly file, define a constant either via your node in the .wixproj file Or via the wixProj's Properties > Build > Define Preprocessor variables field: AssetPath=../MyReferencedProject/bin/$(Configuration)/MyAsset.exe;

Next, place the below code into your .wixProj file. (Edit this with NotePad++ then reload the project in VS)

    <!--To modify your build process, add your task inside one of the targets below and uncomment it.
    Other similar extension points exist, see Wix.targets.-->

    <Target Name="BeforeBuild">
        <ExtractAsmInfo AsmPath="$([System.Text.RegularExpressions.Regex]::Match(&quot;;$(DefineConstants);&quot;, &quot;;AssetPath=(?&lt;path&gt;.*?);&quot;).Groups[&quot;path&quot;].Value)">
            <Output PropertyName="asmCompName" TaskParameter="AsmCompName" />
            <Output PropertyName="asmProdName" TaskParameter="AsmProdName" />
            <Output PropertyName="asmDesc" TaskParameter="AsmDesc" />
            <Output PropertyName="asmCopyright" TaskParameter="AsmCopyright" />
            <Output PropertyName="asmTrademarks" TaskParameter="AsmTrademarks" />
            <Output PropertyName="asmFileVersion" TaskParameter="AsmFileVersion" />
        </ExtractAsmInfo>

        <!--This is needed for the output to be accessible from your .wxs file as "!(wix.asmCompName)"-->
        <CreateProperty Value="asmCompName=$(asmCompName);$(WixVariables)">
            <Output TaskParameter="Value" PropertyName="WixVariables" />
        </CreateProperty>
        <CreateProperty Value="asmProdName=$(asmProdName);$(WixVariables)">
            <Output TaskParameter="Value" PropertyName="WixVariables" />
        </CreateProperty>
        <CreateProperty Value="asmDesc=$(asmDesc);$(WixVariables)">
            <Output TaskParameter="Value" PropertyName="WixVariables" />
        </CreateProperty>
        <CreateProperty Value="asmCopyright=$(asmCopyright);$(WixVariables)">
            <Output TaskParameter="Value" PropertyName="WixVariables" />
        </CreateProperty>
        <CreateProperty Value="asmTrademarks=$(asmTrademarks);$(WixVariables)">
            <Output TaskParameter="Value" PropertyName="WixVariables" />
        </CreateProperty>
        <CreateProperty Value="asmFileVersion=$(asmFileVersion);$(WixVariables)">
            <Output TaskParameter="Value" PropertyName="WixVariables" />
        </CreateProperty>
    </Target>

    <!--<Target Name="AfterBuild"></Target>-->

    <!--Extracts data from the assembly-->
    <UsingTask TaskName="ExtractAsmInfo" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
        <ParameterGroup>
            <!--The assembly path-->
            <AsmPath ParameterType="System.String" Required="true" />
            <!--The return value. Note the return types are extremely limited-->
            <AsmCompName ParameterType="System.String" Output="true" />
            <AsmProdName ParameterType="System.String" Output="true" />
            <AsmDesc ParameterType="System.String" Output="true" />
            <AsmCopyright ParameterType="System.String" Output="true" />
            <AsmTrademarks ParameterType="System.String" Output="true" />
            <AsmFileVersion ParameterType="System.String" Output="true" />
        </ParameterGroup>
        <Task>
            <Reference Include="System.Xml" />
            <Reference Include="System.Xml.Linq" />
            <Using Namespace="System" />
            <Using Namespace="System.Xml.Linq" />
            <Using Namespace="System.Reflection" />
            <Using Namespace="System.Diagnostics" />
            <Code Type="Fragment" Language="cs">
                <![CDATA[
            FileVersionInfo fileInfo = FileVersionInfo.GetVersionInfo(AsmPath);
            AsmCompName = fileInfo.CompanyName;
            AsmProdName = fileInfo.ProductName;
            AsmDesc = fileInfo.FileDescription;
            AsmCopyright = fileInfo.LegalCopyright;
            AsmTrademarks = fileInfo.LegalTrademarks;
            AsmFileVersion = fileInfo.FileVersion;
        ]]>
            </Code>
        </Task>
    </UsingTask>

Finally, in your .wxs file, you can just use:

<!--Note the use of an EXCLAMATION MARK and not Dollar Sign as well as the wix. instead of var.-->
!(wix.asmProdName)
!(wix.asmCompName)
!(wix.asmDesc)
!(wix.asmCopyright)
!(wix.asmTrademarks)
!(wix.asmFileVersion)

<!--Example-->
<Product Id="*" UpgradeCode="1129c4e2-e288-48d5-84dd-587aec927f26"
             Name="!(wix.asmProdName) Installer" Manufacturer="!(wix.asmCompName)"
             Language="1033" Version="!(wix.asmFileVersion)">

        <Package Id="*" Compressed="yes"
                 InstallerVersion="200" InstallPrivileges="elevated" InstallScope="perMachine"
                 Keywords="Installer" Languages="1033" Platform="x64" ReadOnly="no" ShortNames="no" SummaryCodepage="1252"
                 Description="The !(wix.asmDesc) and it's protocol installer."
                 Comments="!(wix.asmCopyright) | !(wix.asmTrademarks)" />
...
</Product>

Refs

Reahreic
  • 596
  • 2
  • 7
  • 26