public string AddUrl(string uri, string type) { var urlAlreadyAdded = (from u in Urls where u.URL == uri && u.Type == type select u).FirstOrDefault(); if (urlAlreadyAdded == null) { var newHuid = new Huid(Name, Version, Arch.ToString(), this.Publisher.PublicKeyToken, uri, type); var urlToAdd = new Url() {URL = uri, Type = type, url_guid= (string)newHuid}; Urls.Add(urlToAdd); return (string) newHuid; } return urlAlreadyAdded.url_guid; }
/* private void addAssemblyGuidsAndIds() { foreach (XmlElement e in SelectNodes(doc, "//in:Assembly")) { var src = SelectSingleNode(e,"@Src").Value; var assmHuid = new Huid(PackageName, PackageVersion, PackageArch, PackagePubToken, src); addAttrib("component_guid", (string)assmHuid, e); var compId = CreateValidIdStr(assmHuid); componentIds.Add(compId); addAttrib("component_id", compId, e); //we also add in proper Type, very simple to do if (e.Attributes["Arch"].Value == "x86" || e.Attributes["Arch"].Value == "x64") { e.SetAttribute("type", "win32"); } else if (e.Attributes["Arch"].Value == "any" && e.Attributes["Platform"].Value == "MSIL") { //its msil e.SetAttribute("type", ".net"); } } }*/ //TODO: Policy assemblies only really work on native assemblies, not .NET private void addPolicyAssemblyGuidsAndIds() { var sl = roles.OfType<SharedLib>(); var pas = from s in sl from pa in s.Files.PolicyAssembly select pa; foreach (var pa in pas) { Huid assmHuid; if (pa.Arch == Arch.any) { pa.type = ".net"; assmHuid = new Huid(PackageName, PackageVersion, PackageArch, PackagePubToken, pa.Src); } else { pa.type = "win32"; assmHuid = new Huid(PackageName, PackageVersion, PackageArch, PackagePubToken, pa.Manifest.Src); } pa.component_guid = (string)assmHuid; var compId = CreateValidIdStr(assmHuid); componentIds.Add(compId); pa.component_id = compId; } }
/* /// <summary> /// Policy Assemblies are given Guids and Ids. Additionally their types are set. /// </summary> private void addPolicyAssemblyGuidsAndIds() { foreach (XmlElement e in SelectNodes(doc, "//in:PolicyAssembly")) { var src = (from XmlElement child in e.ChildNodes where child.LocalName == "Manifest" select child.Attributes["Src"].Value).FirstOrDefault(); var assmHuid = new Huid(PackageName, PackageVersion, PackageArch, PackagePubToken, src); addAttrib("component_guid", (string)assmHuid, e); var compId = CreateValidIdStr(assmHuid); componentIds.Add(compId); addAttrib("component_id", compId, e); //we also add in proper Type, very simple to do if (e.Attributes["Arch"].Value == "x86" || e.Attributes["Arch"].Value == "x64") { e.SetAttribute("type", "win32"); } else if (e.Attributes["Arch"].Value == "any" && e.Attributes["Platform"].Value == "MSIL") { //its msil e.SetAttribute("type", ".net"); } } }*/ //TODO: Why does the old version of this method check for ARCH? private void addFileGuidsAndIds() { foreach (var f in outerFiles.Cast<FileType>()) { var fileHuid = new Huid(PackageName, PackageVersion, PackageArch, PackagePubToken, f.Src); f.component_guid = (string) fileHuid; var compid = CreateValidIdStr(fileHuid); componentIds.Add(compid); f.component_id = compid; } }
/* private void addInstallPropertyGuids() { foreach (XmlElement e in SelectNodes(doc, "//in:InstallProperties/in:Property")) { var parentHuid = e.ParentNode.ParentNode.Attributes["role_guid"].Value; var type = e.Attributes["Type"].Value; var link = e.Attributes["Link"].Value; var target = e.Attributes["Target"].Value; var propHuid = new Huid(PackageName, PackageVersion, PackageArch, PackagePubToken, "property", parentHuid, type, link, target); addAttrib("prop_guid", (string)propHuid, e); } }*/ private void addAssemblyGuidsAndIds() { var assms = from r in roles where r.GetType() == typeof (SharedLib) from a in ((SharedLib) r).Files.Assembly select a; foreach (var a in assms) { var src = a.Src; var assmHuid = new Huid(PackageName, PackageVersion, PackageArch, PackagePubToken, src); a.component_guid = (string) assmHuid; var compId = CreateValidIdStr(assmHuid); componentIds.Add(compId); a.component_id = compId; //we also add in proper Type, very simple to do if (a.Arch == Arch.x86 || a.Arch == Arch.x64) { a.type = "win32"; } else if (a.Arch == Arch.any ) { a.type = ".net"; } } }
/* internal XmlNode SelectSingleNode(XmlNode n, string xpath) { return n.SelectSingleNode(xpath, nsMgr); } internal XmlNodeList SelectNodes(XmlNode n, string xpath) { return n.SelectNodes(xpath, nsMgr); } */ /* /// <summary> /// Gets all the files in the package that don't belong to an assembly or the independent files. /// </summary> /// <returns>an XmlNodeList containing all the nodes corresponding to the independent files</returns> private XmlNodeList getIndependentFiles() { //get immediate children of SharedLib string xpathStr = "/in:Package/in:SharedLib/in:Files/in:File"; //get nonimmediate children of SharedLib xpathStr += "|/in:Package/in:SharedLib/in:Files/in:Folder//in:File"; //get immediate children of DevLib xpathStr += "|/in:Package/in:DeveloperLib/in:Includes/in:File"; //get nonimmediate children of DevLib xpathStr += "|/in:Package/in:DeveloperLib/in:Includes//in:File"; //get LibFiles xpathStr += "|/in:Package/in:DeveloperLib/in:Includes//in:LibFile"; xpathStr += "|/in:Package/in:DeveloperLib/in:Includes//in:LibFile"; //get immediate children of SourceCode xpathStr += "|/in:Package/in:SourceCode/in:CodeFiles/in:File"; //get nonimmediate children of SourceCode xpathStr += "|/in:Package/in:SourceCode/in:CodeFiles/in:Folder//in:File"; xpathStr += "|/in:Package/in:AppRole/in:AppFiles/in:File"; xpathStr += "|/in:Package/in:AppRole/in:AppFiles/in:ExeFile"; xpathStr += "|/in:Package/in:AppRole/in:AppFiles/in:Folder//in:File"; return SelectNodes(doc, xpathStr); } */ /// <summary> /// Takes Huid and turns it into a valid Msi Id. May be the most evil code ever written. /// </summary> /// <param name="h">a Huid that you want to turn into an Msi Id</param> /// <returns>an Id string corresponding to h</returns> private static String CreateValidIdStr(Huid h) { return "s_" + ((string)h).MakeSafeDirectoryId().Replace("{","").Replace("}",""); }
private int main(string[] args) { var options = args.Switches(); var parameters = args.Parameters(); #region Parse Options try { foreach (string arg in options.Keys) { IEnumerable<string> argumentParameters = options[arg]; switch (arg) { /* global switches */ case "load-config": // all ready done, but don't get too picky. break; case "nologo": this.Assembly().SetLogo(""); break; case "verbose": verbose = true; break; case "help": return Help(); case "cert-file": certFile = argumentParameters.First(); break; case "cert-pass": certPass = argumentParameters.First(); break; case "msm-dir": msmDir = argumentParameters.First(); break; case "version": version = argumentParameters.First(); break; } } Logo(); #endregion _candle = new ProcessUtility(ProgramFinder.ProgramFilesAndDotNet.ScanForFile("candle.exe")); _light = new ProcessUtility(ProgramFinder.ProgramFilesAndDotNet.ScanForFile("light.exe")); _signTool = new ProcessUtility(ProgramFinder.ProgramFilesAndDotNet.ScanForFile("signTool.exe")); var pfxStore = PfxStoreLoader.Load(certFile, certPass); if (pfxStore != null) { var codeSigningCert = pfxStore.FindCodeSigningCert(); if (codeSigningCert == null) return Fail("No code signing certificate found."); } else { return Fail("Couldn't open the certificate file."); } var files = Directory.EnumerateFiles(msmDir, "*.msm", SearchOption.TopDirectoryOnly); var groups = from f in files let fi = new FileInfo(f) where fi.Name.StartsWith("Microsoft") && !fi.Name.Contains("Debug") let version = new String(fi.Name.Split('_')[1].Substring(2).TakeAllBut(1).ToArray()) group f by version into versions select new { Version = versions.Key, ArchGroups = (from a in versions let possArch = new String(a.TakeAllBut(4).TakeFromEnd(3).ToArray()) group a by possArch into archs select new { Arch = archs.Key, Files = archs }) }; foreach (var g in groups) { var vers = g.Version; if (version == null || version.ExtendVersion() == vers.ExtendVersion()) { foreach (var a in g.ArchGroups) { Console.WriteLine("Building {0} for {1}".format(vers, a.Arch)); var outputFile = "{0}-{1}-{2}.msi".format("VC", vers.ExtendVersion(), a.Arch); XDocument wix; var huid = new Huid("Visual C/C++ Runtime Library", vers.ExtendVersion(), a.Arch, ""); using (var reader = new StringReader(Resources.WixTemplate)) { wix = XDocument.Load(reader); } var productTag = wix.Descendants("Product").First(); var targetDir = (from d in productTag.Descendants() where d.Name == "Directory" && d.Attribute("Id").Value == "TARGETDIR" select d).First(); productTag.SetAttributeValue("Name", "Visual C/C++ Runtime Library"); productTag.SetAttributeValue("Version", vers.ExtendVersion()); productTag.SetAttributeValue("Manufacturer", "Microsoft"); productTag.SetAttributeValue("Id", huid.ToString()); int counter = 0; var ids = new List<int>(); foreach (var f in a.Files) { targetDir.Add( new XElement("Merge", new XAttribute("Id", "VC" + counter), new XAttribute("SourceFile", f), new XAttribute("DiskId", "1"), new XAttribute("Language", "0"))); ids.Add(counter); counter++; } var feature = productTag.Descendants("Feature").First(); foreach (var i in ids) { feature.Add( new XElement("MergeRef", new XAttribute("Id", "VC" + i))); } var packageTag = productTag.Descendants("Package").First(); packageTag.SetAttributeValue("Platform", a.Arch); //add the Wix namespace XNamespace wixNS = "http://schemas.microsoft.com/wix/2006/wi"; foreach (var n in wix.Descendants()) { n.Name = wixNS + n.Name.LocalName; } var tempPrefix = Path.GetTempFileName(); File.WriteAllText(tempPrefix + ".wxs", wix.ToString()); if (_candle.Exec("-nologo -sw1075 -out {0}.wixobj {0}.wxs", tempPrefix) != 0) return Fail(_candle.StandardOut); //we suppress the lack of UpgradeCode warning since we don't use them if (_light.Exec("-nologo -sw1076 -out {1} {0}.wixobj", tempPrefix, outputFile) != 0) return Fail(_light.StandardOut); if (!signFile(outputFile)) return Fail("Couldn't sign file"); } } } } catch (ConsoleException e) { return Fail(" {0}", e.Message); } catch (Exception e) { Console.WriteLine(e.StackTrace); return Fail(" {0}", e.Message); } return 0; }