Example #1
0
        /// <summary>
        /// Adds manifest references - a public method that calls into private recursive method
        /// that updates file and assembly references.
        /// </summary>
        /// <param name="manifest">Manifest whose references are to be updated</param>
        /// <param name="addDeploy">Specifies is '.deploy' should be appended</param>
        /// <param name="fromDirectory">Directory at which to begin the recursive search</param>
        /// <param name="filesToIgnore">Files that should not be included in the manifest</param>
        /// <param name="lockedFileReporter">Delegate via which locked files will be reported</param>
        /// <param name="sender">Sender</param>
        /// <param name="updateProgress">UpdateProgress event handler</param>
        /// <param name="overwrite">Overwrite event handler</param>
        /// <param name="errors">List of errors</param>
        public static void AddReferences(ApplicationManifest manifest,
                                         bool addDeploy,
                                         string fromDirectory, List <string> filesToIgnore,
                                         LockedFileReporter lockedFileReporter, object sender, UpdateProgressEventHandler updateProgress, OverwriteEventHandler overwrite, ArrayList errors)
        {
            if ((manifest == null) || (fromDirectory == null))
            {
                return;
            }

            // Strip a leading .\ from the path, if present
            if ((fromDirectory.Length >= 2) && fromDirectory.Substring(0, 2) == ".\\")
            {
                fromDirectory = fromDirectory.Substring(2);
            }

            // If stripping a leading .\ yields an empty string, use "."
            if (fromDirectory == "")
            {
                fromDirectory = ".";
            }

            // Append a trailing \ if necessary
            if (fromDirectory.LastIndexOf('\\') != fromDirectory.Length - 1)
            {
                fromDirectory += '\\';
            }

            // Add application manifest file to the ignore list
            string manifestName = (manifest.AssemblyIdentity.Name + ".manifest").ToLower();

            filesToIgnore.Add(manifestName);

            // We need to add the full path as well since the addDeploy
            // method is using the full filename for comparison.
            filesToIgnore.Add(manifest.SourcePath + manifestName);

            if (addDeploy)
            {
                filesToIgnore.Add(manifestName + ".deploy");
                filesToIgnore.Add(manifest.SourcePath + manifestName + ".deploy");
            }

            // Set the source path for the new references
            manifest.SourcePath = fromDirectory;

            updateProgress?.Invoke(sender, new UpdateProgressEventArgs(Action.Begin, ""));

            // Recursively search fromDirectory to get new references
            AddReferences(manifest, addDeploy, fromDirectory, fromDirectory, "", filesToIgnore, lockedFileReporter, sender, updateProgress, overwrite, errors);

            updateProgress?.Invoke(sender, new UpdateProgressEventArgs(Action.SearchComplete, ""));
        }
Example #2
0
        /// <summary>
        /// Adds/updates references, using a breadth-first recursive descent model.
        /// </summary>
        /// <param name="manifest">Manifest whose references are to be updated</param>
        /// <param name="addDeploy">Specifies if '.deploy' should be appended</param>
        /// <param name="root">Directory where search began (does not change during descent)</param>
        /// <param name="searchDirectory">Directory to examine for references and subdirectories</param>
        /// <param name="relativePath">Path from origin directory (codeBase) to current directory</param>
        /// <param name="filesToIgnore">Files that should not be included in the manifest</param>
        /// <param name="lockedFileReporter">Delegate via which locked files will be reported</param>
        /// <param name="sender">Sender</param>
        /// <param name="updateProgress">UpdateProgress event handler</param>
        /// <param name="overwrite">Overwrite event handler</param>
        /// <param name="errors">List of errors</param>
        private static void AddReferences(ApplicationManifest manifest,
                                          bool addDeploy,
                                          string root, string searchDirectory, string relativePath,
                                          List <string> filesToIgnore,
                                          LockedFileReporter lockedFileReporter, object sender, UpdateProgressEventHandler updateProgress, OverwriteEventHandler overwrite, ArrayList errors)
        {
            if ((manifest == null) || (searchDirectory == null))
            {
                return;
            }

            // Process files in current directory
            string[] files;
            try
            {
                files = Directory.GetFiles(searchDirectory);
            }
            catch (System.UnauthorizedAccessException)
            {
                return;
            }

            if (addDeploy)
            {
                files = AppendDeploy(filesToIgnore, files, overwrite, errors);
            }

            bool   launcherBasedDeployment = false;
            string launcherPath            = addDeploy ? Path.Combine(root, LauncherUtil.LauncherFilename + ".deploy") : Path.Combine(root, LauncherUtil.LauncherFilename);

            if (File.Exists(launcherPath))
            {
                launcherBasedDeployment = true;
            }

            List <BaseReference> assembliesToRemove = new List <BaseReference>();
            List <BaseReference> filesToRemove      = new List <BaseReference>();

            foreach (string filePath in files)
            {
                bool bRelativePath = false;
                // Generate codebase from filePath
                string codebase = filePath;
                if (codebase == null)
                {
                    // This could be true if we renamed a file
                    continue;
                }
                string extension = Path.GetExtension(codebase).ToLower();

                // Strip a leading .\ from the path, if present
                if ((codebase.Length >= 2) && codebase.Substring(0, 2) == ".\\")
                {
                    bRelativePath = true;
                    codebase      = codebase.Substring(2);
                }

                // See if this file is in the ignore list.
                // Ignorelist of the .manifest file is using the fullpath at
                // the very beggining so if a -fd . is used it does not find it.
                if (filesToIgnore.Contains(codebase.ToLower()) ||
                    (bRelativePath &&
                     extension == ".manifest" &&
                     filesToIgnore.Contains(Path.GetFullPath(codebase).ToLower())))
                {
                    continue;
                }

                // Strip the root path from the filename, if present
                if (codebase.StartsWith(root))
                {
                    codebase = codebase.Substring(root.Length);
                }

                // See if this file is in the ignore list
                if (filesToIgnore.Contains(codebase.ToLower()) ||
                    Path.GetExtension(codebase).ToLower() == ".netmodule" ||
                    (Path.GetExtension(codebase).ToLower() == ".deploy") && Path.GetExtension(codebase.Substring(0, codebase.Length - 7)).ToLower() == ".netmodule")
                {
                    continue;
                }

                // Use the presence/absence of metadata to indicate whether
                // the file is an assembly or just a regular sort of file.

                AssemblyIdentity assembly = null;

                // If this is a Launcher-based deployment, all files except Launcher should be added as simple files
                // Launcher-based deployments are used for .NET (Core) apps - assembly identity cannot be positively
                // obtained from all types of .NET (Core) assemblies, requiring us to use simple file references.
                if (string.Equals(filePath, launcherPath, StringComparison.OrdinalIgnoreCase) ||
                    !launcherBasedDeployment)
                {
                    try
                    {
                        assembly = AssemblyIdentity.FromFile(filePath);
                    }
                    catch (BadImageFormatException)
                    {
                        // The file does not have a manifest in it
                    }
                    catch (System.Net.WebException)
                    {
                        // Internet connection might not be available
                    }
                }

                bool isAssembly = (assembly != null);

                // Make sure the file isn't locked, print an error message if
                // it is. Without this test, ManifestUtil will throw an
                // exception later when it tries to compute the file's hash.
                try
                {
                    FileInfo f = new FileInfo(filePath);
                    Stream   s = f.OpenRead();
                    s.Close();
                }
                catch (System.Exception)
                {
                    lockedFileReporter?.Invoke(filePath);
                    continue;
                }

                // Create a reference and add it to the appropriate collection.
                Action action = Action.AlreadyPresent;

                if (isAssembly)
                {
                    if (!CollectionContains(manifest.AssemblyReferences, codebase, assembliesToRemove))
                    {
                        AssemblyReference newref = new AssemblyReference
                        {
                            TargetPath = codebase
                        };

                        manifest.AssemblyReferences.Add(newref);
                        action = Action.Added;

                        // Determine if this is the EntryPoint
                        string strippedPath = codebase;
                        if (strippedPath.ToLower().EndsWith(".deploy"))
                        {
                            strippedPath = strippedPath.Substring(0, codebase.Length - 7).ToLower();
                        }

                        if (manifest.EntryPoint != null &&
                            (String.Compare(manifest.EntryPoint.TargetPath, strippedPath, true, CultureInfo.InvariantCulture) == 0))
                        {
                            manifest.EntryPoint = newref;
                        }
                    }
                }
                else
                {
                    if (!CollectionContains(manifest.FileReferences, codebase, filesToRemove))
                    {
                        FileReference newref = new FileReference
                        {
                            TargetPath = codebase
                        };
                        manifest.FileReferences.Add(newref);
                        action = Action.Added;
                    }
                }

                if (updateProgress != null)
                {
                    updateProgress(sender, new UpdateProgressEventArgs(action, codebase));
                }
            }

            // Remove files that were replaced because of renames.
            foreach (BaseReference reference in assembliesToRemove)
            {
                manifest.AssemblyReferences.Remove(reference as AssemblyReference);
            }

            foreach (BaseReference reference in filesToRemove)
            {
                manifest.FileReferences.Remove(reference as FileReference);
            }

            // Descend to subfolders
            string[] subdirs = Directory.GetDirectories(searchDirectory);

            foreach (string eachSubdir in subdirs)
            {
                string subdir = Path.GetFileName(eachSubdir);

                string newRelativePath;

                if ((relativePath.Length == 0) || (relativePath == "."))
                {
                    newRelativePath = subdir;
                }
                else
                {
                    newRelativePath = relativePath + "\\" + subdir;
                }

                AddReferences(manifest, addDeploy, root, eachSubdir, newRelativePath, filesToIgnore, lockedFileReporter, sender, updateProgress, overwrite, errors);
            }
        }