Beispiel #1
0
        /// <summary>
        ///   The (non-static) startup method
        /// </summary>
        /// <param name = "args">
        ///   The command line arguments.
        /// </param>
        /// <returns>
        ///   Process return code.
        /// </returns>
        protected override int Main(IEnumerable<string> args)
        {
            try
            {

                pkgMgr = new PackageManager();

                #region command line parsing

                // default:
                var options = args.Switches();
                var parameters = args.Parameters();

                foreach (var arg in options.Keys)
                {
                    var argumentParameters = options[arg];

                    switch (arg)
                    {
                        /* options  */

                        /* global switches */
                        case "load-config":
                            // all ready done, but don't get too picky.
                            break;

                        case "nologo":
                            this.Assembly().SetLogo(string.Empty);
                            break;

                        case "show-tools":
                            showTools = Boolean.Parse(argumentParameters.First());
                            break;
                        case "help":
                            return Help();

                        default:
                            if (arg.StartsWith("package-"))
                            {
                                var argName = arg.Substring(8);
                                var argValue = argumentParameters.First();
                                switch (argName)
                                {
                                    case "name":
                                        package.PackageName = argValue;
                                        break;
                                    case "version":
                                        package.PackageVersion = argValue;
                                        break;
                                    case "arch":
                                        package.PackageArch = argValue;
                                        break;
                                    case "icon":
                                        package.IconPath = argValue;
                                        break;
                                    case "short-desc":
                                        package.ShortDescriptionPath = argValue;
                                        break;
                                    case "description":
                                        package.DescriptionPath = argValue;
                                        break;
                                    case "author-version":
                                        package.AuthorVersion = argValue;
                                        break;
                                    case "display-name":
                                        package.DisplayName = argValue;
                                        break;
                                    case "policy":
                                        package.BindingPolicy = argValue;
                                        break;
                                    case "license":
                                        package.LicensePath = argValue;
                                        break;
                                    case "license-url":
                                        package.LicenseUrlEntry = argValue;
                                        break;
                                    case "orig-location":
                                        package.Location = argValue;
                                        break;
                                    case "feed-location":
                                        package.Feed = argValue;
                                        break;
                                    default:
                                        throw new ConsoleException(Resources.UnknownParameter, arg);
                                }
                            }
                            else if (arg.StartsWith("identity-"))
                            {
                                var argName = arg.Substring(9);
                                var argValue = argumentParameters.First();

                                switch (argName)
                                {
                                    case "cert-file":
                                        package.CertificateFile = argValue;
                                        break;
                                    case "cert-pass":
                                        certificatePassword = argValue;
                                        break;
                                    case "email":
                                        package.PubEmail = argValue;
                                        break;
                                    case "website":
                                        package.PubWebsite = argValue;
                                        break;
                                    default:
                                        throw new ConsoleException(Resources.UnknownParameter, arg);

                                }
                            }
                            //we do
                            else if (arg.StartsWith("dependency-"))
                            {
                                var argName = arg.Substring(11);
                                var argValue = argumentParameters.First(); ;

                                switch (argName)
                                {
                                    case "add":
                                        package.DependencyNames.Add(argValue);
                                        break;
                                    default:
                                        throw new ConsoleException(Resources.UnknownParameter, arg);

                                }
                            }
                            else if (arg.StartsWith("app-"))
                            {
                                if (package.Apps == null)
                                    package.Apps = new App();

                                parseAppArgument(arg.Substring(4), argumentParameters.First());

                            }
                            else if (arg.StartsWith("sharedlib-"))
                            {
                                if (package.SharedLibs == null)
                                    package.SharedLibs = new SharedLib();

                                parseSharedLibArgument(arg.Substring(10), argumentParameters.First());

                            }
                            else
                            {
                                throw new ConsoleException(Resources.UnknownParameter, arg);
                            }
                            break;

                    }
                }

                Logo();

                /*
                if (parameters.Count() < 1)
                {
                    throw new ConsoleException(Resources.MissingCommand);
                }
                */
                #endregion

                // GS01: I'm putting this in here so that feed resoltion happens before we actually get around to doing something.
                // Look into the necessity later.
                Tasklet.WaitforCurrentChildTasks();

                #region Tool Scanning

                Console.Write(Resources.ToolLookup);

                _candle = new ProcessUtility(ProgramFinder.ProgramFilesAndDotNet.ScanForFile("candle.exe"));
                _light = new ProcessUtility(ProgramFinder.ProgramFilesAndDotNet.ScanForFile("light.exe"));
                _mt = new ProcessUtility(ProgramFinder.ProgramFilesAndDotNet.ScanForFile("mt.exe"));
                _makecat = new ProcessUtility(ProgramFinder.ProgramFilesAndDotNet.ScanForFile("makecat.exe"));
                _al = new ProcessUtility(ProgramFinder.ProgramFilesAndDotNet.ScanForFile("al.exe"));
                _signTool = new ProcessUtility(ProgramFinder.ProgramFilesAndDotNet.ScanForFile("signTool.exe"));
                _sn = new ProcessUtility(ProgramFinder.ProgramFilesAndDotNet.ScanForFile("sn.exe"));
                _pktExtract = new ProcessUtility(ProgramFinder.ProgramFilesAndDotNet.ScanForFile("pktExtract.exe"));

                if (_candle.Executable == null)
                    errors.Add(Resources.MissingCandle);

                if (_light.Executable == null)
                    errors.Add(Resources.MissingLight);

                if (_mt.Executable == null)
                    errors.Add(Resources.MissingMt);

                if (_makecat.Executable == null)
                    errors.Add(Resources.MissingMakeCat);

                if (_al.Executable == null)
                    errors.Add(Resources.MissingAl);

                if (_signTool.Executable == null)
                    errors.Add(Resources.MissingSignTool);

                if (_sn.Executable == null)
                    errors.Add(Resources.MissingSn);

                if (_pktExtract.Executable == null)
                    errors.Add(Resources.MissingPktExtract);

                if (errors.AreFatal())
                {
                    throw new ConsoleException(errors.StringOut());
                }

                Console.WriteLine(Resources.Finished);

                if (showTools)
                {
                    Console.WriteLine("Tools:");
                    Console.WriteLine(_candle.Executable);
                    Console.WriteLine(_light.Executable);
                    Console.WriteLine(_mt.Executable);
                    Console.WriteLine(_makecat.Executable);
                    Console.WriteLine(_al.Executable);
                    Console.WriteLine(_signTool.Executable);
                    Console.WriteLine(_sn.Executable);
                }

                #endregion

                Console.WriteLine(Resources.ScanningInstalledPackages);
                var installedPackages = pkgMgr.GetInstalledPackages(new PackageManagerMessages
                {
                    PackageScanning = (progress) => { Resources.Scanning.PrintProgressBar(progress); }
                });

                installedPackages.Wait();

                // the progress bar never sends in a line break
                Console.WriteLine();

                //TODO check for invalid file paths

                //TODO check for pre-signed files and whether they're properly signed

                //TODO make sure files in app roles are proper children

                //TODO this doesn't work if the packages are a superceding version of the one given
                //TODO this doesn't work if the packages are in the same directory

                //get the dependencies and Assemblies

                foreach (var dep in package.DependencyNames)
                {
                    var depPackage = (from p in installedPackages.Result
                                      where p.CosmeticName.IsWildcardMatch(dep)
                                      orderby p.Version descending
                                      select p).FirstOrDefault();
                    if (depPackage == null)
                    {
                        errors.Add(Resources.DepNotSatifiable.format(dep));
                    }
                    else
                    {
                        package.DependencyInfo.Add(depPackage);
                    }
                }
                //TODO make sure the numbers are not larger than the max a part of a version string
                var policyRegex = new Regex(@"^policy\.\d{1,5}\.\d{1,5}\.\S+$");
                var dependentAssemblies = from p in package.DependencyInfo
                                          from a in p.Assemblies
                                          where !a.Type.Contains("policy") &&
                                          !policyRegex.IsMatch(a.Name)
                                          select a;

                #region Sanity checking primarily

                //let's check for valid roles!
                if (package.SharedLibs == null && package.Apps == null)
                    errors.Add(Resources.NoRoles);

                if (package.PackageArch == null ||
                    (!ValidArchs.Contains(package.PackageArch.ToLower()) && package.PackageArch != "auto"))
                    errors.Add(Resources.MissingPackageArch);

                if (package.PackageVersion == null || !package.PackageVersion.IsValidVersion() &&
                    package.PackageVersion != "auto")
                    errors.Add(Resources.MissingPackageVersion);

                if ((package.PackageArch == "auto" || package.PackageVersion == "auto") && firstBinFile == null)
                    errors.Add(Resources.NoBinaryFileProvided);

                //get Arch and Version if it's auto
                if (package.PackageArch == "auto")
                {
                    if (firstBinFile != null)
                    {
                        var binType = ProgramFinder.GetExeType(firstBinFile);
                        if (binType.HasFlag(ExecutableInfo.any) || binType.HasFlag(ExecutableInfo.managed))
                            package.PackageArch = "any";
                        else if (binType.HasFlag(ExecutableInfo.x86))
                            package.PackageArch = "x86";
                        else if (binType.HasFlag(ExecutableInfo.x64))
                            package.PackageArch = "x64";
                        else
                            errors.Add(Resources.NoArchDiscovered.format(firstBinFile));
                    }
                }

                if (package.PackageVersion == "auto")
                {
                    if (firstBinFile != null)
                    {
                        var versionStr = ProgramFinder.GetToolVersion(firstBinFile);
                        if (versionStr == null || !versionStr.IsValidVersion())
                            errors.Add(Resources.NoVersionDiscovered.format(firstBinFile));
                        else
                            package.PackageVersion = versionStr;

                    }
                }

                //TODO  make sure the name is valid!

                //make sure the major minors given are valid
                if (package.SharedLibs != null)
                {
                    foreach (var i in package.SharedLibs.MajorMinorsToReplace)
                    {
                        if (!i.IsValidMajorMinorVersion())
                        {
                            errors.Add(Resources.InvalidMajorMinor.format(i));
                        }
                    }
                }

                //load and check pfx file

                var pfxStore = PfxStoreLoader.Load(package.CertificateFile, certificatePassword);

                if (pfxStore == null)
                    errors.Add(Resources.InvalidPfx);
                else
                {
                    var codeSigningCert = pfxStore.FindCodeSigningCert();

                    if (codeSigningCert == null)
                        errors.Add(Resources.NoCodeSigningCert);
                    else
                    {
                        if ((package.PubToken = codeSigningCert.PublicKeyTokenAsString()) == null)
                        {
                            errors.Add(Resources.FailedPktExtraction);
                        }

                        var nameParts = codeSigningCert.GetSubjectNameParts();
                        if (nameParts.ContainsKey("CN"))
                        {
                            package.PubName = nameParts["CN"];
                        }
                        else
                        {
                            errors.Add(Resources.NoNameExtracted.format(package.CertificateFile));
                        }

                        if (package.PubEmail == "auto")
                        {
                            if (nameParts.ContainsKey("E"))
                            {
                                package.PubEmail = nameParts["E"];
                            }
                            else
                            {
                                errors.Add(Resources.NoPubEmailFound.format(package.CertificateFile));
                            }
                        }

                    }
                }

                if (package.PubEmail != null && !package.PubEmail.IsEmail())
                {
                    errors.Add(Resources.InvalidEmail.format(package.PubEmail));
                }

                if (package.IconPath != null)
                {
                    try
                    {
                        var iconFile = File.ReadAllBytes(package.IconPath);
                        using (var bytes = new MemoryStream(iconFile))
                        {
                            Image image = Image.FromStream(bytes);
                            if (image.RawFormat != ImageFormat.Png ||
                                image.Height != REQUIRED_ICON_HEIGHT ||
                                image.Width != REQUIRED_ICON_WIDTH)
                            {
                                errors.Add(Resources.InvalidIconFile.
                                    format(package.IconPath, REQUIRED_ICON_WIDTH, REQUIRED_ICON_HEIGHT));
                            }
                        }

                        package.Icon = Convert.ToBase64String(iconFile);
                    }
                    catch (OutOfMemoryException)
                    {
                        errors.Add(Resources.InvalidIconFile.
                            format(package.IconPath, REQUIRED_ICON_WIDTH, REQUIRED_ICON_HEIGHT));
                    }
                    catch (IOException)
                    {

                        errors.Add(Resources.FailedIconFileOpen.format(package.IconPath));
                    }
                }
                else
                {
                    package.Icon = Convert.ToBase64String(Resources.blankicon);
                }

                if (package.ShortDescriptionPath != null)
                {
                    try
                    {
                        package.ShortDescription = File.ReadAllText(package.ShortDescriptionPath);

                        if (package.ShortDescriptionPath.Length > MAX_SUMMARY_DESCRIPTION_LENGTH)
                        {
                            errors.Add(Resources.ShortDescriptionTooLong.
                                format(package.ShortDescriptionPath, MAX_SUMMARY_DESCRIPTION_LENGTH));
                        }
                    }
                    catch (NotSupportedException)
                    {
                        errors.Add(Resources.InvalidShortDescriptionFile.format(package.ShortDescriptionPath));
                    }
                    catch (IOException)
                    {
                        errors.Add(Resources.FailedShortDescriptionFileOpen.format(package.ShortDescriptionPath));
                    }
                }

                if (package.DescriptionPath != null)
                {
                    try
                    {
                        package.Description = File.ReadAllText(package.DescriptionPath);

                    }
                    catch (NotSupportedException)
                    {
                        errors.Add(Resources.InvalidDescriptionFile.format(package.DescriptionPath));
                    }
                    catch (IOException)
                    {
                        errors.Add(Resources.FailedDescriptionFileOpen.format(package.DescriptionPath));
                    }
                }

                if (package.PublishDate != null)
                {
                    try
                    {
                        DateTime.Parse(package.PublishDate);
                    }
                    catch (FormatException)
                    {
                        errors.Add(Resources.InvalidPublishDate.format(package.PublishDate));
                    }
                }
                else
                {
                    package.PublishDate = DateTime.Now.ToShortDateString();
                }

                if (package.LicensePath != null)
                {
                    try
                    {
                        package.LicenseText = File.ReadAllText(package.LicensePath);
                        if (package.LicenseUrlEntry != null)
                        {
                            try
                            {
                                var uri = new Uri(package.LicenseUrlEntry);
                                if (!uri.IsHttpScheme())
                                    errors.Add(Resources.InvalidLicenseUrlScheme.format(package.LicenseUrlEntry));

                                package.LicenseUrl = package.CreateUrl(package.LicenseUrlEntry, "license");
                            }
                            catch (UriFormatException)
                            {
                                errors.Add(Resources.InvalidLicenseUrl.format(package.LicenseUrlEntry));
                            }
                        }
                    }
                    catch (NotSupportedException)
                    {
                        errors.Add(Resources.InvalidLicenseText.format(package.LicensePath));
                    }
                    catch (IOException)
                    {
                        errors.Add(Resources.FailedLicenseFileOpen.format(package.LicensePath));
                    }
                }
                else
                {
                    if (package.LicenseUrlEntry != null)
                    {
                        errors.Add(Resources.LicenseUrlWithoutText, false);
                    }
                }

                if (package.Feed != null)
                {
                    try
                    {
                        var uri = new Uri(package.Feed);
                        if (!uri.IsHttpScheme())
                            errors.Add(Resources.InvalidFeedUrlScheme.format(package.Feed));

                        package.FeedUrl = package.CreateUrl(package.Feed, "feed_location");
                    }
                    catch (UriFormatException)
                    {
                        errors.Add(Resources.InvalidFeedUrl.format(package.Feed));
                    }
                }

                if (package.Location != null)
                {
                    try
                    {
                        var uri = new Uri(package.Location);
                        if (!uri.IsHttpScheme())
                            errors.Add(Resources.InvalidOriginalUrlScheme.format(package.Location));
                        package.LocationUrl = package.CreateUrl(package.Location, "original_location");
                    }
                    catch (UriFormatException)
                    {
                        errors.Add(Resources.InvalidOriginalUrl.format(package.Location));
                    }
                }

                if (errors.AreFatal())
                {
                    throw new ConsoleException(errors.StringOut());
                }

                foreach (Match m in Regex.Matches(package.BindingPolicy, @"{{(\$CURRENT-\d+)}}"))
                {
                    var i = m.Groups[1].Value;
                    var two = i.Split('-');
                    package.BindingPolicy =
                        package.BindingPolicy.Replace(m.Value,
                            (package.PackageVersion.VersionStringToUInt64() - UInt64.Parse(two[1])).UInt64VersiontoString());
                }

                if (package.BindingPolicy.IsValidVersion())
                {
                    if (package.BindingPolicy.VersionStringToUInt64() >= package.PackageVersion.VersionStringToUInt64())
                    {
                        errors.Add(Resources.BindingVersionTooHigh.format(package.BindingPolicy));
                    }
                    else
                    {
                        package.BindingMin = package.BindingPolicy;
                        package.BindingMax = package.BindingPolicy;
                    }

                }

                else
                {
                    var parts = package.BindingPolicy.Split('-');
                    bool ret = parts.Length == 2;
                    for (int i = 0; ret && i < 2; i++)
                    {
                        ret &= parts[i].IsValidVersion();
                    }

                    if (!ret)
                    {
                        errors.Add(Resources.InvalidPolicy.format(package.BindingPolicy));
                    }
                    else
                    {
                        if (parts[0].VersionStringToUInt64() >= package.PackageVersion.VersionStringToUInt64())
                        {
                            errors.Add(Resources.BindingVersionTooHigh.format(parts[0]));
                        }

                        if (parts[1].VersionStringToUInt64() >= package.PackageVersion.VersionStringToUInt64())
                        {
                            errors.Add(Resources.BindingVersionTooHigh.format(parts[1]));
                        }

                        package.BindingMin = parts[0];
                        package.BindingMax = parts[1];
                    }

                }

                //find all the files that need to be found recursively

                if (package.Apps != null)
                {
                    var wildcards = (from p in package.Apps.FilePaths
                                     where p.Contains("*")
                                     select p).ToList();

                    foreach (var w in wildcards)
                    {
                        package.Apps.FilePaths.AddRange(w.FindFilesSmarter(SearchOption.AllDirectories));
                    }

                    //remove wildcards
                    package.Apps.FilePaths.RemoveAll((fp) => fp.Contains("*"));

                    //remove duplicates based on canonical path and make them relative

                    var exeFiles = package.Apps.PrimaryExes.Values.Select((e) => e.ExeFile);

                    var sharedLibFiles = package.SharedLibs.Assemblies.Values.
                        SelectMany((a) => a.PrimaryFile.SingleItemAsEnumerable().Concat(a.OtherFiles));

                    package.Apps.FilePaths = package.Apps.FilePaths.Except(exeFiles.Concat(sharedLibFiles),
                        new PathEqualityComparer()).Select((p) =>
                            Environment.CurrentDirectory.RelativePathTo(p)).ToList();

                }

                if (errors.AreFatal())
                {
                    throw new ConsoleException(errors.StringOut());
                }

                #endregion

                #region Handle Shared Libraries

                //first create the string of all the dependencies elements

                var sharedlib = package.SharedLibs;
                if (sharedlib != null)
                {
                    Console.Write(Resources.SharedLibCreation);
                    if (package.PackageArch != "any")
                    {
                        var dependencyStr = new StringBuilder();

                        foreach (var dep in dependentAssemblies)
                        {
                            dependencyStr.Append(DependencyEntry.Replace("[$LIBTYPE]", dep.Type).Replace("[$LIBNAME]", dep.Name).
                                            Replace("[$LIBVERSION]", dep.Version).Replace("[$ARCH]", dep.Arch).
                                            Replace("[$PUBLICKEYTOKEN]", dep.PublicKeyToken));
                        }

                        foreach (var a in sharedlib.Assemblies.Values)
                        {
                            var manifestFilesString = new StringBuilder();
                            var filesString = new StringBuilder();

                            filesString.Append(FileEntry.Replace("[$FILE]", Path.GetFileName(a.PrimaryFile)));
                            foreach (var f in a.OtherFiles)
                            {
                                filesString.Append(FileEntry.Replace("[$FILE]", Path.GetFileName(f)));
                            }

                            manifestFilesString.Append(SharedLibraryManifest.Replace("[$LIBNAME]", a.Name).
                                    Replace("[$LIBVERSION]", package.PackageVersion).
                                    Replace("[$DEPENDENCY]", dependencyStr.ToString()).Replace("[$PUBLICKEYTOKEN]", package.PubToken).
                                    Replace("[$ARCH]", package.PackageArch).Replace("[$FILES]", filesString.ToString()));

                            a.Manifest = Path.Combine(new FileInfo(a.PrimaryFile).DirectoryName, a.PrimaryFile + ".manifest");
                            //TODO do file checking
                            File.WriteAllText(a.Manifest, manifestFilesString.ToString());

                            // sign all the non-primary BinFiles
                            var binFiles = from f in a.OtherFiles
                                           where Path.GetExtension(f) == ".exe" ||
                                           Path.GetExtension(f) == ".dll"
                                           select f;
                            foreach (var f in binFiles)
                            {
                                signFile(f);
                            }

                            //manifest created. Let's embed it.
                            if (!createManifestAndEmbed(a.PrimaryFile))
                            {
                                throw new ConsoleException(errors.StringOut());
                            }

                            //sign the primary file

                            if (!signFile(a.PrimaryFile))
                                throw new ConsoleException(errors.StringOut());

                            a.CatFile = a.PrimaryFile + ".cat";
                            if (!createAndSignCat(a.Manifest))
                            {
                                throw new ConsoleException(errors.StringOut());
                            }

                            //we're going to create the policy assemblies
                            foreach (var p in package.SharedLibs.MajorMinorsToReplace)
                            {

                                var pa = new PolicyAssemblyDescription(p, a.Name);
                                package.SharedLibs.PolicyAssemblies.Add(pa);

                                var paManifestString = PublisherConfiguration.Replace("[$ASSMNAME]", a.Name).
                                    Replace("[$LIBMAJORMINOR]", p).Replace("[$PUBLICKEYTOKEN]", package.PubToken).
                                    Replace("[$LIBVERSION]", package.PackageVersion).Replace("[$ARCH]", package.PackageArch).
                                    Replace("[$OLDVERSION]", package.BindingPolicy);

                                pa.Manifest = Path.Combine(new FileInfo(a.PrimaryFile).DirectoryName, pa.Name + ".manifest");

                                File.WriteAllText(pa.Manifest, paManifestString);

                                pa.CatFile = pa.Manifest.Replace(".manifest", "") + ".cat";

                                if (!createAndSignCat(pa.Manifest))
                                    throw new ConsoleException(errors.StringOut());

                            }

                        }
                    }

                    else
                    {
                        // it's .NET
                        foreach (var a in sharedlib.Assemblies.Values)
                        {

                            if (!StrongName(a.PrimaryFile))
                            {
                                throw new ConsoleException(errors.StringOut());
                            }

                            if (!signFile(a.PrimaryFile))
                                throw new ConsoleException(errors.StringOut());

                            foreach (var p in package.SharedLibs.MajorMinorsToReplace)
                            {

                                var pa = new PolicyAssemblyDescription(p, a.Name);
                                package.SharedLibs.PolicyAssemblies.Add(pa);

                                pa.PrimaryFile = Path.Combine(new FileInfo(a.PrimaryFile).DirectoryName, pa.Name + ".dll");

                                var paManifestString = MSILPublisherConfiguration.Replace("[$ASSMNAME]", a.Name).
                                    Replace("[$PUBLICKEYTOKEN]", package.PubToken).
                                    Replace("[$LIBVERSION]", package.PackageVersion).
                                    Replace("[$OLDVERSION]", package.BindingPolicy);

                                pa.Manifest = pa.PrimaryFile + ".config";
                                // cleanupFiles.Add(pa.Manifest);
                                File.WriteAllText(pa.Manifest, paManifestString);

                                if (!extractPublicKey())
                                    throw new ConsoleException(errors.StringOut());

                                if (_al.Exec("/link:{0} /out:{1} /delaysign+ /keyfile:{2} /v:{3}", pa.Manifest,
                                     pa.PrimaryFile, publicKeyFile, package.PackageVersion) != 0)
                                {
                                    errors.Add(Resources.FailedPolicyAssemblyBuild.format(pa.PrimaryFile));
                                    throw new ConsoleException(errors.StringOut());
                                }

                                if (!StrongName(pa.PrimaryFile))
                                {
                                    throw new ConsoleException(errors.StringOut());
                                }

                                if (!signFile(pa.PrimaryFile))
                                {
                                    throw new ConsoleException(errors.StringOut());
                                }
                            }

                        }
                    }
                    Console.WriteLine(Resources.Finished);
                }

                #endregion

                #region Handle Apps
                var apps = package.Apps;
                if (apps != null)
                {
                    Console.Write(Resources.AppCreation);

                    if (package.PackageArch != "any")
                    {
                        //it's native
                        var dependencyStr = new StringBuilder();

                        foreach (var dep in dependentAssemblies)
                        {
                            dependencyStr.Append(DependencyEntry.Replace("[$LIBTYPE]", dep.Type).Replace("[$LIBNAME]", dep.Name).
                                            Replace("[$LIBVERSION]", dep.Version).Replace("[$ARCH]", dep.Arch).
                                            Replace("[$PUBLICKEYTOKEN]", dep.PublicKeyToken));
                        }

                        //we needs to add in the other assemblies in this package

                        if (sharedlib != null)
                        {
                            foreach (var dep in sharedlib.Assemblies.Values)
                            {
                                dependencyStr.Append(DependencyEntry.Replace("[$LIBTYPE]", "win32").
                                    Replace("[$LIBNAME]", dep.Name).Replace("[$LIBVERSION]", package.PackageVersion).
                                    Replace("[$ARCH]", package.PackageArch).Replace("[$PUBLICKEYTOKEN]", package.PubToken));
                            }
                        }

                        foreach (var e in apps.PrimaryExes.Values)
                        {
                            var configFilename = e.ExeFile + ".config";
                            File.WriteAllText(configFilename, dependencyStr.ToString());

                            if (!embedManifest(e.ExeFile, configFilename))
                                //we can't keep working on this one but we'll try the rest before failing
                                continue;

                            signFile(e.ExeFile);
                        }

                    }
                    else
                    {
                        //it's .net

                        foreach (var e in apps.PrimaryExes.Values)
                        {
                            if (!StrongName(e.ExeFile))
                            {
                                //we can't keep working on this one but we'll try the rest before failing
                                continue;
                            }

                            signFile(e.ExeFile);
                        }

                    }

                }

                if (errors.AreFatal())
                    throw new ConsoleException(errors.StringOut());

                Console.WriteLine(Resources.Finished);
                #endregion

                #region Write Msi OutToFile
                Console.Write(Resources.CreatingMSI);
                var tempPrefix = Path.GetTempFileName();
                File.WriteAllText(tempPrefix + ".wxs", package.ConvertToWix());

                var outputFile = "{0}-{1}-{2}.msi".format(package.PackageName, package.PackageVersion, package.PackageArch);
                /*
                if (!_dontCreateMsi)
                {

                */
                //we suppress the lack of UpgradeCode warning since we don't use them

                if (_candle.Exec("-nologo -sw1075 -out {0}.wixobj {0}.wxs", tempPrefix) != 0)
                    errors.Add(Resources.FailedCandleExe.format(_candle.StandardOut));

                if (errors.AreFatal())
                    throw new ConsoleException(errors.StringOut());

                //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)
                    errors.Add(Resources.FailedLightExe.format(_light.StandardOut));

                if (errors.AreFatal())
                    throw new ConsoleException(errors.StringOut());

                signFile(outputFile);

                if (errors.AreFatal())
                    throw new ConsoleException(errors.StringOut());
                Console.WriteLine(Resources.Finished);
                #endregion

                Console.WriteLine(errors.StringOut());
            }

            catch (ConsoleException failure)
            {
                CancellationTokenSource.Cancel();
                Fail("{0}\r\n\r\n    {1}", failure.Message, Resources.ForCommandLineHelp);
            }
            finally
            {
                foreach (var f in cleanupFiles)
                {
                    File.Delete(f);
                }
            }
            return 0;
        }
        /// <summary>
        ///   The (non-static) startup method
        /// </summary>
        /// <param name = "args">
        ///   The command line arguments.
        /// </param>
        /// <returns>
        ///   Process return code.
        /// </returns>
        protected override int Main(IEnumerable<string> args)
        {
            try
            {

                _package.CertificateFile = _certificateSettings["#CurrentCertificate"].EncryptedStringValue;

                PackageManager.Instance.Connect("autopackage");
                if (!PackageManager.Instance.IsReady.WaitOne(5000)) {
                    //Verbose("# not connected...");
                    throw new ConsoleException("# Unable to connect to CoApp Service.");
                }

                _pkgMgr = PackageManager.Instance;
                PropertySheet propSheet;

                _pkgMgr.AddFeed(Environment.CurrentDirectory);

                var exceptions = new List<Exception>();
                #region command line parsing
                var configLoaded = false;
                // default:
                var options = args.Switches();
                var parameters = args.Parameters();

                foreach (var arg in options.Keys)
                {
                    var argumentParameters = options[arg];

                    switch (arg)
                    {
                        /* options  */

                        /* global switches */
                        case "load-config":
                            // all ready done, but don't get too picky.
                            break;
                        case "load":
                            propSheet = PropertySheet.Load(argumentParameters.First());
                            PropSheetParser parser = new PropSheetParser(_package);
                            //parser.Parse(propSheet);
                            configLoaded = true;

                            break;
                        case "nologo":
                            this.Assembly().SetLogo(string.Empty);
                            break;

                        case "show-tools":
                            _showTools = Boolean.Parse(argumentParameters.First());
                            break;

                        case "password":
                            _package.CertificatePassword = argumentParameters.First();
                            break;

                        case "autosign":
                            _autosign = true;
                            break;

                        case "remember":
                            _remember = true;
                            break;

                        case "accept-old-bs":
                            _acceptOldBs = true;
                            break;
                        case "help":
                            return Help();

                        default:
                            throw new ConsoleException(Resources.UnknownParameter, arg);

                    }
                }

                Logo();

                if (!configLoaded)
                    throw new ConsoleException(Resources.NoConfigFileLoaded);
                #endregion

                // GS01: I'm putting this in here so that feed resoltion happens before we actually get around to doing something.
                // Look into the necessity later.
                // Tasklet.WaitforCurrentChildTasks();

                #region Tool Scanning

                Console.Write(Resources.ToolLookup);

                _candle = new ProcessUtility(ProgramFinder.ProgramFilesAndDotNet.ScanForFile("candle.exe"));
                _light = new ProcessUtility(ProgramFinder.ProgramFilesAndDotNet.ScanForFile("light.exe"));
                _mt = new ProcessUtility(ProgramFinder.ProgramFilesAndDotNet.ScanForFile("mt.exe"));
                _makecat = new ProcessUtility(ProgramFinder.ProgramFilesAndDotNet.ScanForFile("makecat.exe"));
                _al = new ProcessUtility(ProgramFinder.ProgramFilesAndDotNet.ScanForFile("al.exe"));
                _signTool = new ProcessUtility(ProgramFinder.ProgramFilesAndDotNet.ScanForFile("signTool.exe"));
                _sn = new ProcessUtility(ProgramFinder.ProgramFilesAndDotNet.ScanForFile("sn.exe"));

                if (_candle.Executable == null)
                    exceptions.Add(CreateEndUserException(144));

                if (_light.Executable == null)
                    exceptions.Add(CreateEndUserException(145));

                if (_mt.Executable == null)
                    exceptions.Add(CreateEndUserException(146));

                if (_makecat.Executable == null)
                    exceptions.Add(CreateEndUserException(147));

                if (_al.Executable == null)
                    exceptions.Add(CreateEndUserException(148));

                if (_signTool.Executable == null)
                    exceptions.Add(CreateEndUserException(149));

                if (_sn.Executable == null)
                    exceptions.Add(CreateEndUserException(150));

                if (exceptions.Count > 0)
                {
                    throw new AggregateException(exceptions);
                }

                Console.WriteLine(Resources.Finished);

                if (_showTools)
                {
                    Console.WriteLine("Tools:");
                    Console.WriteLine(_candle.Executable);
                    Console.WriteLine(_light.Executable);
                    Console.WriteLine(_mt.Executable);
                    Console.WriteLine(_makecat.Executable);
                    Console.WriteLine(_al.Executable);
                    Console.WriteLine(_sn.Executable);
                    Console.WriteLine(_signTool.Executable);
                }

                ReadPassword();

                #endregion

                Console.WriteLine(Resources.ScanningInstalledPackages);
                //TODO What will happen when we have feeds in other places????
                IEnumerable<Package> allPackages = null;

                /*
                var tsk = _pkgMgr.GetPackagesInScanLocations(new PackageManagerMessages
                {
                    PackageScanning = (progress) => Resources.Scanning.PrintProgressBar(progress)
                }).ContinueWith((antecedent) =>
                {
                    allPackages = antecedent.Result;

                    " ".PrintProgressBar(100);
                    Console.WriteLine("\r");

                },TaskContinuationOptions.AttachedToParent);

                tsk.Wait();
                */

                //find all the files that need to be found recursively

                //verify that the lefthand side of includes are valid subpaths
                foreach (var i in _package.AllIncludes.Keys)
                {
                    foreach (var include in _package.AllIncludes[i])
                    {
                        if (!include.L.IsSimpleSubPath())
                        {
                            exceptions.Add(CreateEndUserPropertyException(i.IncludeToProp[include.L], 160, include.L));
                        }
                    }
                }

                if (_package.Apps != null)
                {

                    if (_package.Apps.GlobalBinEntry != null)
                    {
                        if (!_package.Apps.GlobalBinEntry.IsBoolean())
                        {
                            exceptions.Add(CreateEndUserPropertyException(_package.Apps.GlobalBinEntryProp, 152));
                        }
                        else
                        {
                            _package.Apps.GlobalBin = Boolean.Parse(_package.Apps.GlobalBinEntry);
                        }
                    }

                    _package.Apps.EvaluateIncludes();

                    //set up the input files
                    foreach (var e in _package.Apps.PrimaryExes)
                    {
                        var input = (from a in _package.Apps.FinalInclude
                                     where a.R.Path.IsWildcardMatch(e.ExeFile)
                                     select a).FirstOrDefault();

                        if (input == null)
                        {
                            if (!File.Exists(e.ExeFile))
                                exceptions.Add(CreateEndUserException(153, e.ExeFile));
                            else
                            {
                                //Exefile wasn't found in the Includes but it really does exist
                                _package.Apps.FinalInclude = _package.Apps.FinalInclude.Concat(new OutputTup { L = new FileInfo(e.ExeFile.Original).Name, R = e.ExeFile }.SingleItemAsEnumerable());
                            }
                        }
                        else
                        {
                            e.ExeFile = input.R;
                        }

                        if (e.GlobalBinEntry != null)
                        {
                            if (!e.GlobalBinEntry.IsBoolean())
                            {
                                exceptions.Add(CreateEndUserPropertyException(e.GlobalBinEntryProp, 152));
                            }
                            else
                            {
                                e.GlobalBin = Boolean.Parse(e.GlobalBinEntry);
                            }
                        }
                    }
                }

                if (_package.SharedLibs != null)
                {
                    var shared = _package.SharedLibs;
                    var sharedEntryValid = false;
                    if (shared.GlobalEntry != null)
                    {
                        if (!shared.GlobalEntry.IsBoolean()) {
                            exceptions.Add(CreateEndUserPropertyException(shared.GlobalEntryProp, 170));
                        }
                        else {
                            shared.Global = Boolean.Parse(shared.GlobalEntry);
                            sharedEntryValid = true;
                        }
                    }

                    foreach (var a in _package.SharedLibs.Assemblies)
                    {
                        a.EvaluateIncludes(true);
                        if (a.GlobalEntry != null)
                        {
                            if (!a.GlobalEntry.IsBoolean()) {
                                exceptions.Add(CreateEndUserPropertyException(a.GlobalEntryProp, 170));
                            }
                            else {
                                a.Global = Boolean.Parse(a.GlobalEntry);
                            }
                        }
                        else if (sharedEntryValid)
                        {
                            a.Global = shared.Global;
                        }
                    }
                }

                if (_package.DeveloperLibs != null)
                {
                    BasicIncludeAndExclude[] items = { _package.DeveloperLibs.Headers, _package.DeveloperLibs.ImportLibs, _package.DeveloperLibs.StaticLibs };
                    foreach (var sec in items)
                    {
                        if (sec.GlobalLinkEntry != null)
                        {
                            if (!sec.GlobalLinkEntry.IsBoolean())
                            {
                                exceptions.Add(CreateEndUserPropertyException(sec.GlobalLinkEntryProp, 169));
                            }
                            else
                            {
                                sec.GlobalLink = Boolean.Parse(sec.GlobalLinkEntry);
                            }
                        }
                        sec.EvaluateIncludes();
                    }

                    //add the proper prefix to all the files
                    _package.DeveloperLibs.Headers.AddPrefix(HEADERS_DIR_NAME);
                    _package.DeveloperLibs.ImportLibs.AddPrefix(IMPORTLIB_DIR_NAME);
                    _package.DeveloperLibs.StaticLibs.AddPrefix(STATICLIB_DIR_NAME);

                }

                if (_package.SourceCodes != null)
                {
                    var sc = _package.SourceCodes;
                    sc.EvaluateIncludes();

                    sc.AddPrefix(SRC_DIR_NAME);
                }

                //copy all the stuff that needs to go to Temp TO Temp
                _package.Prepare();

                foreach (var dep in _package.DependencyNames)
                {
                   /*
                    var temp = new EditableTup<string, string> {L = dep.L, R = _package.ResolveVariables(dep.R)};
                    //TODO this doesn't work if a packages is a superceding version of the one given
                    var depPackage = (from p in allPackages
                                      where p.CosmeticName.IsWildcardMatch(temp.R)
                                      orderby p.Version descending
                                      select p).FirstOrDefault();
                    if (depPackage == null)
                    {
                        if (_package.DependencyNamesProp.ContainsKey(temp.R))
                        {
                            exceptions.Add(CreateEndUserPropertyException(_package.DependencyNamesProp[dep.R], 133, dep.R));
                        }
                        else
                        {
                            exceptions.Add(CreateEndUserException(133, dep.R));
                        }
                    }
                    else
                    {
                        _package.DependencyInfo.Add(depPackage);
                    }*/
                }

                //TODO make sure the numbers are not larger than the max a part of a version string
                var policyRegex = new Regex(@"^policy\.\d{1,5}\.\d{1,5}\.\S+$");
                /*
                var dependentAssemblies = from p in _package.DependencyInfo
                                          from a in p.Assemblies
                                          where !a.Type.Contains("policy") &&
                                          !policyRegex.IsMatch(a.Name)
                                          select a;

                */

                //let's check for valid roles!

                if (_package.Roles.IsNullOrEmpty())
                    exceptions.Add(CreateEndUserException(131));

                //make sure the major minors given are valid
                if (_package.SharedLibs != null)
                {
                    foreach (var i in _package.SharedLibs.MajorMinorsToReplace)
                    {
                        if (!i.IsValidMajorMinorVersion())
                        {
                            if (_package.SharedLibs.MajorMinorsToReplaceProp.ContainsKey(i))
                            {
                                exceptions.Add(CreateEndUserPropertyException(_package.SharedLibs.MajorMinorsToReplaceProp[i], 132, i));
                            }
                            else
                            {
                                exceptions.Add(CreateEndUserException(132, i));
                            }
                        }
                    }
                }

                if (_package.Apps != null)
                {
                    foreach (var e in _package.Apps.PrimaryExes)
                    {
                        if (e.StartMenu != null)
                        {
                            if (!e.StartMenu.IsSimpleSubPath())
                            {
                                exceptions.Add(CreateEndUserPropertyException(e.StartMenuProp, 168, e.StartMenu));
                                continue;
                            }

                            if (!e.StartMenu.EndsWith(".lnk"))
                            {
                                e.StartMenu += ".lnk";
                            }

                        }
                    }
                }

                if (exceptions.Count > 0)
                {
                    throw new AggregateException(exceptions);
                }

                #region Handle Shared Libraries

                //first create the string of all the dependencies elements

                var sharedlib = _package.SharedLibs;
                if (sharedlib != null)
                {

                    //set all the assembly names properly
                    foreach (var a in sharedlib.Assemblies)
                    {
                        if (a.Name == null)
                        {
                            var fi = new FileInfo(a.PrimaryFile);
                            a.Name = fi.NameWithoutExt().Replace(" ", "_");
                        }
                    }

                    Console.Write(Resources.SharedLibCreation);
                    if (_package.PackageArch != "any")
                    {
                        var dependencyStr = new StringBuilder();
                        /*
                        foreach (var dep in dependentAssemblies)
                        {
                            dependencyStr.Append(DependencyEntry.Replace("[$LIBTYPE]", dep.Type).Replace("[$LIBNAME]", dep.Name).
                                            Replace("[$LIBVERSION]", dep.Version).Replace("[$ARCH]", dep.Arch).
                                            Replace("[$PUBLICKEYTOKEN]", dep.PublicKeyToken));
                        }
                        */
                        foreach (var a in sharedlib.Assemblies)
                        {
                            /*
                            var manifestFilesString = new StringBuilder();
                            var filesString = new StringBuilder();

                            filesString.Append(FileEntry.Replace("[$FILE]", Path.GetFileName(a.PrimaryFile)));
                            foreach (var f in a.FinalInclude)
                            {
                                filesString.Append(FileEntry.Replace("[$FILE]", f.L));
                            }

                            manifestFilesString.Append(SharedLibraryManifest.Replace("[$LIBNAME]", a.Name).
                                    Replace("[$LIBVERSION]", _package.PackageVersion).
                                    Replace("[$DEPENDENCY]", dependencyStr.ToString()).Replace("[$PUBLICKEYTOKEN]", _package.PubToken).
                                    Replace("[$ARCH]", _package.PackageArch).Replace("[$FILES]", filesString.ToString()));

                            a.Manifest = Path.Combine(new FileInfo(a.PrimaryFile).DirectoryName, a.PrimaryFile + ".manifest");
                            //TODO do file checking
                            File.WriteAllText(a.Manifest, manifestFilesString.ToString());

                            */

                            // sign all the non-primary BinFiles
                            var binFiles = from f in a.FinalInclude.BinaryFiles()
                                           select f.R;
                            exceptions.AddRange(VerifySigning(binFiles, false));

                            //manifest created. Let's embed it.
                            if (!EmbedManifest(a.PrimaryFile))
                            {
                                exceptions.Add(CreateEndUserException(137, a.PrimaryFile + ".manifest", a.PrimaryFile));
                                continue;
                            }

                            //sign the primary file

                            if (!SignFile(a.PrimaryFile))
                            {
                                exceptions.Add(CreateEndUserException(136, a.PrimaryFile));
                                continue;
                            }

                            a.CatFile = a.PrimaryFile + ".cat";
                            if (!CreateAndSignCat(a.Manifest))
                            {
                                exceptions.Add(CreateEndUserException(138, a.Manifest + ".cdf"));
                                continue;
                            }

                            //we're going to create the policy assemblies
                            foreach (var p in _package.SharedLibs.MajorMinorsToReplace)
                            {

                                var pa = new PolicyAssemblyDescription(p, a.Name);
                                _package.SharedLibs.PolicyAssemblies.Add(pa);

                                var paManifestString = PublisherConfiguration.Replace("[$ASSMNAME]", a.Name).
                                    Replace("[$LIBMAJORMINOR]", p).Replace("[$PUBLICKEYTOKEN]", _package.PubToken).
                                    Replace("[$LIBVERSION]", _package.PackageVersion).Replace("[$ARCH]", _package.PackageArch).
                                    Replace("[$OLDVERSION]", _package.BindingPolicy);

                                pa.Manifest = Path.Combine(new FileInfo(a.PrimaryFile).DirectoryName, pa.Name + ".manifest");

                                File.WriteAllText(pa.Manifest, paManifestString);

                                pa.CatFile = pa.Manifest.Replace(".manifest", "") + ".cat";

                                if (!CreateAndSignCat(pa.Manifest))
                                {
                                    exceptions.Add(CreateEndUserException(138, pa.Manifest + ".cdf"));
                                    continue;
                                }

                            }

                        }
                    }

                    else
                    {
                        // it's .NET
                        foreach (var a in sharedlib.Assemblies)
                        {

                            if (!_codeSigningCert.FinishStrongNaming(a.PrimaryFile))
                            {
                                exceptions.Add(CreateEndUserException(139, a.PrimaryFile));
                                continue;
                            }

                            if (!SignFile(a.PrimaryFile))
                            {
                                exceptions.Add(CreateEndUserException(136, a.PrimaryFile));
                                continue;
                            }

                            foreach (var p in _package.SharedLibs.MajorMinorsToReplace)
                            {

                                var pa = new PolicyAssemblyDescription(p, a.Name);
                                _package.SharedLibs.PolicyAssemblies.Add(pa);

                                pa.PrimaryFile = Path.Combine(new FileInfo(a.PrimaryFile).DirectoryName, pa.Name + ".dll");

                                var paManifestString = MSILPublisherConfiguration.Replace("[$ASSMNAME]", a.Name).
                                    Replace("[$PUBLICKEYTOKEN]", _package.PubToken).
                                    Replace("[$LIBVERSION]", _package.PackageVersion).
                                    Replace("[$OLDVERSION]", _package.BindingMin + "-" + _package.BindingMax);

                                pa.Manifest = pa.PrimaryFile + ".config";
                                // cleanupFiles.Add(pa.Manifest);
                                File.WriteAllText(pa.Manifest, paManifestString);

                                if (!ExtractPublicKey())
                                {
                                    exceptions.Add(CreateEndUserPropertyException(_package.SharedLibs.MajorMinorsToReplaceProp[p],
                                            140, _package.CertificateFile));
                                    continue;
                                }

                                if (_al.Exec("/link:{0} /out:{1} /delaysign+ /keyfile:{2} /v:{3}", pa.Manifest,
                                     pa.PrimaryFile, _publicKeyFile, _package.PackageVersion) != 0)
                                {
                                    exceptions.Add(CreateEndUserPropertyException(_package.SharedLibs.MajorMinorsToReplaceProp[p],
                                        141, pa.PrimaryFile));
                                    continue;
                                }

                                if (!_codeSigningCert.FinishStrongNaming(pa.PrimaryFile))
                                {
                                    exceptions.Add(CreateEndUserPropertyException(_package.SharedLibs.MajorMinorsToReplaceProp[p],
                                        139, pa.PrimaryFile));
                                    continue;
                                }

                                if (!SignFile(pa.PrimaryFile))
                                {
                                    exceptions.Add(CreateEndUserPropertyException(_package.SharedLibs.MajorMinorsToReplaceProp[p],
                                        136, pa.PrimaryFile));
                                    continue;
                                }
                            }

                        }
                    }
                    if (exceptions.Count > 0)
                    {
                        throw new AggregateException(exceptions);
                    }

                    Console.WriteLine(Resources.Finished);
                }

                #endregion

                #region Handle Apps
                var apps = _package.Apps;
                if (apps != null)
                {
                    Console.Write(Resources.AppCreation);

                    if (_package.PackageArch != "any")
                    {
                        //it's native
                        var dependencyStr = new StringBuilder();
                        /*
                        foreach (var dep in dependentAssemblies)
                        {
                            dependencyStr.Append(DependencyEntry.Replace("[$LIBTYPE]", dep.Type).Replace("[$LIBNAME]", dep.Name).
                                            Replace("[$LIBVERSION]", dep.Version).Replace("[$ARCH]", dep.Arch).
                                            Replace("[$PUBLICKEYTOKEN]", dep.PublicKeyToken));
                        }

                        //we needs to add in the other assemblies in this package

                        if (sharedlib != null)
                        {
                            foreach (var dep in sharedlib.Assemblies)
                            {
                                dependencyStr.Append(DependencyEntry.Replace("[$LIBTYPE]", "win32").
                                    Replace("[$LIBNAME]", dep.Name).Replace("[$LIBVERSION]", _package.PackageVersion).
                                    Replace("[$ARCH]", _package.PackageArch).Replace("[$PUBLICKEYTOKEN]", _package.PubToken));
                            }
                        }*/

                        foreach (var e in apps.PrimaryExes)
                        {
                            /*
                            if (dependencyStr.Length > 0)
                            {
                                var configFilename = e.InputFile + ".config";
                                var execManifest = new StringBuilder();
                                execManifest.Append(ExecutableManifest.Replace("[$DEPENDENCY]", dependencyStr.ToString()));
                                File.WriteAllText(configFilename, execManifest.ToString());

                                if (!EmbedManifest(e.InputFile, configFilename))
                                {
                                    exceptions.Add(CreateEndUserException(137, configFilename, e.InputFile));
                                    continue;
                                }
                            }*/

                            if (!SignFile(e.InputFile))
                            {
                                exceptions.Add(CreateEndUserException(136, e.InputFile));
                                continue;
                            }
                        }

                    }
                    else
                    {
                        //it's .net

                        foreach (var e in apps.PrimaryExes)
                        {
                            if (!_codeSigningCert.FinishStrongNaming(e.InputFile))
                            {
                                exceptions.Add(CreateEndUserException(139, e.InputFile));
                                continue;
                            }

                            if (!SignFile(e.InputFile))
                            {
                                exceptions.Add(CreateEndUserException(136, e.InputFile));
                                continue;
                            }
                        }

                    }

                    if (exceptions.Count > 0)
                    {
                        throw new AggregateException(exceptions);
                    }

                    Console.WriteLine(Resources.Finished);
                }

                //check if every binary is actually signed at all
                //yes this is really messy
                var binFilesToCheck = Enumerable.Empty<TempedFile>();
                if (apps != null)
                    binFilesToCheck = binFilesToCheck.Concat(from i in apps.BinaryFilesMinusPrimaries select i.R);

                if (_package.SourceCodes != null)
                    binFilesToCheck = binFilesToCheck.Concat(from i in _package.SourceCodes.FinalInclude.BinaryFiles() select i.R);
                if (_package.DeveloperLibs != null)
                    binFilesToCheck = binFilesToCheck.Concat(from i in _package.DeveloperLibs.Headers.FinalInclude.
                                               Concat(_package.DeveloperLibs.ImportLibs.FinalInclude).
                                               Concat(_package.DeveloperLibs.StaticLibs.FinalInclude).
                                               BinaryFiles()
                                                             select i.R);

                exceptions.AddRange(VerifySigning(binFilesToCheck));

                exceptions.AddRange(DownloadBootstrapManifest());

                if (exceptions.Count > 0)
                {
                    throw new AggregateException(exceptions);
                }

                #endregion

                #region Write Msi OutToFile
                Console.Write(Resources.CreatingMSI);
                var tempPrefix = Path.GetTempFileName();
                File.WriteAllText(tempPrefix + ".wxs", _package.ConvertToWix());

                //we suppress the lack of UpgradeCode warning since we don't use them

                if (_candle.Exec("-nologo -sw1075 -out {0}.wixobj {0}.wxs", tempPrefix) != 0)
                    exceptions.Add(CreateEndUserException(142, _candle.StandardOut));

                if (exceptions.Count > 0)
                {
                    throw new AggregateException(exceptions);
                }

                //we suppress the lack of UpgradeCode warning since we don't use them
                if (_light.Exec("-nologo -sw1076 -out {1} {0}.wixobj", tempPrefix, _package.DefaultOutputFile) != 0)
                    exceptions.Add(CreateEndUserException(143, _light.StandardOut));

                if (exceptions.Count > 0)
                {
                    throw new AggregateException(exceptions);
                }

                if (!SignFile(_package.DefaultOutputFile))
                {
                    exceptions.Add(CreateEndUserException(136, _package.DefaultOutputFile));
                }

                if (exceptions.Count > 0)
                {
                    throw new AggregateException(exceptions);
                }

                if (_remember)
                {
                    //Verbose("Storing certificate details in the registry.");
                    _certificateSettings["#CurrentCertificate"].EncryptedStringValue = _package.CertificateFile;
                    _certificateSettings[Path.GetFileName(_package.CertificateFile), "Password"].EncryptedStringValue = _package.CertificatePassword;
                }

                Console.WriteLine(Resources.Finished);

                #endregion

            }
            catch (AggregateException failures)
            {
                CancellationTokenSource.Cancel();
                Fail("{0}\r\n\r\n    {1}", failures.InnerExceptions, Resources.ForCommandLineHelp);
            }
            catch (Exception failure)
            {
                CancellationTokenSource.Cancel();
                Fail("{0}\r\n\r\n    {1}", "{0} - stacktrace: {1}".format(failure.Message, failure.StackTrace)
                    , Resources.ForCommandLineHelp);
            }
            finally
            {
                foreach (var f in _cleanupFiles)
                {
                    File.Delete(f);
                }
            }
            return 0;
        }