Solved

Getting Information about a WIN NT Service from VB ?

Posted on 1998-05-29
9
549 Views
Last Modified: 2008-02-01
Hi !
Has anyone succceeded with retrieving Service Information
using : the API call QueryServiceConfig from VB.
In that case I want to know how !

Like this:
The API requires a pointer to a structure, containing both numeric and string data.  This I have made with API text viewer. Nothing strange with this!

But, the result in the stucture after a successfull call is a mess within the strings. The Numerics works fine, but the separate strings are all placed in the first string and this one starts with a lot of strange caracters in the beginning !

Anyone ?
0
Comment
Question by:Jedi
9 Comments
 
LVL 6

Expert Comment

by:clifABB
ID: 1462000
Can you post your code?
0
 
LVL 4

Expert Comment

by:zsi
ID: 1462001
What service are you trying to get information on?
0
 
LVL 1

Author Comment

by:Jedi
ID: 1462002
I'm trying to get information about a lot of services, in fact
every registered service

0
Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

 
LVL 1

Author Comment

by:Jedi
ID: 1462003
Ok som e code I'm using:
It's a lot of code to post if it's going to compile, the API calls and error handeling and the declarations takes a lot of space.

I'm mostly interested in code that will retrieve cdata using the:
QueryServiceConfig call:
If there is some need for initializing my VB strings before the call or something.
Some code :
'Declarations:
'-------------
Public Declare Function QueryServiceConfig Lib "advapi32.dll" Alias "QueryServiceConfigA" (ByVal hService As Long, lpServiceConfig As QUERY_SERVICE_CONFIG, ByVal cbBufSize As Long, pcbBytesNeeded As Long) As Long

Type QUERY_SERVICE_CONFIG
        dwServiceType As Long
        dwStartType As Long
        dwErrorControl As Long
        lpBinaryPathName As String '* 255
        lpLoadOrderGroup As String '* 255
        dwTagId As Long
        lpDependencies As String '* 255
        lpServiceStartName As String '* 255
        lpDisplayName As String '* 255
End Type

'---------------------------

'Running
'---------------------------
Dim lresult As Long
Dim pcbBytesNeeded As Long
Dim lpServiceConfig As QUERY_SERVICE_CONFIG
Dim cbBufSize As Long

lpServiceConfig.dwServiceType = 0
lpServiceConfig.dwStartType = 0
lpServiceConfig.dwErrorControl=0
lpServiceConfig.lpBinaryPathName = String(255, vbNullChar)lpServiceConfig.lpLoadOrderGroup = String(255, vbNullChar)lpServiceConfig.dwTagId = 0
lpServiceConfig.lpDependencies = String(255, vbNullChar)lpServiceConfig.lpServiceStartName = String(255, vbNullChar)  lpServiceConfig.lpDisplayName = String(255, vbNullChar)      


cbBufSize = LenB(lpServiceConfig)


'Stop Service it first
'    SvcsStop (lpServiceName)
   
    'Open the DB
'    hSCManager = SvcsOpenDB("")
   
'    If hSCManager = Null Then
'        SvcsDisable = False
'        Exit Function
'        Exit Sub
'    End If
       
    'Open the service in question
'    hService = SvcsOpen(hSCManager, lpServiceName)
   
    'Get the right values
lresult = QueryServiceConfig(hService, lpServiceConfig, cbBufSize, pcbBytesNeeded)

'****The strings within the lpServiceConfig structure are a mess.

Hope it gives some clues

0
 

Expert Comment

by:mwalsh111097
ID: 1462004
The problem arises when you try to access null-terminated strings through pointers embedded in a structure.  In order to do this properly, you need to retrieve the string pointers as integer values (define them as "Long" in your VB type, not "String") and then convert them into VB strings.

The following code is a sample of how to do this.  The C++ code is for a DLL which will convert a pointer stored as an integer value into a VB string, and the VB application is a simple demonstration of how to use the library.

==================================
GetBSTR.cpp
==================================
#define WIN32_LEAN_AND_MEAN
#define WIN32_EXTRA_LEAN
#pragma warning( disable : 4201 )
#include <windows.h>
#include <ole2.h>


char const * const gc_p = "TestString";


/*
 *  test function for returning a pointer to a string as a long
 *  integer value...
 */
extern "C" long __declspec( dllexport ) __stdcall GetString( )
    {
    return long( gc_p );
    }


/*
 *  take the given string pointer and convert it to a Visual Basic
 *  string...
 */
extern "C" BSTR __declspec( dllexport ) __stdcall GetStringFromPointer( char const * const p )
    {
    return ::SysAllocStringByteLen( p
                                  , ::strlen( p )
                                  );
    }



==================================
VB Sample Program
==================================
Option Explicit
Declare Function GetString Lib "GetBSTR.dll" Alias "_GetString@0" () As Long
Declare Function GetStringFromPointer Lib "GetBSTR.dll" Alias "_GetStringFromPointer@4" (ByVal l As Long) As String


Sub main()

Dim l As Long
l = GetString()

Dim s As String
s = GetStringFromPointer(l)

End Sub

0
 
LVL 5

Expert Comment

by:bin_huwairib
ID: 1462005
Jedi,

The main problem here is the size of QUERY_SERVICE_CONFIG is not enough for the API function QueryServiceConfig to retrieve the service information, so you must allocate enough space for QUERY_SERVICE_CONFIG structure before calling QueryServiceConfig.
The following steps must be done:
1- Change the variables with string data type in QUERY_SERVICE_CONFIG type to Long data type.
2- Declare a variable as an array with 10 dimensions of this type and pass it to QueryServiceConfig function with the size (10 * length of the first dimension of variable).
3- To get the string use lstrcpy and lstrlen API functions (you don't have to write a C code to do that).

The following example illustrates how to get the information for Schadule service:

Example
=======
Private Type QUERY_SERVICE_CONFIG
 dwServiceType As Long
 dwStartType As Long
 dwErrorControl As Long
 lpBinaryPathName As Long
 lpLoadOrderGroup As Long
 dwTagId As Long
 lpDependencies As Long
 lpServiceStartName As Long
 lpDisplayName As Long
End Type

Private Const GENERIC_READ = &H80000000
Private Const SERVICE_QUERY_CONFIG = &H1

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 OpenService Lib "advapi32.dll" Alias "OpenServiceA" (ByVal hSCManager As Long, ByVal lpServiceName As String, ByVal dwDesiredAccess As Long) As Long
Private Declare Function CloseServiceHandle Lib "advapi32.dll" (ByVal hSCObject As Long) As Long
Private Declare Function QueryServiceConfig Lib "advapi32.dll" Alias "QueryServiceConfigA" (ByVal hService As Long, lpServiceConfig As QUERY_SERVICE_CONFIG, ByVal cbBufSize As Long, pcbBytesNeeded As Long) As Long
Private Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyA" (ByVal lpString1 As String, ByVal lpString2 As Long) As Long
Private Declare Function lstrlen Lib "kernel32" Alias "lstrlenA" (ByVal lpString As String) As Long

Private Sub Command1_Click()
 Dim hSCM As Long
 Dim hService As Long
 Dim sMachineName As String
 Dim sDatabaseName As String
 Dim lResult As Long
 Dim pcbBytesNeeded As Long
 Dim lpServiceConfig() As QUERY_SERVICE_CONFIG
 Dim sBinaryPathName As String
 Dim sLoadOrderGroup As String
 Dim sDependencies As String
 Dim sServiceStartName As String
 Dim sDisplayName As String
 
 hSCM = OpenSCManager(sMachineName, sDatabaseName, GENERIC_READ)
 hService = OpenService(hSCM, "Schedule", SERVICE_QUERY_CONFIG)
 
 ReDim lpServiceConfig(100) As QUERY_SERVICE_CONFIG
 lResult = QueryServiceConfig(hService, lpServiceConfig(0), 100 * Len(lpServiceConfig(0)), pcbBytesNeeded)
 
 sBinaryPathName = Space(255)
 lResult = lstrcpy(sBinaryPathName, lpServiceConfig(0).lpBinaryPathName)
 sBinaryPathName = Mid(sBinaryPathName, 1, lstrlen(sBinaryPathName))
 
 sLoadOrderGroup = Space(255)
 lResult = lstrcpy(sLoadOrderGroup, lpServiceConfig(0).lpLoadOrderGroup)
 sLoadOrderGroup = Mid(sLoadOrderGroup, 1, lstrlen(sLoadOrderGroup))
 
 sDependencies = Space(255)
 lResult = lstrcpy(sDependencies, lpServiceConfig(0).lpDependencies)
 sDependencies = Mid(sDependencies, 1, lstrlen(sDependencies))
 
 sServiceStartName = Space(255)
 lResult = lstrcpy(sServiceStartName, lpServiceConfig(0).lpServiceStartName)
 sServiceStartName = Mid(sServiceStartName, 1, lstrlen(sServiceStartName))
 
 sDisplayName = Space(255)
 lResult = lstrcpy(sDisplayName, lpServiceConfig(0).lpDisplayName)
 sDisplayName = Mid(sDisplayName, 1, lstrlen(sDisplayName))
 
 MsgBox "Service Type: " & lpServiceConfig(0).dwServiceType & vbCrLf & _
        "Start Type: " & lpServiceConfig(0).dwStartType & vbCrLf & _
        "Error Control: " & lpServiceConfig(0).dwErrorControl & vbCrLf & _
        "Binary Path Name: " & sBinaryPathName & vbCrLf & _
        "Load Order Group: " & sLoadOrderGroup & vbCrLf & _
        "Tag ID: " & lpServiceConfig(0).dwTagId & vbCrLf & _
        "Dependencies: " & sDependencies & vbCrLf & _
        "Service Start Name: " & sServiceStartName & vbCrLf & _
        "Display Name: " & sDisplayName
 
 Call CloseServiceHandle(hService)
 Call CloseServiceHandle(hSCM)
End Sub


Best regards
Bin Huwairib
0
 
LVL 1

Author Comment

by:Jedi
ID: 1462006
Thanks Mwalsh, but the commented answer from Bin is even better.

Exelent answer from Bin Huwairib ,if you post a answer I'll give you the points !
//Jedi

0
 
LVL 5

Accepted Solution

by:
bin_huwairib earned 500 total points
ID: 1462007
Jedi,

I'm glad that you've solved your problem.


Best regards
Bin Huwairib
0
 
LVL 1

Author Comment

by:Jedi
ID: 1462008
Excellent , That was the kind of answerI was looking for,
An explanation and a solution.
Thanks again

//Jedi
0

Featured Post

Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction While answering a recent question about filtering a custom class collection, I realized that this could be accomplished with very little code by using the ScriptControl (SC) library.  This article will introduce you to the SC library a…
Background What I'm presenting in this article is the result of 2 conditions in my work area: We have a SQL Server production environment but no development or test environment; andWe have an MS Access front end using tables in SQL Server but we a…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

816 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

7 Experts available now in Live!

Get 1:1 Help Now