Example #1
0
        protected void WithInstaller(Action <TransactedInstaller> callback)
        {
            if (callback == null)
            {
                throw new ArgumentNullException("callback");
            }

            Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);

            ExecutePreActions();

            using (Installer installer = CreateInstaller())
                using (var ti = new TransactedInstaller())
                {
                    ti.Installers.Add(installer);

                    Assembly assembly = Assembly.GetEntryAssembly();

                    if (assembly == null)
                    {
                        throw new HostException("Assembly.GetEntryAssembly() is null for some reason.");
                    }

                    string   path        = string.Format("/assemblypath={0}", assembly.Location);
                    string[] commandLine = { path };

                    var context = new InstallContext(null, commandLine);
                    ti.Context = context;

                    callback(ti);
                }

            ExecutePostActions();
        }
        protected ManageDiagnosticsService()
        {
            base.Account     = ServiceAccount.LocalSystem;
            base.StartMode   = ServiceStartMode.Automatic;
            base.DisplayName = Strings.DiagnosticsServiceDisplayName;
            base.Description = Strings.DiagnosticsServiceDescription;
            string         binPath        = ConfigurationContext.Setup.BinPath;
            InstallContext installContext = new InstallContext();

            installContext.Parameters["logtoconsole"] = "false";
            installContext.Parameters["assemblypath"] = Path.Combine(binPath, "Microsoft.Exchange.Diagnostics.Service.exe");
            base.FirstFailureActionType      = ServiceActionType.Restart;
            base.FirstFailureActionDelay     = 5000U;
            base.SecondFailureActionType     = ServiceActionType.Restart;
            base.SecondFailureActionDelay    = 5000U;
            base.AllOtherFailuresActionType  = ServiceActionType.Restart;
            base.AllOtherFailuresActionDelay = 60000U;
            base.FailureResetPeriod          = 3600U;
            base.FailureActionsFlag          = true;
            base.ServiceInstallContext       = installContext;
            base.CategoryCount      = 2;
            base.ServicesDependedOn = null;
            base.CategoryCount      = 2;
            base.EventMessageFile   = Path.Combine(ConfigurationContext.Setup.BinPath, "Microsoft.Exchange.Diagnostics.Service.EventLog.dll");
        }
Example #3
0
        public ManageMailboxReplicationService()
        {
            base.Account     = ServiceAccount.LocalSystem;
            base.StartMode   = ServiceStartMode.Automatic;
            base.DisplayName = Strings.MailboxReplicationServiceDisplayName;
            base.Description = Strings.MailboxReplicationServiceDescription;
            InstallContext installContext = new InstallContext();

            installContext.Parameters["logtoconsole"] = "false";
            installContext.Parameters["assemblypath"] = Path.Combine(ConfigurationContext.Setup.BinPath, "MSExchangeMailboxReplication.exe");
            base.EventMessageFile            = Path.Combine(ConfigurationContext.Setup.ResPath, "Microsoft.Exchange.MailboxReplicationService.EventLog.dll");
            base.CategoryCount               = 2;
            base.FirstFailureActionType      = ServiceActionType.Restart;
            base.FirstFailureActionDelay     = 5000U;
            base.SecondFailureActionType     = ServiceActionType.Restart;
            base.SecondFailureActionDelay    = 5000U;
            base.AllOtherFailuresActionType  = ServiceActionType.Restart;
            base.AllOtherFailuresActionDelay = 5000U;
            base.FailureResetPeriod          = 0U;
            base.ServiceInstallContext       = installContext;
            base.ServicesDependedOn          = new List <string>(base.ServicesDependedOn)
            {
                "NetTcpPortSharing"
            }.ToArray();
            base.AddFirewallRule(new MSExchangeMailboxReplicationFirewallRule());
        }
        public static bool StopService(InstallContext context)
        {
            bool result = true;

            try
            {
                var controller = new ServiceController(AppSettings.ServiceName);
                if (controller.Status != ServiceControllerStatus.Running)
                {
                    throw new Exception(string.Format("Can't stop the service because it is in the '{0}' state.",
                                                      controller.Status));
                }

                controller.Stop();
                LogMessage("Service stopped successfully.", context);
            }
            catch (Exception ex)
            {
                result = false;
                LogMessage(
                    "An error occurred while start the service, please start it manually or reboot the computer.",
                    context);
                WriteExceptions(ex, context);
            }

            return(result);
        }
Example #5
0
        private static void Install(CommandLine commandLine)
        {
            string options = GetServiceCommandLine(commandLine);

            string         logFile      = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "install.log");
            string         assemblyPath = typeof(MachineNode).Assembly.Location;
            InstallContext context      = new InstallContext(logFile,
                                                             new string[] {
                String.Format("/assemblypath={0}", assemblyPath),
                String.Format("/logfile={0}", logFile)
            });

            if (!String.IsNullOrEmpty(options))
            {
                context.Parameters["AdditionalOptions"] = options;
            }

            ListDictionary savedState = new ListDictionary();

            AssemblyInstaller installer = new AssemblyInstaller(typeof(MachineNodeService).Assembly, new string[0]);

            installer.Context       = context;
            installer.UseNewContext = false;
            installer.AfterInstall += AfterInstall;
            installer.Install(savedState);
            installer.Commit(savedState);
        }
Example #6
0
        static void InstallService()
        {
            try
            {
                ServiceProcessInstaller processInstaller = new ServiceProcessInstaller();
                processInstaller.Account = ServiceAccount.LocalSystem;

                ServiceInstaller installer = new ServiceInstaller();
                InstallContext   context   = new InstallContext();
                string           path      = String.Format("/assemblypath={0}", Assembly.GetExecutingAssembly().Location);
                string[]         cmdLine   = { path };

                context               = new InstallContext(LogPath, cmdLine);
                installer.Context     = context;
                installer.DisplayName = SERVICE_DISPLAYNAME;
                installer.Description = SERVICE_DESC;
                installer.ServiceName = SERVICE_NAME;
                installer.StartType   = ServiceStartMode.Automatic;
                installer.Parent      = processInstaller;

                ListDictionary state = new ListDictionary();
                installer.Install(state);
            } catch (Exception e)
            {
                Log(e.Message);
            }
        }
Example #7
0
        private void PrintStartText(string activity)
        {
            if (this.UseNewContext)
            {
                InstallContext context = this.CreateInstallContext();
                if (base.Context != null)
                {
                    base.Context.LogMessage(Res.GetString("InstallLogContent", new object[] { this.Path }));
                    base.Context.LogMessage(Res.GetString("InstallFileLocation", new object[] { context.Parameters["logfile"] }));
                }
                base.Context = context;
            }
            base.Context.LogMessage(string.Format(CultureInfo.InvariantCulture, activity, new object[] { this.Path }));
            base.Context.LogMessage(Res.GetString("InstallLogParameters"));
            if (base.Context.Parameters.Count == 0)
            {
                base.Context.LogMessage("   " + Res.GetString("InstallLogNone"));
            }
            IDictionaryEnumerator enumerator = (IDictionaryEnumerator)base.Context.Parameters.GetEnumerator();

            while (enumerator.MoveNext())
            {
                string key  = (string)enumerator.Key;
                string str2 = (string)enumerator.Value;
                if (key.Equals("password", StringComparison.InvariantCultureIgnoreCase))
                {
                    str2 = "********";
                }
                base.Context.LogMessage("   " + key + " = " + str2);
            }
        }
Example #8
0
        public static ActionResult ExecuteAll(Session session)
        {
            try
            {
                session.Log("Begin Execute All Custom Actions");

                IInstallLogger emptyLogger    = new EmptyLogger();
                InstallContext installContext = new InstallContext();
                foreach (string key in session.CustomActionData.Keys)
                {
                    installContext.Parameters.Add(key, session.CustomActionData[key]);
                }

                session.Log("Setting up configuration");

                Configuration config = new Configuration(session.CustomActionData);

                session.Log("Creating and executing action");

                using (Action action = new Action(config))
                {
                    action.Context = installContext;
                    action.Install(new Hashtable());
                }

                session.Log("End Execute All Custom Actions");
                return(ActionResult.Success);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Error occurred during install");
                EventLog.WriteEntry("MsiInstaller", $"{ex.Message} {ex.InnerException?.Message}", EventLogEntryType.Error);
                return(ActionResult.Failure);
            }
        }
Example #9
0
        public static string GetBinDirectory(InstallContext ctx, IDictionary state)
        {
            // order of precedence:
            // [basedirectory]\installers
            // [sourcedirectory]\bin
            // [currentpath]\installers

            StringBuilder sb = new StringBuilder();

            // determine the source and target dirs
            string binDir = (Environment.CurrentDirectory + @"\installers").Replace(@"\\", @"\");

            if (!Directory.Exists(binDir) || new DirectoryInfo(binDir).GetFiles().Length == 0)
            {
                sb.AppendLine(binDir);
                binDir = (Utility.GetSourceDirectory(ctx, state) + @"\bin").Replace(@"\\", @"\");
                if (!Directory.Exists(binDir) || new DirectoryInfo(binDir).GetFiles().Length == 0)
                {
                    sb.AppendLine(binDir);
                    throw new InvalidOperationException("BinDirectory not found.  Checked the following: " + sb.ToString());
                }
            }

            return(binDir);
        }
Example #10
0
        public static string GetTargetDirectory(InstallContext ctx, IDictionary state, string appName)
        {
            string ret = null;

            // pull from context if possible
            if (ctx != null)
            {
                ret = ctx.Parameters["tgt"];
                if (String.IsNullOrEmpty(ret))
                {
                    ret = ctx.Parameters["TARGETDIR"];
                }
            }

            if (state != null && String.IsNullOrEmpty(ret))
            {
                ret = state["TARGETDIR"] as string;
            }

            if (String.IsNullOrEmpty(ret))
            {
                // look to the registry if we can't glean it from the context
                ret = Registry.GetValue(RootRegistryKey + @"\" + appName, "InstallDir", "") as string;
                if (String.IsNullOrEmpty(ret))
                {
                    // and finally the current directory as a last-ditch effort
                    ret = Environment.CurrentDirectory;
                }
            }
            if (ctx != null)
            {
                ctx.Parameters["tgt"] = ret;
            }
            return(ret);
        }
Example #11
0
        public static string GetSourceDirectory(InstallContext ctx, IDictionary state)
        {
            string ret = null;

            if (ctx != null)
            {
                ret = ctx.Parameters["src"];
                if (String.IsNullOrEmpty(ret))
                {
                    ret = ctx.Parameters["SOURCEDIR"];
                }
            }


            if (String.IsNullOrEmpty(ret) && state != null)
            {
                ret = state["SOURCEDIR"] as string;
            }

            if (String.IsNullOrEmpty(ret))
            {
                ret = Registry.GetValue(RootRegistryKey, "SourceDir", "") as string;
            }

            if (ctx != null)
            {
                ctx.Parameters["src"] = ret;
            }
            return(ret);
        }
Example #12
0
        public string hash_file(string filePath)
        {
            if (!_fileSystem.file_exists(filePath))
            {
                return(string.Empty);
            }

            try
            {
                var hash = _hashAlgorithm.ComputeHash(_fileSystem.read_file_bytes(filePath));

                return(BitConverter.ToString(hash).Replace("-", string.Empty));
            }
            catch (IOException ex)
            {
                this.Log().Warn(() => "Error computing hash for '{0}'{1} Hash will be special code for locked file or file too big instead.{1} Captured error:{1}  {2}".format_with(
                                    InstallContext.NormalizeMessage(filePath), Environment.NewLine, InstallContext.NormalizeMessage(ex.Message)));

                if (file_is_locked(ex))
                {
                    return(ApplicationParameters.HashProviderFileLocked);
                }

                //IO.IO_FileTooLong2GB (over Int32.MaxValue)
                return(ApplicationParameters.HashProviderFileTooBig);
            }
        }
Example #13
0
    public static void ProcessArguments(string[] args)
    {
        // IMPORTANT: Make sure this class don't have any static references to x360ce.Engine library or
        // program tries to load x360ce.Engine.dll before AssemblyResolve event is available and fails.
        AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
        //for (int i = 0; i < args.Length; i++)
        // Console.WriteLine(string.Format("{0}. {1}", i, args[i]));
        // Requires System.Configuration.Installl reference.
        var ic          = new InstallContext(null, args);
        var script      = ic.Parameters["s"];
        var environment = ic.Parameters["a"];
        var scriptFile  = new FileInfo(script);
        var scriptName  = System.IO.Path.GetFileNameWithoutExtension(scriptFile.Name);

        // Show parameters
        Console.Title = string.Format("{0} Script", scriptName);
        Console.WriteLine("Searching. Please wait...");
        var transforms = GetTransforms(scriptFile.Directory.FullName);

        if (string.IsNullOrEmpty(environment))
        {
            environment = ShowEnvironmentPrompt(transforms);
            // Return if no answer.
            if (string.IsNullOrEmpty(environment))
            {
                return;
            }
        }
        TransformFolder(transforms, environment);
    }
        public ManageHealthManagerService()
        {
            base.Account     = ServiceAccount.LocalSystem;
            base.StartMode   = ServiceStartMode.Automatic;
            base.DisplayName = Strings.HealthManagerServiceDisplayName;
            base.Description = Strings.HealthManagerServiceDescription;
            InstallContext installContext = new InstallContext();

            installContext.Parameters["logtoconsole"] = "false";
            installContext.Parameters["assemblypath"] = Path.Combine(ConfigurationContext.Setup.BinPath, "MSExchangeHMHost.exe");
            base.FirstFailureActionType      = ServiceActionType.Restart;
            base.FirstFailureActionDelay     = 5000U;
            base.SecondFailureActionType     = ServiceActionType.Restart;
            base.SecondFailureActionDelay    = 5000U;
            base.AllOtherFailuresActionType  = ServiceActionType.Restart;
            base.AllOtherFailuresActionDelay = 5000U;
            base.FailureResetPeriod          = 0U;
            base.ServiceInstallContext       = installContext;
            base.ServicesDependedOn          = new string[]
            {
                "eventlog",
                "MSExchangeADTopology"
            };
            base.EventMessageFile = Path.Combine(ConfigurationContext.Setup.ResPath, "Microsoft.Exchange.ActiveMonitoring.EventLog.dll");
            base.CategoryCount    = 2;
        }
Example #15
0
        public void RunPrecompiler()
        {
            var appBase    = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
            var targetFile = Path.Combine(appBase, "RunPrecompiler.dll");

            File.Delete(targetFile);

            var parent     = new ParentInstaller();
            var precompile = new PrecompileInstaller();

            precompile.TargetAssemblyFile = targetFile;
            precompile.ViewPath           = "MonoRail.Tests.Views";
            precompile.DescribeBatch     += ((sender, e) => e.Batch.For <StubController>().Include("*").Include("_*"));

            var context = new InstallContext();
            var state   = new Hashtable();

            parent.Installers.Add(precompile);
            parent.Install(state);
            parent.Commit(state);

            Assert.That(File.Exists(targetFile), "File exists");

            var result = Assembly.LoadFrom(targetFile);

            Assert.AreEqual(3, result.GetTypes().Count());
        }
Example #16
0
        protected void next_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(this.account.Text) ||
                (!IsDC &&
                 (string.IsNullOrWhiteSpace(this.password.Text) ||
                  this.password.Text.Trim().Length < 6)))
            {
                this.AjaxPage.PageEngine.ShowMessageBox("参数设定错误");
                this.AjaxPage.PageEngine.UpdateControlRender(this);
                return;
            }
#if !DEBUG
            try
            {
#endif
            InstallContext.Settings["account"]  = this.account.Text.Trim();
            InstallContext.Settings["password"] = this.password.Text.Trim();
            InstallContext.Save();
            this.InstallPage.NextStep();
#if !DEBUG
        }

        catch (Exception ex)
        {
            this.AjaxPage.PageEngine.ShowMessageBox(ex.Message);
            this.AjaxPage.PageEngine.UpdateControlRender(this);
        }
#endif
        }
        public static bool StartService(InstallContext context)
        {
            bool result = true;

            try
            {
                ServiceController controller = new ServiceController(GlobalConstants.ServiceName);

                if(controller.Status != ServiceControllerStatus.Stopped)
                {
                    throw new Exception(string.Format("Can't start the service because it is in the '{0}' state.", controller.Status.ToString()));
                }

                controller.Start();
                LogMessage("Service started successfully.", context);
                LogMessage("Setting Recovery Options.", null);
                SetRecoveryOptions();
                LogMessage("Recovery Options successfully set.", null);
            }
            catch(Exception ex)
            {
                result = false;
                LogMessage("An error occurred while starting the service, please start it manually or reboot the computer.", context);
                WriteExceptions(ex, context);
            }

            return result;
        }
Example #18
0
        protected ManageFileDistributionService()
        {
            base.Account     = ServiceAccount.LocalSystem;
            base.StartMode   = ServiceStartMode.Automatic;
            base.DisplayName = Strings.FDServiceDisplayName;
            base.Description = Strings.FDServiceDescription;
            InstallContext installContext = new InstallContext();

            installContext.Parameters["logtoconsole"] = "false";
            installContext.Parameters["assemblypath"] = Path.Combine(ConfigurationContext.Setup.BinPath, "MSExchangeFDS.exe");
            base.EventMessageFile            = Path.Combine(ConfigurationContext.Setup.ResPath, "Microsoft.Exchange.Data.FileDistributionService.EventLog.dll");
            base.CategoryCount               = 2;
            base.FirstFailureActionDelay     = 5000U;
            base.FirstFailureActionType      = ServiceActionType.Restart;
            base.SecondFailureActionType     = ServiceActionType.Restart;
            base.SecondFailureActionDelay    = 5000U;
            base.AllOtherFailuresActionType  = ServiceActionType.Restart;
            base.AllOtherFailuresActionDelay = 5000U;
            base.FailureActionsFlag          = true;
            base.FailureResetPeriod          = 0U;
            base.ServiceInstallContext       = installContext;
            base.ServicesDependedOn          = new string[]
            {
                ManageFileDistributionService.ActiveDirectoryTopologyService,
                "lanmanworkstation"
            };
            base.ServiceInstallContext          = installContext;
            base.ServiceInstaller.AfterInstall += this.AfterInstallEventHandler;
        }
        protected ManageADTopologyService()
        {
            base.Account     = ServiceAccount.LocalSystem;
            base.StartMode   = ServiceStartMode.Automatic;
            base.DisplayName = Strings.ADTopologyServiceDisplayName;
            base.Description = Strings.ADTopologyServiceDescription;
            InstallContext installContext = new InstallContext();

            installContext.Parameters["logtoconsole"] = "false";
            installContext.Parameters["assemblypath"] = Path.Combine(ConfigurationContext.Setup.BinPath, "Microsoft.Exchange.Directory.TopologyService.exe");
            base.FirstFailureActionType      = ServiceActionType.Restart;
            base.FirstFailureActionDelay     = 5000U;
            base.SecondFailureActionType     = ServiceActionType.Restart;
            base.SecondFailureActionDelay    = 5000U;
            base.AllOtherFailuresActionType  = ServiceActionType.Restart;
            base.AllOtherFailuresActionDelay = 5000U;
            base.FailureResetPeriod          = 0U;
            base.ServiceInstallContext       = installContext;
            List <string> list = new List <string>
            {
                "NetTcpPortSharing"
            };

            base.ServicesDependedOn = list.ToArray();
            base.AddFirewallRule(new MSExchangeADTopologyWCFFirewallRule());
        }
Example #20
0
        static TransactedInstaller CreateTransactedInstaller(Installer installer)
        {
            var transactedInstaller = new TransactedInstaller();

            transactedInstaller.Installers.Add(installer);

            Assembly assembly = Assembly.GetEntryAssembly();

            if (assembly == null)
            {
                throw new TopshelfException("Assembly.GetEntryAssembly() is null for some reason.");
            }

#if NETCORE
// Must run off Self Contained Deployment
            string path = $"/assemblypath={assembly.Location.Replace(".dll", ".exe")}";
#else
            string path = $"/assemblypath={assembly.Location}";
#endif
            string[] commandLine = { path };

            var context = new InstallContext(null, commandLine);
            transactedInstaller.Context = context;

            return(transactedInstaller);
        }
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        private static void Main(string[] args)
        {
            NameValueCollection appSettings = ConfigurationManager.AppSettings;

            appSettings.Set("GentleConfigFile", String.Format(@"{0}\gentle.config", PathManager.GetDataPath));

            string opt = null;

            if (args.Length >= 1)
            {
                opt = args[0];
            }

            if (opt != null && opt.ToUpperInvariant() == "/INSTALL")
            {
                TransactedInstaller ti = new TransactedInstaller();
                ProjectInstaller    mi = new ProjectInstaller();
                ti.Installers.Add(mi);
                String path = String.Format("/assemblypath={0}",
                                            System.Reflection.Assembly.GetExecutingAssembly().Location);
                String[]       cmdline = { path };
                InstallContext ctx     = new InstallContext("", cmdline);
                ti.Context = ctx;
                ti.Install(new Hashtable());
                return;
            }
            if (opt != null && opt.ToUpperInvariant() == "/UNINSTALL")
            {
                TransactedInstaller ti = new TransactedInstaller();
                ProjectInstaller    mi = new ProjectInstaller();
                ti.Installers.Add(mi);
                String path = String.Format("/assemblypath={0}",
                                            System.Reflection.Assembly.GetExecutingAssembly().Location);
                String[]       cmdline = { path };
                InstallContext ctx     = new InstallContext("", cmdline);
                ti.Context = ctx;
                ti.Uninstall(null);
                return;
            }
            // When using /DEBUG switch (in visual studio) the TvService is not run as a service
            // Make sure the real TvService is disabled before debugging with /DEBUG
            if (opt != null && opt.ToUpperInvariant() == "/DEBUG")
            {
                Service1 s = new Service1();
                s.DoStart(new string[] { "/DEBUG" });
                do
                {
                    Thread.Sleep(100);
                } while (true);
            }

            // More than one user Service may run within the same process. To add
            // another service to this process, change the following line to
            // create a second service object. For example,
            //
            //   ServicesToRun = new ServiceBase[] {new Service1(), new MySecondUserService()};
            //
            ServiceBase[] ServicesToRun = new ServiceBase[] { new Service1() };
            ServiceBase.Run(ServicesToRun);
        }
Example #22
0
        private static void InstallService()
        {
            ProjectInstaller pi = null;

            try
            {
                pi = new ProjectInstaller();

                string path = string.Format(CultureInfo.InvariantCulture,
                                            PathArgument,
                                            System.Reflection.Assembly.GetExecutingAssembly().Location);

                string[] cmdline = { path, "LogToConsole" };

                System.IO.File.Delete(InstallLogfile);

                InstallContext ctx = new InstallContext(InstallLogfile, cmdline);
                pi.Context = ctx;

                pi.Install(new Hashtable());
            }
            catch (Exception exp)
            {
                Console.WriteLine(exp.ToString());
            }
            finally
            {
                if (null != pi)
                {
                    pi.Dispose();
                }
            }
        }
        protected ManageRecoveryActionArbiterService()
        {
            base.Account     = ServiceAccount.LocalSystem;
            base.StartMode   = ServiceStartMode.Automatic;
            base.DisplayName = Strings.RecoveryActionArbiterServiceDisplayName;
            base.Description = Strings.RecoveryActionArbiterServiceDescription;
            InstallContext installContext = new InstallContext();

            installContext.Parameters["logtoconsole"] = "false";
            installContext.Parameters["assemblypath"] = Path.Combine(ConfigurationContext.Setup.BinPath, "Microsoft.Forefront.RecoveryActionArbiter.RaaService.exe");
            base.FirstFailureActionType      = ServiceActionType.Restart;
            base.FirstFailureActionDelay     = 5000U;
            base.SecondFailureActionType     = ServiceActionType.Restart;
            base.SecondFailureActionDelay    = 5000U;
            base.AllOtherFailuresActionType  = ServiceActionType.Restart;
            base.AllOtherFailuresActionDelay = 5000U;
            base.ServiceInstallContext       = installContext;
            base.CategoryCount    = 1;
            base.EventMessageFile = Path.Combine(ConfigurationContext.Setup.BinPath, "Microsoft.Forefront.RecoveryActionArbiter.RaaServiceMsg.dll");
            List <string> list = new List <string>
            {
                "NetTcpPortSharing"
            };

            base.ServicesDependedOn = list.ToArray();
        }
Example #24
0
        public virtual void Install(string serviceName)
        {
            _logger.Info("Installing service '{0}'", serviceName);


            var installer = new ServiceProcessInstaller
            {
                Account = ServiceAccount.LocalSystem
            };

            var serviceInstaller = new ServiceInstaller();


            String[] cmdline = { @"/assemblypath=" + Process.GetCurrentProcess().MainModule.FileName };

            var context = new InstallContext("service_install.log", cmdline);

            serviceInstaller.Context            = context;
            serviceInstaller.DisplayName        = serviceName;
            serviceInstaller.ServiceName        = serviceName;
            serviceInstaller.Description        = "NzbDrone Application Server";
            serviceInstaller.StartType          = ServiceStartMode.Automatic;
            serviceInstaller.ServicesDependedOn = new[] { "EventLog", "Tcpip" };

            serviceInstaller.Parent = installer;

            serviceInstaller.Install(new ListDictionary());

            _logger.Info("Service Has installed successfully.");
        }
Example #25
0
        /// <summary>
        /// Updates the config files.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="action">The action.</param>
        /// <param name="target">The target.</param>
        private static void UpdateConfigFiles(InstallContext context, string action, string target)
        {
            ArrayList li = new ArrayList();

            //context.LogMessage("Enter Method UpdateConfigFiles with: " + (string.IsNullOrEmpty(action) ? "action is null or empty" : action));
            //if (!string.IsNullOrEmpty(action) && "install".Equals(action) && !string.IsNullOrEmpty(target))
            //{
            //  DirectoryInfo dir = new DirectoryInfo(target);

            //  foreach (FileInfo fi in dir.GetFiles("*.config"))
            //  {
            //    li.Add(string.Format("Name: {0} - FullName: {1}", fi.Name, fi.FullName));
            //    string path = target + fi.Name;
            //    XmlDocument doc = new XmlDocument();
            //    doc.Load(path);

            //    XmlNodeList nodes = doc.SelectNodes("/configuration/replicatedSharedCache/serverSetting/@ServiceCacheIpAddress");
            //    if (nodes != null)
            //    {
            //      nodes[0].Value = COM.Handler.Network.GetFirstIPAddress().ToString();
            //      doc.Save(path);
            //    }
            //  }
            //}

            //context.LogMessage("Exit Method UpdateConfigFiles");

            //CreateTextFileWithAdaptedConfigEntries(li);
        }
Example #26
0
        public static void InstallService(string serviceName, string customArg)
        {
            try
            {
                var savedState = new Hashtable();

                var installContext = new InstallContext(Path.ChangeExtension(ExecutablePath, ".InstallLog"), new[] { string.Empty });
                installContext.Parameters["assemblypath"] = string.IsNullOrEmpty(customArg) ? ExecutablePath :
                                                            ExecutablePath + " \"" + customArg + "\"";

                var hostServiceInstaller = new HostServiceInstaller(serviceName)
                {
                    Context = installContext
                };
                hostServiceInstaller.Install(savedState);
                hostServiceInstaller.Commit(savedState);
            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Service install failed:");
                Console.WriteLine(ex);
                Console.ResetColor();
            }
        }
Example #27
0
        void WriteFileContext(string path)
        {
            string fileContent;

            if (!File.Exists(path))
            {
                return;
            }

            if (Path.GetExtension(path) == Constants.PackageExtension)
            {
                var pkg  = new OptimizedZipPackage(path);
                var ver1 = pkg.Version.ToString();
                var ver2 = pkg.Version.Version.ToString();
                if (ver1 == ver2 || $"{ver1}.0" == ver2)
                {
                    fileContent = ver2;
                }
                else
                {
                    fileContent = $"{ver1} (normalized: {ver2})";
                }
            }
            else
            {
                fileContent = File.ReadAllText(path);
            }

            string shortPath = InstallContext.NormalizeMessage(path);

            LogService.console.Info($"{shortPath}: {fileContent}");
        }
Example #28
0
        private void InstallService()
        {
            Logger.Write("Installing service.");
            ProgressMessageChanged?.Invoke(this, "Installing Remotely service.");
            var serv = ServiceController.GetServices().FirstOrDefault(ser => ser.ServiceName == "Remotely_Service");

            if (serv == null)
            {
                var command          = new string[] { "/assemblypath=" + Path.Combine(InstallPath, "Remotely_Agent.exe") };
                var context          = new InstallContext("", command);
                var serviceInstaller = new ServiceInstaller()
                {
                    Context          = context,
                    DisplayName      = "Remotely Service",
                    Description      = "Background service that maintains a connection to the Remotely server.  The service is used for remote support and maintenance by this computer's administrators.",
                    ServiceName      = "Remotely_Service",
                    StartType        = ServiceStartMode.Automatic,
                    DelayedAutoStart = true,
                    Parent           = new ServiceProcessInstaller()
                };

                var state = new System.Collections.Specialized.ListDictionary();
                serviceInstaller.Install(state);
                Logger.Write("Service installed.");
                serv = ServiceController.GetServices().FirstOrDefault(ser => ser.ServiceName == "Remotely_Service");

                ProcessEx.StartHidden("cmd.exe", "/c sc.exe failure \"Remotely_Service\" reset= 5 actions= restart/5000");
            }
            if (serv.Status != ServiceControllerStatus.Running)
            {
                serv.Start();
            }
            Logger.Write("Service started.");
        }
        public void ItPersistsArgumentsInFile(
            string adminUsername, string adminPassword, string containerDirectory, string machineIp, string syslogHostIp, string syslogPort, string machineName)
        {
            using (var tempDirectory = new TempDirectory())
            {
                var configurationManager = new ConfigurationManagerTest();
                var context = new InstallContext();
                context.Parameters.Add("ADMIN_USERNAME", adminUsername);
                context.Parameters.Add("ADMIN_PASSWORD", adminPassword);
                context.Parameters.Add("CONTAINER_DIRECTORY", containerDirectory);
                context.Parameters.Add("MACHINE_IP", machineIp);
                context.Parameters.Add("SYSLOG_HOST_IP", syslogHostIp);
                context.Parameters.Add("SYSLOG_PORT", syslogPort);
                context.Parameters.Add("assemblypath", tempDirectory.ToString());
                context.Parameters.Add("MACHINE_NAME", machineName);
                configurationManager.Context = context;
                configurationManager.OnBeforeInstall(null);

                var javaScriptSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
                var jsonString           = File.ReadAllText(Path.Combine(tempDirectory.ToString(), @"..\parameters.json"));
                var hash = javaScriptSerializer.Deserialize <Dictionary <string, string> >(jsonString);
                Assert.False(hash.ContainsKey("ADMIN_PASSWORD"));
                Assert.Equal(hash["CONTAINER_DIRECTORY"], containerDirectory);
                Assert.Equal(hash["MACHINE_IP"], machineIp);
                Assert.Equal(hash["SYSLOG_HOST_IP"], syslogHostIp);
                Assert.Equal(hash["SYSLOG_PORT"], syslogPort);
                Assert.Equal(hash["MACHINE_NAME"], machineName);
            }
        }
Example #30
0
        private static void DoUninstall(IDictionary <string, string> options)
        {
            String serviceName = options[OPT_SERVICE_NAME];

            if (serviceName != null)
            {
                ProjectInstaller.ServiceName = serviceName;
            }
            TransactedInstaller ti = new TransactedInstaller();

            string[] cmdline =
            {
                Assembly.GetExecutingAssembly().Location
            };
            AssemblyInstaller ai = new AssemblyInstaller(
                cmdline[0],
                new string[0]);

            ti.Installers.Add(ai);
            InstallContext ctx = new InstallContext("uninstall.log",
                                                    cmdline);

            ti.Context = ctx;
            ti.Uninstall(null);
        }
Example #31
0
	static void Perform (bool install, string executable)
	{
		ArrayList order = new ArrayList ();
		Hashtable states = new Hashtable ();
		
		try {
			Assembly a;

			if (assembly != null)
				a = Assembly.Load (assembly);
			else
				a = Assembly.LoadFrom (executable);
			
			Type [] types = a.GetTypes ();

			// todo: pass arguments, they are kind of useless though.
			InstallContext ctx = new InstallContext ();
			
			foreach (Type t in types){
				if (!t.IsSubclassOf (typeof (Installer)))
					continue;

				object [] attrs = t.GetCustomAttributes (typeof (RunInstallerAttribute), false);
				if (attrs == null || attrs.Length == 0)
					continue;

				RunInstallerAttribute ria = attrs [0] as RunInstallerAttribute;
				if (ria == null || !ria.RunInstaller)
					continue;

				try {
					Installer installer = (Installer) Activator.CreateInstance (t);
					Hashtable state = new Hashtable ();
					
					order.Add (installer);
					states [installer] = state;
					
					if (install)
						Call (installer, "OnBeforeInstall", state);
					else
						Call (installer, "OnBeforeUninstall", state);
					
					installer.Install (state);

					if (install)
						Call (installer, "OnAfterInstall", state);
					else
						Call (installer, "OnAfterUninstall", state);
					
				} catch (Exception e) {
					Error (String.Format ("Can not create installer of type {0}", t));
					
					//
					// According to the docs uninstall should not do rollback
					//
					if (install){
						foreach (Installer installer in order){
							Hashtable state = (Hashtable) states [installer];
								
							Call (installer, "OnBeforeRollback", state);
							installer.Rollback (state);
							Call (installer, "OnAfterRollback", state);
						}
					}
				}
			}
			//
			// Got it, now commit them
			//
			if (install){
				foreach (Installer inst in order){
					Hashtable state = (Hashtable) states [inst];
					
					Call (inst, "OnCommitting", state);
					inst.Commit (state);
					Call (inst, "OnCommitted", state);
				}
			}
		} catch {
			Error (String.Format ("Unable to load assembly {0}", assembly));
		}		
	}
		private void ScriptIndexes(InstallContext context, SchemaObject schemaObject, string columnName = null)
		{
			// get the indexes and constraints on a table
			// NOTE: we don't script system named indexes because we assume they are specified as part of the table definition
			// NOTE: order by type: do the clustered indexes first because they also drop nonclustered indexes if the object is a view (not a table)

			// generate some sql to determine the proper index
			string sql = @"SELECT ObjectID=i.object_id, IndexID=i.index_id,
				Name=QUOTENAME(i.name), 
				TableName=QUOTENAME(OBJECT_SCHEMA_NAME(o.object_id)) + '.' + QUOTENAME(OBJECT_NAME(o.object_id)), 
				Type=i.type_desc, IsUnique=i.is_unique, IsConstraint=CONVERT(bit, CASE WHEN k.object_id IS NOT NULL THEN 1 ELSE 0 END), IsPrimaryKey=CONVERT(bit, CASE WHEN k.type_desc = 'PRIMARY_KEY_CONSTRAINT' THEN 1 ELSE 0 END), DataSpace=";
			sql += context.IsAzure ? "NULL" : "ISNULL(f.name, p.name)";

			// get the data for the dependent indexes
			if (schemaObject.SchemaObjectType == SchemaObjectType.Index)
			{
				sql += @" FROM sys.indexes currentindex
						JOIN sys.indexes i ON (currentindex.object_id = i.object_id AND currentindex.index_id <> i.index_id)
						JOIN sys.objects o ON (i.object_id = o.object_id)
						LEFT JOIN sys.key_constraints k ON (o.object_id = k.parent_object_id AND i.index_id = k.unique_index_id AND is_system_named = 0)";
			}
			else
			{
				sql += @" FROM sys.indexes i
						JOIN sys.objects o ON (i.object_id = o.object_id)
						LEFT JOIN sys.key_constraints k ON (o.object_id = k.parent_object_id AND i.index_id = k.unique_index_id AND is_system_named = 0)";
			}

			// SQL Server may put the index on different filegroups
			if (!context.IsAzure)
			{
				sql += @" LEFT JOIN sys.partition_schemes p ON (i.data_space_id = p.data_space_id) 
						LEFT JOIN sys.filegroups f ON (i.data_space_id = f.data_space_id)";
			}

			// add the where clause
			if (schemaObject.SchemaObjectType == SchemaObjectType.Index)
			{
				sql += @" WHERE currentindex.object_id = OBJECT_ID(@ObjectName) AND currentIndex.type_desc = 'CLUSTERED' AND i.name IS NOT NULL";
			}
			else
			{
				sql += @" WHERE o.object_id = OBJECT_ID(@ObjectName) AND i.Name IS NOT NULL";
			}

			// filter by column if appropriate
			if (columnName != null)
			{
				sql += @" AND i.index_id IN (SELECT index_id 
								FROM sys.index_columns ic
								JOIN sys.columns c ON (c.object_id = ic.object_id AND c.column_id = ic.column_id)
								WHERE ic.object_id = OBJECT_ID(@ObjectName) AND c.name = @ColumnName)";
			}
			sql += @" ORDER BY Type";

			// find the indexes on the table
			var indexes = _connection.QuerySql(
				sql,
				new Dictionary<string, object>()
				{
					{ "ObjectName", schemaObject.SqlName.FullName }, 
					{ "ColumnName", columnName } 
				});
			foreach (dynamic index in indexes)
			{
				// get the columns in the key from the database
				var columns = _connection.QuerySql(@"
					SELECT ColumnName=c.name
					FROM sys.indexes i
					JOIN sys.index_columns ic ON (i.object_id = ic.object_id AND i.index_id = ic.index_id)
					JOIN sys.columns c ON (ic.object_id = c.object_id AND ic.column_id = c.column_id)
					WHERE i.object_id = @ObjectID AND i.index_id = @IndexID",
					new Dictionary<string, object>()
					{
						{ "ObjectID", index.ObjectID },
						{ "IndexID", index.IndexID },
					});

				StringBuilder sb = new StringBuilder();
				if (index.IsConstraint)
				{
					sb.AppendFormat("ALTER TABLE {3} ADD CONSTRAINT {2} {0}{1} (",
						index.IsPrimaryKey ? "PRIMARY KEY " : index.IsUnique ? "UNIQUE " : "",
						index.Type,
						index.Name,
						index.TableName);
				}
				else
				{
					sb.AppendFormat("CREATE {0}{1} INDEX {2} ON {3} (",
						index.IsUnique ? "UNIQUE " : "",
						index.Type,
						index.Name,
						index.TableName);
				}
				sb.Append(String.Join(",", columns.Select((dynamic c) => SqlParser.FormatSqlName(c.ColumnName))));
				sb.Append(")");

				// if the index is on another filegroup or partition scheme, add that
				if (index.DataSpace != null)
				{
					sb.AppendFormat(" ON {0}", SqlParser.FormatSqlName(index.DataSpace));

					// get the partition columns (this will be empty for non-partitioned indexes)
					if (!context.IsAzure)
					{
						var partitionColumns = _connection.QuerySql(@"
								SELECT ColumnName=c.name
								FROM sys.index_columns ic
								JOIN sys.columns c ON (ic.object_id = c.object_id AND ic.column_id = c.column_id)
								JOIN sys.indexes i ON (i.object_id = ic.object_id AND i.index_id = ic.index_id)
								WHERE i.object_id = @ObjectID AND i.index_id = @IndexID AND ic.partition_ordinal <> 0
								ORDER BY ic.partition_ordinal",
							new Dictionary<string, object>()
							{ 
								{ "ObjectID", index.ObjectID },
								{ "IndexID", index.IndexID }
							});

						if (partitionColumns.Any())
						{
							sb.Append("(");
							sb.Append(String.Join(",", partitionColumns.Select((dynamic p) => p.ColumnName)));
							sb.Append(")");
						}
					}
				}

				var dropObject = new SchemaObject(sb.ToString());

				ScriptUpdate(context, dropObject);
			}
		}
		/// <summary>
		/// Script the standard dependencies such as stored procs and triggers.
		/// </summary>
		/// <param name="context">The installation context.</param>
		/// <param name="schemaObject">The schemaObject to script.</param>
		private void ScriptStandardDependencies(InstallContext context, SchemaObject schemaObject)
		{
			// can only script dependencies for objects with names
			if (schemaObject.SqlName.SchemaQualifiedObject == null)
				return;

			// find all of the dependencies on the object
			// this will find things that use views or tables
			// note that there will be more than one dependency if more than one column is referenced
			// ignore USER_TABLE, since that is calculated columns
			// for CHECK_CONSTRAINTS, ignore system-named constraints, since they are part of the table and will be handled there
			var dependencies = _connection.QuerySql(@"
				SELECT DISTINCT
					Name = QUOTENAME(OBJECT_SCHEMA_NAME(o.object_id)) + '.' + QUOTENAME(OBJECT_NAME(o.object_id)),
					SqlType = o.type_desc, IsSchemaBound=d.is_schema_bound_reference
				FROM sys.sql_expression_dependencies d
				JOIN sys.objects o ON (d.referencing_id = o.object_id)
				LEFT JOIN sys.check_constraints c ON (o.object_id = c.object_id)
				WHERE ISNULL(c.is_system_named, 0) = 0 AND
					o.type_desc <> 'USER_TABLE' AND 
					(o.parent_object_id = OBJECT_ID(@QualifiedName) OR
					d.referenced_id =
						CASE WHEN d.referenced_class_desc = 'TYPE' THEN 
							(SELECT user_type_id 
							FROM sys.types t JOIN sys.schemas s ON (t.schema_id = s.schema_id)
							WHERE s.name = @SchemaName AND t.name = @ObjectName)
						ELSE OBJECT_ID(@QualifiedName)
					END)",
				new Dictionary<string, object>()
				{
					{ "QualifiedName", schemaObject.SqlName.SchemaQualifiedObject },
					{ "SchemaName", schemaObject.SqlName.Schema },
					{ "ObjectName", schemaObject.SqlName.Object },
				});

			foreach (dynamic dependency in dependencies)
			{
				// we only have to update schemabound dependencies
				if (schemaObject.SchemaObjectType == SchemaObjectType.Table && !dependency.IsSchemaBound)
					continue;

				// since the object isn't already being dropped, create a new SchemaObject for it and rebuild that
				SchemaObject dropObject = null;
				string dependencyType = dependency.SqlType;
				string dependencyName = dependency.Name;

				switch (dependencyType)
				{
					case "SQL_STORED_PROCEDURE":
					case "SQL_SCALAR_FUNCTION":
					case "SQL_TABLE_VALUED_FUNCTION":
					case "SQL_TRIGGER":
					case "VIEW":
						// these objects can be rebuilt from the definition of the object in the database
						dropObject = new SchemaObject(_connection.ExecuteScalarSql<string>("SELECT definition FROM sys.sql_modules WHERE object_id = OBJECT_ID(@Name)", new Dictionary<string, object>() { { "Name", dependencyName } }));
						break;

					case "CHECK_CONSTRAINT":
						// need to do a little work to re-create the check constraint
						dynamic checkConstraint = _connection.QuerySql(@"
							SELECT TableName=QUOTENAME(OBJECT_SCHEMA_NAME(o.object_id)) + '.' + QUOTENAME(OBJECT_NAME(o.object_id)),
							ConstraintName=c.name, Definition=c.definition
							FROM sys.check_constraints c
							JOIN sys.objects o ON (c.parent_object_id = o.object_id) WHERE c.object_id = OBJECT_ID(@Name)",
							new Dictionary<string, object>() { { "Name", dependencyName } }).First();

						dropObject = new SchemaObject(String.Format(
							"ALTER TABLE {0} ADD CONSTRAINT {1} CHECK {2}",
							SqlParser.FormatSqlName(checkConstraint.TableName),
							SqlParser.FormatSqlName(checkConstraint.ConstraintName),
							checkConstraint.Definition));
						break;

					default:
						throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Cannot generate dependencies for object {0}.", dependencyName));
				}

				ScriptUpdate(context, dropObject);
			}
		}
		private void ScriptForeignKeys(InstallContext context, SchemaObject schemaObject)
		{
			IList<FastExpando> foreignKeys = null;

			if (schemaObject.SchemaObjectType == SchemaObjectType.PrimaryKey)
			{
				foreignKeys = _connection.QuerySql(@"
					SELECT ObjectID=f.object_id, Name=f.name, 
					TableName=QUOTENAME(OBJECT_SCHEMA_NAME(o.object_id)) + '.' + QUOTENAME(OBJECT_NAME(o.object_id)),
					RefTableName=QUOTENAME(OBJECT_SCHEMA_NAME(ro.object_id)) + '.' + QUOTENAME(OBJECT_NAME(ro.object_id)),
					DeleteAction=delete_referential_action_desc, UpdateAction=update_referential_action_desc
					FROM sys.foreign_keys f
					JOIN sys.key_constraints k ON (f.referenced_object_id = k.parent_object_id)
					JOIN sys.objects o ON (f.parent_object_id = o.object_id)
					JOIN sys.objects ro ON (k.parent_object_id = ro.object_id)
					WHERE k.parent_object_id = OBJECT_ID(@ObjectID)",
				new Dictionary<string, object>() { { "ObjectID", schemaObject.SqlName.SchemaQualifiedTable } });
			}

			foreach (dynamic foreignKey in foreignKeys)
			{
				// get the columns in the key from the database
				var columns = _connection.QuerySql(@"
						SELECT FkColumnName=fc.name, PkColumnName=kc.name
						FROM sys.foreign_key_columns f
						JOIN sys.columns fc ON (f.parent_object_id = fc.object_id AND f.parent_column_id = fc.column_id)
						JOIN sys.columns kc ON (f.referenced_object_id = kc.object_id AND f.referenced_column_id = kc.column_id)
						WHERE f.constraint_object_id = @KeyID",
					new Dictionary<string, object>() { { "KeyID", foreignKey.ObjectID } });

				StringBuilder sb = new StringBuilder();
				sb.AppendFormat("ALTER TABLE {0} ADD CONSTRAINT {1} FOREIGN KEY (",
						SqlParser.FormatSqlName(foreignKey.TableName),
						SqlParser.FormatSqlName(foreignKey.Name));
				sb.Append(String.Join(",", columns.Select((dynamic c) => SqlParser.FormatSqlName(c.FkColumnName))));
				sb.AppendFormat(") REFERENCES {0} (", SqlParser.FormatSqlName(foreignKey.RefTableName));
				sb.Append(String.Join(",", columns.Select((dynamic c) => SqlParser.FormatSqlName(c.PkColumnName))));
				sb.AppendFormat(") ON DELETE {0} ON UPDATE {1}", foreignKey.DeleteAction.Replace("_", " "), foreignKey.UpdateAction.Replace("_", " "));

				var dropObject = new SchemaObject(sb.ToString());

				ScriptUpdate(context, dropObject);
			}
		}
		private void ScriptColumnsAndConstraints(InstallContext context, SchemaObject schemaObject, string oldTableName, string newTableName)
		{
			#region Detect Column Changes
			Func<dynamic, dynamic, bool> compareColumns = (dynamic c1, dynamic c2) => (String.Compare(c1.Name, c2.Name, StringComparison.OrdinalIgnoreCase) == 0);
			Func<dynamic, dynamic, bool> areColumnsEqual = (dynamic c1, dynamic c2) =>
				c1.TypeName == c2.TypeName &&
				c1.MaxLength == c2.MaxLength &&
				c1.Precision == c2.Precision &&
				c1.Scale == c2.Scale &&
				c1.IsNullable == c2.IsNullable &&
				c1.IsIdentity == c2.IsIdentity &&
				c1.IdentitySeed == c2.IdentitySeed &&
				c1.IdentityIncrement == c2.IdentityIncrement &&
				c1.Definition == c2.Definition
				;
			Func<dynamic, dynamic, bool> areDefaultsEqual = (dynamic c1, dynamic c2) =>
				((String.Compare(c1.DefaultName, c2.DefaultName, StringComparison.OrdinalIgnoreCase) == 0) || (c1.DefaultIsSystemNamed == true && c2.DefaultIsSystemNamed == true)) &&
				c1.DefaultDefinition == c2.DefaultDefinition
				;
			Func<dynamic, string> getConstraintName = (dynamic c) => new SqlName(oldTableName, 2).Append(c.Name).FullName;

			// get the columns for each of the tables
			var oldColumns = GetColumnsForTable(oldTableName);
			var newColumns = GetColumnsForTable(newTableName);

			// if we are planning on dropping the constraint on a column, then clear it from the old column definition
			foreach (dynamic oldColumn in oldColumns.Where(c => context.DropObjects.Any(d => String.Compare(d.ObjectName, getConstraintName(c), StringComparison.OrdinalIgnoreCase) == 0)))
			{
				oldColumn.DefaultName = null;
				oldColumn.DefaultIsSystemNamed = false;
			}

			// calculate which columns changed
			var missingColumns = oldColumns.Except(newColumns, compareColumns).ToList();
			var addColumns = newColumns.Except(oldColumns, compareColumns).ToList();
			var changedColumns = newColumns.Where((dynamic cc) =>
			{
				dynamic oldColumn = oldColumns.FirstOrDefault(oc => compareColumns(cc, oc));

				return (oldColumn != null) && (!areColumnsEqual(oldColumn, cc) || !areDefaultsEqual(oldColumn, cc));
			}).ToList();
			#endregion

			#region Change Columns
			// if we want to modify a computed column, we have to drop/add it
			var changedComputedColumns = changedColumns.Where(c => c.Definition != null).ToList();
			foreach (var cc in changedComputedColumns)
			{
				missingColumns.Add(cc);
				addColumns.Add(cc);
				changedColumns.Remove(cc);
			}

			// delete old columns - this should be pretty free
			if (missingColumns.Any())
			{
				// if the column has a default, drop it
				foreach (dynamic oldColumn in missingColumns.Where(c => c.DefaultName != null))
				{
					// script the default drop
					context.DropObjects.Add(new SchemaRegistryEntry() { Type = SchemaObjectType.Default, ObjectName = SqlParser.FormatSqlName(oldTableName, oldColumn.Name) });
				}

				// script the column drop
				StringBuilder sb = new StringBuilder();
				sb.AppendFormat("ALTER TABLE {0}", oldTableName);
				sb.Append(" DROP");
				sb.AppendLine(String.Join(",", missingColumns.Select((dynamic o) => String.Format(" COLUMN {0}", SqlParser.FormatSqlName(o.Name)))));
				context.AddObjects.Add(new SchemaObject(SchemaObjectType.Table, oldTableName, sb.ToString()));
			}

			// add new columns - this is free when the columns are nullable and possibly with a default
			if (addColumns.Any())
			{
				StringBuilder sb = new StringBuilder();
				sb.AppendFormat("ALTER TABLE {0}", oldTableName);
				sb.Append(" ADD ");
				sb.AppendLine(String.Join(", ", addColumns.Select((dynamic o) => GetColumnDefinition(o) + GetDefaultDefinition(o))));
				context.AddObjects.Add(new SchemaObject(SchemaObjectType.Table, oldTableName, sb.ToString()));
			}

			// alter columns - either the definition or the default
			foreach (dynamic column in changedColumns)
			{
				// find any indexes that are on that column
				ScriptIndexes(context, schemaObject, column.Name);

				// find the old column
				dynamic oldColumn = oldColumns.First(oc => compareColumns(column, oc));

				// if the columns aren't equal then alter the column
				if (!areColumnsEqual(column, oldColumn))
				{
					StringBuilder sb = new StringBuilder();

					// if the old column is nullable and the new one is not, and there is a default, then convert the data
					if (oldColumn.IsNullable && !column.IsNullable && column.DefaultName != null)
					{
						string defaultDefinition = column.DefaultDefinition.Substring(2, column.DefaultDefinition.Length - 4);
						sb.AppendFormat("UPDATE {0} SET {1} = 2 WHERE {1} IS NULL\n", oldTableName, column.Name, defaultDefinition);
					}

					// alter the column
					sb.AppendFormat("ALTER TABLE {0} ALTER COLUMN ", oldTableName);
					sb.AppendFormat(GetColumnDefinition(column));
					context.AddObjects.Add(new SchemaObject(SchemaObjectType.Table, oldTableName, sb.ToString()));
				}

				// modify the defaults
				if (!areDefaultsEqual(column, oldColumn))
				{
					StringBuilder sb = new StringBuilder();

					// delete the old default if it exists but it's not in the registry
					if (oldColumn.DefaultName != null && !context.SchemaRegistry.Contains(getConstraintName(oldColumn)))
					{
						// script the default drop
						sb.AppendFormat("ALTER TABLE {0} DROP CONSTRAINT {1}\nGO\n", oldTableName, SqlParser.FormatSqlName(oldColumn.DefaultName));
					}

					// add the new default if we want one
					if (column.DefaultName != null)
					{
						// script the add
						sb.AppendFormat("ALTER TABLE {0} ADD ", oldTableName);
						sb.AppendFormat(GetDefaultDefinition(column));
						sb.AppendFormat(" FOR {0}", SqlParser.FormatSqlName(column.Name));
					}

					context.AddObjects.Add(new SchemaObject(SchemaObjectType.Table, oldTableName, sb.ToString()));
				}
			}
			#endregion
		}
		/// <summary>
		/// Script the permissions on an object and save the script to add the permissions back later
		/// </summary>
		/// <param name="context">The installation context.</param>
		/// <param name="schemaObject">The object to drop</param>
		private void ScriptPermissions(InstallContext context, SchemaObject schemaObject)
		{
			IList<FastExpando> permissions = null;

			if (schemaObject.SchemaObjectType == SchemaObjectType.Role)
			{
				// get the current permissions on the object
				permissions = _connection.QuerySql(@"SELECT UserName=u.name, Permission=p.permission_name, ClassType=p.class_desc, ObjectName=ISNULL(o.name, t.name)
								FROM sys.database_principals u
								JOIN sys.database_permissions p ON (u.principal_id = p.grantee_principal_id)
								LEFT JOIN sys.objects o ON (p.class_desc = 'OBJECT_OR_COLUMN' AND p.major_id = o.object_id)
								LEFT JOIN sys.types t ON (p.class_desc = 'TYPE' AND p.major_id = t.user_type_id)
								WHERE u.name = @ObjectName",
						new Dictionary<string, object>() { { "ObjectName", schemaObject.SqlName.Object } });
			}
			else if (schemaObject.SchemaObjectType == SchemaObjectType.AutoProc)
			{
				// handle permissions for autoprocs
				foreach (var proc in new AutoProc(schemaObject.Name, new SqlColumnDefinitionProvider(_connection), context.SchemaObjects).GetProcs())
				{
					ScriptPermissions(context, new SchemaObject(SchemaObjectType.StoredProcedure, proc.Item2, ""));
				}

				return;
			}
			else if (schemaObject.SchemaObjectType == SchemaObjectType.UserDefinedType)
			{
				// get the current permissions on the object
				permissions = _connection.QuerySql(@"SELECT UserName=u.name, Permission=p.permission_name, ClassType=p.class_desc, ObjectName=QUOTENAME(t.name)
								FROM sys.database_principals u
								JOIN sys.database_permissions p ON (u.principal_id = p.grantee_principal_id)
								JOIN sys.types t ON (p.class_desc = 'TYPE' AND p.major_id = t.user_type_id)
								WHERE t.name = @ObjectName",
						new Dictionary<string, object>() { { "ObjectName", schemaObject.SqlName.Object } });
			}
			else
			{
				// get the current permissions on the object
				permissions = _connection.QuerySql(@"SELECT UserName=u.name, Permission=p.permission_name, ClassType=p.class_desc, 
								ObjectName=QUOTENAME(OBJECT_SCHEMA_NAME(o.object_id)) + '.' + QUOTENAME(OBJECT_NAME(o.object_id))
								FROM sys.database_principals u
								JOIN sys.database_permissions p ON (u.principal_id = p.grantee_principal_id)
								JOIN sys.objects o ON (p.class_desc = 'OBJECT_OR_COLUMN' AND p.major_id = o.object_id)
								WHERE o.object_id = OBJECT_ID(@ObjectName)",
						new Dictionary<string, object>() { { "ObjectName", schemaObject.SqlName.FullName } });
			}

			// create a new permission schema object to install for each existing permission
			foreach (dynamic permission in permissions)
				context.AddObjects.Add(new SchemaObject(String.Format("GRANT {0} ON {1}{2} TO {3} -- DEPENDENCY", permission.Permission, permission.ClassType == "TYPE" ? "TYPE::" : "", SqlParser.FormatSqlName(permission.ObjectName), SqlParser.FormatSqlName(permission.UserName))));
		}
		/// <summary>
		/// Script the update of a table.
		/// </summary>
		/// <param name="context">The installation context.</param>
		/// <param name="schemaObject">The object to update.</param>
		private void ScriptTableUpdate(InstallContext context, SchemaObject schemaObject)
		{
			string oldTableName = schemaObject.SqlName.FullName;
			string newTableName = InsightTemp + DateTime.Now.Ticks.ToString(CultureInfo.InvariantCulture);

			try
			{
				// make a temporary table so we can analyze the difference
				// note that we rename the table and its constraints so that we don't have conflicts when creating it
				string tempTable = schemaObject.Sql;
				tempTable = createTableRegex.Replace(tempTable, "CREATE TABLE " + newTableName);
				tempTable = constraintRegex.Replace(tempTable, match => "CONSTRAINT " + SqlParser.FormatSqlName(InsightTemp + SqlParser.UnformatSqlName(match.Groups[1].Value)));
				_connection.ExecuteSql(tempTable);

				// detect if the table was created on a different data space and throw
				var oldDataSpace = _connection.ExecuteScalarSql<int>("SELECT data_space_id FROM sys.indexes i WHERE i.object_id = OBJECT_ID(@Name) AND type <= 1", new Dictionary<string, object> { { "Name", oldTableName } });
				var newDataSpace = _connection.ExecuteScalarSql<int>("SELECT data_space_id FROM sys.indexes i WHERE i.object_id = OBJECT_ID(@Name) AND type <= 1", new Dictionary<string, object> { { "Name", newTableName } });
				if (oldDataSpace != newDataSpace)
					throw new SchemaException(String.Format(CultureInfo.InvariantCulture, "Cannot move table {0} to another filegroup or partition", oldTableName));

				// update the columns and constraints
				ScriptColumnsAndConstraints(context, schemaObject, oldTableName, newTableName);
			}
			finally
			{
				try
				{
					// clean up the temporary table
					_connection.ExecuteSql("DROP TABLE " + newTableName);
				}
				catch (SqlException)
				{
					// eat this and throw the original error
				}
			}
		}
        /// <summary>
        /// Schedule an update by adding the appropriate delete, update and add records
        /// </summary>
		/// <param name="context">The installation context.</param>
        /// <param name="schemaObject">The object to update.</param>
		private void ScriptUpdate(InstallContext context, SchemaObject schemaObject)
        {
			// if we are dropping and readding an object, then make sure we put the object in the drop list at the right time
			if (schemaObject.OriginalOrder == 0)
			{
				// if the object matches an existing schema object (probably), then find it and copy its installation order
				var originalObject = context.SchemaObjects.Find(o => schemaObject.SchemaObjectType == o.SchemaObjectType && String.Compare(schemaObject.Name, o.Name, StringComparison.OrdinalIgnoreCase) == 0);
				if (originalObject != null)
					schemaObject.OriginalOrder = originalObject.OriginalOrder;
				else if (context.AddObjects.Any())
					schemaObject.OriginalOrder = context.AddObjects.Max(o => o.OriginalOrder) + 1;
				else
					schemaObject.OriginalOrder = 1;
			}

			// if we have already scripted this object, then don't do it again
			if (context.AddObjects.Any(o => o.Name == schemaObject.Name))
				return;

			// if this is a table, then let's see if we can just modify the table
			if (schemaObject.SchemaObjectType == SchemaObjectType.Table)
			{
				ScriptStandardDependencies(context, schemaObject);
				ScriptTableUpdate(context, schemaObject);
				return;
			}

			// add the object to the add queue before anything that depends on it, as well as any permissions on the object
			context.AddObjects.Add(schemaObject);

			// don't log any of our scripting
			ScriptPermissions(context, schemaObject);
			ScriptStandardDependencies(context, schemaObject);

			// handle dependencies for different types of objects
			if (schemaObject.SchemaObjectType == SchemaObjectType.IndexedView)
			{
				ScriptIndexes(context, schemaObject);
			}
			else if (schemaObject.SchemaObjectType == SchemaObjectType.PrimaryKey)
			{
				ScriptForeignKeys(context, schemaObject);
				ScriptXmlIndexes(context, schemaObject);
			}
			else if (schemaObject.SchemaObjectType == SchemaObjectType.PrimaryXmlIndex)
			{
				ScriptXmlIndexes(context, schemaObject);
			}
			else if (schemaObject.SchemaObjectType == SchemaObjectType.Index)
			{
				ScriptIndexes(context, schemaObject);
			}

			// drop the object after any dependencies are dropped
			SchemaRegistryEntry dropEntry = context.SchemaRegistry.Find(schemaObject.Name);
			if (dropEntry == null)
			{
				dropEntry = new SchemaRegistryEntry()
				{
					Type = schemaObject.SchemaObjectType,
					ObjectName = schemaObject.Name
				};
			}

			context.DropObjects.Add(dropEntry);
        }
		public void Install(string schemaGroup, SchemaObjectCollection schema)
		{
			_connection.ResetLog();

			// validate the arguments
			if (schemaGroup == null) throw new ArgumentNullException("schemaGroup");
			if (schema == null) throw new ArgumentNullException("schema");

			// make sure the schema objects are valid
			schema.Validate();

			// number the objects so when we compare them we have a final comparison
			List<SchemaObject> schemaObjects = schema.Where(o => o.SchemaObjectType != SchemaObjectType.Unused).ToList();
			for (int i = 0; i < schemaObjects.Count; i++)
				schemaObjects[i].OriginalOrder = i;
			// order the changes by reverse install order
			schemaObjects.Sort((o1, o2) => -CompareByInstallOrder(o1, o2));

			// get the list of objects to install, filtering out the extra crud
			InstallContext context = new InstallContext();
			context.SchemaObjects = schemaObjects;

			// azure doesn't support filegroups or partitions, so we need to know if we are on azure
			context.IsAzure = _connection.ExecuteScalarSql<bool>("SELECT CONVERT(bit, CASE WHEN SERVERPROPERTY('edition') = 'SQL Azure' THEN 1 ELSE 0 END)", null);

			// NOTE: we can't use System.Transactions.TransactionScope here, because certain operations cause SQL server to commit internal data structures
			// and then if an exception is thrown, our registry changes wouldn't be in sync with the database.
			try
			{
				_connection.ExecuteSql("BEGIN TRANSACTION");

				// load the schema registry from the database
				context.SchemaRegistry = new SchemaRegistry(_connection, schemaGroup);

				// find all of the objects that we need to drop
				// sort to drop in reverse dependency order 
				context.DropObjects = context.SchemaRegistry.Entries
					.Where(e => !context.SchemaObjects.Any(o => String.Compare(e.ObjectName, o.Name, StringComparison.OrdinalIgnoreCase) == 0))
					.ToList();
				context.DropObjects.Sort((e1, e2) => -CompareByInstallOrder(e1, e2));

				// find all of the objects that are not in the registry and don't exist
				context.AddObjects = context.SchemaObjects.Where(o => !context.SchemaRegistry.Contains(o) && !o.Exists(_connection)).ToList();

				// find all of the objects that have changed
				_connection.DoNotLog(() =>
				{
					// for anything that's not entirely new
					foreach (var change in context.SchemaObjects.Except(context.AddObjects))
					{
						// if the object is in the registry and the signature matches, then there is no change
						var registryEntry = context.SchemaRegistry.Find(change);
						if (registryEntry != null && context.SchemaRegistry.Find(change).Signature == change.GetSignature(_connection, schema))
							continue;

						// if the object is NOT in the registry, but already exists (we know because it's not in the add list already)
						// then we assume it has changed
						// UNLESS this is not a type we can drop, and we are in repair mode, we will skip it
						if (registryEntry == null && !change.CanModify(context, _connection) && AllowRepair)
						{
							Console.WriteLine("WARNING: {0} {1} already exists in the database and cannot be modified. Assuming that it has not changed.", change.SchemaObjectType, change.Name);
							continue;
						}

						ScriptUpdate(context, change);
					}
				});

				// sort the objects in install order
				context.AddObjects.Sort(CompareByInstallOrder);

				// make the changes
				DropObjects(context.DropObjects);
				AddObjects(context);
				VerifyObjects(context.SchemaObjects);

				// update the schema registry
				context.SchemaRegistry.Update(context.SchemaObjects);

				// complete the changes
				_connection.ExecuteSql("COMMIT");
			}
			catch (Exception)
			{
				// rollback the transaction
				// this shouldn't fail
				// if it does, then the outer application may need to roll it back
				try { _connection.ExecuteSql("ROLLBACK"); }
				catch (SqlException) { }

				throw;
			}
		}
		/// <summary>
		/// Add all of the objects that need to be added.
		/// </summary>
		/// <param name="addObjects">The objects to add.</param>
		/// <param name="objects">The entire schema. Needed for AutoProcs.</param>
		private void AddObjects(InstallContext context)
		{
			// create objects
			foreach (SchemaObject schemaObject in context.AddObjects)
			{
				if (CreatingObject != null)
					CreatingObject(this, new SchemaEventArgs(SchemaEventType.BeforeCreate, schemaObject));

				schemaObject.Install(_connection, context.SchemaObjects);

				if (CreatedObject != null)
					CreatedObject(this, new SchemaEventArgs(SchemaEventType.AfterCreate, schemaObject));
			}
		}
		private void ScriptXmlIndexes(InstallContext context, SchemaObject schemaObject)
		{
			IList<FastExpando> xmlIndexes;

			if (schemaObject.SchemaObjectType == SchemaObjectType.PrimaryXmlIndex)
			{
				// find any secondary indexes dependent upon the primary index
				xmlIndexes = _connection.QuerySql(@"
						IF NOT EXISTS (SELECT * FROM sys.system_objects WHERE name = 'xml_indexes') SELECT TOP 0 Nothing=NULL ELSE
						SELECT ObjectID=i.object_id, IndexID=i.index_id, 
						Name=QUOTENAME(i.name), 
						TableName=QUOTENAME(OBJECT_SCHEMA_NAME(o.object_id)) + '.' + QUOTENAME(OBJECT_NAME(o.object_id)),
						SecondaryType=i.secondary_type_desc, ParentIndexName=QUOTENAME(@ObjectName)
						FROM sys.xml_indexes i
						JOIN sys.objects o ON (i.object_id = o.object_id)
						JOIN sys.xml_indexes p ON (p.index_id = i.using_xml_index_id)
						WHERE p.name = @ObjectName",
					new Dictionary<string, object>() { { "ObjectName", schemaObject.SqlName.Object } });
			}
			else
			{
				// for tables and primary keys, look for primary xml indexes
				xmlIndexes = _connection.QuerySql(@"
						IF NOT EXISTS (SELECT * FROM sys.system_objects WHERE name = 'xml_indexes') SELECT TOP 0 Nothing=NULL ELSE
						SELECT ObjectID=i.object_id, IndexID=i.index_id,
						Name=QUOTENAME(i.name),
						TableName=QUOTENAME(OBJECT_SCHEMA_NAME(o.object_id)) + '.' + QUOTENAME(OBJECT_NAME(o.object_id)),
						SecondaryType=i.secondary_type_desc, ParentIndexName=u.name
						FROM sys.xml_indexes i
						JOIN sys.objects o ON (i.object_id = o.object_id)
						LEFT JOIN sys.xml_indexes u ON (i.using_xml_index_id = u.index_id)
						WHERE i.object_id = OBJECT_ID(@ObjectName)",
					new Dictionary<string, object>() { { "ObjectName", schemaObject.SqlName.FullName } });
			}

			foreach (dynamic xmlIndex in xmlIndexes)
			{
				// get the columns in the key from the database
				var columns = _connection.QuerySql(@"
					SELECT ColumnName=QUOTENAME(c.name)
					FROM sys.xml_indexes i
					JOIN sys.index_columns ic ON (i.object_id = ic.object_id AND i.index_id = ic.index_id)
					JOIN sys.columns c ON (ic.object_id = c.object_id AND ic.column_id = c.column_id)
					WHERE i.object_id = @ObjectID AND i.index_id = @IndexID",
					new Dictionary<string, object>()
					{ 
						{ "ObjectID", xmlIndex.ObjectID },
						{ "IndexID", xmlIndex.IndexID }
					});

				StringBuilder sb = new StringBuilder();
				sb.AppendFormat("CREATE {0}XML INDEX {1} ON {2} (",
					(xmlIndex.ParentIndexName == null) ? "PRIMARY " : "",
					xmlIndex.Name,
					xmlIndex.TableName);
				sb.Append(String.Join(",", columns.Select((dynamic c) => SqlParser.FormatSqlName(c.ColumnName))));
				sb.Append(")");
				if (xmlIndex.SecondaryType != null)
				{
					sb.AppendFormat(" USING XML INDEX {0} FOR ", xmlIndex.ParentIndexName);
					sb.Append(xmlIndex.SecondaryType);
				}

				var dropObject = new SchemaObject(sb.ToString());

				ScriptUpdate(context, dropObject);
			}
		}