public override void Install(IDictionary stateSaver) { base.Context.LogMessage(Res.GetString("InstallingService", new object[] { this.ServiceName })); try { CheckEnvironment(); string servicesStartName = null; string password = null; ServiceProcessInstaller parent = null; if (base.Parent is ServiceProcessInstaller) { parent = (ServiceProcessInstaller)base.Parent; } else { for (int j = 0; j < base.Parent.Installers.Count; j++) { if (base.Parent.Installers[j] is ServiceProcessInstaller) { parent = (ServiceProcessInstaller)base.Parent.Installers[j]; break; } } } if (parent == null) { throw new InvalidOperationException(Res.GetString("NoInstaller")); } switch (parent.Account) { case ServiceAccount.LocalService: servicesStartName = @"NT AUTHORITY\LocalService"; break; case ServiceAccount.NetworkService: servicesStartName = @"NT AUTHORITY\NetworkService"; break; case ServiceAccount.User: servicesStartName = parent.Username; password = parent.Password; break; } string binaryPath = base.Context.Parameters["assemblypath"]; if ((binaryPath == null) || (binaryPath.Length == 0)) { throw new InvalidOperationException(Res.GetString("FileName")); } binaryPath = "\"" + binaryPath + "\""; if (!string.IsNullOrEmpty(m_commandLineOptions)) binaryPath += " " + m_commandLineOptions; if (!ValidateServiceName(this.ServiceName)) { object[] args = new object[] { this.ServiceName, 80.ToString(CultureInfo.CurrentCulture) }; throw new InvalidOperationException(Res.GetString("ServiceName", args)); } if (this.DisplayName.Length > 0xff) { throw new ArgumentException(Res.GetString("DisplayNameTooLong", new object[] { this.DisplayName })); } string dependencies = null; if (this.ServicesDependedOn.Length > 0) { StringBuilder builder = new StringBuilder(); for (int k = 0; k < this.ServicesDependedOn.Length; k++) { string name = this.ServicesDependedOn[k]; try { ServiceController controller = new ServiceController(name, "."); name = controller.ServiceName; } catch { } builder.Append(name); builder.Append('\0'); } builder.Append('\0'); dependencies = builder.ToString(); } IntPtr databaseHandle = SafeNativeMethods.OpenSCManager(null, null, 0xf003f); IntPtr zero = IntPtr.Zero; if (databaseHandle == IntPtr.Zero) { throw new InvalidOperationException(Res.GetString("OpenSC", new object[] { "." }), new Win32Exception()); } int serviceType = 0x10; int num4 = 0; for (int i = 0; i < base.Parent.Installers.Count; i++) { if (base.Parent.Installers[i] is ServiceInstallerEx) { num4++; if (num4 > 1) { break; } } } if (num4 > 1) { serviceType = 0x20; } try { zero = NativeMethods.CreateService(databaseHandle, this.ServiceName, this.DisplayName, 0xf01ff, serviceType, (int)this.StartType, 1, binaryPath, null, IntPtr.Zero, dependencies, servicesStartName, password); if (zero == IntPtr.Zero) { throw new Win32Exception(); } if (this.Description.Length != 0) { NativeMethods.SERVICE_DESCRIPTION serviceDesc = new NativeMethods.SERVICE_DESCRIPTION(); serviceDesc.description = Marshal.StringToHGlobalUni(this.Description); bool flag = NativeMethods.ChangeServiceConfig2(zero, 1, ref serviceDesc); Marshal.FreeHGlobal(serviceDesc.description); if (!flag) { throw new Win32Exception(); } } stateSaver["installed"] = true; } finally { if (zero != IntPtr.Zero) { SafeNativeMethods.CloseServiceHandle(zero); } SafeNativeMethods.CloseServiceHandle(databaseHandle); } base.Context.LogMessage(Res.GetString("InstallOK", new object[] { this.ServiceName })); } finally { base.Install(stateSaver); } }
/// <summary>Installs the service by writing service application information to the registry. This method is meant to be used by installation tools, which process the appropriate methods automatically.</summary> /// <param name="stateSaver">An <see cref="T:System.Collections.IDictionary" /> that contains the context information associated with the installation. </param> /// <exception cref="T:System.InvalidOperationException">The installation does not contain a <see cref="T:System.ServiceProcess.ServiceProcessInstaller" /> for the executable.-or- The file name for the assembly is null or an empty string.-or- The service name is invalid.-or- The Service Control Manager could not be opened. </exception> /// <exception cref="T:System.ArgumentException">The display name for the service is more than 255 characters in length.</exception> /// <exception cref="T:System.ComponentModel.Win32Exception">The system could not generate a handle to the service. -or-A service with that name is already installed.</exception> /// <PermissionSet> /// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" /> /// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode" /> /// <IPermission class="System.Security.Permissions.UIPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" /> /// </PermissionSet> public override void Install(IDictionary stateSaver) { base.Context.LogMessage(Res.GetString("InstallingService", this.ServiceName)); try { ServiceInstaller.CheckEnvironment(); string servicesStartName = null; string password = null; ServiceProcessInstaller serviceProcessInstaller = null; if (base.Parent is ServiceProcessInstaller) { serviceProcessInstaller = (ServiceProcessInstaller)base.Parent; } else { int num = 0; while (num < base.Parent.Installers.Count) { if (!(base.Parent.Installers[num] is ServiceProcessInstaller)) { num++; continue; } serviceProcessInstaller = (ServiceProcessInstaller)base.Parent.Installers[num]; break; } } if (serviceProcessInstaller == null) { throw new InvalidOperationException(Res.GetString("NoInstaller")); } switch (serviceProcessInstaller.Account) { case ServiceAccount.LocalService: servicesStartName = "NT AUTHORITY\\LocalService"; break; case ServiceAccount.NetworkService: servicesStartName = "NT AUTHORITY\\NetworkService"; break; case ServiceAccount.User: servicesStartName = serviceProcessInstaller.Username; password = serviceProcessInstaller.Password; break; } string text = base.Context.Parameters["assemblypath"]; if (string.IsNullOrEmpty(text)) { throw new InvalidOperationException(Res.GetString("FileName")); } if (text.IndexOf('"') == -1) { text = "\"" + text + "\""; } if (!ServiceInstaller.ValidateServiceName(this.ServiceName)) { throw new InvalidOperationException(Res.GetString("ServiceName", this.ServiceName, 80.ToString(CultureInfo.CurrentCulture))); } if (this.DisplayName.Length > 255) { throw new ArgumentException(Res.GetString("DisplayNameTooLong", this.DisplayName)); } string dependencies = null; if (this.ServicesDependedOn.Length != 0) { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < this.ServicesDependedOn.Length; i++) { string text2 = this.ServicesDependedOn[i]; try { text2 = new ServiceController(text2, ".").ServiceName; } catch { } stringBuilder.Append(text2); stringBuilder.Append('\0'); } stringBuilder.Append('\0'); dependencies = stringBuilder.ToString(); } IntPtr intPtr = SafeNativeMethods.OpenSCManager(null, null, 983103); IntPtr intPtr2 = IntPtr.Zero; if (intPtr == IntPtr.Zero) { throw new InvalidOperationException(Res.GetString("OpenSC", "."), new Win32Exception()); } int serviceType = 16; int num2 = 0; for (int j = 0; j < base.Parent.Installers.Count; j++) { if (base.Parent.Installers[j] is ServiceInstaller) { num2++; if (num2 > 1) { break; } } } if (num2 > 1) { serviceType = 32; } try { intPtr2 = NativeMethods.CreateService(intPtr, this.ServiceName, this.DisplayName, 983551, serviceType, (int)this.StartType, 1, text, null, IntPtr.Zero, dependencies, servicesStartName, password); if (intPtr2 == IntPtr.Zero) { throw new Win32Exception(); } if (this.Description.Length != 0) { NativeMethods.SERVICE_DESCRIPTION sERVICE_DESCRIPTION = default(NativeMethods.SERVICE_DESCRIPTION); sERVICE_DESCRIPTION.description = Marshal.StringToHGlobalUni(this.Description); bool num3 = NativeMethods.ChangeServiceConfig2(intPtr2, 1u, ref sERVICE_DESCRIPTION); Marshal.FreeHGlobal(sERVICE_DESCRIPTION.description); if (!num3) { throw new Win32Exception(); } } if (Environment.OSVersion.Version.Major > 5 && this.StartType == ServiceStartMode.Automatic) { NativeMethods.SERVICE_DELAYED_AUTOSTART_INFO sERVICE_DELAYED_AUTOSTART_INFO = default(NativeMethods.SERVICE_DELAYED_AUTOSTART_INFO); sERVICE_DELAYED_AUTOSTART_INFO.fDelayedAutostart = this.DelayedAutoStart; if (!NativeMethods.ChangeServiceConfig2(intPtr2, 3u, ref sERVICE_DELAYED_AUTOSTART_INFO)) { throw new Win32Exception(); } } stateSaver["installed"] = true; } finally { if (intPtr2 != IntPtr.Zero) { SafeNativeMethods.CloseServiceHandle(intPtr2); } SafeNativeMethods.CloseServiceHandle(intPtr); } base.Context.LogMessage(Res.GetString("InstallOK", this.ServiceName)); } finally { base.Install(stateSaver); } }
/// <include file='doc\ServiceInstaller.uex' path='docs/doc[@for="ServiceInstaller.Install"]/*' /> /// <devdoc> /// <para>Installs the service by writing service application /// information to the registry. This method is meant to be used by installation /// tools, which process the appropriate methods automatically.</para> /// </devdoc> public unsafe override void Install(IDictionary stateSaver) { Context.LogMessage(Res.GetString(Res.InstallingService, ServiceName)); try { CheckEnvironment(); string userName = null; string password = null; // find the ServiceProcessInstaller for our process. It's either the // parent or one of our peers in the parent's Installers collection. ServiceProcessInstaller processInstaller = null; if (Parent is ServiceProcessInstaller) { processInstaller = (ServiceProcessInstaller)Parent; } else { for (int i = 0; i < Parent.Installers.Count; i++) { if (Parent.Installers[i] is ServiceProcessInstaller) { processInstaller = (ServiceProcessInstaller)Parent.Installers[i]; break; } } } if (processInstaller == null) { throw new InvalidOperationException(Res.GetString(Res.NoInstaller)); } switch (processInstaller.Account) { case ServiceAccount.LocalService: userName = LocalServiceName; break; case ServiceAccount.NetworkService: userName = NetworkServiceName; break; case ServiceAccount.User: userName = processInstaller.Username; password = processInstaller.Password; break; } // check all our parameters string moduleFileName = Context.Parameters["assemblypath"]; if (String.IsNullOrEmpty(moduleFileName)) { throw new InvalidOperationException(Res.GetString(Res.FileName)); } // Put quotas around module file name. Otherwise a service might fail to start if there is space in the path. // Note: Though CreateService accepts a binaryPath allowing // arguments for automatic services, in /assemblypath=foo, // foo is simply the path to the executable. // Therefore, it is best to quote if there are no quotes, // and best to not quote if there are quotes. if (moduleFileName.IndexOf('\"') == -1) { moduleFileName = "\"" + moduleFileName + "\""; } //Check service name if (!ValidateServiceName(ServiceName)) { //Event Log cannot be used here, since the service doesn't exist yet. throw new InvalidOperationException(Res.GetString(Res.ServiceName, ServiceName, ServiceBase.MaxNameLength.ToString(CultureInfo.CurrentCulture))); } // Check DisplayName length. if (DisplayName.Length > 255) { // MSDN suggests that 256 is the max length, but in // fact anything over 255 causes problems. throw new ArgumentException(Res.GetString(Res.DisplayNameTooLong, DisplayName)); } //Build servicesDependedOn string string servicesDependedOn = null; if (ServicesDependedOn.Length > 0) { StringBuilder buff = new StringBuilder(); for (int i = 0; i < ServicesDependedOn.Length; ++i) { // we have to build a list of the services' short names. But the user // might have used long names in the ServicesDependedOn property. Try // to use ServiceController's logic to get the short name. string tempServiceName = ServicesDependedOn[i]; try { ServiceController svc = new ServiceController(tempServiceName, "."); tempServiceName = svc.ServiceName; } catch { } //The servicesDependedOn need to be separated by a null buff.Append(tempServiceName); buff.Append('\0'); } // an extra null at the end indicates end of list. buff.Append('\0'); servicesDependedOn = buff.ToString(); } // Open the service manager IntPtr serviceManagerHandle = SafeNativeMethods.OpenSCManager(null, null, NativeMethods.SC_MANAGER_ALL); IntPtr serviceHandle = IntPtr.Zero; if (serviceManagerHandle == IntPtr.Zero) { throw new InvalidOperationException(Res.GetString(Res.OpenSC, "."), new Win32Exception()); } int serviceType = NativeMethods.SERVICE_TYPE_WIN32_OWN_PROCESS; // count the number of UserNTServiceInstallers. More than one means we set the SHARE_PROCESS flag. int serviceInstallerCount = 0; for (int i = 0; i < Parent.Installers.Count; i++) { if (Parent.Installers[i] is ServiceInstaller) { serviceInstallerCount++; if (serviceInstallerCount > 1) { break; } } } if (serviceInstallerCount > 1) { serviceType = NativeMethods.SERVICE_TYPE_WIN32_SHARE_PROCESS; } try { // Install the service serviceHandle = NativeMethods.CreateService(serviceManagerHandle, ServiceName, DisplayName, NativeMethods.ACCESS_TYPE_ALL, serviceType, (int)StartType, NativeMethods.ERROR_CONTROL_NORMAL, moduleFileName, null, IntPtr.Zero, servicesDependedOn, userName, password); if (serviceHandle == IntPtr.Zero) { throw new Win32Exception(); } // A local variable in an unsafe method is already fixed -- so we don't need a "fixed { }" blocks to protect // across the p/invoke calls below. if (Description.Length != 0) { NativeMethods.SERVICE_DESCRIPTION serviceDesc = new NativeMethods.SERVICE_DESCRIPTION(); serviceDesc.description = Marshal.StringToHGlobalUni(Description); bool success = NativeMethods.ChangeServiceConfig2(serviceHandle, NativeMethods.SERVICE_CONFIG_DESCRIPTION, ref serviceDesc); Marshal.FreeHGlobal(serviceDesc.description); if (!success) { throw new Win32Exception(); } } if (Environment.OSVersion.Version.Major > 5) { if (StartType == ServiceStartMode.Automatic) { NativeMethods.SERVICE_DELAYED_AUTOSTART_INFO serviceDelayedInfo = new NativeMethods.SERVICE_DELAYED_AUTOSTART_INFO(); serviceDelayedInfo.fDelayedAutostart = DelayedAutoStart; bool success = NativeMethods.ChangeServiceConfig2(serviceHandle, NativeMethods.SERVICE_CONFIG_DELAYED_AUTO_START_INFO, ref serviceDelayedInfo); if (!success) { throw new Win32Exception(); } } } stateSaver["installed"] = true; } finally { if (serviceHandle != IntPtr.Zero) { SafeNativeMethods.CloseServiceHandle(serviceHandle); } SafeNativeMethods.CloseServiceHandle(serviceManagerHandle); } Context.LogMessage(Res.GetString(Res.InstallOK, ServiceName)); } finally { base.Install(stateSaver); } }