Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

web service that controls windows services

Posted on 2006-04-07
43
Medium Priority
?
323 Views
Last Modified: 2012-06-21
hi,

can anyone illustrate how to make a web service allow control over window services through an asp/ aspx webpage?  Im kinda leaning towards vb or asp syntax rather then c# if you can produce an example.

I would like a webservice with turnServiceOn, turnServiceOff, getServices functions so that I can display them within a webpage and then control the service through the webpage?  I believe this is possible.

Many thanks,
0
Comment
Question by:jimbona27
  • 27
  • 13
  • 2
42 Comments
 
LVL 3

Expert Comment

by:gsalier
ID: 16404973
Add a reference to the System.ServiceProcess and go from there

Get a list of Services on a machine (This code will list the local services0

Imports System.ServiceProcess

Public Class SomeClass
    Sub DoSomething()
        Dim servicesArray As ServiceController() = ServiceController.GetServices()
        For Each service As ServiceController In servicesArray
            Console.WriteLine(service.DisplayName)
        Next
    End Sub

End Class
If you look at the service object with intellisense you will see a lot of methods for controlling the service

Be very careful with security allowing this sort of process.

Regards
0
 
LVL 4

Expert Comment

by:broadbent
ID: 16406651
I have found it quite difficult to send messages to a Windows Service, but I have found this method.

In the Windows Service code:
Protected Overrides Sub OnCustomCommand(byval command as Integer)
this is always available

and in the calling application:
Dim MyWindowsService as New System.ServiceProcess.ServiceController("MyService")
MyWindowsService.Start (if required)
MyWindowsService.ExecuteCommand(219)

you can only use an integer number. Also some of these numbers are predefined and used by Windows, but I believe that a number greater than 200 works. I haven't tested this though.
0
 

Author Comment

by:jimbona27
ID: 16415203
thanks for this although my .net knowledge is quite little.  is this code to be put in a asp.net web page or vb.net application?  thanks.
0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

 
LVL 4

Expert Comment

by:broadbent
ID: 16415371
This code was used for a windows service.
0
 

Author Comment

by:jimbona27
ID: 16415381
yup, i got that but where do i put it?
0
 
LVL 3

Accepted Solution

by:
gsalier earned 1200 total points
ID: 16415561
jimbona27,

What you are asking doesn't require a web service to work. If the purpose of the application is to control services on the same machine as your web application is to be running then the code can just be put into a class within your web application. Web services are best used when you need to distribute data or services amongst different sources i.e a web app, a windows app, an app running on a unix box and a mobile device.

If the result you are trying to achieve is to control services on a box that is within your own network, then using the computer management mmc snap in and connecting to the computer running the service is probably the way to go.

If you really want to do this in a web service then you would need to do something like the following.
Create a new .net web service
put the following in a code file.

Imports System.Web.Services
Imports System.ServiceProcess

<System.Web.Services.WebService(Namespace:="http://tempuri.org/Q_21805263/Service1")> _
Public Class MyServiceController
    Inherits System.Web.Services.WebService

    <WebMethod()> _
    Public Function StopService(ByVal strServiceName As String, ByVal strMachineName As String) As Boolean


        Try
            Dim objServiceToStop As ServiceController = New ServiceController(strServiceName, strMachineName)
            'If the service is stopped or is stopping
            If objServiceToStop.Status = ServiceControllerStatus.Stopped Or objServiceToStop.Status = ServiceControllerStatus.StopPending Then
                'Leave now
                Return True
            End If

            If (objServiceToStop.CanStop) Then
                objServiceToStop.Stop()
                'Wait thirty seconds for this to stop or timeout
                objServiceToStop.WaitForStatus(ServiceControllerStatus.Stopped, New TimeSpan(0, 0, 30))
                If (objServiceToStop.Status = ServiceControllerStatus.Stopped) Then
                    Return True
                End If
                'You could continue to wait here but probably not advisable
            End If
        Catch ex As Exception
            Return False
        End Try

        ''The service has not stopped yet (but we haven't had an error so return what you want)
        Return False

    End Function

    <WebMethod()> _
    Public Function StartService(ByVal strServiceName As String, ByVal strMachineName As String) As Boolean
        Try
            Dim objServiceToStart As ServiceController = New ServiceController(strServiceName, strMachineName)
            'If the service is stating or has started
            If objServiceToStart.Status = ServiceControllerStatus.StartPending Or _
                objServiceToStart.Status = ServiceControllerStatus.Running Then
                Return True
            End If

            objServiceToStart.Start()
            'Wait thirty seconds for this to Start or timeout
            objServiceToStart.WaitForStatus(ServiceControllerStatus.Running, New TimeSpan(0, 0, 30))
            If (objServiceToStart.Status = ServiceControllerStatus.Running) Then
                Return True
            End If
            'You could continue to wait here but probably not advisable

        Catch ex As Exception
            Return False
        End Try

        ''The service has not started yet (but we haven't had an error so return what you want)
        Return False
    End Function

End Class



Once you have compiled this then in your other project add a new web reference to this service (http://localhost/MyServiceProjectName/MyServiceController.asmx) and go from there.

MSDN can help for more detail.

If you removed the web service stuff you could just run this from a normal app.
0
 
LVL 3

Expert Comment

by:gsalier
ID: 16415575
For your homework, you can workout how to return an array of service names through your web service. (Hint: use the code I posted in the first comment as a basis)
0
 
LVL 3

Expert Comment

by:gsalier
ID: 16415589
You also need to make sure that the security context executing this code has the necessary priviledges to control services on the host machine.
0
 

Author Comment

by:jimbona27
ID: 16444418
ok thanks, although Im having stupid problems with this...  Im creating a .net webpage then viewing the code and I get this:

Public Class WebForm1
    Inherits System.Web.UI.Page
    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Put user code to initialize the page here
        Label1.text = "hello"
    End Sub

End Class


on the actual webpage I have the following code:

<%@ Page Language="vb" Codebehind="WebForm1.aspx.vb" Inherits="gogogadgetgo.WebForm1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
      <HEAD>
            <title>WebForm1</title>
            <meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
            <meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
            <meta name="vs_defaultClientScript" content="JavaScript">
            <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
      </HEAD>
      <body MS_POSITIONING="GridLayout">
            <form id="Form1" method="post" runat="server">
            <asp:Label id="Label1" runat="server">Label</asp:Label>
            </form>
      </body>
</HTML>

the hello in the load sub doesnt populate the label?  Please advise.  
0
 
LVL 3

Expert Comment

by:gsalier
ID: 16449282

Public Class WebForm1
    Inherits System.Web.UI.Page
   
    'This is missing...
    Protected WithEvents Label1 As System.Web.UI.WebControls.Label

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Put user code to initialize the page here
        Label1.text = "hello"
    End Sub

End Class

You must declare any controls you are going to use. Usually with Protected WithEvents
 

0
 

Author Comment

by:jimbona27
ID: 16476313


thanks for this, this is great.  I've made the function as above that returns an array of the services but how can I create labels dynamically?  thanks.
0
 

Author Comment

by:jimbona27
ID: 16476325
got it..

        Dim test As New Label
        test.Text = "HELLO"
        Controls.Add(test)
0
 

Author Comment

by:jimbona27
ID: 16476407
almost there now although im having problems accessing the web methods:

this is just a simple example function that returns PI from my web service.

 Dim MyPIService As New localhost.PIWebService
 Label1.Text = MyPIService.PI

when typing MyPIService. I get the PI function within the list, although my other functions I've created, one is included below I dont see them within the list:

<WebMethod()> _
    Public Function listServices() As String()
        Dim servicesArray As ServiceController() = ServiceController.GetServices()
        Dim counter As Integer = 0
        Dim myArray(100) As String

        For Each service As ServiceController In servicesArray
            myArray(counter) = service.DisplayName
            counter = counter + 1
        Next

        listServices = myArray

    End Function

many thanks.
 
0
 
LVL 3

Expert Comment

by:gsalier
ID: 16476871
You need to rebuild (refresh) your web references.

Right click on the web reference and select update...
0
 

Author Comment

by:jimbona27
ID: 16476917
thanks for your advice although i've done this.
0
 

Author Comment

by:jimbona27
ID: 16476928
note that all my functions are within the same class.

so on my website i have this for the page load:

Dim test As New localhost.PIWebService

I only get the option of PIWebService but that would make sense as all functions are within this class.

I've tried

Dim test2 As New localhost.PIWebService.AnotherFunction

Surely each class can have multiple functions, must be not doing something right.


0
 
LVL 3

Expert Comment

by:gsalier
ID: 16477159
If you go into the code for the reference.vb located within the web reference, check to see that all your functions are there. If not, delete the web reference and add it again.
0
 

Author Comment

by:jimbona27
ID: 16477858
thanks, that bit is working now.  

is it possible to display the current status of the service?
0
 

Author Comment

by:jimbona27
ID: 16479393
and Im having problems with the stop and start service.  invoking the function through the asmx file returns false.  Could this be anything to do with the IWAM and IUSER users?
0
 
LVL 3

Expert Comment

by:gsalier
ID: 16482051
You need to Impersonate most likely. Either yourself or an user with the required priviledges.

myServiceControl.Status
0
 

Author Comment

by:jimbona27
ID: 16482106
ok thanks, i'll try this tomorrow and let you know as unfortunately Im away from that computer now.
0
 

Author Comment

by:jimbona27
ID: 16485467
I've looked around how to get the status of the service and your suggestion isnt working for me:

Dim MyPIService As New localhost.PIWebService

label1.Text = MyPIService.listServices(22).Status


My listServices functions works well, illustrated below:

      For i = 1 To UBound(MyPIService.listServices)
          Dim test As New Label
          test.Text = MyPIService.listServices(i)
          Controls.Add(test)
      Next

This will display all the services on the local machine.
0
 
LVL 3

Expert Comment

by:gsalier
ID: 16485593
Status is an Enum not a string
0
 

Author Comment

by:jimbona27
ID: 16485707
to be honest Im not entirely sure how to use Enum.

I've checked this tutorial out
http://aspnet.4guysfromrolla.com/articles/042804-1.aspx

Are you saying something like this:

    Public Enum theService
        currentStatus = MyPIService.status
    End Enum

0
 

Author Comment

by:jimbona27
ID: 16485755
i've made this test in my web service using just the Help and support service as a test:

<WebMethod()> _
    Public Function getStatus() As Boolean

        Dim sc As New ServiceController("Help and Support")
        Return sc.Status

    End Function

when the function returns an integer it seems to work, sort of as the service being on seems to be a value of 4 and when its off it seems to return a value of 1.

but how it is, boolean as a return value is seems to always return true.

0
 

Author Comment

by:jimbona27
ID: 16485923
so basically, will this suffice? reliable (?)


        Dim sc As New ServiceController("Help and Support")
        If sc.Status() = 4 Then
            Return True
        Else
            Return False
        End If
0
 

Author Comment

by:jimbona27
ID: 16486165
i've increased points.
0
 

Author Comment

by:jimbona27
ID: 16486321
Using the following function as provided above runs the exception clause unfortunately.  Is there anyway I can see why this happens?


 Try
            Dim objServiceToStart As ServiceController = New ServiceController(strServiceName)

            'If the service is starting or has started

            If objServiceToStart.Status = ServiceControllerStatus.StartPending Or objServiceToStart.Status = ServiceControllerStatus.Running Then
                'Return True
                Return 1
            End If

            objServiceToStart.Start()

            'Wait thirty seconds for this to Start or timeout

            objServiceToStart.WaitForStatus(ServiceControllerStatus.Running, New TimeSpan(0, 0, 30))

            If (objServiceToStart.Status = ServiceControllerStatus.Running) Then
                'Return True
                Return 1
            End If

        Catch ex As Exception
            Return 1234
        End Try
0
 
LVL 3

Expert Comment

by:gsalier
ID: 16492169
Part 1.
What is the exception? and What line does it occur on?

Part 2
If you are trying to return a boolean then you must return a boolean (true or false) if you are trying to return an integer then specifiy it.

Specifying a return type of boolean and returning a non-zero number is the same as returning true.

The getStatus() function queries an Enumeration (Status) so therefore it should either return an Enumeration or the raw integer value of the result.

This is sample code I gave you. You need to work out how you solve your problem using the code I gave you.

0
 

Author Comment

by:jimbona27
ID: 16498566
1)
trying to start my Print Spooler service I get this back:

There is an error in XML document (1, 318).


code on page:

        Dim MyPIService As New localhost.PIWebService
        Try
            MyPIService.StartService("Print Spooler")
            label1.Text = "Seems fine"
        Catch ex As Exception
            label1.Text = ex.Message
        End Try

if the service is already started it returns Seems Fine but when its not it returns the error as above.
0
 

Author Comment

by:jimbona27
ID: 16499179
through my browser:

http://localhost/180406/Service1.asmx

then I have a web method called startService

with the following code:


    <WebMethod()> _
    Public Function StartService(ByVal strServiceName As String) As Integer
        Try
            Dim objServiceToStart As ServiceController = New ServiceController(strServiceName)

            'If the service is starting or has started

            If objServiceToStart.Status = ServiceControllerStatus.StartPending Or objServiceToStart.Status = ServiceControllerStatus.Running Then
                'Return True
                Return 1
            End If

            objServiceToStart.Start()

            'Wait thirty seconds for this to Start or timeout

            objServiceToStart.WaitForStatus(ServiceControllerStatus.Running, New TimeSpan(0, 0, 30))

            If (objServiceToStart.Status = ServiceControllerStatus.Running) Then
                'Return True
                Return 1
            End If
        Catch ex As Exception
            Return 1234
        End Try

        'The service has not started yet (but we haven't had an error?? permissions maybe?)
        Return 0

    End Function


When a service is already started, i.e. Print Spooler clicking the startService method and entering Print Spooler for the parameter returns 1.  But if the service is not started the web method as above returns 1234.
0
 

Author Comment

by:jimbona27
ID: 16499200
this line causes the exception:

objServiceToStart.Start()

0
 

Author Comment

by:jimbona27
ID: 16499418
taken from microsoft the following example crashes out when it hits this line:

 If sc.Status = ServiceControllerStatus.Stopped Then


full code below taken from http://msdn2.microsoft.com/en-us/library/yb9w7ytd.aspx


    Public Function test() As String

        Dim sc As New ServiceController
        sc.ServiceName = "Printer Spooler"

        If sc.Status = ServiceControllerStatus.Stopped Then
            ' Start the service if the current status is stopped.

            Try
                ' Start the service, and wait until its status is "Running".
                sc.Start()
                sc.WaitForStatus(ServiceControllerStatus.Running)

                ' Display the current service status.
            Catch ex As Exception
                Return ex.Message
            End Try
        End If
    End Function
0
 

Author Comment

by:jimbona27
ID: 16499434
sorry it doesnt crash crash but it loads the http://localhost/180406/Service1.asmx/test but Page cannot be displayed and then it just waits
0
 

Author Comment

by:jimbona27
ID: 16499476
i've added this:


    Public Function test() As String

        Dim sc As New ServiceController
        sc.ServiceName = "Printer Spooler"


        Try

            If sc.Status = ServiceControllerStatus.Stopped Then
                ' Start the service if its stopped

                Try
                    ' Start the service, and wait until its status is "Running".
                    sc.Start()
                    sc.WaitForStatus(ServiceControllerStatus.Running)
                Catch ex As Exception
                    Return "11111 " & ex.Message
                End Try

            End If

        Catch ex As Exception
            Return "22222 " & ex.Message
        End Try

    End Function


and it returns 22222 Cannot open Printer Spooler service on computer
0
 

Author Comment

by:jimbona27
ID: 16499511
the service is assigned to the local system account.
0
 
LVL 3

Expert Comment

by:gsalier
ID: 16502316
I don't know a huge amount about printers but trying to start the Printer Spooler service seems like it will never work. If the Printer Spooler is not started then maybe there is a problem with the service. It also depends on the RPC service so if that is not running then you may have a problem there as well.

Do you have your permissions setup correctly? Can the impersonated account in your web service start and stop services?

0
 

Author Comment

by:jimbona27
ID: 16503637
it must be permissions because I justed pasted the code into a vb.net form and it worked.
it must be a webby type permission problem...
Im not sure how the impersonate thing works although I know theres a web.config and a machine.config file.  
Should I put impersonate=true user="" password="" in?  I dont know what impersonate is really, with classic ASP you would normally get around any permission problem, i.e. FileSystemObject issues by giving full permission to the IWAM and IUSER accounts.  I guess impersonate is the .net way although I only know what I've mentioned in this comment.
0
 

Author Comment

by:jimbona27
ID: 16503639
I havent done anything with the impersonate thing as I dont really know what to do, although I know of it.
0
 
LVL 3

Expert Comment

by:gsalier
ID: 16506586
Web Services don't run under the accout of the calling web or windows application so you need to impersonate a user.

Your web.config file in your web service application should have a section

<configuration>
   <system.web>
       <identity impersonate="true|false" userName="domain\username" password="password"/>
etc
0
 
LVL 3

Expert Comment

by:gsalier
ID: 16694729
I did actually answer the original question here, the question grew into a bit of a Hydra...
0
 

Author Comment

by:jimbona27
ID: 16697057
hi, sorry about this.
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
This article shows how to deploy dynamic backgrounds to computers depending on the aspect ratio of display
Loops Section Overview
How can you see what you are working on when you want to see it while you to save a copy? Add a "Save As" icon to the Quick Access Toolbar, or QAT. That way, when you save a copy of a query, form, report, or other object you are modifying, you…
Suggested Courses
Course of the Month11 days, 2 hours left to enroll

571 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