views:

446

answers:

6

I use a routine that can start and stop services via Delphi but I also need to be able to disable them, is it possible?

+3  A: 

You really only need to set the appropriate registry key for the service. The start type is determined by the "Start" keyword in service configuration section of the registry:

HKLM\System\CurrentControlSet\services\YOUR_SVC_NAME\

You'll notice a REG_DWORD called Start. To set this service's startup type to Disabled, change the value of the Start key to 0x4.

Other valid options for the Start key are:

     Boot        0x0
     System      0x1
     Automatic   0X2
     Manual      0x3
     Disabled    0x4

Here's a function to get you started. Note that I have not tested this function, but it should work as-is. You will need to include the Registry unit in your uses clause like this:

uses
   Registry;

// [.........]

function SetSvcStartup(iStartType: integer): Boolean;
var
  Reg: TRegistry;
  Path: string;
begin

  //    Boot        0x0
  //    System      0x1
  //    Automatic   0x2
  //    Manual      0x3
  //    Disabled    0x4

  Reg := TRegistry.Create;
  try
    with Reg do
    begin
      RootKey := HKEY_LOCAL_MACHINE;
      Path := 'System\CurrentControlSet\services\YOUR_SVC_NAME';

      if KeyExists(Path) then
      begin
        OpenKey(Path, True);
        WriteInteger('Start', iStartType);
      end;
    end;
  finally
    Reg.CloseKey;
    Reg.Free;
  end;
end;

To set a service's startup type to "disabled", you call the function like this:

SetSvcStartup(4);
Mick
-1 for encouraging direct modification of the registry when there are API functions designed to do the same task in a controlled manner.
Rob Kennedy
Fair enough, potato, potahto.
Mick
* This is likely to fail or ignored in new Windows versions. * The code also does not take access rights into account (missing Ifs)* It closes a key that was never opened.* And why do you check for an existing key, and if it does not exist you open it?
ChristianWimmer
I fixed the error you spotted in the code.
Mick
+6  A: 
ShellExecute(0, nil, 'cmd.exe', 'sc config "the service name" start=disabled', nil, SW_HIDE);
ShellExecute(0, nil, 'cmd.exe', 'sc config "the service name" start=auto', nil, SW_HIDE);
ShellExecute(0, nil, 'cmd.exe', 'sc config "the service name" start=demand', nil, SW_HIDE);
SimaWB
That's poor man service management. sc.exe is designed to be used by command line or scripts - and it not available on older Windows versions - application should use the SCM API.And if you'd really like to use SC, there's no need to invoke a shell. Run sc.exe directly.
ldsandon
I understand that's not que ideal solution but it worked as I needed for a specific problem. I'm evaluating the OpenService solution for general use.
Eder Gusatto
Also consider that using the SCM API it's much easier to get errors, if any. Using a command line tool besides the exit code you may have to intercept and parse the output, which is more difficult and may be language-specific. For a quick-and-dirty solution it's ok, but I would not use it as a general solution. Also check the JCL, IIRC there are some classes to manage services.
ldsandon
+13  A: 

Open the service with OpenService, and then disable it by passing Service_Disabled as the dwStartType parameter for ChangeServiceConfig. Specify a null pointer or Service_No_Change for the rest of the parameters since you're not interested in changing them.

Rob Kennedy
Also be aware the user must have proper rights to change service configurations.
ldsandon
+2  A: 

This is what i use

It's just a little wrapper around some Windows API Functions we found useful to handle NT-Services. It allows you to query, start, stop, pause and enable/disable NT-Services on the local or a remote system.

http://blog.marcduerst.com/post/How-to-use-TServiceManager-to-manage-Windows-services.aspx

Which lets you write 'nice' delphi code ;)

procedure DisableService(ServiceName: PChar);
var SM: TServiceManager;
begin
  SM:=TServiceManager.Create;
   try
     SM.Connect;
     SM.OpenServiceConnection(ServiceName);

   //not working with TServiceManager as is
   //but its easy to fix, see below        
    SM.DisableService;


   finally
    SM.Free;
   end;
end;

the DisableService section hasnt been written, but all that is needed is

 procedure TServiceManager.DisableService;
 begin
   ChangeServiceConfig(ServiceHandle, SERVICE_NO_CHANGE,SERVICE_DISABLED,SERVICE_NO_CHANGE, nil, nil, nil, nil, nil, nil, nil);
 end;
Christopher Chase
The Delphi code would be nicer if it demonstrated what Eder asked for instead of what he said he already knows how to do.
Rob Kennedy
yes your right, i didn't read the question completely, i shall update it
Christopher Chase
+4  A: 

Besides using the previous methods, if you need more control you can use WMI.
With Win32_Service class have access to all information of the services installed on the machine and you can has access to methods: Start, Stop, Pause, Resume, Interrogate, Create, Delete, Change, ChangeStartMode...

Here (Web / SourceForge)you can find a set of components to work with WMI (GLibWMI components Library); There are one called CServiceInfo thah give you all information and some methods of this class.

In addition with the package tere are some demos; One is called (ServiceControl) and implement all methods.

alt text

All the package are source included. See the code it can be usefull for you.

Regards.

Neftalí
El proyecto tiene muy buena pinta Neftalí... Felicitaciones por la iniciativa!
jachguate
Gracias Juan Antonio. La verdad es que aun está en la primera fase, pero tiene muchas posibilidades para ampliar funcionalidades. Un saludo.
Neftalí
+2  A: 

You can use file JclSvcCtrl.pas from JEDI Components Library (JCL). I have written a pseudo example that you could use. However, be aware that I didn't test it. But in this way it should work (error checks omitted):

M := TJclSCManager.Create;
For i := 0 to M.Count -1 do
begin
  S := M.Services[i]; //TJclNtService
  if CompareText(S.ServiceName, 'bla') then
  begin
    S.Stop;
    S.StartType := sstDisabled;   
    break;
  end;
end;
ChristianWimmer
Of course you can also use M.FindService. It does exactly the same!
ChristianWimmer
I'm a big fan of JEDI Library, I'm definitely use it.
Eder Gusatto