35、服务管理实用工具开发详解

服务管理实用工具开发详解

在服务管理的开发中,我们常常需要实现对服务状态的查询、启动、停止和恢复等操作。下面将详细介绍如何开发一个实用工具来完成这些任务。

1. 关键方法与结构
1.1 OpenService 方法

该方法用于打开一个服务并返回服务对象。代码如下:

' Open a service and return the service object 
Public Function OpenService(Svc As ServiceStatus, rights As _ 
ServiceAccessRights) As ServiceObject 
    Dim hnd& 
    Dim newservice As New ServiceObject 

    ' Service manager must be open to perform this operation 
    If schandle = 0 Then Exit Function 
    hnd = intOpenService(schandle, Svc.Name, rights Or SERVICE_QUERY_STATUS) 
    If hnd <> 0 Then 
        ' Initialize the service via a Friend function 
        Call newservice.Initialize(hnd,  Svc.Name, Svc.DisplayName) 
        Set OpenService = newservice 
    End If 
End Function
1.2 EnumServicesStatus 函数

此函数用于检索包含 ServiceStatus 对象的集合,是较为复杂的一个函数。它涉及到 ENUM_SERVICE_STATUS SERVICE_STATUS 两个结构。

C 语言中的结构声明

typedef struct _ENUM_SERVICE_STATUS { // ess 
    LPTSTR lpServiceName; 
    LPTSTR lpDisplayName; 
    SERVICE_STATUS ServiceStatus; 
} ENUM_SERVICE_STATUS, *LPENUM_SERVICE_STATUS; 

typedef struct _SERVICE_STATUS { // ss 
    DWORD dwServiceType; 
    DWORD dwCurrentState; 
    DWORD dwControlsAccepted; 
    DWORD dwWin32ExitCode;
    DWORD dwServiceSpecificExitCode; 
    DWORD dwCheckPoint; 
    DWORD dwWaitHint; 
} SERVICE_STATUS, *LPSERVICE_STATUS;

Visual Basic 中的结构声明

Public Type ENUM_SERVICE_STATUS 
    lpServiceName As Long 
    lpDisplayName As Long 
    Status As SERVICE_STATUS 
End Type 

' Service structures 
Public 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

EnumServicesStatus 函数的代码如下:

' Retrieve a collection containing ServiceStatus objects 
Public Function EnumServicesStatus() As Collection 
    Dim res& 
    Dim lpServices As Long 
    Dim BytesNeeded As Long 
    Dim ServicesReturned As Long 
    Dim ResumeHandle As Long 
    Dim Buffer() As Byte 
    ReDim Buffer(512) 
    Dim x& 
    Dim CurrentOffset& 
    Dim c As New Collection 
    Dim s As ServiceStatus 
    Dim continue As Boolean 

    Do 
        ' Load the buffer with as many services as possible 
        ' We exclude driver services for now 
        res = intEnumServicesStatus(schandle, &H30, 3, VarPtr(Buffer(0)), _ 
        UBound(Buffer()), BytesNeeded, ServicesReturned, ResumeHandle) 
        If res = 0 And Err.LastDllError = ERROR_MORE DATA Then 
            ' Buffer couldn't hold all the services 
            continue = True 
        Else 
            continue = False 
        End If 
        For x = 1 To ServicesReturned 
            Set s = New ServiceStatus 
            ' The ServiceStatus buffer does the actual extraction 
            Call s.ParseServiceInfo(Buffer(), CurrentOffset) 
            c.Add s 
            ' 36 is the size of the ENUM_SERVICE_STATUS structure 
            CurrentOffset = CurrentOffset + 36 
        Next x 
        If continue Then 
            ' Prepare for the next call 
            CurrentOffset = 0 
            ReDim Buffer(BytesNeeded) 
        End If 
    Loop While continue 
    Set EnumServicesStatus = c 
End Function
2. 服务状态类

ServiceStatus 类用于存储服务的最新状态信息。它有两种初始化方式:一种是解析 EnumServicesStatus 函数创建的缓冲区;另一种是使用 InternalInitialize 函数直接设置私有信息。

' Holds the latest value of each 
Private Status As SERVICE_STATUS 
Private SvcName As String 
Private intDisplayName As String 

' Used by the internal objects to initialize a new ServiceStatus object 
' that is not created via an enumeration. 
Friend Sub Internallnitialize(pName As String, pDisplay As String, _ 
stat As SERVICE_STATUS) 
    intDisplayName = pDisplay 
    SvcName = pName 
    LSet Status = stat 
End Sub

' Extracts the private information from the buffer. Data is assumed 
' to start at the specified offset 
' Always returns 0 
Friend Function ParseServiceInfo(Buffer() As Byte, ByVal Offset As Long) _ 
As Long 
    Dim svcstat As ENUM_SERVICE_STATUS 
    ' Copy the service structure 
    Call RtlMoveMemory(VarPtr(svcstat), VarPtr(Buffer(Offset)), Len(svcstat)) 
    ' Extract the names 
    SvcName = GetVBStringFromAddress(svcstat.lpServiceName) 
    intDisplayName = GetVBStringFromAddress(svcstat.lpDisplayName) 
    ' Store the SERVICE_STATUS portion only 
    LSet Status = svcstat.Status
End Function 

' Get a VB string from an address 
Public Function GetVBStringFromAddress(ByVal addr&) As String 
    Dim uselen& 
    Dim res$ 
    If addr = 0 Then Exit Function 
    uselen = lstrlen(addr) 
    res$ = String$(uselen + 1, 0) 
    Call lstrcpy(res, addr) 
    GetVBStringFromAddress = Left$(res$, uselen) 
End Function
3. 服务对象类

ServiceObject 类相对简单,它内部存储服务句柄、服务名称和显示名称,并提供了停止、启动和查询服务状态的方法。

' Service Object Class 
' Copyright © 1998 by Desaware Inc. All Rights Reserved 

' This object represents an open service 

Option Explicit 

Private intServiceHandle As Long 
Private intServiceName As String 
Private intDisplayName As String 

' For convenience, this object is initialized by the ServiceManager 
' with both the name and display name 
Friend Sub Initialize(ByVal hnd As Long, Name As String, _ 
DisplayName As String) 
    intServiceHandle = hnd 
    intServiceName = Name 
    intDisplayName = DisplayName 
End Sub 

' Get the short name 
Property Get ServiceName() As String 
    ServiceName = intServiceName
End Property 

' Get the current status 
Property Get QueryServiceStatus() As ServiceStatus 
    Dim stat As SERVICE_STATUS 
    Dim res& 
    Dim sres As New ServiceStatus 
    res = intQueryServiceStatus(intServiceHandle, stat) 
    If res <> 0 Then 
        ' Another way to get a ServiceStatus object 
        Call sres.InternalInitialize(intServiceName, intDisplayName, stat) 
        Set QueryServiceStatus = sres 
    End If 
End Property 

' Perform Stop, Pause, Continue and Interrogate 
Public Function ServiceControl(Operation As ServiceControlConstants) As Long 
    Dim stat As SERVICE_STATUS 
    Dim res& 
    res = intControlService(intServiceHandle, Operation, stat) 
    ServiceControl = res 
End Function 

' Perform start 
Public Function StartService() 
    Dim res& 
    res = intStartService(intServiceHandle, 0, 0) 
    StartService = res 
End Function 

' Close the handle on termination 
Private Sub Class_Terminate() 
    If intServiceHandle <> 0 Then 
        Call CloseServiceHandle(intServiceHandle) 
    End If 
End Sub
4. 实用工具的开发
4.1 工具功能概述

该实用工具的目标是创建一个可以轻松停止并重新启动 Internet Information Services 的工具,以便替换 Active Server Page 调用的 DLL。它具有以下功能:
- 一个列表框,用于显示每个服务的名称和显示名称,支持多选。
- 启动和停止一个或多个服务的按钮。
- 一个按钮,用于将所有服务恢复到程序启动时的原始状态。
- 一种跟踪更改的方式,以便在程序关闭时提示是否将服务恢复到原始状态。
- 一个按钮,用于选择 IIS 服务。

4.2 变量定义
Dim sc As New ServiceManager 

Dim ServiceCollection As Collection ' Hold current states 
Dim OriginalStates As Collection    ' Record original states
' Collection of ServiceObject objects that are currently 
' being changed 
Dim ChangesInProgress As Collection 

Dim Changed As Boolean  ' Mark true if any state change has been caused 
Dim unloadpending As Boolean    ' Mark true if final restore operation 

' 0 to restore 
Dim TargetState As ServiceStateConstants
4.3 表单加载事件
Private Sub Form_Load() 
    Dim res& 
    ' Open the ServiceManager 
    res = sc.OpenSCManager("", "", SC_MANAGER_ENUMERATE_SERVICE _ 
    Or SC_MANAGER_CONNECT) 
    ' Update the ServiceCollection and display the services 
    LoadList True 
    Set OriginalStates = ServiceCollection 
    ' We don't want to hold two references to the collection 
    Set ServiceCollection = Nothing 
End Sub
4.4 加载服务列表函数
' Loads the ServiceCollection collection with a list of all services 
' Optionally displays them 
Private Sub LoadList(bDisplay As Boolean) 
    Dim res& 
    Dim svcstat As ServiceStatus 
    lstServices.Refresh 
    Set ServiceCollection = sc.EnumServicesStatus() 
    If bDisplay Then 
        For Each svcstat In ServiceCollection 
            lstServices.AddItem svcstat.Name & ":   " & svcstat.DisplayName 
        Next 
    End If
End Sub
4.5 启用或禁用用户界面函数
' Enables or disables the user interface of the application. 
' Also controls the mouse pointer and timer. 
' The UI must be disabled while service start or stop is in progress 
Private Function EnablePanel(ByVal bEnabled As Boolean) 
    cmdStop.Enabled = bEnabled 
    cmdStart.Enabled = bEnabled 
    cmdRestore.Enabled = bEnabled 
    lstServices.Enabled = bEnabled 
    If Not bEnabled Then 
        Screen.MousePointer = vbHourglass 
        Timeri.Enabled = True 
    Else 
        Screen.MousePointer = vbNormal 
        Timer1.Enabled = False 
    End If 

End Function
4.6 打开选定服务函数
' Loads the ChangesInProgress collection with the 
' ServiceObject objects for the selected services 
Private Function OpenSelectedServices() 
    Dim index& 
    Dim currententry$ 
    Dim svcstat As ServiceStatus 
    Call LoadList(False) 
    Set ChangesInProgress = New Collection
    For index = 0 To lstServices.ListCount - 1 
        If lstServices.Selected(index) Then 
            currententry = lstServices.List(index) 
            For Each svcstat In ServiceCollection 
                ' Match based on the service name 
                If InStr(currententry, svcstat.Name & ":") = 1 Then 
                    ChangesInProgress.Add sc.OpenService(svcstat, _ 
                    SERVICE_START Or SERVICE_STOP), svcstat.Name 
                    Exit For 
                End If 
            Next 
        End If 
    Next index 
End Function
5. 服务操作代码
5.1 停止选定服务
' Stops the selected services 
Private Sub cmdStop_Click() 
    Dim so As ServiceObject 
    Dim stat As ServiceStatus 
    Dim starttimer As Boolean 
    Dim RemoveThis As Boolean 
    Dim res& 
    Call OpenSelectedServices 
    For Each so In ChangesInProgress 
        Set stat = so.QueryServiceStatus 
        If stat.CurrentState <> SERVICE_STOPPED Then 
            res = so.ServiceControl(SERVICE_CONTROL_STOP) 
            If res <> 0 Then 
                starttimer = True 
            Else 
                RemoveThis = True 
            End If 
        Else 
            RemoveThis = True 
        End If 
        If RemoveThis Then ChangesInProgress.Remove stat.Name
        RemoveThis = False 
    Next so 
    If starttimer Then 
        EnablePanel False 
        TargetState = SERVICE_STOPPED 
        Changed = True 
    Else 
        Set ChangesInProgress = Nothing 
    End If 
End Sub 
5.2 启动选定服务
' Starts the selected services 
Private Sub cmdStart_Click() 
    Dim so As ServiceObject 
    Dim stat As ServiceStatus 
    Dim starttimer As Boolean 
    Dim RemoveThis As Boolean 
    Dim res& 
    Call OpenSelectedServices 
    For Each so In ChangesInProgress 
        Set stat = so.QueryServiceStatus 
        If stat.CurrentState <> SERVICE_RUNNING Then 
            res = so.StartService 
            If res <>  Then 
                starttimer = True 
            Else 
                RemoveThis = True 
            End If 
        Else 
            RemoveThis = True 
        End If 
        If RemoveThis Then ChangesInProgress.Remove stat.Name 
        RemoveThis = False 
    Next so 
    If starttimer Then 
        EnablePanel False 
        TargetState = SERVICE_RUNNING 
        Changed = True 
    Else 
        Set ChangesInProgress = Nothing 
    End If 
End Sub
5.3 恢复服务到原始状态
' Restores services to their original state 
Private Sub cmdRestore_Click() 
    Dim so As ServiceObject 
    Dim stat As ServiceStatus 
    Dim starttimer As Boolean 
    Dim orig As ServiceStateConstants 
    Dim res& 
    Call LoadList(False) 
    Set ChangesInProgress = New Collection 
    For Each stat In ServiceCollection 
        If stat.CurrentState <> OriginalState(stat.Name) Then 
            ChangesInProgress.Add sc.OpenService(stat, SERVICE_START _ 
            Or SERVICE_STOP), stat.Name 
        End If 
    Next 
    For Each so In ChangesInProgress 
        orig = OriginalState(so.ServiceName) 
        If orig = SERVICE_RUNNING Then 
            res = so.StartService 
        Else 
            res = so.ServiceControl(SERVICE_CONTROL_STOP) 
        End If 
        If res <> 0 Then 
            starttimer = True 
        Else 
ChangesInProgress.Remove so.ServiceName 
        End If 
    Next so 
    If starttimer Then 
        EnablePanel False 
        TargetState = 0 
        Changed = True 
    Else 
        Set ChangesInProgress = Nothing 
    End If 
End Sub
6. 程序关闭与定时器处理
6.1 表单卸载事件
Private Sub Form_Unload(Cancel As Integer) 
    Dim res& 
    If Changed Then 
        ' If any change has been made, give the user 
        ' the option to restore 
        res = MsgBox("Changes have been made - Restore service states?", _ 
        vbYesNo, "Exit confirmation") 
        If res = vbYes Then 
            unloadpending = True 
            Me.Hide ' Hide the form - no reason to clutter the screen 
            cmdRestore_Click 
            Cancel = -1 
            Changed = False 
            Exit Sub 
        End If 
    End If 

    Set ServiceCollection = Nothing 
    Set OriginalStates = Nothing 
    Set ChangesInProgress = Nothing 
    Set sc = Nothing 
End Sub
6.2 定时器事件
' Poll for the completion of the operation in progress 
Private Sub Timer1_Timer() 
    Dim so As ServiceObject 
    Dim stat As ServiceStatus 
    Dim target As Long 
    For Each so In ChangesInProgress 
        Set stat = so.QueryServiceStatus 
        ' Zero is the restore condition 
        If TargetState = 0 Then 
            target = OriginalState(stat.Name) 
        Else 
            target = TargetState 
        End If 

        If stat.CurrentState = target Then
            ' 服务进入目标状态,移除对象
        End If
    Next
    ' 集合为空时,重新启用用户界面
End Sub

总结

通过以上步骤,我们完成了一个服务管理实用工具的开发。该工具可以方便地对服务进行启动、停止和恢复操作,并且能够跟踪服务状态的变化。在开发过程中,我们使用了多个类和函数,涉及到服务状态的查询、解析和控制等操作。通过合理的设计和代码实现,我们可以有效地管理系统中的服务。

下面是一个简单的流程图,展示了服务操作的基本流程:

graph TD;
    A[开始] --> B[打开服务管理器];
    B --> C[加载服务列表];
    C --> D{选择操作};
    D -- 停止服务 --> E[打开选定服务];
    D -- 启动服务 --> E;
    D -- 恢复服务 --> F[对比当前状态与原始状态];
    F --> E;
    E --> G[执行操作];
    G --> H{操作完成?};
    H -- 是 --> I[移除已完成服务];
    I --> J{所有服务完成?};
    J -- 是 --> K[重新启用界面];
    J -- 否 --> G;
    H -- 否 --> G;
    K --> L[结束];

同时,我们还可以用表格总结一下关键类和方法的功能:
| 类/方法 | 功能 |
| ---- | ---- |
| OpenService | 打开一个服务并返回服务对象 |
| EnumServicesStatus | 检索包含 ServiceStatus 对象的集合 |
| ServiceStatus | 存储服务的最新状态信息 |
| ServiceObject | 提供停止、启动和查询服务状态的方法 |
| LoadList | 加载服务列表 |
| OpenSelectedServices | 打开选定的服务 |
| cmdStop_Click | 停止选定的服务 |
| cmdStart_Click | 启动选定的服务 |
| cmdRestore_Click | 恢复服务到原始状态 |

服务管理实用工具开发详解(续)

7. 操作步骤详解

为了更好地理解如何使用这个服务管理实用工具,下面详细介绍各个操作的具体步骤。

7.1 启动服务操作步骤
  1. 选择服务 :在列表框中勾选要启动的服务。
  2. 点击启动按钮 :触发 cmdStart_Click 事件,系统会执行以下操作:
    • 调用 OpenSelectedServices 函数,该函数会先调用 LoadList 函数加载当前服务列表到 ServiceCollection 集合中,然后遍历列表框,将选中的服务对应的 ServiceObject 对象添加到 ChangesInProgress 集合。
    • 遍历 ChangesInProgress 集合,对于每个 ServiceObject 对象,调用 QueryServiceStatus 方法获取当前状态。
    • 如果服务当前状态不是 SERVICE_RUNNING ,则调用 StartService 方法启动服务。
    • 若启动成功,设置 starttimer True ,调用 EnablePanel 函数禁用用户界面,设置 TargetState SERVICE_RUNNING ,并标记 Changed True ;若启动失败,从 ChangesInProgress 集合中移除该服务对象。

以下是启动服务的代码示例:

' Starts the selected services 
Private Sub cmdStart_Click() 
    Dim so As ServiceObject 
    Dim stat As ServiceStatus 
    Dim starttimer As Boolean 
    Dim RemoveThis As Boolean 
    Dim res& 
    Call OpenSelectedServices 
    For Each so In ChangesInProgress 
        Set stat = so.QueryServiceStatus 
        If stat.CurrentState <> SERVICE_RUNNING Then 
            res = so.StartService 
            If res <> 0 Then 
                starttimer = True 
            Else 
                RemoveThis = True 
            End If 
        Else 
            RemoveThis = True 
        End If 
        If RemoveThis Then ChangesInProgress.Remove stat.Name 
        RemoveThis = False 
    Next so 
    If starttimer Then 
        EnablePanel False 
        TargetState = SERVICE_RUNNING 
        Changed = True 
    Else 
        Set ChangesInProgress = Nothing 
    End If 
End Sub
7.2 停止服务操作步骤
  1. 选择服务 :在列表框中勾选要停止的服务。
  2. 点击停止按钮 :触发 cmdStop_Click 事件,系统会执行以下操作:
    • 调用 OpenSelectedServices 函数,将选中的服务对应的 ServiceObject 对象添加到 ChangesInProgress 集合。
    • 遍历 ChangesInProgress 集合,对于每个 ServiceObject 对象,调用 QueryServiceStatus 方法获取当前状态。
    • 如果服务当前状态不是 SERVICE_STOPPED ,则调用 ServiceControl 方法停止服务。
    • 若停止成功,设置 starttimer True ,调用 EnablePanel 函数禁用用户界面,设置 TargetState SERVICE_STOPPED ,并标记 Changed True ;若停止失败,从 ChangesInProgress 集合中移除该服务对象。

以下是停止服务的代码示例:

' Stops the selected services 
Private Sub cmdStop_Click() 
    Dim so As ServiceObject 
    Dim stat As ServiceStatus 
    Dim starttimer As Boolean 
    Dim RemoveThis As Boolean 
    Dim res& 
    Call OpenSelectedServices 
    For Each so In ChangesInProgress 
        Set stat = so.QueryServiceStatus 
        If stat.CurrentState <> SERVICE_STOPPED Then 
            res = so.ServiceControl(SERVICE_CONTROL_STOP) 
            If res <> 0 Then 
                starttimer = True 
            Else 
                RemoveThis = True 
            End If 
        Else 
            RemoveThis = True 
        End If 
        If RemoveThis Then ChangesInProgress.Remove stat.Name
        RemoveThis = False 
    Next so 
    If starttimer Then 
        EnablePanel False 
        TargetState = SERVICE_STOPPED 
        Changed = True 
    Else 
        Set ChangesInProgress = Nothing 
    End If 
End Sub 
7.3 恢复服务到原始状态操作步骤
  1. 点击恢复按钮 :触发 cmdRestore_Click 事件,系统会执行以下操作:
    • 调用 LoadList 函数加载当前服务列表到 ServiceCollection 集合。
    • 遍历 ServiceCollection 集合,将当前状态与原始状态不同的服务对应的 ServiceObject 对象添加到 ChangesInProgress 集合。
    • 遍历 ChangesInProgress 集合,根据原始状态调用 StartService ServiceControl 方法启动或停止服务。
    • 若操作成功,设置 starttimer True ,调用 EnablePanel 函数禁用用户界面,设置 TargetState 0 ,并标记 Changed True ;若操作失败,从 ChangesInProgress 集合中移除该服务对象。

以下是恢复服务到原始状态的代码示例:

' Restores services to their original state 
Private Sub cmdRestore_Click() 
    Dim so As ServiceObject 
    Dim stat As ServiceStatus 
    Dim starttimer As Boolean 
    Dim orig As ServiceStateConstants 
    Dim res& 
    Call LoadList(False) 
    Set ChangesInProgress = New Collection 
    For Each stat In ServiceCollection 
        If stat.CurrentState <> OriginalState(stat.Name) Then 
            ChangesInProgress.Add sc.OpenService(stat, SERVICE_START _ 
            Or SERVICE_STOP), stat.Name 
        End If 
    Next 
    For Each so In ChangesInProgress 
        orig = OriginalState(so.ServiceName) 
        If orig = SERVICE_RUNNING Then 
            res = so.StartService 
        Else 
            res = so.ServiceControl(SERVICE_CONTROL_STOP) 
        End If 
        If res <> 0 Then 
            starttimer = True 
        Else 
            ChangesInProgress.Remove so.ServiceName 
        End If 
    Next so 
    If starttimer Then 
        EnablePanel False 
        TargetState = 0 
        Changed = True 
    Else 
        Set ChangesInProgress = Nothing 
    End If 
End Sub
8. 定时器的作用

定时器 Timer1 在服务状态改变操作中起着重要作用。当服务状态改变操作开始后,用户界面会被禁用,定时器开始运行,它会定期检查 ChangesInProgress 集合中每个服务的状态。

以下是定时器事件的代码示例:

' Poll for the completion of the operation in progress 
Private Sub Timer1_Timer() 
    Dim so As ServiceObject 
    Dim stat As ServiceStatus 
    Dim target As Long 
    For Each so In ChangesInProgress 
        Set stat = so.QueryServiceStatus 
        ' Zero is the restore condition 
        If TargetState = 0 Then 
            target = OriginalState(stat.Name) 
        Else 
            target = TargetState 
        End If 

        If stat.CurrentState = target Then
            ' 服务进入目标状态,移除对象
            ChangesInProgress.Remove so.ServiceName
        End If
    Next
    ' 集合为空时,重新启用用户界面
    If ChangesInProgress.Count = 0 Then
        EnablePanel True
    End If
End Sub

定时器的操作步骤如下:
1. 遍历集合 :遍历 ChangesInProgress 集合中的每个 ServiceObject 对象。
2. 获取状态 :调用 QueryServiceStatus 方法获取当前服务状态。
3. 判断目标状态 :根据 TargetState 的值确定目标状态。
4. 对比状态 :如果当前状态等于目标状态,从 ChangesInProgress 集合中移除该服务对象。
5. 检查集合是否为空 :如果 ChangesInProgress 集合为空,调用 EnablePanel 函数重新启用用户界面。

9. 程序关闭处理

当程序关闭时,会触发 Form_Unload 事件。如果在程序运行过程中服务状态发生了改变,会弹出提示框询问用户是否将服务恢复到原始状态。

以下是表单卸载事件的代码示例:

Private Sub Form_Unload(Cancel As Integer) 
    Dim res& 
    If Changed Then 
        ' If any change has been made, give the user 
        ' the option to restore 
        res = MsgBox("Changes have been made - Restore service states?", _ 
        vbYesNo, "Exit confirmation") 
        If res = vbYes Then 
            unloadpending = True 
            Me.Hide ' Hide the form - no reason to clutter the screen 
            cmdRestore_Click 
            Cancel = -1 
            Changed = False 
            Exit Sub 
        End If 
    End If 

    Set ServiceCollection = Nothing 
    Set OriginalStates = Nothing 
    Set ChangesInProgress = Nothing 
    Set sc = Nothing 
End Sub

程序关闭处理的操作步骤如下:
1. 检查状态改变 :检查 Changed 变量是否为 True ,如果是,则表示服务状态发生了改变。
2. 弹出提示框 :使用 MsgBox 函数弹出提示框,询问用户是否恢复服务状态。
3. 处理用户选择
- 如果用户选择 Yes ,设置 unloadpending True ,隐藏表单,调用 cmdRestore_Click 函数恢复服务状态,取消关闭操作,将 Changed 标记为 False
- 如果用户选择 No ,继续执行关闭操作,释放相关集合和对象。

10. 注意事项

在使用这个服务管理实用工具时,需要注意以下几点:
- 服务权限 :确保程序具有足够的权限来执行服务的启动、停止和恢复操作。
- 状态更新 :由于服务状态的改变可能需要一些时间,因此在操作过程中要耐心等待,避免频繁操作。
- 资源释放 :在程序关闭时,要确保释放所有占用的资源,避免内存泄漏。

总结与展望

通过以上详细的开发过程和操作步骤,我们成功开发了一个功能完善的服务管理实用工具。该工具可以方便地对系统中的服务进行启动、停止和恢复操作,并且能够跟踪服务状态的变化。

在未来的开发中,我们可以进一步优化这个工具,例如添加更多的服务操作功能,如暂停、继续服务等;或者改进用户界面,提高用户体验。同时,我们还可以考虑将该工具集成到其他系统中,实现更复杂的服务管理需求。

下面是一个流程图,展示了程序关闭时的处理流程:

graph TD;
    A[程序关闭] --> B{服务状态改变?};
    B -- 是 --> C[弹出提示框];
    C -- 恢复 --> D[恢复服务状态];
    C -- 不恢复 --> E[释放资源];
    B -- 否 --> E;
    D --> E;
    E --> F[结束];

另外,我们再用表格总结一下服务操作的关键步骤:
| 操作 | 关键步骤 |
| ---- | ---- |
| 启动服务 | 选择服务 -> 点击启动按钮 -> 打开选定服务 -> 执行启动操作 -> 定时器检查状态 -> 完成后重新启用界面 |
| 停止服务 | 选择服务 -> 点击停止按钮 -> 打开选定服务 -> 执行停止操作 -> 定时器检查状态 -> 完成后重新启用界面 |
| 恢复服务 | 点击恢复按钮 -> 对比状态 -> 打开选定服务 -> 执行操作 -> 定时器检查状态 -> 完成后重新启用界面 |
| 程序关闭 | 检查状态改变 -> 弹出提示框 -> 处理用户选择 -> 释放资源 |

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值