oleg-shilo / wixsharp

Framework for building a complete MSI or WiX source code by using script files written with C# syntax.
MIT License
1.05k stars 168 forks source link

Externl Ui and Silent intallation #1512

Open Diddlik opened 1 month ago

Diddlik commented 1 month ago

I have built an external UI for the installer and this starts the msi installer under the hood. Everything works fine. But what I can't manage is the possibility to build silent isntaller with external ui.

I.e. I start e.g. myinstaller.exe --mode:silent --path: "c:\data\mayapp" and it is installed in the background in my path, if you start it without parameters, it runs as usual via gui

I read this topic (https://github.com/oleg-shilo/wixsharp/issues/594) but direct usage off parameters starts ui nevertheless

oleg-shilo commented 1 month ago

you can always start your msi with the dedicated launcher msiexec.exe

It has a special command line arg for starting it without UI. image

Diddlik commented 1 month ago

I thought msi file is integrated in exe of custom ui at least the size of the exe indicates this. Is it possible not to include the msi via the resourse.resx file?

Diddlik commented 1 month ago

Or wait, do you mean in this part of code?

I catch the command line and start msiexec as a process with needed parameters?

private void Application_Startup(object sender, StartupEventArgs e) { splashscreen = new SplashScreen(); splashscreen.Show(); App.DoEvents();

byte[] msiData = MyInstaller.Properties.Resources.MyApp;
MsiFile = Path.Combine(Path.GetTempPath(), "myApp.msi");

if (!File.Exists(MsiFile) || new FileInfo(MsiFile).Length != msiData.Length)
    File.WriteAllBytes(MsiFile, msiData);

AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;

}

oleg-shilo commented 1 month ago

Pavel, you are loosing me :)

You are asking me about the project you have implemented. I have no idea what you are dealing with. The only description you gave me is "I have built an external UI for the installer and this starts the msi installer under the hood".

What exactly are you building?

Diddlik commented 1 month ago

I have made an external_ui for the installer, as in the samples from WixSharp. This creates a wpf externl ui, which in turn uses a msi file

MSI file is created according to this code

static public void Main(string[] args)
    {

        string path = @"..\Build\";
        var dirsList = new List<WixEntity> { new DirFiles(Path.Combine(path, "*.*")) };
        dirsList.AddRange(GetSubdirectories(path)
            .Select(d => new Dir(d.Replace(path, ""), new DirFiles(Path.Combine(d, "*.*")))));

        var project = new Project("MyApp",
                        new LaunchCondition("CUSTOM_UI=\"true\" OR REMOVE=\"ALL\"", "Please run setup.exe instead."),
                        new Dir(@"%ProgramFiles%\MyApp\", dirsList.ToArray()));

        project.GUID = new Guid("6fe30b47-2577-43ad-9095-1861ba25878b");
        project.Platform = Platform.x64;

        project.UI = WUI.WixUI_Common;

        project.ResolveWildCards()
            .FindFirstFile("UI.exe")
            .Shortcuts = new[]
        {
                new FileShortcut("MyApp", "INSTALLDIR"),
                new FileShortcut("MyApp", "%Desktop%")
        };
        project.ResolveWildCards()
            .FindFirstFile("UI.exe").Associations = new FileAssociation[]
        {
                new FileAssociation("my", "application/", "open", "\"%1\"")
        };

        project.BuildMsi();

    }

after compiling I have my extern_ui exe file, which installs my program. MSI file is included in this exe. what i did not understand, how can i start my external_ui in silent mode so that my program installs

oleg-shilo commented 1 month ago

Great. Then we are talking about the <Wix# Samples>\External_UI\WpfSetup based project.

In this sample the click on 'install' button triggers the base.StartInstall of the MyProductSetup class.

image

Since the base class StartInstall does not do the job you need, you need to provide your own alternative implementation:


public class MyProductSetup : GenericSetup
{
. . .
    public override void StartInstall(string msiParams = null)
    {
        if (!IsCurrentlyInstalled)
        {
            // Experiment in the command prompt to find the required params
            Process.Start("msiexec.exe", $" /i \"{MsiFile}\" /qn {msiParams}");

            LogFileCreated = true;
            IsRunning = true;
        }
        else
        {
            ErrorStatus = "Product is already installed";
        }
    }

However, if you do not need MSI default UI, why don't you just switch it off all completely when you build your msi?

project.UI = WUI.WixUI_ProgressOnly;

Then you don't need to do anything in your WPF UI at all. as MSI will only have UI that is a tiny progress dialog. It's just an option for you to consider...

Diddlik commented 1 month ago

My idea was to have both, UI installer and silent mode for automatic deployment. Since I don't need MSI GUI, I would make it leaner with your template. I'll try with StartInstall function.

Thanks for the tips!