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"); }
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); }
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); }
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); } }
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); } }
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); } }
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); }
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); }
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); }
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); } }
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; }
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()); }
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; }
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()); }
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); }
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(); }
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."); }
/// <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); }
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(); } }
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}"); }
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); } }
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); }
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); } }