Ejemplo n.º 1
0
        public static void Install(string vsExe, IInstallableExtension vsix, string rootSuffix)
        {
            using (var esm = ExternalSettingsManager.CreateForApplication(vsExe, rootSuffix))
            {
                var ems = new ExtensionManagerService(esm);
                IInstalledExtension installedVsix = null;
                if (ems.TryGetInstalledExtension(vsix.Header.Identifier, out installedVsix))
                {
                    Console.WriteLine($"Extension {vsix.Header.Name} version {vsix.Header.Version} already installed, unistalling first.");
                    ems.Uninstall(installedVsix);
                }

                ems.Install(vsix, perMachine: false);
            }
        }
Ejemplo n.º 2
0
        private static IInstalledExtension PerformInstallation(IInstallableExtension vsix, string devenvPath, string hive)
        {
            IInstalledExtension extension;

            using (var settingsManager = ExternalSettingsManager.CreateForApplication(devenvPath, hive))
            {
                var identifier = vsix.Header.Identifier;
                var name       = vsix.Header.Name;

                Log($"Preparing to install '{name}' with identifier '{identifier}' into '{hive}'");

                var extensionManager = new ExtensionManagerService(settingsManager);

                if (extensionManager.TryGetInstalledExtension(identifier, out extension))
                {
                    Log($"Extension '{name}' was already installed. Uninstalling...");
                    try
                    {
                        extensionManager.Uninstall(extension);
                        extensionManager.CommitExternalUninstall(extension);
                    }
                    catch (Exception ex)
                    {
                        LogError($"An error ocurred while trying to uninstall '{name}'. Rolling back...", ex);
                        RevertUninstall(extensionManager, extension);
                        throw;
                    }
                }
                try
                {
                    Log($"Starting installation of '{name}'");
                    extensionManager.Install(vsix, perMachine: false);
                    extension = extensionManager.GetInstalledExtension(identifier);
                    Log($"Installation of '{name}' into '{hive}' completed successfully.");
                }
                catch (Exception ex)
                {
                    LogError($"An error ocurred while trying to install '{name}'. Rolling back...", ex);
                    RevertUninstall(extensionManager, extension);
                    throw;
                }
            }

            return(extension);
        }
Ejemplo n.º 3
0
        public static int Main(string[] args)
        {
            if (args.Length == 0)
            {
                PrintUsage();
                return(0);
            }

            var argList = new List <string>(args);

            var rootSuffix = ExtractArg(argList, "rootSuffix") ?? "Exp";
            var skipIfEqualOrNewerInstalled = FindArg(argList, "skipIfEqualOrNewerInstalled");
            var uninstall    = FindArg(argList, "u");
            var uninstallAll = FindArg(argList, "uninstallAll");
            var printHelp    = FindArg(argList, "?") || FindArg(argList, "h") || FindArg(argList, "help");
            var vsInstallDir = ExtractArg(argList, "vsInstallDir") ?? Environment.GetEnvironmentVariable("VsInstallDir");

            var expectedArgCount = uninstallAll ? 0 : 1;

            if (argList.Count != expectedArgCount)
            {
                PrintUsage();
                return(1);
            }

            string extensionPath = uninstallAll ? string.Empty : argList[0];
            string devenvPath;

            try
            {
                devenvPath = GetDevenvPath(vsInstallDir);

                var assemblyResolutionPaths = new string[] {
                    Path.Combine(vsInstallDir, @"Common7\IDE"),
                    Path.Combine(vsInstallDir, @"Common7\IDE\PrivateAssemblies"),
                    Path.Combine(vsInstallDir, @"Common7\IDE\PublicAssemblies")
                };

                AppDomain.CurrentDomain.AssemblyResolve += (object sender, ResolveEventArgs eventArgs) => {
                    var assemblyFileName = $"{eventArgs.Name.Split(',')[0]}.dll";

                    foreach (var assemblyResolutionPath in assemblyResolutionPaths)
                    {
                        var assemblyFilePath = Path.Combine(assemblyResolutionPath, assemblyFileName);

                        if (File.Exists(assemblyFilePath))
                        {
                            return(Assembly.LoadFrom(assemblyFilePath));
                        }
                    }

                    return(null);
                };

                Console.WriteLine(Environment.CommandLine);

                if (IsRunningAsAdmin())
                {
                    Console.WriteLine("  Running as Admin.");
                }

                RunProgram();

                // Move all of this into a local method so that it only causes the assembly loads after the resolver has been hooked up
                void RunProgram()
                {
                    var installedExtensionComparer = Comparer <IInstalledExtension> .Create((left, right) =>
                    {
                        if (left.References.Count() == 0)
                        {
                            // When left.References.Count() is zero, then we have two scenarios:
                            //    * right.References.Count() is zero, and the order of the two components doesn't matter, so we return 0
                            //    * right.References.Count() is not zero, which means it should be uninstalled after left, so we return -1
                            return(right.References.Count() == 0 ? 0 : -1);
                        }
                        else if (right.References.Count() == 0)
                        {
                            // When left.References.Count() is not zero, but right.References.Count() is, then we have one scenario:
                            //    * right should be uninstalled before left, so we return 1
                            return(1);
                        }

                        if (left.References.Any((extensionReference) => extensionReference.Identifier == right.Header.Identifier))
                        {
                            // When left.References contains right, then we have one scenario:
                            //    * left is dependent on right, which means it must be uninstalled afterwards, so we return 1
                            return(1);
                        }
                        else if (right.References.Any((extensionReference) => extensionReference.Identifier == left.Header.Identifier))
                        {
                            // When right.References contains left, then we have one scenario:
                            //    * right is dependent on left, which means it must be uninstalled afterwards, so we return -1
                            return(-1);
                        }

                        // Finally, if both projects contain references, but neither depends on the other, we have one scenario:
                        //    * left and right are independent of each other, and the order of the two components doesn't matter, so we return 0
                        return(0);
                    });

                    using (var settingsManager = ExternalSettingsManager.CreateForApplication(devenvPath, rootSuffix))
                    {
                        ExtensionManagerService extensionManagerService = null;

                        try
                        {
                            extensionManagerService = new ExtensionManagerService(settingsManager);

                            if (uninstallAll)
                            {
                                Console.WriteLine("  Uninstalling all local extensions...");
                                UninstallAll();
                            }
                            else
                            {
                                var extensionManager     = (IVsExtensionManager)(extensionManagerService);
                                var installableExtension = extensionManager.CreateInstallableExtension(extensionPath);

                                var status = GetInstallStatus(installableExtension.Header);
                                var installedVersionIsEqualOrNewer = installableExtension.Header.Version < status.installedExtension?.Header.Version;

                                if (uninstall)
                                {
                                    if (status.installed)
                                    {
                                        if (installedVersionIsEqualOrNewer && skipIfEqualOrNewerInstalled)
                                        {
                                            Environment.ExitCode = INSTALL_OR_UNINSTALL_SKIPPED_EXCEPTION_CODE;
                                            throw new Exception($"Skipping uninstall of version ({status.installedExtension.Header.Version}), which is equal to or newer than the one supplied on the command line ({installableExtension.Header.Version}).");
                                        }

                                        if (status.installedGlobally)
                                        {
                                            Console.WriteLine($"  Skipping uninstall for global extension: '{status.installedExtension.InstallPath}'");
                                        }
                                        else
                                        {
                                            Console.WriteLine($"  Uninstalling local extension: '{status.installedExtension.InstallPath}'");
                                            Uninstall(status.installedExtension);
                                        }
                                    }
                                    else
                                    {
                                        Console.WriteLine("  Nothing to uninstall...");
                                    }
                                }
                                else
                                {
                                    if (status.installed)
                                    {
                                        if (installedVersionIsEqualOrNewer && skipIfEqualOrNewerInstalled)
                                        {
                                            Environment.ExitCode = INSTALL_OR_UNINSTALL_SKIPPED_EXCEPTION_CODE;
                                            throw new Exception($"Skipping install of version ({installableExtension.Header.Version}), which is older than the one currently installed ({status.installedExtension.Header.Version}).");
                                        }

                                        if (status.installedGlobally)
                                        {
                                            if (installedVersionIsEqualOrNewer)
                                            {
                                                Environment.ExitCode = GLOBAL_VERSION_NEWER_EXCEPTION_CODE;
                                                throw new Exception($"The version you are attempting to install ({installableExtension.Header.Version}) has a version that is less than the one installed globally ({status.installedExtension.Header.Version}).");
                                            }
                                            else
                                            {
                                                Console.WriteLine($"  Installing local extension ({extensionPath}) over global extension ({status.installedExtension.InstallPath})");
                                            }
                                        }
                                        else
                                        {
                                            Console.WriteLine($"  Updating local extension ({status.installedExtension.InstallPath}) to '{extensionPath}'");
                                            Uninstall(status.installedExtension);
                                        }
                                    }
                                    else
                                    {
                                        Console.WriteLine($"  Installing local extension: '{extensionPath}'");
                                    }

                                    Install(installableExtension);
                                }
                            }
                        }
                        finally
                        {
                            extensionManagerService?.Close();
                            extensionManagerService = null;
                        }

                        bool IsInstalledGlobally(IInstalledExtension installedExtension)
                        {
                            return(installedExtension.InstalledPerMachine || installedExtension.InstallPath.StartsWith(vsInstallDir, StringComparison.OrdinalIgnoreCase));
                        }

                        (bool installed, bool installedGlobally, IInstalledExtension installedExtension) GetInstallStatus(IExtensionHeader extensionHeader)
                        {
                            var installed         = extensionManagerService.TryGetInstalledExtension(extensionHeader.Identifier, out var installedExtension);
                            var installedGlobally = installed && IsInstalledGlobally(installedExtension);

                            return(installed, installedGlobally, installedExtension);
                        }

                        void Install(IInstallableExtension installableExtension)
                        {
                            extensionManagerService.Install(installableExtension, perMachine: false);
                            var settingsStore = settingsManager.GetWritableSettingsStore(SettingsScope.UserSettings);

                            EnableLoadingAllExtensions(settingsStore);
                            RemoveExtensionFromPendingDeletions(settingsStore, installableExtension.Header);
                            UpdateLastExtensionsChange(settingsStore);

                            // Recreate the extensionManagerService to force the extension cache to recreate
                            extensionManagerService?.Close();
                            extensionManagerService = new ExtensionManagerService(settingsManager);

                            var status = GetInstallStatus(installableExtension.Header);

                            if (!status.installed)
                            {
                                Environment.ExitCode = INSTALL_FAILED_NOTFOUND_EXCEPTION_CODE;
                                throw new Exception($"The extension failed to install. It could not be located.");
                            }
                            else if (status.installedExtension.Header.Version != installableExtension.Header.Version)
                            {
                                Environment.ExitCode = INSTALL_FAILED_VERSION_EXCEPTION_CODE;
                                throw new Exception($"The extension failed to install. The located version ({status.installedExtension.Header.Version}) does not match the expected version ({installableExtension.Header.Version}).");
                            }
                            else if (status.installedGlobally)
                            {
                                Console.WriteLine($"    The extension was succesfully installed globally: '{status.installedExtension.InstallPath}'");
                            }
                            else
                            {
                                Console.WriteLine($"    The extension was succesfully installed locally: '{status.installedExtension.InstallPath}'");
                            }
                        }

                        void Uninstall(IInstalledExtension installedExtension)
                        {
                            extensionManagerService.Uninstall(installedExtension);

                            // Recreate the extensionManagerService to force the extension cache to recreate
                            extensionManagerService?.Close();
                            extensionManagerService = new ExtensionManagerService(settingsManager);

                            var status = GetInstallStatus(installedExtension.Header);

                            if (status.installed)
                            {
                                var wasInstalledGlobally = IsInstalledGlobally(installedExtension);

                                if (wasInstalledGlobally)
                                {
                                    // We should never hit this case, as we shouldn't be passing in gobally installed extensions

                                    if (status.installedGlobally)
                                    {
                                        Environment.ExitCode = GLOBAL_UNINSTALL_FAILED_EXCEPTION_CODE;
                                        throw new Exception("The global extension failed to uninstall.");
                                    }
                                    else
                                    {
                                        // This should be impossible even if we tried to uninstall a global extension...
                                        Environment.ExitCode = LOCAL_UNINSTALL_FAILED_EXCEPTION_CODE;
                                        throw new Exception($"The global extension was uninstalled. A local extension still exists: '{status.installedExtension.InstallPath}'");
                                    }
                                }
                                else if (status.installedGlobally)
                                {
                                    Console.WriteLine($"    The local extension was succesfully uninstalled. A global extension still exists: '{status.installedExtension.InstallPath}'");
                                }
                                else
                                {
                                    throw new Exception("The local extension failed to uninstall.");
                                }
                            }
                            else
                            {
                                Console.WriteLine("    The local extension was succesfully uninstalled.");
                            }
                        }

                        void UninstallAll()
                        {
                            // We only want extensions which are not installed per machine and we want them sorted by their dependencies.
                            var installedExtensions = extensionManagerService.GetInstalledExtensions()
                                                      .Where((installedExtension) => !IsInstalledGlobally(installedExtension))
                                                      .OrderBy((installedExtension) => installedExtension, installedExtensionComparer);

                            foreach (var installedExtension in installedExtensions)
                            {
                                Console.WriteLine($"    Uninstalling local extension: '{installedExtension.InstallPath}'");
                                Uninstall(installedExtension);
                            }
                        }
                    }
                }
            }
            catch (Exception e) when(Environment.ExitCode != 0)
            {
                if (Environment.ExitCode < 0)
                {
                    Console.Error.WriteLine(e);
                }
                else
                {
                    Console.WriteLine("  " + e.Message);
                }
            }

            return(Environment.ExitCode);
        }
Ejemplo n.º 4
0
        public static int Main(string[] args)
        {
            if (args.Length == 0)
            {
                PrintUsage();
                return(0);
            }

            var argList = new List <string>(args);

            var rootSuffix   = ExtractArg(argList, "rootSuffix") ?? "Exp";
            var uninstall    = FindArg(argList, "u");
            var uninstallAll = FindArg(argList, "uninstallAll");
            var printHelp    = FindArg(argList, "?") || FindArg(argList, "h") || FindArg(argList, "help");
            var vsInstallDir = ExtractArg(argList, "vsInstallDir") ?? Environment.GetEnvironmentVariable("VsInstallDir");

            var expectedArgCount = uninstallAll ? 0 : 1;

            if (argList.Count != expectedArgCount)
            {
                PrintUsage();
                return(1);
            }

            string vsixPath = uninstallAll ? string.Empty : argList[0];
            string devenvPath;

            try
            {
                devenvPath = GetDevenvPath(vsInstallDir);

                var assemblyResolutionPaths = new string[] {
                    Path.Combine(vsInstallDir, @"Common7\IDE"),
                    Path.Combine(vsInstallDir, @"Common7\IDE\PrivateAssemblies"),
                    Path.Combine(vsInstallDir, @"Common7\IDE\PublicAssemblies")
                };

                AppDomain.CurrentDomain.AssemblyResolve += (object sender, ResolveEventArgs eventArgs) => {
                    var assemblyFileName = $"{eventArgs.Name.Split(',')[0]}.dll";

                    foreach (var assemblyResolutionPath in assemblyResolutionPaths)
                    {
                        var assemblyFilePath = Path.Combine(assemblyResolutionPath, assemblyFileName);

                        if (File.Exists(assemblyFilePath))
                        {
                            return(Assembly.LoadFrom(assemblyFilePath));
                        }
                    }

                    return(null);
                };

                RunProgram();

                // Move all of this into a local method so that it only causes the assembly loads after the resolver has been hooked up
                void RunProgram()
                {
                    using (var settingsManager = ExternalSettingsManager.CreateForApplication(devenvPath, rootSuffix))
                    {
                        ExtensionManagerService extensionManagerService = null;

                        try
                        {
                            extensionManagerService = new ExtensionManagerService(settingsManager);

                            if (uninstallAll)
                            {
                                Console.WriteLine("Uninstalling all... ");
                                UninstallAll(extensionManagerService);
                            }
                            else
                            {
                                var extensionManager    = (IVsExtensionManager)(extensionManagerService);
                                var vsixToInstall       = extensionManager.CreateInstallableExtension(vsixPath);
                                var vsixToInstallHeader = vsixToInstall.Header;

                                var foundBefore             = extensionManagerService.TryGetInstalledExtension(vsixToInstallHeader.Identifier, out var installedVsixBefore);
                                var installedGloballyBefore = foundBefore && installedVsixBefore.InstallPath.StartsWith(vsInstallDir, StringComparison.OrdinalIgnoreCase);

                                if (uninstall)
                                {
                                    if (foundBefore && !installedGloballyBefore)
                                    {
                                        Console.WriteLine("Uninstalling {0}... ", vsixPath);
                                        extensionManagerService.Uninstall(installedVsixBefore);
                                    }
                                    else
                                    {
                                        Console.WriteLine("Nothing to uninstall... ");
                                    }
                                }
                                else
                                {
                                    if (foundBefore && installedGloballyBefore && (vsixToInstallHeader.Version < installedVsixBefore.Header.Version))
                                    {
                                        throw new Exception($"The version you are attempting to install ({vsixToInstallHeader.Version}) has a version that is less than the one installed globally ({installedVsixBefore.Header.Version}).");
                                    }
                                    else if (foundBefore && !installedGloballyBefore)
                                    {
                                        Console.WriteLine("Updating {0}... ", vsixPath);
                                        extensionManagerService.Uninstall(installedVsixBefore);
                                    }
                                    else
                                    {
                                        Console.WriteLine("Installing {0}... ", vsixPath);
                                    }

                                    extensionManagerService.Install(vsixToInstall, perMachine: false);
                                    var settingsStore = settingsManager.GetWritableSettingsStore(SettingsScope.UserSettings);

                                    EnableLoadingAllExtensions(settingsStore);
                                    RemoveExtensionFromPendingDeletions(settingsStore, vsixToInstallHeader);
                                    UpdateLastExtensionsChange(settingsStore);

                                    // Recreate the extensionManagerService to force the extension cache to recreate
                                    extensionManagerService?.Close();
                                    extensionManagerService = new ExtensionManagerService(settingsManager);

                                    var foundAfter             = extensionManagerService.TryGetInstalledExtension(vsixToInstallHeader.Identifier, out var installedVsixAfter);
                                    var installedGloballyAfter = foundAfter && installedVsixAfter.InstallPath.StartsWith(vsInstallDir, StringComparison.OrdinalIgnoreCase);

                                    if (uninstall && foundAfter)
                                    {
                                        if (installedGloballyBefore && installedGloballyAfter)
                                        {
                                            throw new Exception($"The extension failed to uninstall. It is still installed globally.");
                                        }
                                        else if (!installedGloballyBefore && installedGloballyAfter)
                                        {
                                            Console.WriteLine("The local extension was succesfully uninstalled. However, the global extension is still installed.");
                                        }
                                        else
                                        {
                                            Console.WriteLine("The extension was succesfully uninstalled.");
                                        }
                                    }
                                    else if (!uninstall)
                                    {
                                        if (!foundAfter)
                                        {
                                            throw new Exception($"The extension failed to install. It could not be located.");
                                        }
                                        else if (installedVsixAfter.Header.Version != vsixToInstallHeader.Version)
                                        {
                                            throw new Exception("The extension failed to install. The located version does not match the expected version.");
                                        }
                                        else
                                        {
                                            Console.WriteLine("The extension was succesfully installed.");
                                        }
                                    }
                                }
                            }
                        }
                        finally
                        {
                            extensionManagerService?.Close();
                            extensionManagerService = null;
                        }

                        Console.WriteLine("Done!");
                    }
                }
            }
            catch (Exception e)
            {
                string message = e.GetType().Name + ": " + e.Message + Environment.NewLine + e.ToString();
                Console.Error.WriteLine(message);
                return(2);
            }

            return(0);
        }