Giter Site home page Giter Site logo

oleg-shilo / wixsharp Goto Github PK

View Code? Open in Web Editor NEW
1.1K 30.0 169.0 69.58 MB

Framework for building a complete MSI or WiX source code by using script files written with C# syntax.

License: MIT License

C# 89.93% HTML 0.24% CSS 0.11% Batchfile 0.50% Smalltalk 0.26% PowerShell 0.11% C 7.06% C++ 1.73% NSIS 0.02% VBScript 0.01% JavaScript 0.01% ASP.NET 0.03%

wixsharp's Introduction

stand with Ukraine

Build status NuGet version (WixSharp) Donate

paypal

Wix# (WixSharp) - managed interface for WiX

Framework for building a complete MSI or WiX source code by using script files written with the C# syntax.

In July 2014 Wix# was migrated to CodePlex Wix# and re-released under MIT license. It was subsequently migrated from CodePlex to GitHub. You can still find old releases and some useful content from the past discussions on CodePlex.

Project Description

Wix# (WixSharp) is a member of the CS-Script family. Wix# allows building a complete MSI or WiX source code by executing script files written with the plain C# syntax. Wix# engine uses a C# class structure to mimic WiX entities and their relationships to produce a valid deployment model.

Wix# answers many MSI authoring challenges. It solves the common MSI/WiX authoring limitations in a very elegant yet unorthodox way. Wix# follows the steps of other transcompilers like Script#, CoffeeScript or GWT by using source code of a more manageable syntax (C# in this case) to produce the desired source code of a less manageable syntax (WiX). A "more manageable syntax" in this context means less verbose and more readable code, better compile-time error checking and availability of more advanced tools.

Wix# also removes the necessity to develop MSI sub-modules (Custom Actions) in a completely different language (e.g. C++) by allowing both the components and behaviour to be defined in the same language (C#). This also allows homogeneous, simplified and more consistent source code structure.

Overview

If you are planning to use Wix# on Linux you may find this article useful. Please note that Wix# builds MSI deployment packages and while MSI can be built on Linux it cannot be run on Linux as MSI is a pure Windows technology.

Please note that WixSharp NuGet packages are targeting .NET Framework only. This is because WiX does not support integration with any other .NET flavours but .NET Framework only.

You can find the instructions on how to author MSI setups with WixSharp in the Documentation section. And this section only highlights some of the available features.

You can use Visual Studio console application project and NuGet package as the starting point. image

Alternatively you can install "WixSharp Project Templates" Visual Studio extension. Read more about the Wix# VS templates here.

Wix# allows a very simple and expressive deployment definition. This is an example of a simple Wix# script:

using System;
using WixSharp;
 
class Script
{
    static public void Main(string[] args)
    {
        var project = new Project("MyProduct",
                          new Dir(@"%ProgramFiles%\My Company\My Product",
                              new File(@"Files\Docs\Manual.txt"),
                              new File(@"Files\Bin\MyApp.exe")));
 
        project.GUID = new Guid("6f330b47-2577-43ad-9095-1861ba25889b");
 
        Compiler.BuildMsi(project);
    }
}

One of the most intriguing features of Wix# is the ability to define/implement managed Custom Actions directly in the script file:

using System;
using System.Windows.Forms;
using WixSharp;
using Microsoft.Deployment.WindowsInstaller;
 
class Script
{
    static public void Main(string[] args)
    {
        var project = new Project("CustomActionTest",
                          new Dir(@"%ProgramFiles%\My Company\My Product",
                              new DirFiles(@"Release\Bin\*.*")),
                          new ManagedAction(CustomActions.MyAction));
 
        BuildMsi(project);
    }
}
 
public class CustomActions
{
    [CustomAction]
    public static ActionResult MyAction(Session session)
    {
        MessageBox.Show("Hello World!", "Embedded Managed CA");
        session.Log("Begin MyAction Hello World");
 
        return ActionResult.Success;
    }
}

Another important feature is the support for custom UI including WPF external UI: image

The Samples Folder an extensive collection of Wix# samples covering the following development scenarios:

  • Visual Studio integration including NuGet packages and VS2013/2015 project templates extension
  • Installing file(s) into Program Files directory
  • Changing installation directory
  • Installing shortcuts to installed files
  • Conditional installations
  • Installing Windows service
  • Installing IIS Web site
  • Modifying app config file as a post-install action (Deferred actions)
  • Installing "Uninstall Product" shortcut into "Program Menu" directory
  • Installing registry key
  • Showing custom licence file during the installation
  • Launching installed application after/during the installation with Custom Action
  • Executing VBScript Custom Action
  • Executing Managed (C#) Custom Action
  • Executing conditional actions
  • Targeting x64 OSs
  • Registering assembly in GAC
  • File Type registration
  • Setting/Reading MSI properties during the installation
  • Run setup with no/minimal/full UI
  • Localization
  • Major Upgrade deployment
  • Authoring and using MergeModules
  • Pre-install registry search
  • Customization of setup dialogs images
  • Rebooting OS after the installation
  • Building MSI with and without Visual Studio
  • Simplified Managed bootstrapper for UI based deployments
  • Simple Native bootstrapper
  • Custom MSI dialogs
  • Custom WinForms dialogs
  • Custom external UI
  • Console setup application
  • WinForm setup application
  • WPF setup application

wixsharp's People

Contributors

alxcp avatar bajotumn avatar bradh avatar bykiev avatar epilyaev avatar geghamyan avatar gilesbathgate avatar havendv avatar icnocop avatar itn3000 avatar jonreis avatar jtsymon-fw avatar krippz avatar lbs-contributor avatar mbinic avatar noctis0430 avatar nodchip avatar note-do avatar oleg-shilo avatar pbalassone-nrgsys avatar q-sharp avatar qianmoxi avatar snechaev avatar stassss2011 avatar stevewoj avatar taras-au avatar tibel avatar tigrananchorfree avatar xaddan avatar xplicit avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wixsharp's Issues

Copy Files to already installed Software

Hallo, i have 2 questions. Hope you can help me.
Q1:
How do i copy some files to two various Folder. Here is problem: i need to install unknown count of files with xml and dll to 2 different path folders .
I can get Path to Software via Reagistry and execute ManagedAction. That works fine, but i dont know how to get property to installdir in project.
myproject looks like

var project = 
    new ManagedPorject("Myproduct",
        new ManagedAction(CustomActions.GetModulePath1, Return.Check, When.After, Step. Installfinilize, Condition.InstallInitialize),
        new Dir(CustomActions.GetModulePath2 + "\Extension\MyProductAddin",
            new File("myxmlfile"). 

Until here its works.

And here begins difficulty - how do i set session["INSTALLDIR"] in project for another files which are different for xml and dll /tlb ?
Q2: How do i add dependency files for my maindll in Project ? Just like File - with new File (dependecy1.dll etc. ) or i have to do this some different ?

fileshortcut for uninstall

Hi,
i have some Problems with my Wix# ManagedProject and hope someone can help me with.
I want create a Shortcut for Uninstall myapp.exe, but shortcut for doesnt get msiexec.exe for uninstall.
My Project looks like

 var project = new ManagedProject("winapp1",
                             new Dir(@"C:\Apps\my company\Winapp1",
                             new File(@"C:\Users\me\Documents\visual studio 2015\Projects\winapp1\winapp1\bin\Debug\winapp1.exe",
                             new FileShortcut("winapp1", "INSTALLDIR")
                             {
                                 IconFile = @"C:\Users\me\Documents\visual studio 2015\Projects\winapp1\WixSharp Setup1\Images\pc.ico",
                                 WorkingDirectory = @"%WINDIR%\System32",
                                 Target = "msiexec.exe",
                                 Arguments = "/x {Productcode}"
                             }),
                             new Dir("Uninstall",
                                new File(@"C:\Users\me\Documents\visual studio 2015\Projects\winapp1\WixSharp Setup1\Uninstall\resetWindowsService.bat"))));

Did i something wrong ? I can compile my Installproject without Problems and installed it. Also shortcut is in Installdirectory. Seems fine, but i dont get uninstallshortcut for uninstall myapp1.exe.
I need some help for this.
Thanks for Answers.

WixCLRDialog error

Hello!
I've added an dialog inherited from WixCLRDialog.
Depending on the input data I want to inject my dialog using project.InjectClrDialog or not inject.

project.UI = WUI.WixUI_InstallDir;
if (args[0] == "InjectClrDialog")
{
    project.InjectClrDialog("ShowCustomDialog", NativeDialogs.InstallDirDlg,
                        NativeDialogs.VerifyReadyDlg);
}
project.RemoveDialogsBetween(NativeDialogs.WelcomeDlg, NativeDialogs.InstallDirDlg);

If project.InjectClrDialog is called, it's OK.

If project.InjectClrDialog isn't called, I've got the errors:

The command "cd "C:\Work\app-installer\AppInstaller\" "C:\Work\app-installer\AppInstaller\bin\Debug\Setup.exe" 111" exited with code 1.
Dependent assembly not supplied: WixSharp.UI, Version=1.3.0.0, Culture=neutral, PublicKeyToken=3775edd25acc43c2
System.IO.FileLoadException: Cannot resolve dependency to assembly 'WixSharp.UI, Version=1.3.0.0, Culture=neutral, PublicKeyToken=3775edd25acc43c2' because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.

WixSharp.Files generation : same folder on different features

Is it possible to improve Files resolution to create sub WiwSharp.Dir only if not exist?

See this simple use case:

Folder structure:

โ”œโ”€ Main
|	โ””โ”€ run.exe
โ”œโ”€ Feature1
|	โ””โ”€ Docs
|	       โ””โ”€ file.txt
โ”œโ”€ Feature2
|	โ””โ”€ Docs
|	       โ””โ”€ file.txt

WixSharp Code:

var main = new Feature("Main");
var feature1 = new Feature("Feature1");
var feature2 = new Feature("Feature2");
...
new Dir(main, @"%ProgramFiles%\My company\My product",
  new Files(main, @"Main\*"			  
   ...
   new Dir(common,"Files",
	...
	new Files(feature1, @"Files\Feature1\*"),
	new Files(feature2, @"Files\Feature2\*")
   )                            
 );

This doesn't work, because "Docs" folder and "file.txt" are created twice.

Property SetupEventArgs.IsModifying has other behavior than method Extensions.IsModifying()

I noticed that SetupEventArgs.IsModifying uses other logic than Extensions.IsModifying(), thus returning different values, at least in some install scenarios.

    public bool IsModifying { get { return IsInstalled && !Data["REINSTALL"].SameAs("ALL", ignoreCase: true); } }

vs

    static public bool IsModifying(this Session session)
    {
        return session.IsInstalled() && !session.IsUninstalling();
    }

They should be equivalent (maybe a good time to implement the DRY pattern), or am I missing something?

Compiler.WixLocation - Error using relative path

Hi,

I've been trying to compile a project in a machine without the Wix Toolset, using the package WixSharp.wix.bin.

I can compile it using the fullpath

Compiler.WixLocation = @"c:\tfs\dev\packages\WixSharp.wix.bin.3.10.1\tools\bin";

But if I set the Compiler.WixLocation to the relative path to the package, I got the following error:

Compiler.WixSdkLocation = @"..\..\..\packages\WixSharp.wix.bin.3.10.1\tools\SDK";

5>  Wix project file has been built: C:\TFS\DEV\Service\Service.Installer\Service.WixSharp\Installer\MSI\MyMIS Service.wxs
5>  
5>  
5>  Unhandled Exception: System.ComponentModel.Win32Exception: The system cannot find the file specified
5>     at System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo)
5>     at System.Diagnostics.Process.Start()
5>     at WixSharp.Compiler.Run(String file, String args)
5>     at WixSharp.Compiler.Build(Project project, String path, OutputType type)
5>     at WixSharp.Compiler.Build(Project project, OutputType type)
5>     at WixSharp.Compiler.BuildMsi(Project project)
5>     at WixSharp.Project.BuildMsi(String path)
5>     at WixSharpSetup.Program.Main(String[] args) in C:\TFS\DEV\Service\Service.Installer\Service.WixSharp\Program.cs:line 101
5>C:\TFS\DEV\packages\WixSharp.1.2.0.0\build\WixSharp.targets(6,5): error MSB3073: The command ""C:\TFS\DEV\Service\Service.Installer\Service.WixSharp\bin\Debug\WixSharpSetup.exe" "/MSBUILD:Service.WixSharp"" exited with code -532459699.
========== Build: 11 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Am I doing something wrong?

AppSearch.GetProducts() crashes

The msiexec.exe log files only says
SFXCA: RUNDLL32 returned error code: -1073741819 .
CustomAction _... returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)

How to get your sample 'Conditional Installation' to work as a ManagedProject ?

Hi, I want to make my installer put a program shortcut onto the user's desktop optionally, and I see that you already provided a sample "Conditional Installation" that does this. However, my installer, built following your advice -- is a ManagedProject, not a Project.

I copied your code from the sample:

            var project = new ManagedProject( "DesignForge Throttle",
                                              new Dir( @"%ProgramFiles%\DesignForge\Throttle",
                                                  new Files( @"Files\Bin\*.*", f => !f.EndsWith( ".xml" ) && !f.EndsWith( ".pdb" ) ) ),
                                              new Property( "INSTALLDESKTOPSHORTCUT", "no" ),
                                              new ManagedAction( CustomActions.MyAction, Return.ignore, When.Before, Step.LaunchConditions, Condition.NOT_Installed, Sequence.InstallUISequence )
                                           );

...
project.ManagedUI = new ManagedUI();

            project.ManagedUI.InstallDialogs.Add( Dialogs.Welcome )
                                            .Add( Dialogs.Licence )
                                            //.Add( Dialogs.SetupType )
                                            //.Add( Dialogs.Features )
                                            .Add( Dialogs.InstallDir )
                                            .Add( Dialogs.Progress )
                                            .Add( Dialogs.Exit );

...
and then added this ManagedAction after class Script:

public class CustomActions
{
    [CustomAction]
    public static ActionResult MyAction( Session session )
    {
        if (DialogResult.Yes == MessageBox.Show( "Do you want to install desktop shortcut", "Installation", MessageBoxButtons.YesNo ))
            session["INSTALLDESKTOPSHORTCUT"] = "yes";

        return ActionResult.Success;
    }
}

But no message-box appears to ask me whether I want to install the desktop shortcut.

While on the topic of message-boxes, I also could not get your other method for launching them to work. Within this ManagedProject, I added these 3 methods:

    static void Msi_Load( SetupEventArgs e )
    {
        if (!e.IsUISupressed && !e.IsUninstalling)
            MessageBox.Show( e.ToString(), "Load" );
    }

    static void Msi_BeforeInstall( SetupEventArgs e )
    {
        if (!e.IsUISupressed && !e.IsUninstalling)
            MessageBox.Show( e.ToString(), "BeforeInstall" );
    }

    static void Msi_AfterInstall( SetupEventArgs e )
    {
        if (!e.IsUISupressed && !e.IsUninstalling)
            MessageBox.Show( e.ToString(), "AfterExecute" );
    }

and hooked them to the project events thusly:

            project.Load += Msi_Load;
            project.BeforeInstall += Msi_BeforeInstall;
            project.AfterInstall += Msi_AfterInstall;

However, again -- nothing seemed to appear. It seems that within each of those event-handlers, e.IsUISupressed is true, so the example does not work. Is there another way to tell when this installer is being run as a silent process with no user-interaction?

Thank you oleg

James Hurst
Setup.txt

Arguments are not supported on FileShortcut

Oleg,

I'm unable to utilize the Arguments property on a FileShortcut instance. I took a peek at Compiler and it looks like the property is not being translated.

Thanks,
-james

File.Attributes (on parent Component) after setting File.NeverOverwrite will not work

Hello,

I'm adding a File instance to a project. I need the file (it is a database file) to be both permanent and to be never overwritten on upgrade/reinstallation.
I saw that the Attributes property of the File class is supporting a way to specify an attribute of the parent component element of the file, but if I set the File.NeverOverwrite property to true before setting the File.Attributes property with a new dictionary containing the value { "Component:Permanent", "yes" } then the resulting auto-generated .wxs file contains the desired component with only the NeverOverwrite attribute set.
If I don't set the File.NeverOverwrite property, but I add also the value {"Component:NeverOverwrite", "yes" } to the File.Attributes dictionary, the resulting component has both the NeverOverwrite and Permanent attributes correctly set.

Case #1 (not working)

Code:

File databaseFile = new File(fileFullPath)
          {
            NeverOverwrite = true,
            Attributes = new Dictionary<string, string> { { "Component:Permanent", "yes" } }
          };

The code above generates the following xml elements in the auto-generated .wxs file:

<Component Id="Component.db.sqlite" Guid="123cb6bc-2fd4-4d54-a496-90ea76d1f866" NeverOverwrite="yes">
    <File Id="db.sqlite" Source="Database\db.sqlite" />
    <RemoveFolder Id="INSTALLDIR.Database" On="uninstall" />
    <RegistryKey Root="HKCU" Key="Software\WixSharp\Used">
        <RegistryValue Value="0" Type="string" KeyPath="yes" />
    </RegistryKey>
</Component>

Case #2 (properly working)

Code:

File databaseFile = new File(fileFullPath)
          {
            Attributes = new Dictionary<string, string> { { "Component:Permanent", "yes" }, { "Component:NeverOverwrite", "yes" } }
          };

The code above generates the following xml elements in the auto-generated .wxs file:

<Component Id="Component.db.sqlite" Guid="d96a16ee-d566-4745-9a90-0c72b953ae00" Permanent="yes" NeverOverwrite="yes">
    <File Id="db.sqlite" Source="Database\db.sqlite" />
    <RemoveFolder Id="INSTALLDIR.Database" On="uninstall" />
    <RegistryKey Root="HKCU" Key="Software\WixSharp\Used">
        <RegistryValue Value="0" Type="string" KeyPath="yes" />
    </RegistryKey>
</Component>

I hope I was clear enough, I really appreciate your work.

Thanks

Multiple Languages

Hey,

I have in my Setup-Project an Folder with my *.wxl Files for all of my Dialogs.
So I have the Question if itยดs possible to Build for each Language an Setup at once.

Like:
project.LocalizationFile = "Language\\Filename_*(for all the Languages).wxl";
and than
project.Language = "en-US, fr-fr, de-de (...)";

Thanks Christobal25

Show dialog with option (remove or cancel) if another version of product already installed

Hello!
How to make folowing case?

  1. When installator started (double clicked on .msi), search another version of product (older or newer). If another version already installed, show dialog with message "Another version of this product is already installed. Remove current version of product to continue".
  2. Dialog has 2 buttons: "yes" - for removing current version, and "no" - for cancel installation

In wix sharp sources, i find example "AppSearch.IsProductInstalled". In my case, method returns false, but product installed. Maybe it's a bug?
And, how to start removing of other version application?

Uninstall failing with no reason

I have successfully written a WiX# program that generates a MSI installer that works like a charm. The problem comes when I try to uninstall the application... installer is always failing. The worst is that no error log can be found neither in Windows Events, nor even provided by the installer itself.

After searching for some hours, I've discovered that Wix Toolset recommends to use UPPERCASE guids for compatibility reasons. The problem is that Wix# is generating lowercase guids in the WXS file so this may be causing the error. Besides, some other developers in Stackoverflow recommend to programmatically convert them to uppercase before generating the MSI.

Is there anyway in which I can configure a WixManagedProject to generate uppercase GUIDS?.

Any help will be appreciated. Thanks.

UILevel changing on differents steps

Hi,
There is a strange behaviour with UILevel, (with managedUI).
You can test it in this repository sample "Managed Setup".
If you check for UILevel (setupArgs.UILevel) in all events, it is:
-not the same in each event
-seems to be wrong (0 or 2=silent )

In UIInitialized, it is 0, looks OK.
But in Load and AfterInstall, it is setted to 2.

Is it a normal behaviour? I know than there is lot of different execution context in MSI engine, like AfterInstall is a deferred Action. But Load is a direct action right? Or something with UI type (managed one)
? but in sample UILevel is tested, so I may miss somthing.

So if it is nomal, how can I detect if my setup is in silent mode at each step?

Windows installer process stay open after build

In few cases Windows Installer process remain active.
I have seen it when building project, and also after installing my application.

You can reproduce this by creating a project via visual studio.
Create project via WixSharp template "WixSharp Managed Setup" & Install package nuget.

Generate the solution (the msi file should also been generated), and you will see in process Windows Installer will never stop.

If you kill it, and run the msi for installation, same happend after install. Few Windows Installer are runned, but one is never killed.

Sorry I didn't investigate a lot, I have no more informations/tests.

OS: Windows 10

command line arguments

Can I get command line arguments for the processing of the script
MyProduct.msi arg1="abc" arg2="bcd"?

installation in different folders

Hello!
I try to install exe-files in "c:\MyPrograms", and ini-files in "d:\MyData".
I do it like this:
string productName = "MyProduct";
string installDir = @"c:\MyPrograms" + productName;
string installDataDir = @"d:\MyData" + productName;
var project = new ManagedProject(productName,
new Dir(new Id("program"), installDir,
new Dir(set1, "Set1", new Files(set1, filesToInstall_set1)),
new Dir(set2, "Set2", new Files(set2, filesToInstall_set2))),
new Dir(new Id("data"), installDataDir, new Files(dataFilesToInstall))
);

but there is a compilation error:
error LGHT0091: Duplicate symbol 'CustomAction:Set_INSTALLDIR_AbsolutePath' found. This typically means that an Id is duplicated. Check to make sure all your identifiers of a given type (File, Component, Feature) are unique.

How can I install files on 2 different drives?

wixsharp DLL not compiled for 4.0v

Just wanted know if the WixSharp , Wixsharp.ui and Wixsharp.msi DLLs would be moving to the 4.X framework?

I wanted to use a few other libs for my msi and cannot due to the version of these dlls being v2.0.

How do I make a Wissharp MSI always remove a previous version?

I am looking for a solution where the MSI always uninstalls the previous version and installs a new one, irrespective a of an upgrade.(without showing the dialogue which says -- "Another version of this product is already installed. Installation of this version cannot continue.
To configure or remove the existing version of this product, use Add/Remove Programs on the Control Panel. ") I found the link to solve this using Wix (http://stackoverflow.com/questions/11732290/how-do-i-make-a-wix-msi-always-remove-a-previous-version).

I am looking for doing the same using Wix#. I am not sure how to generate a new GUID each time the program is built and MSi is generated. Is there a way that this could be done? please help me with this.

UtilRegistrySearch not working ?

bootstrapper.AddWixFragment("Wix/Bundle",
           new UtilRegistrySearch()
           {
               Root = Microsoft.Win32.RegistryHive.LocalMachine,
               Key = @"SOFTWARE\Microsoft\VisualStudio\12.0\VC\Runtimes\x86\Installed",
               Value = "1",
               Result = SearchResult.exists,
               Variable = "Vcredist2013Installed",
           });`

Results in "Registry key not found" in the install log.
Checked with regedit; the key syntax is correct and it exists.
All UtilRegistrySearch in my project fail the same way.

Wix# 1.4.2
VS 2015
Windows 10

iis:Certificate

I'm trying to figure out how I can install an SSL cert into an iis website akin to wix's iis:Certificate xml node

InstalledFileAction

how is it possible to acsess to file from the .MSI file folder and not from the install dir

packages

Hello! I use WixSharp in visual studio 2015. When I execute "Install-Package WixSharp", automatically creates "packages" folder. I have many WixSharp projects, and all of them contain "packages" folder. This is bad for me, because the projects are stored and built on buildserver.

I'm trying to create a project without a command "Install-Package WixSharp", and manually add WixSharp.dll, WixSharp.Msi.dll, WixSharp.UI.dll into the References. When I build project, it create WixSharpSetup.exe file, but I need msi file. What I have to do to create msi file after building project without executing "Install-Package WixSharp"?
p.s.: sorry for my English

Attributes inheritance in Files and DirFiles

Is there a "trick" to use custom attribues with Files and DirFiles ?

I m trying to do something like this (set DiskId to all files):

new DirFiles(feature1, @"Files\Feature1\Docs\*.*")
{
    AttributesDefinition = "DiskId=1"
},

For Files, as there is two wix Elements (dir and file), we should use same syntax used for file and component:

new Files(feature1, @"Files\Feature1\Docs\*")
{
     AttributesDefinition = "File:DiskId=1;Dir:AnotherAttribute=Value"
},

Another question, related to my DiskId use:
WixSharp support only one Media element?

This code doesn't work, only last cab is on wxs output.
I suppose only one is used , because project have a property (not a collection) project.Media.

new Project("Project1"
   new Media() { Id = 1, Cabinet = "media1.cab" },
   new Media() { Id = 2, Cabinet = "media2.cab" },
)

I don't understand this limitation when I see what WixSharp is able to do! It is really extensible so I rewrite wxs after generation, but it should be natively supported. (Or there is a good reason I did'nt see ;) )

*.g.wxs not created in TeamCity build

When building a Wixsharp project in Visual Studio as a part of the solution, a [ProjectName].g.wxs file is generated in the wix folder in the root of the project and build process completes successfully and .msi files is generated.

However, when I try to build the same project on TeamCity CI server, the *.g.wxs file is not generated and build fails. If I include .g.wxs files to commits, the builds succeeds.

I want to exclude .g.wxs files from from Git commits because if included, the file changes all the time due to its auto-generation nature and I don't want to record/keep all those auto-generated changes.

Is there a way that I can guarantee generating *.g.wxs files in TeamCity?

Check for .NET462

Hey,
when I wanยดt to check if .NET462 is installed it is not possible.

project.SetNetFxPrerequisite("NETFRAMEWORK462='#1'", "Please install .NET 4.6.2 first");

this throws an Exception

error LGHT0094: Unresolved reference to symbol 'Property:NETFRAMEWORK462'

WixToolset v.3.11+ is installed

Thanks Christobal25

feature

hello!
How can I set feature state to enabled (or disabled) from Msi_Load (or Msi_BeforeInstall) function?

How to mark a .NET assembly to be NGen'd during install

In Wix XML it is possible to add the NetFxExtension which enables the netfx:NativeImage sub-element to be added under the element.

Wix# apparently have a predefined set of sub-elements that are allowed to put inside , so this approach seems to not be possible.

What is the usual / recommended way to NGen assemblies during install via Wix#? Any examples?

Remove default text from UI when using background or banner images

I set a project to WixUI_Minimal and then set background and banner images. However, I notice that the default text (for example [ProgressDlgTitleInstalling]) is still visible on top of the banner. How do I either set the text to an empty string or make the banner image be the top most control? Thanks.

deleting files on upgrading

Hello!
I create config.ini file in after instal event:

       static void Msi_AfterInstall(SetupEventArgs e)
        {
            if (!e.IsUninstalling && !e.IsInstalled && !e.IsUpgrading)
            {
                INIManager ini = new INIManager((@"c:\MyPrograms\BaseInstaller\Config.ini"));
                if (e.Session.Property("MOBIL") == "1")
                {
                    ini.WritePrivateString("TYPE", "MOBIL", "1");
                }
                else
                {
                    ini.WritePrivateString("TYPE", "MOBIL", "0");
                }
            }
        }

Why when I upgrade my program, this file re-created?

Cannot add environment variables to project object if only merge modules are present.

I'm having issues building an msi out of several merge modules, while at the same time adding an environment variable to the project object. Here's what I'm trying to do:

static void Main(string[] args)
        {
            var feature = new Feature("Complete");
            var project = new Project("testproject",
                new Dir(@"%ProgramFiles%\somedir",
                    new Merge(feature, @"D:\path\merge.msm")),
                new EnvironmentVariable("foo", "bar"));

            project.DefaultFeature = feature;
            project.Platform = Platform.x64;

            project.PreserveTempFiles = true;

            project.BuildMsi();
        }

If I run this code, I end up with the following error:

Unhandled Exception: System.InvalidOperationException: Sequence contains no elements
at System.Linq.Enumerable.First[TSource](IEnumerable1 source) at WixSharp.Compiler.GetTopLevelDir(XElement product) at WixSharp.Compiler.ProcessEnvVars(Project wProject, Dictionary2 featureComponents, List`1 defaultFeatureComponents
, XElement product)
at WixSharp.Compiler.GenerateWixProj(Project project)
at WixSharp.Compiler.BuildWxs(Project project, String path, OutputType type)
at WixSharp.Compiler.BuildWxs(Project project, OutputType type)
at WixSharp.Compiler.Build(Project project, String path, OutputType type)
at WixSharp.Compiler.Build(Project project, OutputType type)
at WixSharp.Compiler.BuildMsi(Project project)
at WixSharp.Project.BuildMsi(String path)
at BlastZone.Program.Main(String[] args) in C:\Users\user\Documents\Visual Studio 2015\Projects\BlastZone\BlastZone
\Program.cs:line 27

However, I don't get this error if I add a File object like so:

static void Main(string[] args)
        {

            var feature = new Feature("Complete");
            var project = new Project("testproject",
                new Dir(@"%ProgramFiles%\somedir",
                    new File(@"C:\Public\somefile.txt"),
                    new Merge(feature, @"D:\path\merge.msm")),
                new EnvironmentVariable("foo", "bar"));

            project.DefaultFeature = feature;
            project.Platform = Platform.x64;

            project.PreserveTempFiles = true;

            project.BuildMsi();
        }

I've been able to work around the issue be modifying the WiX directly, so I know this it's possible to do what I'm seeking. Is the requirement on a File object in the install Directory intended, or is it a bug?

Thanks.

ExeFileShortcut

Hello! I try create ExeFileShortcut with some arguments:
new ExeFileShortcut("MyApp", @"[INSTALLDIR]\MyApp.exe", "{abc" )
but it not work. Without '{' - all ok, but I need '{'

WixSharp.targets build execution and script arguments

I want to pass arguments to my Wix# script while building in Visual Studio.
It would be pretty easy with Post-Build events in VS.
But!
Wix# build is being executed from WixSharp.targets file. Hardcoded.
I can modify targets file, but this is bad practice. These changes will be lost with package update. Package is not in source control.
I vote for remove hardcoded build execution from the Wix# package target file.
Build process should be started explicitly by developer and the build process should be customizable.

Execute .batch from RessourceManager

Hallo Oleg, i need some help with execute a batch file from Ressourcesmanger in my ManagedProject.
Situation: i have dll in my project and i have to register mydll as com-object. I tried heat.exe file mydll.dll -out mydll.wxs, but after installation dll is not registered as com.
My workaround was with write batch which run regasm,exe and register mydll as com. Here i need some help.
How can i execute .batch during installation ? CustomAction maybe ? What should i do in Return, Step and Condition ? Some codeexample would be good. Thanks for your help.

Compiler.BuildMsi() & async/await

Hello!

I got an exception from Compiler.BuildMsi() method. I tried to find the reason and it took me a long time. Below I will explain my situation and my solution. I think it will help you to improve Wix#.

Compiler.BuildMsi() builds an installer in separated AppDomain. When AppDomain is created .NET passes CallContext of the parent domain to the created child domain. It means content of this CallContext will be serialized and then deserialized to be transferred it between domains. If CallContext contains non-serializable instance any invocation to the child AppDomain will return an exception. And that exception will not reflect the real problem.

Also we can't control content of the CallContext because we can use a third party code. So it would be great if we had "clean" CallContext before creating new AppDomain. To do this we can use ExecutionContext.SuppressFlow() method which suppresses the flow of the execution context i.e. after call SuppressFlow() new threads won't get parent CallContext and will have to use its own "clean" CallContext. Consequently you can create new AppDomain within new thread and don't worry about CallContext.

After work with child AppDomain you must restore the flow of the execution context using AsyncFlowControl.Undo() method. The Undo() method must be called in the same thread where SuppressFlow() method was invoked thus next code waits for completion a thread using Task.Wait() and doesn't use await.

Unfortunately only this workaround helped me and I can use Compiler in any CallContext (include async/await code). Probably there is more elegant solution but I think it must be part of your library. :)

// ...

await ExecuteInNewContext(() => Compiler.BuildMsi(...));

// ...

private static Task<T> ExecuteInNewContext<T>(Func<T> action)
{
    var taskResult = new TaskCompletionSource<T>();

    var asyncFlow = ExecutionContext.SuppressFlow();

    try
    {
        Task.Run(() =>
                 {
                     try
                     {
                         var result = action();

                         taskResult.SetResult(result);
                     }
                     catch (Exception exception)
                     {
                         taskResult.SetException(exception);
                     }
                 })
            .Wait();
    }
    finally
    {
        asyncFlow.Undo();
    }

    return taskResult.Task;
}

See original issue here.

UPDATE

I've created a little test project which demonstrates my issue and my suggestion.

https://github.com/AlexMAS/WixSharpAsyncTests.git

All test cases are in the file WixSharpAsyncTest.cs which represents NUnit test.

Enhancement: add session.IsUpgrade / setupEventArgs.IsUpgrade

There is a property for all cases:

  • IsInstalling
  • IsUpgrading
  • IsModifying
  • IsUninstalling
  • IsInstalled

But not when an installing product is an upgrade, we can see only during uninstall (IsUpgrading ).

May be:

public bool IsUpgrade { get { return Data["UPGRADEFOUND"].IsNotEmpty(); } }

It is a very minor thing and it can be done easily manually (session.Property("UPGRADEFOUND")), but it should be added to complete the pattern.

Including a 3rd party exe installer

Previously, using WixSharp 1.0, we had an 3rd party exe (an installer) that was included in our source files. A custom action started the exe at the end of our install.

Now, having upgraded to the latest via NuGet, the same project gets an error:

System.BadImageFormatException: Could not load file or assembly 'file:///C:\3rdparty.exe' or one of its dependencies. The module was expected to contain an assembly manifest.

Server stack trace:
at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String
codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint,
StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean
throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName
assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly,
StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean
throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.InternalLoadFrom(String assemblyFile,
Evidence securityEvidence, Byte[] hashValue, AssemblyHashAlgorithm
hashAlgorithm, Boolean forIntrospection, Boolean suppressSecurityChecks,
StackCrawlMark& stackMark)
at System.Reflection.Assembly.ReflectionOnlyLoadFrom(String assemblyFile)
at WixSharp.AsmReflector.OriginalAssemblyFile(String file)
at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage
(IntPtr md, Object[] args, Object server, Object[]& outArgs)
at
System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage
msg)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage
reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&
msgData, Int32 type)
at WixSharp.AsmReflector.OriginalAssemblyFile(String file)
at
WixSharp.Utils.<>c__DisplayClass4_0.b__0(AsmReflector
asm)
at WixSharp.Utils.ExecuteInTempDomain[T](Func2 action)
at WixSharp.Utils.OriginalAssemblyFile(String file)
at WixSharp.Compiler.PackageManagedAsm(String asm, String nativeDll,
String[] refAssemblies, String outDir, String configFilePath, Nullable1
platform, Boolean embeddedUI, String batchFile)
at WixSharp.Compiler.ProcessCustomActions(Project wProject, XElement
product)
at WixSharp.Compiler.GenerateWixProj(Project project)
at WixSharp.Compiler.BuildWxs(Project project, String path, OutputType type)
at WixSharp.Compiler.BuildWxs(Project project, OutputType type)
at WixSharp.Compiler.Build(Project project, String path, OutputType type)
at WixSharp.Compiler.Build(Project project, OutputType type)
at MsiBuilder.MsiBuilder.Build() ...

=> var msi = Compiler.BuildMsi(project);

Note that the 3rd party exe is listed in the project.DefaultRefAssemblies.
Ideas?

Pete

Can't install dll to windows/system32

Hello, Oleg!
I want to install MyLibrary.dll to windows/system32. After installation there isn't MyLibrary.dll in windows/system32.
My code:

var project = new Project("MyProduct",
            new Dir(@"%SystemFolder%", new File("MyLibrary.dll")));

Output msi:

<Directory Id = "TARGETDIR" Name="SourceDir">
    <Directory Id = "INSTALLDIR" Name="%SystemFolder%">
    <Component Id = "Component.MyLibrary.dll" Guid="107476c8-8665-4b14-a6bd-008f39ec5786">
        <File Id = "MyLibrary.dll" Source="MyLibrary.dll" />
    </Component>
    </Directory>
</Directory>

%SystemFolder% isn't Wix environment constant.
I have the same problem with Assembly.

Installing in "%SystemFolder%/TestFolder" is OK.

Unable to retieve value from Session["propertyName"]

Hi Oleg,

I have declared the project in the Main() method as follows:-

var project = 
        new ManagedProject("MyProduct", 
            new Dir(@"C:\",new Dir(@"MyWindowService", new DirFiles(@"..\MyWindowsService\bin\Release\*.*"))),
            new ElevatedManagedAction(CustomActions.InstallService,
                                          Return.check,
                                          When.After,
                                          Step.InstallFiles,
                                          Condition.Always),
            new ElevatedManagedAction(CustomActions.UnInstallService,
                                      Return.check,
                                      When.Before,
                                      Step.RemoveFiles,
                                      Condition.BeingRemoved));

I am assigning some value to Session["propertyName"] in the next button click event of the CustomDialog as follows:-

void next_Click(object sender, EventArgs e)
{
     MsiRuntime.Session["ConnectionString"] = connectionStringValue;
}

I am trying to access this value in the Custom Action InstallService method and Msi_AfterInstall method as follows:-

[CustomAction]
public static ActionResult InstallService(Session session)
{
      var connectionString = session["ConnectionString"];
       .........
}

static void Msi_AfterInstall(SetupEventArgs e)
{
      var connectionString=e.Session["ConnectionString"];
      ...........
}

But the value is not accessible and its throwing below error for both the methods when I am trying to get the value from Session["propertyName"].

Errors:-
Info: Exception thrown by custom action:
Info: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> Microsoft.Deployment.WindowsInstaller.InstallerException: Cannot access session details from a non-immediate custom action
at Microsoft.Deployment.WindowsInstaller.Session.ValidateSessionAccess()
at Microsoft.Deployment.WindowsInstaller.Session.get_Item(String property)
at MySetup.CustomActions.InstallService(Session session) in H:\MySetup\CustomActions.cs:line 21
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object parameters, Object arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture)
at Microsoft.Deployment.WindowsInstaller.CustomActionProxy.InvokeCustomAction(Int32 sessionHandle, String entryPoint, IntPtr remotingDelegatePtr)

Info: Calling custom action WixSharp!WixSharp.ManagedProjectActions.WixSharp_AfterInstall_Action
Info: WixSharp aborted the session because of the error:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> Microsoft.Deployment.WindowsInstaller.InstallerException: Cannot access session details from a non-immediate custom action
at Microsoft.Deployment.WindowsInstaller.Session.ValidateSessionAccess()
at Microsoft.Deployment.WindowsInstaller.Session.get_Item(String property)
at MySetup.Program.Msi_AfterInstall(SetupEventArgs e)
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object parameters, Object arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture)
at WixSharp.ManagedProject.InvokeClientHandler(String info, SetupEventArgs eventArgs)
at WixSharp.ManagedProject.InvokeClientHandlers(Session session, String eventName, IShellView UIShell)

Am I following some wrong syntax?
Please advise. Thanks in advance.

"Newer version already installed" dialog does not show if using project.ManagedUI

Hello!
I want to show dialog if newer version already installed. Then stop the installation process.

error

If i use project.UI. Dialog is shown and installation is stopped.
project.UI = WUI.WixUI_InstallDir;

If i use project.ManagedUI. Dialog is not shown. Although the installation is stopped. And in log i see error with message "Newer version already installed"

project.ManagedUI.InstallDialogs.Add(Dialogs.Welcome)
                                            .Add(Dialogs.Licence)
                                            .Add(Dialogs.InstallDir)
                                            .Add(Dialogs.Progress)
                                            .Add(Dialogs.Exit);

How to show this dialog when i use ManagedUI?

Wix error when using multiple directories

With the following code:

using WixSharp;

namespace WixSharpSetup
{
    class Program
    {
        static void Main()
        {
            var project = new ManagedProject()
            {
                Name = "MyProduct",
                Dirs = new[]
                {
                    new Dir("%ProgramFilesFolder%/Foo"),
                    new Dir(@"C:\something\else")
                }
            };
            project.BuildMsi();
        }
    }
}

The build ends with:

Wix project file has been built: c:\users\admin\documents\visual studio 2015\Projects\ClassLibrary1\WixSharp Setup1\setup.wxs
1>
1> Windows Installer XML Toolset Compiler version 3.10.3.3007
1> Copyright (c) .NET Foundation and contributors. All rights reserved.
1>
1> setup.wxs
1>c:\users\admin\documents\visual studio 2015\Projects\ClassLibrary1\WixSharp Setup1\setup.wxs(19): error CNDL0027: The Directory/@name attribute's value, 'C:\something\else', is not a valid long name because it contains illegal characters. Legal long names contain no more than 260 characters and must contain at least one non-period character. Any character except for the follow may be used: \ ? | > < : / * ".
1> Cannot build c:\users\admin\documents\visual studio 2015\Projects\ClassLibrary1\WixSharp Setup1\setup.wxs
1>c:\users\admin\documents\visual studio 2015\Projects\ClassLibrary1\packages\WixSharp.1.2.0.0\build\WixSharp.targets(6,5): error MSB3073: The command ""c:\users\admin\documents\visual studio 2015\Projects\ClassLibrary1\WixSharp Setup1\bin\Debug\WixSharpSetup.exe" "/MSBUILD:WixSharp Setup1"" exited with code -1.

The .wxs file ends up with:

    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFilesFolder" Name="ProgramFilesFolder">
        <Directory Id="INSTALLDIR" Name="Foo">

          <Component Id="INSTALLDIR.EmptyDirectory" Guid="73a032e4-80fb-4301-bde9-58247c74d6ad" KeyPath="yes">
            <CreateFolder />
            <RemoveFolder Id="INSTALLDIR" On="uninstall" />
          </Component>

        </Directory>
      </Directory>

      <Directory Id="TARGETDIR.C_.something.else" Name="C:\something\else">

        <Component Id="else.EmptyDirectory" Guid="73a032e4-80fb-4301-bde9-5824ae4ac65b" KeyPath="yes">
          <CreateFolder />
          <RemoveFolder Id="TARGETDIR.C_.something.else" On="uninstall" />
        </Component>

      </Directory>

I am currently working around this using a load-time hook (which was actually more elegant anyway), but it looks like a possible bug to allow multiple entries in .Dirs but for the Name attribute to be invalid.

External Install software

hi

i have an installer that i wrote with custom ui (winform base)
i want to add to it an sqlexpress and .net(if needed)
i tryied to run it from the installer , but i cant run 2 windows installer at the same time
i tryied to do it with bootsrap but it doesnt show my ui (at least i didnt succeed to do it)
i saw your WixBootstrapper UI example but as i understand i require a big change

what is the easiest way to do it

Enhancement: Attributes inheritance in Files and DirFiles for generated items (File and Dir)

Extend WixSharp.DirFiles and WixSharp.Files to support attributes inheritance for generated items.

WixSharp.DirFiles

new DirFiles(feature1, @"Files\Feature1\Docs\*.*")
{
    AttributesDefinition = "Attribute1=value1;Attribute2=value2"
},

Should Generate collection of

new File(feature1, @"Files\Feature1\Docs\File1")
{
    AttributesDefinition = "Attribute1=value1;Attribute2=value2"
},
...

WixSharp.Files

Files is recursive and generate WixSharp.File and WixSharp.Dir item, so we need to differentiate target.
Should use same syntax as Component cibling. As Component can't have a Dir children,
"Component :Attribute=value" can target File element.

new Files(feature1, @"Files\Feature1\Docs\*")
{
    AttributesDefinition = "File:Attribute1=value1;Component:Attribute2=value2;Dir:Attribute3=value3"
},

Should Generate collections of

new File(feature1, @"Files\Feature1\Docs\File1")
{
    AttributesDefinition = "Attribute1=value1;Component:Attribute2=value2"
},
...
new Dir(feature1, "MyDir")
{
    AttributesDefinition = "Attribute3=value3"
},
...

Permenanet Files

Hallo Oleg,

how do i set Files or Folders as permanent ? i have to prevent Folders/Files from being delete on uninstall.
I need some Help here.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.