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 }
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); }
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(); }
/// <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; }
/// <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; } }
/// <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; }
/// <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; }
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); }