Add Zip Files to TARGETDIR in WiX - wix

In my Visual Studio 2017 solution, I have a WiX 3 setup project that pulls in the output several other projects (libraries, executables, assets, content). Under the directory structure for the solution but not added to the solution as a project, I have a project that compiles some browser extensions using webpack. This webpack project outputs to an artifacts folder with subdirectories for each browser. Inside each subdirectory is the compiled extension with the version number included in the file name like:
artifacts
Chrome
myextension-0.1.0.0.zip
myextension-0.1.0.1.zip
myextension-0.1.0.2.zip
At compile time, ultimately I want to include the files matching the version number i.e. myextension-\$(var.VERSION).zip into the MSI package so it can then be placed into the application folder during installation. Even when I hard-code the version number i.e. myextension-0.1.0.2.zip into the component, I get an error from light:
LGHT0001: The system cannot find the path specified. (Exception from HRESULT: 0x80070003)
I'm getting the directory with a define like this:
<?define ChromeTargetDir=$(var.SolutionDir)Extensions\artifacts\chrome\?>
And then my component looks like this:
<Component Id="ChromeExt"
Location="local"
Guid="GUID_HERE">
<CreateFolder/>
<File Id="ChromeExtension"
Name="myextension-0.1.0.2.zip"
Source="$(var.ChromeTargetDir)myextension-0.1.0.2.zip"
KeyPath="yes"/>
</Component>
When I look in the wixobj created by candle, I see the full correct path replaced for the file where it resides on my system:
<field>C:\Users\me\source\repos\mysolution\Extensions\artifacts\chrome\myextension-0.1.0.2.zip</field>
So my question is, what is the correct way to include "arbitrary" files in my WiX project?

1) Solution vs Project Dir: The first thing I would try would be to replace $(var.SolutionDir) with $(var.ProjectDir) and try a recompile. I'll follow up if the problem is something else. Let's just rule that out first.
2) Quotes: I also use quotes around my paths:
<?define ChromeTargetDir="C:\Sources\Packages\MyChromeExtension\Files\" ?>
3) Project Variables: And finally you need a reference added to your project for project references and variables to work: WiX: How to use relative path to SolutionDir.
Maybe add: %ProgramFiles (x86)%\WiX Toolset v3.11\bin\WixUIExtension.dll
WiX Documentation: Using Project References and Variables
Obscure: More obscure causes could be lacking access rights (file not seen by the build process and light.exe - running impersonated?). Corrupted file or folder? (try to replace). And whatever else might conspire against you. Locked files?

Related

MSBUILD Dynamically Create Config XML Dotfuscator

I am trying to obfuscate bunch of files in a directory and every build there are more and more files being generated. I would like to know if there is a way I can dynamically create the Dotfuscator configuration xml file using a MSBUILD task that will generate the xml file every time there is a new file added to the directory?
This might be a good time to use the Directory input. Rather than representing a single assembly (.exe or .dll), this type of Dotfuscator input captures all the assemblies in a directory. When the contents of the directory change, Dotfuscator's build will automatically pick up any new assemblies.
To make a Dotfuscator config file with a Directory input, open the GUI and add an input as you normally would (directions for Community Edition's GUI and for Professional Edition's standalone GUI), but instead of selecting a file from the Browse... dialog, just navigate to the directory and click "Open" while the "File name" is still listed as "Folder Select". Then, save your configuration.
From now on, whenever you run Dotfuscator (whether from the standalone GUI, the command line, the Visual Studio integration, or the MSBuild task), all assemblies in the directory will be processed as input.
Note: If you look at the config file itself, you might be surprised that it will still list individual assemblies:
<input>
<loadpaths />
<asmlist>
<package refid="19e1b0c5-7221-476f-af4b-bafef68edc95">
<file dir="C:\code\BasicTestApp\BasicTestApp\bin" name="Debug" />
<asmlist>
<inputassembly refid="a6da5d8d-c181-4103-840d-d8cc7c85937a">
<option>honoroas</option>
<option>stripoa</option>
<option>transformxaml</option>
<file dir="" name="BasicTestApp.exe" />
</inputassembly>
<inputassembly refid="df84dad0-fbe8-49ab-b8c8-9fb59e706785">
<option>honoroas</option>
<option>stripoa</option>
<option>library</option>
<option>transformxaml</option>
<file dir="" name="ClassLibrary.dll" />
</inputassembly>
</asmlist>
</package>
</asmlist>
</input>
Despite this layout, Dotfuscator will process all assemblies in the C:\code\BasicTestApp\BasicTestApp\bin\Debug directory when it runs a build based off this config file, not just those two listed.
The assembly elements in the config are just there so that you can still make rules against individual assemblies in the GUI (e.g., to make one assembly be in Library Mode).
The list represents the state of the directory when the GUI last modified the config.
Disclaimer: I work for the Dotfuscator team, and am answering this question as part of my job.
Additional note due to clarification in the comments: the directory package has a feature where you can exclude certain assemblies from obfuscation. These assemblies will be treated as a Package Artifact and just copied from input-to-output without modification. Any obfuscated assemblies that refer to these excluded assemblies will still be processed correctly.
To do this in the GUI, right-click on the assembly within the package, and select "Exclude assembly from package". Or, if you'd prefer to edit the config file, add the following <option> tag as a child of each relevant <inputassembly> tag:
<option>artifact</option>
The latest Dotfuscator version 4.41.1 has the latest flag
true
This will generate the Dotfuscator config file if the file is missing. Also you can add this to the csproj as documented in the latest getting started guide https://www.preemptive.com/dotfuscator/pro/userguide/en/getting_started_protect.html

How do I change target filename in NuGet Package?

JavaScript naming convention requires version number in the file name such as jQuery.1.34.min.js, and I have text template which will output my-library.js in output folder.
I want to create NuGet Package with my-library.js in such way that on installation it should be deployed as my-library.1.34.js
If I build nuget package as part of msbuild process, there is no way I can rename my output js file.
I already have a long workaround, in which I have a console app which copies files to folder structure as given version number and then it builds a nuspec file and then it is passed onto nuget.exe, if there is any easy, I would like to avoid such long steps.
I found I could rename include files by specifying a full file name for the target.
For example (nuspec snippet):
<files>
<file src="my-library.js" target="content/my-library.$VERSION$.js">
</files>
and nuget would be run like:
nuget.exe pack mypackage.nuspec -Prop VERSION=1.34
Note: The File extension in src and target must match or the specified target will be treated like a directory.

Windows Installer XML relative Path for Patch

I'm using the Microsoft Team Foundation Server to manage and Deploy Setups for my Applications.
My Setups are WiX-Setups with relative Paths.
p.e.
Components
<Component Id="Anwendung.exe" Directory="INSTALLLOCATION" Guid="*">
<File Id="Anwendung.exe" KeyPath="yes" Source="$(var.SourceFiles)\Anwendung.exe" />
</Component>
Variables.wxi:
<Include>
<?define SourceFiles = "..\OutputFiles"?>
</Include>
Setups are building correctly.
The Problem: I'm using Torch and Pyro to generate Patches for my applications.
I'm using a pure Wix Patch Project with manipulated build events and additional linker information
(Pre Build - Torch)
(Post Build - Pyro)
(Linker additional Parameters - output as wixmsp)
When I build my Patch, I'm getting 579Failures.
(1x)
Error 776 The command ""C:\Program Files (x86)\WiX Toolset v3.8\bin\pyro.exe" Patch.wixmsp -out Patch.msp -t AnwendungBaseline diff.wixmst" exited with code 103.
C:\Program Files (x86)\MSBuild\Microsoft\WiX\v3.x\wix2010.targets
and (578x)
Error 322 The system cannot find the file '..\SourceFiles\Anwendung.exe'. C:\Patch\Client\Upgrade\Setup\ComponentMain.wxs
I'm sure it's not resolving the paths from the sourcesetups correctly.
Could anybody help me? Rob Arnson , Rob Mensching, Heath Steward? Please :)
To get around issues like this, you can write a custom build activity for TFS to update variables in your WiX config file with fully qualified paths. For instance, you can create a build activity that takes in the path to a config file, the name of a variable, and value for that variable, and then write the new value to the config file. You can keep the config file with relative paths checked into source control, but then the build will update the config file to use the fully qualified path just for the build.
If you are unfamiliar with creating custom build activities, there is a great blog series on it here. The link is for TFS 2010 but the process is similar for TFS 2012.

WiX project that references an SSDT project fails to build in TFSBuild - Undefined preprocessor variable '$(var.DatabaseProject.TargetDir)'

My project which is part of a larger solution was converted from a dbproj to asqlproj (SSDT). The solution includes a WiX installer which references the SSDT project. The WiX project builds fine on multiple developer systems through VS2010. The automated builds that we've always used, however, are failing with this error:
error CNDL0150: Undefined preprocessor variable '$(var.DatabaseProject.TargetDir)'.
The solution has been built by TFS automated builds for many months without issue prior to this project being converted. I can see from the build log that the SSDT project is being built, here are some relevant lines from the build log:
Project "C:\B\1\SourcePath\Server\Server.wixproj" (8) is building "C:\B\1\SourcePath\Database\DatabaseProject.sqlproj" (12) on node 1 (default targets).
...
Done Building Project "C:\B\1\SourcePath\Database\DatabaseProject.sqlproj" (default targets).
I can also see that the .dacpac and .dll files for the database project are created and copied into the output directory that TFS build has redirected the projects to.
The reference to the database project seems fine and TFS build seems to know that it should be built, but WiX is complaining about the undefined preprocessor variable for TargetDir.
I must be missing something...Is the output redirect employed by TFS causing my issue? I'm not sure where to go from here and appreciate any help you can suggest.
MORE INFO
Looking at the log file for the build in more detail I can see that the parameters for the .sqlproj project aren't being passed on the command line to candle.exe. When I build locally in VS2010, I can see the expected parameters passed as follows (just like the other projects referenced by the WiX project):
-d"DatabaseProject.FullConfiguration=Release|AnyCPU"
-dDatabaseProject.Platform=AnyCPU
-dDatabaseProject.ProjectDir=C:\SourcePath\Database\
-dDatabaseProject.ProjectExt=.sqlproj
-dDatabaseProject.ProjectFileName=DatabaseProject.sqlproj
-dDatabaseProject.ProjectName=DatabaseProject
-dDatabaseProject.ProjectPath=C:\SourcePath\Database\DatabaseProject.sqlproj
-dDatabaseProject.TargetDir=C:\SourcePath\Database\sql\release\
-dDatabaseProject.TargetExt=.dll
-dDatabaseProject.TargetFileName=DatabaseProject.dll
-dDatabaseProject.TargetName=DatabaseProject
-dDatabaseProject.TargetPath=C:\SourcePath\Database\sql\release\DatabaseProject.dll
None of these parameters are being passed to candle.exe during the TFS build. I figured this information might be useful for helping answer the question.
Any help is greatly appreciated!
Based on #RobMenching's answer, you won't be able to rely on the SSDT project variable to be set by any command-line build, so you'll need to find another way to reference the project's output.
Fortunately, in a standard TFS build, the output folders will be the same for all projects in a given build configuration. Assuming you haven't redirected the output somehow, you should be able to use any of the other projects (which are working properly) as the reference path. E.g., assuming that you have a DatabaseProject.sqlproj and an DataAccessProject.csproj in the solution, you should be able to do:
<Component Id='MyComponent' Guid='12345678-1234-1234-1234-123456789012'>
<?ifdef DatabaseProject.TargetDir ?>
<File Id='foo' Name='foo' src='$(var.DatabaseProject.TargetDir)\foo.dacpac' />
<?else?>
<File Id='foo' Name='foo' src='$(var.DataAccessProject.TargetDir)\foo.dacpac' />
<?endif?>
</Component>
For builds done inside VS2010, where each project is built to its own output folder, the correct preprocessor variable ought to be defined and it will use the first option. For TFS builds, where the preprocessor variable is not defined, TFS will have redirected the SSDT's output to the same folder as all of the other projects, so any one of the preprocessor variables should work just as well.
I believe the root issue here is that the .sqlproj does not support the necessary Visual Studio integration to provide the data for the preprocessor variable. This has created a lot of problems for the WiX toolset over the years. Unfortunately, fixing it requires the owners of the .sqlproj to fix their project system.

Add a folder to installer in wix not files?

My installer has to copy files into installdir... My application has around 2000 files and it is not possible for me to write the script to add each and every file to the installer.
Is there any option in wix so that I can add all the files or the entire folder consisting the files at once? I am new to wix and i didnt find any option in any tutorial for this... Please do assist me and thanks in advance.....
Heat is the WiX harvest tool. You can run it on a directory to generate the necessary WiX source code.
EDIT:
If you want to run heat before your VS project builds, add it to your project prebuild events as seen in the screenshot below (this is how I have my project setup to dynamically generate WiX source for our ever changing help content):
Note the -var wix.HelpSource switch that I have. The WiX source files generated by heat will set the location of the source files to that variable instead of hard-coding it. So the generated source will have components that look something like this:
<Component Id="Welcome.htm" Directory="Content" Guid="INSERT-GUID-HERE">
<File Id="Welcome.htm" KeyPath="yes" Source="!(wix.HelpSource)\Content\Welcome.htm" />
</Component>
And in my particular case, I define that variable on the Tool Settings screen of my WiX VS project to the relative directory ..\..\Help\Output as seen below:
NOTE: Harvesting files in this manner will cause the GUIDs of the components harvested to change every time you build. If you don't want your GUIDs to change, you may have to write some wrapper that calls heat to harvest the files, then updates your original WiX source, leaving all the GUIDs alone.