Class for defining a WiX standard Burn-based bootstrapper. By default the bootstrapper is using WiX default WiX bootstrapper UI.
상속: WixProject
예제 #1
0
        public void Should_Process_XmlAttribute()
        {
            var bootstrapper = new Bundle("test_name")
            {
                AboutUrl = "a_url",
                DisableRollback = false,
                IconFile = "icon.ico",
                Version = new Version("1.2.3.4"),
                UpgradeCode = new Guid("00000000-0000-0000-0000-000000000007")
            };

            var xml = bootstrapper.ToXml().Cast<XElement>().First();

            //<Bundle Name="test_name" DisableRollback="no" AboutUrl="a_url" IconSourceFile="icon.ico" UpgradeCode="00000000-0000-0000-0000-000000000007" Version="1.2.3.4" />
            Assert.Equal(6, xml.Attributes().Count());

            Assert.Equal("test_name", xml.ReadAttribute("Name"));
            Assert.Equal("a_url", xml.ReadAttribute("AboutUrl"));
            Assert.Equal("no", xml.ReadAttribute("DisableRollback"));
            Assert.Equal("icon.ico", xml.ReadAttribute("IconSourceFile"));
            Assert.Equal("1.2.3.4", xml.ReadAttribute("Version"));
            Assert.Equal("00000000-0000-0000-0000-000000000007", xml.ReadAttribute("UpgradeCode"));

            Assert.Null(xml.ReadAttribute("DisableSystemRestore")); //bool?
            Assert.Null(xml.ReadAttribute("Copyright"));//string
        }
예제 #2
0
        public void Should_Produce_BundleXml()
        {
            var bootstrapper =
                new Bundle("My Product",
                    new PackageGroupRef("NetFx40Web"),
                    new ExePackage(@"Samples\Setup1.exe")
                    {
                        Payloads = new[] { @"Samples\setup1.dll" },
                        InstallCommand = "/q /norestart",
                        PerMachine = true
                    },
                    new MsiPackage(@"Samples\SetupB.msi") { Vital = false },
                    new RollbackBoundary(),
                    new MsiPackage(@"Samples\SetupA.msi"));

            bootstrapper.AboutUrl = "https://wixsharp.codeplex.com/";
            bootstrapper.IconFile = "icon.ico";
            bootstrapper.Version = new Version("1.0.0.0");
            bootstrapper.UpgradeCode = new Guid("00000000-0000-0000-0000-000000000007");
            bootstrapper.Application.LicensePath = "readme.rtf";
            bootstrapper.Application.LocalizationFile = "en-us.wxl";
            bootstrapper.Application.LogoFile = "app_logo.png";

            var xml = bootstrapper.ToXml().First().ToString();

            var expected = @"<Bundle Name=""My Product"" AboutUrl=""https://wixsharp.codeplex.com/"" IconSourceFile=""icon.ico"" UpgradeCode=""00000000-0000-0000-0000-000000000007"" Version=""1.0.0.0"">
              <BootstrapperApplicationRef Id=""WixStandardBootstrapperApplication.RtfLicense"">
            <WixStandardBootstrapperApplication LogoFile=""app_logo.png"" LocalizationFile=""en-us.wxl"" LicenseFile=""readme.rtf"" xmlns=""http://schemas.microsoft.com/wix/BalExtension"" />
              </BootstrapperApplicationRef>
              <Chain>
            <PackageGroupRef Id=""NetFx40Web"" />
            <ExePackage InstallCommand=""/q /norestart"" SourceFile=""Samples\Setup1.exe"" PerMachine=""yes"">
              <Payload SourceFile=""Samples\setup1.dll"" />
            </ExePackage>
            <MsiPackage SourceFile=""Samples\SetupB.msi"" Vital=""no"" />
            <RollbackBoundary />
            <MsiPackage SourceFile=""Samples\SetupA.msi"" />
              </Chain>
            </Bundle>";
            Assert.Equal(expected, xml);
        }
예제 #3
0
        public static void Main(string[] args)
        {
            Feature appFeature = new Feature("Application files", "Main application files", true, false, @"INSTALLDIR");
            var shortcut = new FileShortcut(appFeature, "digiCamControl", @"%ProgramMenu%\digiCamControl") { WorkingDirectory = @"INSTALLDIR" };
            var shortcutD = new FileShortcut(appFeature, "digiCamControl", @"%Desktop%") { WorkingDirectory = @"INSTALLDIR" };
            var appDir = new Dir(@"digiCamControl",
                new File(appFeature, "CameraControl.exe", shortcut, shortcutD),
                new File(appFeature, "CameraControl.PluginManager.exe"),
                new File(appFeature, "CameraControlCmd.exe"),
                new File(appFeature, "CameraControlRemoteCmd.exe"),
                new File(appFeature, "dcraw.exe"),
                new File(appFeature, "ffmpeg.exe"),
                new File(appFeature, "ngrok.exe"),
                new File(appFeature, "MtpTester.exe"),
                //new File(appFeature, "PhotoBooth.exe",new FileShortcut(appFeature, "PhotoBooth", @"%ProgramMenu%\digiCamControl")),
                new DirFiles(appFeature, @"*.dll"),
            #if DEBUG
                new DirFiles(appFeature, @"*.pdb"),
            #endif
                new File(appFeature, "regwia.bat"),
                new File(appFeature, "logo.ico"),
                new File(appFeature, "logo_big.jpg"),
                new File(appFeature, "baseMtpDevice.xml"),
                new DirFiles(appFeature, @"*.png"),
                new File(appFeature, "DigiCamControl.xbs"),
                new Dir(appFeature, "Data",
                    new Files(appFeature, @"Data\*.*")),
                //new Dir(appFeature, "Plugins",
                //    new Files(appFeature, @"Plugins\*.*", "MahApps.Metro.*", "System.Windows.Interactivity.*",
                //        "WriteableBitmapEx.Wpf.*", "GalaSoft.MvvmLight.*", "*.config")),
                new Dir(appFeature, "Plugins",
                    new Dir(appFeature, "CameraControl.Plugins",
                        new File(appFeature, "Plugins\\CameraControl.Plugins\\CameraControl.Plugins.dll"),
                        new File(appFeature, "Plugins\\CameraControl.Plugins\\dcc.plugin")),
                    new Dir(appFeature, "Plugin.DeviceControlBox",
                        new File(appFeature, "Plugins\\Plugin.DeviceControlBox\\Plugin.DeviceControlBox.dll"),
                        new File(appFeature, "Plugins\\Plugin.DeviceControlBox\\dcc.plugin"))
                    ),
                new Dir(appFeature, "Languages",
                    new DirFiles(appFeature, @"Languages\*.xml")),
                new Dir(appFeature, "Licenses",
                    new DirFiles(appFeature, @"Licenses\*.*")),
                new Dir(appFeature, "x64",
                    new DirFiles(appFeature, @"x64\*.*")),
                new Dir(appFeature, "x86",
                    new DirFiles(appFeature, @"x86\*.*")),
                new Dir(appFeature, "Tools",
                    new DirFiles(appFeature, @"Tools\*.*")),
                new Dir(appFeature, "WebServer",
                    new Files(appFeature, @"WebServer\*.*"))
                );

            var baseDir = new Dir(@"%ProgramFiles%",
                appDir
                );

            Project project = new Project("digiCamControl",
                baseDir,
                new ManagedAction(Setup.CustomActions.MyAction, Return.ignore, When.Before, Step.InstallExecute,
                    Condition.NOT_Installed, Sequence.InstallExecuteSequence),
                new ManagedAction(Setup.CustomActions.SetRightAction, Return.ignore, When.Before, Step.InstallFinalize,
                    Condition.Always, Sequence.InstallExecuteSequence),
                new RegValue(appFeature, RegistryHive.ClassesRoot,
                    @"Wow6432Node\CLSID\{860BB310-5D01-11d0-BD3B-00A0C911CE86}\Instance\{628C6DCD-6A0A-4804-AAF3-91335A83239B}",
                    "FriendlyName",
                    "digiCamControl Virtual WebCam"),
                new RegValue(appFeature, RegistryHive.CurrentUser,
                    @"SOFTWARE\IP Webcam",
                    "url",
                    "http://*****:*****@"SOFTWARE\IP Webcam",
                    "width","640"),
                new RegValue(appFeature, RegistryHive.CurrentUser,
                    @"SOFTWARE\IP Webcam",
                    "height", "426")
                );

            project.UI = WUI.WixUI_InstallDir;
            project.GUID = new Guid("19d12628-7654-4354-a305-9ab0932af676");
            //project.SetNetFxPrerequisite("NETFRAMEWORK45='#1'");

            #if DEBUG
            project.SourceBaseDir =
                Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, @"..\CameraControl\bin\Debug\"));
            #else
            project.SourceBaseDir =
                Path.GetFullPath(System.IO.Path.Combine(Environment.CurrentDirectory, @"..\CameraControl\bin\Release\"));
            #endif
            /* Not particularly proud of this change, nor the matching one in ObsPluginSetup.cs, but it seems necessary to allow these
             * programs to be built regardless of the layout choosen for the files */
            FileVersionInfo ver = null;
            try
            {
                ver =
                    FileVersionInfo.GetVersionInfo(Path.Combine(project.SourceBaseDir, "CameraControl.exe"));
            }
            catch (FileNotFoundException ex)
            {
                project.SourceBaseDir = project.SourceBaseDir.Replace(@"Setup\bin\", "");
                ver =
                    FileVersionInfo.GetVersionInfo(Path.Combine(project.SourceBaseDir, "CameraControl.exe"));
            }

            project.LicenceFile = @"Licenses\DigiCamControlLicence.rtf";

            project.Version = new Version(ver.FileMajorPart, ver.FileMinorPart, ver.FileBuildPart, ver.FilePrivatePart);
            project.MajorUpgradeStrategy = MajorUpgradeStrategy.Default;
            //project.MajorUpgradeStrategy.NewerProductInstalledErrorMessage = "A version of the digiCamControl already installed. Unistall it first from Control Panel !";
            project.MajorUpgradeStrategy.RemoveExistingProductAfter = Step.InstallInitialize;
            ////project.MajorUpgradeStrategy.UpgradeVersions = VersionRange.ThisAndOlder;
            ////project.MajorUpgradeStrategy.PreventDowngradingVersions = VersionRange.ThisAndOlder;

            project.ControlPanelInfo.Manufacturer = "Duka Istvan";
            project.OutFileName = string.Format("digiCamControlsetup_{0}", ver.FileVersion);
            project.ControlPanelInfo.ProductIcon = "logo.ico";
            if (System.IO.Directory.Exists(Path.Combine(project.SourceBaseDir, "Branding")))
            {
                appDir.AddDir(new Dir(appFeature, "Branding",
                    new Files(appFeature, @"Branding\*.*")));
            }

            string branding = Path.Combine(project.SourceBaseDir, "branding.xml");
            if (System.IO.File.Exists(branding))
            {
                var doc = new XmlDocument();
                doc.LoadXml(System.IO.File.ReadAllText(branding));
                string name = doc.DocumentElement.SelectSingleNode("/Branding/ApplicationTitle").InnerText;
                project.ControlPanelInfo.Manufacturer = name;
                project.OutFileName = string.Format(name.Replace(" ", "_") + "_{0}", ver.FileVersion);
                appDir.AddFile(new File(appFeature, "branding.xml"));
                project.Name = name;
                if (System.IO.File.Exists(Path.Combine(project.SourceBaseDir, "Branding", "logo.ico")))
                {
                    project.ControlPanelInfo.ProductIcon = Path.Combine(project.SourceBaseDir, "Branding", "logo.ico");
                    shortcut.IconFile = Path.Combine(project.SourceBaseDir, "Branding", "logo.ico");
                    shortcutD.IconFile = Path.Combine(project.SourceBaseDir, "Branding", "logo.ico");
                    shortcut.Name = name;
                    shortcutD.Name = name;
                }
                if (System.IO.File.Exists(Path.Combine(project.SourceBaseDir, "Branding", "Licence.rtf")))
                    project.LicenceFile = "Branding\\Licence.rtf";

            }
            project.InstallScope = InstallScope.perMachine;
            project.ResolveWildCards();
            Compiler.PreserveTempFiles = false;
            string productMsi = Compiler.BuildMsi(project);
            string obsMsi = ObsPluginSetup.Execute();
            Thread.Sleep(2000);
            var dict = new Dictionary<string, string>();
            dict.Add("Visible","yes");
            var bootstrapper =new Bundle(project.Name,
            new PackageGroupRef("NetFx46Web"),
            //new ExePackage("vcredist_x86.exe"){InstallCommand ="/quite" },
            new MsiPackage(Path.Combine(Path.GetDirectoryName(productMsi), "IPCamAdapter.msi")) { Permanent = false,Attributes = dict},
            new MsiPackage(obsMsi) { Id = "ObsPackageId", Attributes = dict },
            new MsiPackage(productMsi) { Id = "MyProductPackageId", DisplayInternalUI = true, Attributes = dict });

            bootstrapper.Copyright = project.ControlPanelInfo.Manufacturer;
            bootstrapper.Version = project.Version;
            bootstrapper.UpgradeCode = new Guid("19d12628-7654-4354-a305-3A2057E2E6C9");
            bootstrapper.DisableModify = "yes";
            bootstrapper.DisableRemove = true;
            //bootstrapper.Application = new LicenseBootstrapperApplication()
            //{
            //    LicensePath = Path.Combine(project.SourceBaseDir, project.LicenceFile),
            //    LogoFile = project.ControlPanelInfo.ProductIcon,

            //};
            bootstrapper.IconFile = project.ControlPanelInfo.ProductIcon;
            bootstrapper.PreserveTempFiles = true;
            bootstrapper.OutFileName = project.OutFileName;

            bootstrapper.Build();
        }
예제 #4
0
        /// <summary>
        /// Builds WiX Bootstrapper application from the specified <see cref="Bundle"/> project instance.
        /// </summary>
        /// <param name="project">The project.</param>
        /// <param name="path">The path.</param>
        /// <exception cref="System.ApplicationException">Wix compiler/linker cannot be found</exception>
        public static string Build(Bundle project, string path)
        {
            if (Compiler.ClientAssembly.IsEmpty())
                Compiler.ClientAssembly = System.Reflection.Assembly.GetCallingAssembly().Location;

            string oldCurrDir = Environment.CurrentDirectory;

            try
            {
                //System.Diagnostics.Debug.Assert(false);
                Compiler.TempFiles.Clear();
                string compiler = Utils.PathCombine(WixLocation, "candle.exe");
                string linker = Utils.PathCombine(WixLocation, "light.exe");

                if (!IO.File.Exists(compiler) || !IO.File.Exists(linker))
                {
                    Console.WriteLine("Wix binaries cannot be found. Expected location is " + IO.Path.GetDirectoryName(compiler));
                    throw new ApplicationException("Wix compiler/linker cannot be found");
                }
                else
                {
                    string wxsFile = BuildWxs(project);

                    if (!project.SourceBaseDir.IsEmpty())
                        Environment.CurrentDirectory = project.SourceBaseDir;

                    string objFile = IO.Path.ChangeExtension(wxsFile, ".wixobj");
                    string pdbFile = IO.Path.ChangeExtension(wxsFile, ".wixpdb");

                    string extensionDlls = "";
                    foreach (string dll in project.WixExtensions.Distinct())
                        extensionDlls += " -ext \"" + dll + "\"";

                    string wxsFiles = "";
                    foreach (string file in project.WxsFiles.Distinct())
                        wxsFiles += " \"" + file + "\"";

                    Run(compiler, CandleOptions + " " + extensionDlls + " \"" + wxsFile + "\" "+ wxsFiles + " -out \"" + objFile + "\"");

                    if (IO.File.Exists(objFile))
                    {
                        string msiFile = wxsFile.PathChangeExtension(".exe");
                        if (IO.File.Exists(msiFile))
                            IO.File.Delete(msiFile);

                        //if (project.IsLocalized && IO.File.Exists(project.LocalizationFile))
                        //    Run(linker, LightOptions + " \"" + objFile + "\" -out \"" + msiFile + "\"" + extensionDlls + " -cultures:" + project.Language + " -loc \"" + project.LocalizationFile + "\"");
                        //else
                        Run(linker, LightOptions + " \"" + objFile + "\" -out \"" + msiFile + "\"" + extensionDlls + " -cultures:" + project.Language);

                        if (IO.File.Exists(msiFile))
                        {
                            Compiler.TempFiles.Add(wxsFile);

                            Console.WriteLine("\n----------------------------------------------------------\n");
                            Console.WriteLine("Bootstrapper file has been built: " + path + "\n");
                            Console.WriteLine(" Name       : " + project.Name);
                            Console.WriteLine(" Version    : " + project.Version);
                            Console.WriteLine(" UpgradeCode: {" + project.UpgradeCode + "}\n");
                            IO.File.Delete(objFile);
                            IO.File.Delete(pdbFile);

                            if (path != msiFile)
                            {
                                if (IO.File.Exists(path))
                                    IO.File.Delete(path);
                                IO.File.Move(msiFile, path);
                            }
                        }
                    }
                    else
                    {
                        Console.WriteLine("Cannot build " + wxsFile);
                        Trace.WriteLine("Cannot build " + wxsFile);
                    }
                }

                if (!PreserveTempFiles && !project.PreserveTempFiles)
                    foreach (var file in Compiler.TempFiles)
                        try
                        {
                            if (IO.File.Exists(file))
                                IO.File.Delete(file);
                        }
                        catch { }

            }
            finally
            {
                Environment.CurrentDirectory = oldCurrDir;
            }

            return path;
        }
예제 #5
0
        /// <summary>
        /// Builds the WiX source file (*.wxs) from the specified <see cref="Bundle"/> instance.
        /// </summary>
        /// <param name="project">The project.</param>
        /// <returns></returns>
        public static string BuildWxs(Bundle project)
        {
            lock (typeof(Compiler))
            {
                //very important to keep "ClientAssembly = " in all "public Build*" methods to ensure GetCallingAssembly
                //returns the build script assembly but not just another method of Compiler.
                if (ClientAssembly.IsEmpty())
                    ClientAssembly = System.Reflection.Assembly.GetCallingAssembly().Location;

                WixEntity.ResetIdGenerator();
                string file = IO.Path.GetFullPath(IO.Path.Combine(project.OutDir, project.OutFileName) + ".wxs");

                if (IO.File.Exists(file))
                    IO.File.Delete(file);

                string extraNamespaces = project.WixNamespaces.Distinct()
                                                          .Select(x => x.StartsWith("xmlns:") ? x : "xmlns:" + x)
                                                          .ConcatItems(" ");

                var doc = XDocument.Parse(
                  @"<?xml version=""1.0"" encoding=""utf-8""?>
                         <Wix xmlns=""http://schemas.microsoft.com/wix/2006/wi"" " + extraNamespaces + @">
                        </Wix>");

                doc.Root.Add(project.ToXml());

                AutoElements.NormalizeFilePaths(doc, project.SourceBaseDir, EmitRelativePaths);

                project.InvokeWixSourceGenerated(doc);
                if (WixSourceGenerated != null)
                    WixSourceGenerated(doc);

                string xml = "";
                using (IO.StringWriter sw = new StringWriterWithEncoding(Encoding.Default))
                {
                    doc.Save(sw, SaveOptions.None);
                    xml = sw.ToString();
                }

                //of course you can use XmlTextWriter.WriteRaw but this is just a temporary quick'n'dirty solution
                //http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2657663&SiteID=1
                xml = xml.Replace("xmlns=\"\"", "");

                DefaultWixSourceFormatedHandler(ref xml);

                project.InvokeWixSourceFormated(ref xml);
                if (WixSourceFormated != null)
                    WixSourceFormated(ref xml);

                using (var sw = new IO.StreamWriter(file, false, Encoding.Default))
                    sw.WriteLine(xml);

                Console.WriteLine("\n----------------------------------------------------------\n");
                Console.WriteLine("Wix project file has been built: " + file + "\n");

                project.InvokeWixSourceSaved(file);
                if (WixSourceSaved != null)
                    WixSourceSaved(file);

                return file;
            }
        }
예제 #6
0
        /// <summary>
        /// Builds the WiX source file and generates batch file capable of building
        /// WiX/MSI bootstrapper with WiX toolset.
        /// </summary>
        /// <param name="project">The project.</param>
        /// <param name="path">The path to the batch file to be created.</param>
        /// <exception cref="System.ApplicationException">Wix compiler/linker cannot be found</exception>
        public static string BuildCmd(Bundle project, string path = null)
        {
            if (Compiler.ClientAssembly.IsEmpty())
                Compiler.ClientAssembly = System.Reflection.Assembly.GetCallingAssembly().Location;

            if (path == null)
                path = IO.Path.GetFullPath(IO.Path.Combine(project.OutDir, "Build_" + project.OutFileName) + ".cmd");

            //System.Diagnostics.Debug.Assert(false);
            string compiler = Utils.PathCombine(WixLocation, "candle.exe");
            string linker = Utils.PathCombine(WixLocation, "light.exe");
            string batchFile = path;

            if (!IO.File.Exists(compiler) || !IO.File.Exists(linker))
            {
                Console.WriteLine("Wix binaries cannot be found. Expected location is " + IO.Path.GetDirectoryName(compiler));
                throw new ApplicationException("Wix compiler/linker cannot be found");
            }
            else
            {
                string wxsFile = BuildWxs(project);

                if (!project.SourceBaseDir.IsEmpty())
                    Environment.CurrentDirectory = project.SourceBaseDir;

                string objFile = IO.Path.ChangeExtension(wxsFile, ".wixobj");
                string pdbFile = IO.Path.ChangeExtension(wxsFile, ".wixpdb");

                string extensionDlls = "";
                foreach (string dll in project.WixExtensions.Distinct())
                    extensionDlls += " -ext \"" + dll + "\"";

                string wxsFiles = "";
                foreach (string file in project.WxsFiles.Distinct())
                    wxsFiles += " \"" + file + "\"";

                string batchFileContent = "\"" + compiler + "\" " + CandleOptions + " " + extensionDlls + " \"" + IO.Path.GetFileName(wxsFile) + "\" "+ wxsFiles + "\r\n";
                //Run(compiler, CandleOptions + " " + extensionDlls + " \"" + wxsFile + "\" -out \"" + objFile + "\"");

                //if (project.IsLocalized && IO.File.Exists(project.LocalizationFile))
                //    Run(linker, LightOptions + " \"" + objFile + "\" -out \"" + msiFile + "\"" + extensionDlls + " -cultures:" + project.Language + " -loc \"" + project.LocalizationFile + "\"");
                //else
                //Run(linker, LightOptions + " \"" + objFile + "\" -out \"" + msiFile + "\"" + extensionDlls + " -cultures:" + project.Language);
                batchFileContent += "\"" + linker + "\" " + LightOptions + " \"" + objFile + "\" " + extensionDlls + " -cultures:" + project.Language + "\r\npause";

                using (var sw = new IO.StreamWriter(batchFile))
                    sw.Write(batchFileContent);
            }

            return path;
        }
예제 #7
0
        /// <summary>
        /// Builds WiX Bootstrapper application from the specified <see cref="Bundle"/> project instance.
        /// </summary>
        /// <param name="project">The project.</param>
        /// <returns></returns>
        public static string Build(Bundle project)
        {
            if (Compiler.ClientAssembly.IsEmpty())
                Compiler.ClientAssembly = System.Reflection.Assembly.GetCallingAssembly().Location;

            string outFile = IO.Path.GetFullPath(IO.Path.Combine(project.OutDir, project.OutFileName) + ".exe");

            Utils.EnsureFileDir(outFile);

            if (IO.File.Exists(outFile))
                IO.File.Delete(outFile);

            Build(project, outFile);

            return IO.File.Exists(outFile) ? outFile : null;
        }
예제 #8
0
        public void Should_Resolve_NoLicenseType()
        {
            var bootstrapper = new Bundle("My Product");

            bootstrapper.UpgradeCode = new Guid("00000000-0000-0000-0000-000000000007");
            bootstrapper.Application.LicensePath = null;

            var xml = bootstrapper.ToXml().First().ToString();

            var expected = @"<Bundle Name=""My Product"" UpgradeCode=""00000000-0000-0000-0000-000000000007"">
  <BootstrapperApplicationRef Id=""WixStandardBootstrapperApplication.HyperlinkLicense"">
    <WixStandardBootstrapperApplication LicenseUrl="""" xmlns=""http://schemas.microsoft.com/wix/BalExtension"" />
  </BootstrapperApplicationRef>
  <Chain />
</Bundle>";
            Assert.Equal(expected, xml);
        }