Click here to Skip to main content
Click here to Skip to main content

Remote NT Service Control COM Component and WPF Client Application

, 7 Dec 2011 CPOL
Rate this:
Please Sign up or sign in to vote.
Sample application demonstrating variety of MS technologies

ClientUI.png

Introduction

Several years back, I was preparing for an interview at some well-known software company. And one of the interview prerequisites was writing a sample application for remote Windows NT service controlling. This application had to consist of two components: COM component written in C++, allowing controlling services remotely (start, stop, pause, resume & restart) and a client application in VB demonstrating this component capability. All this was back in the days of VS 6.0 – VS 2003.

The idea behind such an interview requirement was to filter out candidates which were not really interested in getting that offered position. Plus candidates were demonstrating their technical skills: as you know, sometimes the code tells more than words.

A while ago, I decide to update this application using WPF and share it with others as a help to those who might need to develop a similar application.

Background

The best place to learn how Windows NT controls its services is MSDN. We are interested in a few API functions:

Developing COM Component

From the very beginning, I decided to encapsulate the actual functionality in one layer of C++ classes (Model layer), and use ATL to expose this functionality via COM (Façade layer).

ServiceControlLib.png

The Model layer implementation uses smart service handles to automate handles management, and C++ exceptions to report errors to the Façade layer. All system error messages are thrown via CAutoThrowError, and component’s errors are thrown via CMessageError. Error messages are compiled with the Message compiler (MC.exe).

Service operations (start, stop, etc.) can take a while to complete. So, for all exposed operations via CService, you can define wait interval for the operation to complete.

try
{
    // Open Service Control Manager (SCM)
    CServiceControllerPtr scm(new CServiceController(CComBSTR(_T("TargetMachineName"))));

    // Open service by its Key/Display name
    CServicePtr service = scm->OpenServiceByKeyName(CComBSTR(_T("Browser")));

    // Access service properties
    DWORD state = service->CurrentState();
        
    // Execute operations
    DWORD waitMSec = 2000;
    service->Start(waitMSec);
}
catch (CError& err)
{
    // You can get error details here:
    HRESULT hr = err.GetId();
    CComBSTR description = err.GetDescription();
}

The Façade layer supports “Both” apartment model with Free-Threaded Marshaler (FTM), so these components can be safely used in a multi-threaded environment.

The component supports side-by-side execution (SxS), so it can be deployed without registration.

Public interface is very similar to the internal one, and can be used from any COM supporting language or platform (like .NET, VB, etc.).

try
{
    // Open Service Control Manager (SCM)
    IServiceController scm = new ServiceController();
    scm.Connect(Environment.MachineName);

    // Open service by its Key/Display name
    IService service = scm.FindServiceByKeyName("Browser");

    // Access service properties
    CurrentState state = service.CurrentState;

    // Execute operations
    int waitMSec = 2000;
    service.Start(waitMSec);
}
catch (COMException e)
{
    int id = e.ErrorCode;
    string description = e.Message;
}

Developing the Client Application

During the project upgrade, I decided to re-implement the client application using WPF. Microsoft’s Services MMC Snap-in was a source of inspiration for the UI.

It consists of 3 basic views and a number of commands service commands. To keep things organized, I used MVC pattern with Mediator (to communicate between the controllers).

ServiceControl.png

All service calls were implemented asynchronously to make the UI more responsible to user actions (by means of System.Threading.Task).

I intentionally avoided the usage of any third-party toolkits (like MVVM, etc.) to keep this program as neat and simple as possible.

The client application uses the COM component as an Isolated COM. In other words, you do not need to register COM component to run it, just keep it along with the manifest file in the same directory with the client.

Known Issues

After upgrading this solution till VS 2010, I started getting the following error sometimes during the solution builds:

Error 1 general error c101008d: Failed to write the updated manifest to the 
resource of file ".\Debug\ServiceControlLib.dll". 
The process cannot access the file because it is being used by another process. mt.exe

Microsoft has not provided any solutions for this problem yet. The best option which worked for me was to exclude build folders from the antivirus monitoring.

Special Thanks

History

  • Version 1.0. First release
  • Version 1.1. Added code samples
  • Version 1.2. Minor updates of the source code and demo

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

deBUGer!

Russian Federation Russian Federation
No Biography provided

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150414.1 | Last Updated 7 Dec 2011
Article Copyright 2011 by deBUGer!
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid