jilamints
asked on
Handling Windows Services
Hi All:
Allow me to be very specific here, I'm trying to get something that will specifically tell me if the Messenger service is "Automatically" started ? Then, all the user to to disable this. And secondly, just tell the user if it is running at the moment and of course give them the option to start and stop it...
Im not talking about MSN Messenger, Im talking about the net send version - I want something I can distribute to my networked machines and friends or clients - Instead of making them do it the old fashion way !!
Thanks in advance !
Allow me to be very specific here, I'm trying to get something that will specifically tell me if the Messenger service is "Automatically" started ? Then, all the user to to disable this. And secondly, just tell the user if it is running at the moment and of course give them the option to start and stop it...
Im not talking about MSN Messenger, Im talking about the net send version - I want something I can distribute to my networked machines and friends or clients - Instead of making them do it the old fashion way !!
Thanks in advance !
Hi,
I have two ideas. First, you can use NETSVC.EXE (part of the Windows 2000 Resource Kit) to query, stop and start services. It's a command line tool, so you could write a simple batch file to control it. It will start/stop the service on remote machines too, which may be useful in the context you describe.
Second, there are APIs to control services. The code below is from http://www.allapi.net/, a site that describes lots of APIs and gives example of how to use them. The main API is EnumServicesStatus but as you can see from the code below, there are others you will need too.
Regards
Crescendo
Const ERROR_MORE_DATA = 234
Const SERVICE_ACTIVE = &H1
Const SERVICE_INACTIVE = &H2
Const SC_MANAGER_ENUMERATE_SERVI CE = &H4
Const SERVICE_WIN32_OWN_PROCESS As Long = &H10
Const SERVICE_WIN32_SHARE_PROCES S As Long = &H20
Const SERVICE_WIN32 As Long = SERVICE_WIN32_OWN_PROCESS + SERVICE_WIN32_SHARE_PROCES S
Private Type SERVICE_STATUS
dwServiceType As Long
dwCurrentState As Long
dwControlsAccepted As Long
dwWin32ExitCode As Long
dwServiceSpecificExitCode As Long
dwCheckPoint As Long
dwWaitHint As Long
End Type
Private Type ENUM_SERVICE_STATUS
lpServiceName As Long
lpDisplayName As Long
ServiceStatus As SERVICE_STATUS
End Type
Private Declare Function OpenSCManager Lib "advapi32.dll" Alias "OpenSCManagerA" (ByVal lpMachineName As String, ByVal lpDatabaseName As String, ByVal dwDesiredAccess As Long) As Long
Private Declare Function EnumServicesStatus Lib "advapi32.dll" Alias "EnumServicesStatusA" (ByVal hSCManager As Long, ByVal dwServiceType As Long, ByVal dwServiceState As Long, lpServices As Any, ByVal cbBufSize As Long, pcbBytesNeeded As Long, lpServicesReturned As Long, lpResumeHandle As Long) As Long
Private Declare Function CloseServiceHandle Lib "advapi32.dll" (ByVal hSCObject As Long) As Long
Private Declare Function lstrcpy Lib "kernel32.dll" Alias "lstrcpyA" (szDest As String, szcSource As Long) As Long
Private Sub Form_Load()
'KPD-Team 2000
'URL: http://www.allapi.net/
'E-Mail: KPDTeam@Allapi.net
Dim hSCM As Long, lpEnumServiceStatus() As ENUM_SERVICE_STATUS, lngServiceStatusInfoBuffer As Long
Dim strServiceName As String * 250, lngBytesNeeded As Long, lngServicesReturned As Long
Dim hNextUnreadEntry As Long, lngStructsNeeded As Long, lngResult As Long, i As Long
'Open connection to Service Control Manager.
hSCM = OpenSCManager(vbNullString , vbNullString, SC_MANAGER_ENUMERATE_SERVI CE)
If hSCM = 0 Then
MsgBox "OpenSCManager failed. LastDllError = " & CStr(Err.LastDllError)
Exit Sub
End If
'Get buffer size (bytes) without passing a buffer
'and make sure starts at 0th entry.
hNextUnreadEntry = 0
lngResult = EnumServicesStatus(hSCM, SERVICE_WIN32, SERVICE_ACTIVE Or SERVICE_INACTIVE, ByVal &H0, &H0, lngBytesNeeded, lngServicesReturned, hNextUnreadEntry)
'We should receive MORE_DATA error.
If Not Err.LastDllError = ERROR_MORE_DATA Then
MsgBox "LastDLLError = " & CStr(Err.LastDllError)
Exit Sub
End If
'Calculate the number of structures needed.
lngStructsNeeded = lngBytesNeeded / Len(lpEnumServiceStatus(0) ) + 1
'Redimension the array according to our calculation.
ReDim lpEnumServiceStatus(lngStr uctsNeeded - 1)
'Get buffer size in bytes.
lngServiceStatusInfoBuffer = lngStructsNeeded * Len(lpEnumServiceStatus(0) )
'Get services information starting entry 0.
hNextUnreadEntry = 0
lngResult = EnumServicesStatus(hSCM, SERVICE_WIN32, SERVICE_ACTIVE Or SERVICE_INACTIVE, lpEnumServiceStatus(0), lngServiceStatusInfoBuffer , lngBytesNeeded, lngServicesReturned, hNextUnreadEntry)
If lngResult = 0 Then
MsgBox "EnumServicesStatus failed. LastDllError = " & CStr(Err.LastDllError)
Exit Sub
End If
'Get the strings and display them.
Me.AutoRedraw = True
Me.Print "All registered services:" + vbCrLf
For i = 0 To lngServicesReturned - 1
lngResult = lstrcpy(ByVal strServiceName, ByVal lpEnumServiceStatus(i).lpS erviceName )
Me.Print StripTerminator(strService Name) + " - ";
lngResult = lstrcpy(ByVal strServiceName, ByVal lpEnumServiceStatus(i).lpD isplayName )
Me.Print StripTerminator(strService Name)
Next i
'Clean up.
CloseServiceHandle (hSCM)
End Sub
Function StripTerminator(sInput As String) As String
Dim ZeroPos As Integer
ZeroPos = InStr(1, sInput, Chr$(0))
If ZeroPos > 0 Then
StripTerminator = Left$(sInput, ZeroPos - 1)
Else
StripTerminator = sInput
End If
End Function
I have two ideas. First, you can use NETSVC.EXE (part of the Windows 2000 Resource Kit) to query, stop and start services. It's a command line tool, so you could write a simple batch file to control it. It will start/stop the service on remote machines too, which may be useful in the context you describe.
Second, there are APIs to control services. The code below is from http://www.allapi.net/, a site that describes lots of APIs and gives example of how to use them. The main API is EnumServicesStatus but as you can see from the code below, there are others you will need too.
Regards
Crescendo
Const ERROR_MORE_DATA = 234
Const SERVICE_ACTIVE = &H1
Const SERVICE_INACTIVE = &H2
Const SC_MANAGER_ENUMERATE_SERVI
Const SERVICE_WIN32_OWN_PROCESS As Long = &H10
Const SERVICE_WIN32_SHARE_PROCES
Const SERVICE_WIN32 As Long = SERVICE_WIN32_OWN_PROCESS + SERVICE_WIN32_SHARE_PROCES
Private Type SERVICE_STATUS
dwServiceType As Long
dwCurrentState As Long
dwControlsAccepted As Long
dwWin32ExitCode As Long
dwServiceSpecificExitCode As Long
dwCheckPoint As Long
dwWaitHint As Long
End Type
Private Type ENUM_SERVICE_STATUS
lpServiceName As Long
lpDisplayName As Long
ServiceStatus As SERVICE_STATUS
End Type
Private Declare Function OpenSCManager Lib "advapi32.dll" Alias "OpenSCManagerA" (ByVal lpMachineName As String, ByVal lpDatabaseName As String, ByVal dwDesiredAccess As Long) As Long
Private Declare Function EnumServicesStatus Lib "advapi32.dll" Alias "EnumServicesStatusA" (ByVal hSCManager As Long, ByVal dwServiceType As Long, ByVal dwServiceState As Long, lpServices As Any, ByVal cbBufSize As Long, pcbBytesNeeded As Long, lpServicesReturned As Long, lpResumeHandle As Long) As Long
Private Declare Function CloseServiceHandle Lib "advapi32.dll" (ByVal hSCObject As Long) As Long
Private Declare Function lstrcpy Lib "kernel32.dll" Alias "lstrcpyA" (szDest As String, szcSource As Long) As Long
Private Sub Form_Load()
'KPD-Team 2000
'URL: http://www.allapi.net/
'E-Mail: KPDTeam@Allapi.net
Dim hSCM As Long, lpEnumServiceStatus() As ENUM_SERVICE_STATUS, lngServiceStatusInfoBuffer
Dim strServiceName As String * 250, lngBytesNeeded As Long, lngServicesReturned As Long
Dim hNextUnreadEntry As Long, lngStructsNeeded As Long, lngResult As Long, i As Long
'Open connection to Service Control Manager.
hSCM = OpenSCManager(vbNullString
If hSCM = 0 Then
MsgBox "OpenSCManager failed. LastDllError = " & CStr(Err.LastDllError)
Exit Sub
End If
'Get buffer size (bytes) without passing a buffer
'and make sure starts at 0th entry.
hNextUnreadEntry = 0
lngResult = EnumServicesStatus(hSCM, SERVICE_WIN32, SERVICE_ACTIVE Or SERVICE_INACTIVE, ByVal &H0, &H0, lngBytesNeeded, lngServicesReturned, hNextUnreadEntry)
'We should receive MORE_DATA error.
If Not Err.LastDllError = ERROR_MORE_DATA Then
MsgBox "LastDLLError = " & CStr(Err.LastDllError)
Exit Sub
End If
'Calculate the number of structures needed.
lngStructsNeeded = lngBytesNeeded / Len(lpEnumServiceStatus(0)
'Redimension the array according to our calculation.
ReDim lpEnumServiceStatus(lngStr
'Get buffer size in bytes.
lngServiceStatusInfoBuffer
'Get services information starting entry 0.
hNextUnreadEntry = 0
lngResult = EnumServicesStatus(hSCM, SERVICE_WIN32, SERVICE_ACTIVE Or SERVICE_INACTIVE, lpEnumServiceStatus(0), lngServiceStatusInfoBuffer
If lngResult = 0 Then
MsgBox "EnumServicesStatus failed. LastDllError = " & CStr(Err.LastDllError)
Exit Sub
End If
'Get the strings and display them.
Me.AutoRedraw = True
Me.Print "All registered services:" + vbCrLf
For i = 0 To lngServicesReturned - 1
lngResult = lstrcpy(ByVal strServiceName, ByVal lpEnumServiceStatus(i).lpS
Me.Print StripTerminator(strService
lngResult = lstrcpy(ByVal strServiceName, ByVal lpEnumServiceStatus(i).lpD
Me.Print StripTerminator(strService
Next i
'Clean up.
CloseServiceHandle (hSCM)
End Sub
Function StripTerminator(sInput As String) As String
Dim ZeroPos As Integer
ZeroPos = InStr(1, sInput, Chr$(0))
If ZeroPos > 0 Then
StripTerminator = Left$(sInput, ZeroPos - 1)
Else
StripTerminator = sInput
End If
End Function
ASKER
TimCottee: Thanks for that, that is really fantastic stuff ! I'm of course no expert with VB, but that was easy enough to get my head around after a little thing - I'm sure I can now use this within my own code... If you could look into that issue of the Autostart, that would be great...
The same deal again - Want to be able to test its state, and of course enable or disable it...
Now correct me if I'm wrong here (because I had to get the computers name via the API) I could really now get a list of computer names within the workgroup, or domain, and then do the same thing ?
Check service status etc ? Correct ? Just wondering...
The same deal again - Want to be able to test its state, and of course enable or disable it...
Now correct me if I'm wrong here (because I had to get the computers name via the API) I could really now get a list of computer names within the workgroup, or domain, and then do the same thing ?
Check service status etc ? Correct ? Just wondering...
ASKER
I would also like to say, I will be increasing the points to provide crescendo with his fair share... I would like to offer you 250 points for your efforts if you think that is fair... As for TimCottee, I will still give you the 500 points, but would like to offer more if you can complete my question in full... :-)
Thanks again guys ! GREAT HELP !
Thanks again guys ! GREAT HELP !
ASKER
Sorry for the number of posts, but I have just tested this on Windows 2000 & XP - Both work fine... NT I can't test it on but on Windows 2000 Adv. Server, it says the service is not found ? How can that be ? It is exactly the same ?
Hi jilamints
Thanks for the offer of points. Did you try using netsvc.exe? It's really easy to use to start and stop services, and find out if they are running. For example, you could create a batch file that sends it output to a text file, and the text file is easy to parse. The responses you get from netsvc.exe are simply:
Service is running on \\ComputerName
Service is stopped on \\ComputerName
Service is pending start on \\ComputerName
Service is pending stop on \\ComputerName
So a batch file like below would do the trick:
@ECHO OFF
NETSVC.EXE %1 %2 %3 > C:\MyDir\Results.txt
Where %1 is the service name ("Messenger" in your case)
%2 is the computer name
%3 is the action, /query, /stop, /start
You shell this in VB, then open the text file C:\MyDir\Results.txt and see if it says "Service is running" etc. and take action accordingly. That does everything you asked for, and is easy to code.
crescendo
Thanks for the offer of points. Did you try using netsvc.exe? It's really easy to use to start and stop services, and find out if they are running. For example, you could create a batch file that sends it output to a text file, and the text file is easy to parse. The responses you get from netsvc.exe are simply:
Service is running on \\ComputerName
Service is stopped on \\ComputerName
Service is pending start on \\ComputerName
Service is pending stop on \\ComputerName
So a batch file like below would do the trick:
@ECHO OFF
NETSVC.EXE %1 %2 %3 > C:\MyDir\Results.txt
Where %1 is the service name ("Messenger" in your case)
%2 is the computer name
%3 is the action, /query, /stop, /start
You shell this in VB, then open the text file C:\MyDir\Results.txt and see if it says "Service is running" etc. and take action accordingly. That does everything you asked for, and is easy to code.
crescendo
ASKER
I have seen it done like this before but was trying to consider my long term options such as allowing the application to work over a network. In such an event I thought that *maybe* using something like Tims answers might be just a touch bit better ? Not sure but I do like to keep my options open !
Kind Regards
Kind Regards
But netsvc.exe DOES work over a network, which is why I suggested it.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
TimCottee: Any Luck ?
Indeed, I remembered how you can do this. It is actually governed by registry entries:
HKEY_LOCAL_MACHINE\SYSTEM\ CurrentCon trolSet\Se rvices\Rpc net\Start = 2
For example is Automatic.
The values for this key are:
START TYPE LOADER MEANING
0x0 Kernel Represents a part of the
(Boot) driver stack for the boot
(startup) volume and must
therefore be loaded by the
Boot Loader.
0x1 I/O Represents a driver to be loaded
(System) subsystem at Kernel initialization.
0x2 Service To be loaded or started
(Auto load) Control automatically for all startups,
Manager regardless of service type.
0x3 Service Available, regardless of type,
(Load on Control but will not be started until
demand) Manager the user starts it (for example,
by using the Devices icon in
Control Panel).
0x4 Service NOT TO BE STARTED UNDER ANY
(disabled) Control CONDITIONS.
Manager
For more info see http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/q103/0/00.asp&NoWebContent=1
HKEY_LOCAL_MACHINE\SYSTEM\
For example is Automatic.
The values for this key are:
START TYPE LOADER MEANING
0x0 Kernel Represents a part of the
(Boot) driver stack for the boot
(startup) volume and must
therefore be loaded by the
Boot Loader.
0x1 I/O Represents a driver to be loaded
(System) subsystem at Kernel initialization.
0x2 Service To be loaded or started
(Auto load) Control automatically for all startups,
Manager regardless of service type.
0x3 Service Available, regardless of type,
(Load on Control but will not be started until
demand) Manager the user starts it (for example,
by using the Devices icon in
Control Panel).
0x4 Service NOT TO BE STARTED UNDER ANY
(disabled) Control CONDITIONS.
Manager
For more info see http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/q103/0/00.asp&NoWebContent=1
By the way, the wbem scripting approach works over a network too - assuming that you have the correct privileges.
ASKER
DominicCronin: Your answer sounds like its the pick of the bunch here... However could you just clear up one thing... What privileges would be required to use this over a network ? See I wouldn't mind (although Im not sure how) listing in a treeview or whatever, a list of networked computers and being able to try and apply this code to those machines...
But if it could detect if it had access, that would be great... I know Im kinda going beyond my orginal question but yeah... Any help would be great...
PS: Any other reason why this would NOT work on a Windows 2000 or XP machine that I need to know about...
Also to everyone else... At this stage I do prefer DominicCronin answer and will give him full points... With that said, I also feel crescendo should get a little something too as should you Tim ? If you want to add to this, let me know - Will arrange a new blank question and give out the points as you all see fit...
Kind Regards,
Jilamints
But if it could detect if it had access, that would be great... I know Im kinda going beyond my orginal question but yeah... Any help would be great...
PS: Any other reason why this would NOT work on a Windows 2000 or XP machine that I need to know about...
Also to everyone else... At this stage I do prefer DominicCronin answer and will give him full points... With that said, I also feel crescendo should get a little something too as should you Tim ? If you want to add to this, let me know - Will arrange a new blank question and give out the points as you all see fit...
Kind Regards,
Jilamints
Providing you have administrator privileges on the domain and these have not been explicitly modified or denied on any of the machines that are part of the domain then Dominic's approach will work on any NT based system from NT3.51 up. There are some applications which do this specifically, VNCCon for example is a great tool that allows you to manage VNC installations and services across multiple domains in fact always with the proviso that you have the correct administrative privileges.
jil - I'm also happy with a split or something - there's plenty of good effort gone in here.
At Tim says - basically you need to have sufficient privileges that you could do the action if you were the interactive user. Check out MSDN for details of extra things you can specify to control security. Any recent version of Windows supports this.
At Tim says - basically you need to have sufficient privileges that you could do the action if you were the interactive user. Check out MSDN for details of extra things you can specify to control security. Any recent version of Windows supports this.
ASKER
I have been of course playing around with all this and found that using Dominics method can *sometimes* when you go to start the service, fail to do so - For that reason, I think I might use Tims answer for that side of things and Doms for the Auto start part which seems to work perfectly (not an error in the code btw...)
Would anyone think this could cause problems down the track ?
Tim: I will set up a new question to provide points to yourself - Will then prepare to close this off in the next few days...
Once again, many thanks to all ! I think my next question will be a networking one hahahaha ! Thanks again guys !
Regards,
Jilamints
Would anyone think this could cause problems down the track ?
Tim: I will set up a new question to provide points to yourself - Will then prepare to close this off in the next few days...
Once again, many thanks to all ! I think my next question will be a networking one hahahaha ! Thanks again guys !
Regards,
Jilamints
ASKER
When you start a service using a wbem script, the function returns a code indicating either 0 for success or various error codes.
http://www.timcottee.tk has a sample application that can manipulate services. It will cover the second part of your request (being able to stop and start). Will have a look into the automatic start/disable stuff shortly.
Tim Cottee MCSD, MCDBA, CPIM
Brainbench MVP for Visual Basic
http://www.brainbench.com
Experts-Exchange Advisory Board Member