2009-09-25 10 views

Respuesta

8

Puede utilizar las API Win32 nativas OpenService() y ChangeServiceConfig() para ese fin. Creo que hay alguna información en pinvoke.net y por supuesto en MSDN. Es posible que desee comprobar el P/Invoke Interopt Assistant.

+6

Downvoter: sería útil si quisiera explicarlo. –

9

En el instalador de servicio que tiene que decir

[RunInstaller(true)] 
public class ProjectInstaller : System.Configuration.Install.Installer 
{ 
    public ProjectInstaller() 
    { 
     ... 
     this.serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Automatic; 
    } 
} 

También podría pedir al usuario durante la instalación y luego establecer este valor. O simplemente establezca esta propiedad en el diseñador de estudio visual.

+0

Ah OK, por lo que no es posible después de instalar sin necesidad de desinstalar el servicio? – joshcomley

+0

¿Quieres hacer esa post instalación? Entonces debes usar WMI. – Arthur

0
ServiceInstaller myInstaller = new System.ServiceProcess.ServiceInstaller(); 
myInstaller.StartType = System.ServiceProcess.ServiceStartMode.Automatic; 
2

En ProjectInstaller.cs, haga clic/seleccione el componente Service1 en la superficie de diseño. En las propiedades windo hay una propiedad startType para que usted configure esto.

-2

Una forma sería desinstalar el servicio anterior e instalar uno nuevo con parámetros actualizados directamente desde su aplicación C#.

Necesitará WindowsServiceInstaller en su aplicación.

[RunInstaller(true)] 
public class WindowsServiceInstaller : Installer 
{ 
    public WindowsServiceInstaller() 
    { 
     ServiceInstaller si = new ServiceInstaller(); 
     si.StartType = ServiceStartMode.Automatic; // get this value from some global variable 
     si.ServiceName = @"YOUR APP"; 
     si.DisplayName = @"YOUR APP"; 
     this.Installers.Add(si); 

     ServiceProcessInstaller spi = new ServiceProcessInstaller(); 
     spi.Account = System.ServiceProcess.ServiceAccount.LocalSystem; 
     spi.Username = null; 
     spi.Password = null; 
     this.Installers.Add(spi); 
    } 
} 

y para volver a instalar el servicio simplemente use estas dos líneas.

ManagedInstallerClass.InstallHelper(new string[] { "/u", Assembly.GetExecutingAssembly().Location }); 
ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetExecutingAssembly().Location }); 
0

Puede hacerlo en la clase de instalación para el servicio estableciendo la propiedad ServiceInstaller.StartType a cualquier valor que se obtiene (es probable que tenga que hacer esto en una acción personalizada, ya que desea que el usuario especifique) o puede modificar la entrada REG_DWORD "Inicio" del Servicio, el valor 2 es automático y 3 es manual. Está en HKEY_LOCAL_MACHINE \ SYSTEM \ Services \ YourServiceName

+0

La modificación del registro sería la mejor manera de cambiar el tipo de inicio después de la instalación. Puede usar la clase Microsoft.Win32.Registry para hacerlo. –

+2

No hagas eso. Los hacks como estos son exactamente la razón por la cual hay toneladas de compatibilidad en las versiones de Windows más nuevas. Hay API perfectamente razonables para hacerlo, solo que no están administradas. Sin embargo, cuando sabes que estás en Windows (ya sabes, en ambos casos, Registry o API/unmanged), eso no debería importar. –

+0

¿Cómo se usa el registro de la manera en que debe ser usado como un hack? La API modifica el registro, es solo una capa de abstracción ... – SpaceghostAli

47

Escribí blog post sobre cómo hacer esto usando P/Invoke. Utilizando la clase ServiceHelper de mi publicación, puede hacer lo siguiente para cambiar el Modo de inicio.

var svc = new ServiceController("ServiceNameGoesHere"); 
ServiceHelper.ChangeStartMode(svc, ServiceStartMode.Automatic); 
+0

¡Funciona perfectamente en XP! ¿Esto funcionará en Windows 7, etc.? – Tom

+0

@Tom No he probado esto en Win7, así que no puedo decirlo con certeza ... –

+2

Probé esto en algunas máquinas virtuales, y todo parece funcionar bien en Win 7. Gracias de nuevo. – Tom

5

Puede utilizar WMI para consultar todos los servicios y luego coincidir con el nombre del servicio al usuario el valor introducido

Una vez que el servicio se ha encontrado simplemente cambiar la propiedad StartMode

   if(service.Properties["Name"].Value.ToString() == userInputValue) 
       { 
        service.Properties["StartMode"].Value = "Automatic"; 
        //service.Properties["StartMode"].Value = "Manual"; 

       } 

// Esto hará que todos los Servicios se ejecuten en una Computadora de dominio y cambie el Servicio de "Dispositivo móvil de Apple" al Modo de inicio de Automático. Estas dos funciones, obviamente, deben ser separados, pero es fácil de cambiar un modo de puesta en servicio después de la instalación mediante WMI

private void getServicesForDomainComputer(string computerName) 
    { 
     ConnectionOptions co1 = new ConnectionOptions(); 
     co1.Impersonation = ImpersonationLevel.Impersonate; 
     //this query could also be: ("select * from Win32_Service where name = '" + serviceName + "'"); 
     ManagementScope scope = new ManagementScope(@"\\" + computerName + @"\root\cimv2"); 
     scope.Options = co1; 

     SelectQuery query = new SelectQuery("select * from Win32_Service"); 

     using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query)) 
     { 
      ManagementObjectCollection collection = searcher.Get(); 

      foreach (ManagementObject service in collection) 
      { 
       //the following are all of the available properties 
       //boolean AcceptPause 
       //boolean AcceptStop 
       //string Caption 
       //uint32 CheckPoint 
       //string CreationClassName 
       //string Description 
       //boolean DesktopInteract 
       //string DisplayName 
       //string ErrorControl 
       //uint32 ExitCode; 
       //datetime InstallDate; 
       //string Name 
       //string PathName 
       //uint32 ProcessId 
       //uint32 ServiceSpecificExitCode 
       //string ServiceType 
       //boolean Started 
       //string StartMode 
       //string StartName 
       //string State 
       //string Status 
       //string SystemCreationClassName 
       //string SystemName; 
       //uint32 TagId; 
       //uint32 WaitHint; 
       if(service.Properties["Name"].Value.ToString() == "Apple Mobile Device") 
       { 
        service.Properties["StartMode"].Value = "Automatic"; 

       } 
      } 
     }   
    } 

quería mejorar esta respuesta ...Un método para cambiar StartMode de equipo especificado, el servicio:

public void changeServiceStartMode(string hostname, string serviceName, string startMode) 
    { 
     try 
     { 
      ManagementObject classInstance = 
         new ManagementObject(@"\\" + hostname + @"\root\cimv2", 
         "Win32_Service.Name='" + serviceName + "'", 
         null); 

      // Obtain in-parameters for the method 
      ManagementBaseObject inParams = 
       classInstance.GetMethodParameters("ChangeStartMode"); 

      // Add the input parameters. 
      inParams["StartMode"] = startMode; 

      // Execute the method and obtain the return values. 
      ManagementBaseObject outParams = 
       classInstance.InvokeMethod("ChangeStartMode", inParams, null); 

      // List outParams 
      //Console.WriteLine("Out parameters:"); 
      //richTextBox1.AppendText(DateTime.Now.ToString() + ": ReturnValue: " + outParams["ReturnValue"]); 
     } 
     catch (ManagementException err) 
     { 
      //richTextBox1.AppendText(DateTime.Now.ToString() + ": An error occurred while trying to execute the WMI method: " + err.Message); 
     } 
    } 
2

¿Qué hay de hacer uso de c: \ windows \ system32 \ sc.exe a hacer eso?!

En Códigos VB.NET, use System.Diagnostics.Process para llamar a sc.exe y cambiar el modo de inicio de un servicio de Windows. Lo que sigue es mi código de ejemplo

Public Function SetStartModeToDisabled(ByVal ServiceName As String) As Boolean 
    Dim sbParameter As New StringBuilder 
    With sbParameter 
     .Append("config ") 
     .AppendFormat("""{0}"" ", ServiceName) 
     .Append("start=disabled") 
    End With 

    Dim processStartInfo As ProcessStartInfo = New ProcessStartInfo() 
    Dim scExeFilePath As String = String.Format("{0}\sc.exe", Environment.GetFolderPath(Environment.SpecialFolder.System)) 
    processStartInfo.FileName = scExeFilePath 
    processStartInfo.Arguments = sbParameter.ToString 
    processStartInfo.UseShellExecute = True 

    Dim process As Process = process.Start(processStartInfo) 
    process.WaitForExit() 

    Return process.ExitCode = 0 

End Function

Cuestiones relacionadas