I was creating a wix installer for my product.
I need to run mainly 3 sections in the installer.
Install the postgres database as pre-requisites
Install my product(I have created a msi for my product using wix)
Execute the database scripts(batch file which in turns executes some sql files).
For these steps, I created a wix bundle, and executed the exe package for the postgres database.
Then I executed the msi package for my product. And finally I need to run the batch file. So I used the same bundle and added exe package as shown below
< Chain >
<ExePackage Id="PostgresInstaller" ......>
</ExePackage>
<MsiPackage Id="MyProductPackage" ...... >
</MsiPackage>
<ExePackage Id="DatabaseScipts"
DisplayName="DatabaseScipts"
Description="Configuration files for database"
SourceFile="Scripts\create.bat"
/>
</Chain>
But the problem is, the create.bat file inturns calls some sql files from some other directory. I have added those files in bundle project. But it is not
coming with final bundle exe. Is there any other way to include the sql files in the bundle.
My aim is to execute the bat having sql files after the msi package installer.
In product.wxs file, make sure you include all the files needed.
<!-- Step 1: Define the directory structure -->
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLDIR" Name="My Application Name"/>
</Directory>
</Directory>
<!-- Step 2: Add files to your installer package -->
<DirectoryRef Id="INSTALLDIR">
<Component Id="create.bat" Guid="PUT-GUID-HERE">
<File Id="create.bat" Source="Scripts\create.bat" KeyPath="yes"/>
</Component>
//Other required files in similar ways
</DirectoryRef>
In product.wxs page (not bundle.wxs), add a custom action something like this:
<Fragment>
<CustomAction
Id='RunDbScript'
Directory='INSTALLDIR'
Execute='commit'
Impersonate='yes'
ExeCommand='"[SystemFolder]cmd.exe" /C "[INSTALLDIR]create.bat"'
Return='check'/>
</Fragment>
And add install execute sequence:
<InstallExecuteSequence>
<Custom Action="RunDbScript" Before="InstallFinalize">NOT REMOVE</Custom>
</InstallExecuteSequence>
Related
We have some executables which we need to create our setups. So we have packed
the external dependencies which are some .exe files into a nuget package. But on NuGet restore they are added to project root.
How can we achieve this ?
Have searched around but haven't found any solution so far.
Since we use nuspec file, this is what i have it as:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>VCRedistributable</id>
<version>$version$</version>
<title>VCRedistributable</title>
<authors>--</authors>
<owners>--</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>InstallVCRedistributable assemblies</description>
<contentFiles>
<files include="**" exclude="**" buildAction="None" copyToOutput="false"
/>
</contentFiles>
</metadata>
<files>
<file src="VC\x86\*.*" target="content\x86" />
<file src="VC\x64\*.*" target="content\x64" />
</files>
Any ideas ?
Prevent content files to be added on Nuget restore
You should target to the tools folder instead of content folder.
So, your .nupsec file should be:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>VCRedistributable</id>
<version>$version$</version>
<title>VCRedistributable</title>
<authors>--</authors>
<owners>--</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>InstallVCRedistributable assemblies</description>
</metadata>
<files>
<file src="VC\x86\*.*" target="tools\x86" />
<file src="VC\x64\*.*" target="tools\x64" />
</files>
</package>
That because the content directory is a convention-based working directory, which contents are copied to the project root:
Convention-based working directory:
Besides, if you nuget package just include external some .exe files, you do not have to add the contentFiles label, this label is used for the content file for packagereference.
<contentFiles>
<files include="**" exclude="**" buildAction="None" copyToOutput="false"
/>
</contentFiles>
If you are interested in, you can check this document for some more details.
Update:
Is it good convention to create our own folder structure other than
NuGet defined since based on the tools folder description from above
it seems they will be accessible via Package Manager Console.
Of course, you can use your own folder structure other than NuGet defined. But you need to notice that there will be a limit to do this. You can NOT just include your own folder structure, you need also need add a NuGet defined folder structure in your .nuspec, otherwise, nuget will install failed with the error like:
Could not install package 'MyCustomPackage 1.0.0'. You are trying to
install this package into a project that targets
'.NETFramework,Version=v4.6.1', but the package does not contain any
assembly references or content files that are compatible with that
framework.
Because nuget did not detect that you added assembly references or content files to the project.
Hope this helps.
Here is the WXS file content for copying the individual files
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="MergeRedirectFolder">
<Component Id="owcF3EB3D7C133F5B48E5859309ABDC2EE0" Guid="5a6040ae-b91e-47b6-8438-d9cd47fb947a">
<File Id="owfF3EB3D7C133F5B48E5859309ABDC2EE0"
Source="$(var.SourceDir)\api-ms-win-core-console-l1-1-0.dll" KeyPath="yes" />
</Component>
<Component Id="owcB0E3C7251F136710A0F11E0C18525364" Guid="f80e6202-0436-d488-52cf-827e37483096">
<File Id="owfB0E3C7251F136710A0F11E0C18525364"
Source="$(var.SourceDir)\api-ms-win-core-datetime-l1-1-0.dll" KeyPath="yes" />
</Component>
<Component Id="owc4B0AD9DF281D253C1207D4E82DEB0DD2" Guid="4ac4edbd-2c6a-8aed-125e-11237a36e4f8">
<File Id="owf0E5D53A7E23AE08AF9D984ADC41AC589"
Source="$(var.SourceDir)\publish\sos_amd64_amd64_4.6.26628.05.dll" KeyPath="yes" />
I have defined my source directory as follow
<?define SourceDir="..\..\Services\bin\Debug\netcoreapp2.1\win7-x64\"?>
How can I specify WIX to copy all files instead of specifying one in each line?
Why?
My publish output files having different versions in different machines, so i do not want to hard code file versions in WIX configurations.
Publish folder has below files depend on the system it got published
In Dev machine, I have file
sos_amd64_amd64_4.6.26725.06
In Build machine, I have file
sos_amd64_amd64_4.6.26725.05
If you see the, the version is different in above files. So Wix build is failing due to mismatched version in *.wxs file. So I want to read all files from folder, rather than specifying individual files.
I can see from the authoring that you are using IsWiX (disclaimer: I'm the author). IsWiX was designed to only support static authoring not the kind of authoring that you are trying to do. I've blogged many times on why I feel that's the better safer to do but telling that story on Stack Overflow doesn't usually go over well.
That said, IsWiX will not prevent you from doing what you are trying to do. Generally what I recommend doing is:
In your main setup project in the Code folder create a new wxs fragment called "HarvestedComponents.wxs"
Commit this empty file to source control and add it to your .gitignore if using Git.
Put the following in the prebuild step of the project
C:\Program Files (x86)\WiX Toolset v3.11\bin\heat.exe" dir "$(SolutionDir)Deploy\Path-To-Some-Directory-To-Harvest" -dr INSTALLLOCATION -cg HarvestedComponents -gg -g1 -sf -srd -scom -sreg -ke -var "var.Deploy" -out "$(SolutionDir)ClientTools\Code\harvestedcomponents.wxs
You'll have to tweak that a little to match your desired directory structure in Features.wxs.
Build the project and notice the HarvestedComponents.wxs get data. You don't want to commit this to source control but it shouldn't hurt if you do. I wouldn't.
Now to wire these harvested components up to your installer you need to edit Code\Features.wxs. Add:
<ComponentGroupRef Id="HarvestedComponents" />
to the feature that you want these components associated with.
The final MSI will now dynamically author these folders/files into the MSI along with whatever you statically define in the mege module wxs using IsWiX.
Note: Please be aware that there are trade offs with this approach. Mainly:
http://blog.iswix.com/2007/06/dealing-with-very-large-number-of-files.html
I also wonder why your sos artifact is version 06 on the dev box and version 05 on the build box. How often does this change? If this is simply a version mismactch and the artifact rarely changes then you may be solving the wrong problem. If the version is deisgned to be controlled by the build environment and changes frequently and the folder names and file names change from version to version then this might be the right solution for your needs.
You could try the harvesting tool heat. Here is the documentation
For Wix 3: https://wixtoolset.org/docs/v3/overview/heat/
For Wix 4: https://wixtoolset.org/docs/reference/heat/
I am creating a Windows Installer MSI using WIX. I want to separate files into different fragments, to have small chunks of code in each wxs file.
Currently I have below files:
- Product.wxs which contains Product, Package, MediaTemplate and Feature elements.
- Directories.wxs which contains folders structures and components to give permissions to user and remove folders on uninstall.
I want to take all my features out of Product.wxs too, and create it's own file, called Features.wxs.
Inside Directories.wxs, I have below line of code:
<Component Id="Component1" Guid="PUT_GUID_HERE" Directory="Subfolder">
<CreateFolder>
<util:PermissionEx GenericAll="yes" ChangePermission="yes" Delete="yes" DeleteChild="yes" User="Users"/>
</CreateFolder>
</Component>
With having above code, since I am referencing this Component in a Feature element, I am certain that my Product.wxs and Directories are linked.
But when I create a Feature.wxs file and move below lines of code to it:
<Feature Id="CreateDirectoriesFeature" Title="Feature1" Level="1">
<ComponentRef Id="Component1"/>
</Feature>
I don't know how/where to reference this fragment/features in my Product.wxs.
Create a FeatureGroup with FeatureRef elements and then in Product.wxs use a FeatureGroupRef to bring into scope.
I put my Feature stuff in a different file as well, and the only thing that I need to reference them is the Feature's ID.
Here's a code example. Here's an entire feature file that I have:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<Feature Id="Feature_Name"
Level="1">
<ComponentRef Id="Component_Name"/>
</Feature>
</Fragment>
</Wix>
And here's how I reference it in Product.wxs. I'll show you the entire file from the MajorUpgrade element to its bitter end:
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes"/>
<FeatureRef Id="Feature_Name"/>
</Product>
</Wix>
That's it. Maybe you're not using FeatureRef?
I have two builds of my main executable: standard and premium. For simplicity of development they are built from a single solution in Visual Studio by changing a special #define variable.
Now I'm curious if it's possible to do the same with the WiX installer for this project?
I basically need to control the inclusion of only one of the following xml nodes:
1: For standard version MSI:
<Product Name='Foobar 1.0 - Standard'
Id='8E9CF27F-B92F-4CB3-BBA0-0AAE5376D5EB'
UpgradeCode='20A89269-D206-490D-9134-349594662619'
Language='1033'
Codepage='1252'
Version='1.0.0'
Manufacturer='Acme Ltd.'>
and later:
<Component Id='MainExecutable' Guid='E1FE2BBE-C72D-4F27-A66D-78417F597D7A'>
<File Id='FoobarEXE' Name='FoobarAppStandardl10.exe' DiskId='1' Source='FoobarApplStandard10.exe' KeyPath='yes'>
2: For premium version MSI:
<Product Name='Foobar 1.0 - Premium'
Id='8E9CF27F-B92F-4CB3-BBA0-0AAE5376D5EC'
UpgradeCode='20A89269-D206-490D-9134-34959466261A'
Language='1033'
Codepage='1252'
Version='1.0.0'
Manufacturer='Acme Ltd.'>
and then:
<Component Id='MainExecutable' Guid='E1FE2BBE-C72D-4F27-A66D-78417F597D7B'>
<File Id='FoobarEXE' Name='FoobarAppPremiuml10.exe' DiskId='1' Source='FoobarApplPremium10.exe' KeyPath='yes'>
PS. I can obviously make 2 WiX projects... I'm seeking a way to do it in one.
I found it. Here it is for whoever else is interested.
In my case, i need to pass the symbol compilation to the project that will compile. I solved recompiling and passing the symbols.
For this, edit the wix project e.g. "xx.wixproj", and at the end of the file insert:
<Target Name="MyName" AfterTargets="AfterResolveReferences">
<MSBuild Projects="Path\xx.csproj" Properties="Configuration=$(Configuration);Platform=$(Platform);DefineConstants=$(DefineConstants)%3bMYSYMBOL;OutputPath=$(OutputPath)" />
</Target>
Unfortunately, this solution in vs 2017 (with .netstandard dlls) and WiX 4, not run.
I am new to WiX, I am facing a problem in adding a folder which contains necessary images and icons to wix project, I am able to include required dlls and files using
<Component Id='HelperLibrary'>
<File Id='HelperDLL' Name='Helper.dll' />
</Component>
Any help will be appreciated.
As you are working with a .NET project, adding of DLLs to the WIX installer from the project output folder of the referred project can be done as following by using the TargetDir item:
<Component Guid="*" Directory="BinFolder">
<File Id="BinFolder.Helper.dll" Source="$(var.ProjectToPackage.TargetDir)Helper.dll"/>
</Component>
Similar way, you can add other files from the project whihch doesn't come under the project output can be added as following using the ProjectDir item from the referred project:
<Component Guid="*" Directory="ImageFolder">
<File Id="ImageFolder.Icon.jpg" Source="$(var.ProjectToPackage.ProjectDir)Icons\Icon.jpg" />
</Component>
Note: Here it is expecting that your WIX project is having reference to the project to be packaged and the project reference is named as ProjectToPackage in this example above.