web service that controls windows services

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,
jimbona27Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

gsalierCommented:
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
broadbentCommented:
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
jimbona27Author Commented:
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
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

broadbentCommented:
This code was used for a windows service.
0
jimbona27Author Commented:
yup, i got that but where do i put it?
0
gsalierCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
gsalierCommented:
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
gsalierCommented:
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
jimbona27Author Commented:
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
gsalierCommented:

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
jimbona27Author Commented:


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
jimbona27Author Commented:
got it..

        Dim test As New Label
        test.Text = "HELLO"
        Controls.Add(test)
0
jimbona27Author Commented:
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
gsalierCommented:
You need to rebuild (refresh) your web references.

Right click on the web reference and select update...
0
jimbona27Author Commented:
thanks for your advice although i've done this.
0
jimbona27Author Commented:
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
gsalierCommented:
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
jimbona27Author Commented:
thanks, that bit is working now.  

is it possible to display the current status of the service?
0
jimbona27Author Commented:
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
gsalierCommented:
You need to Impersonate most likely. Either yourself or an user with the required priviledges.

myServiceControl.Status
0
jimbona27Author Commented:
ok thanks, i'll try this tomorrow and let you know as unfortunately Im away from that computer now.
0
jimbona27Author Commented:
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
gsalierCommented:
Status is an Enum not a string
0
jimbona27Author Commented:
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
jimbona27Author Commented:
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
jimbona27Author Commented:
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
jimbona27Author Commented:
i've increased points.
0
jimbona27Author Commented:
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
gsalierCommented:
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
jimbona27Author Commented:
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
jimbona27Author Commented:
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
jimbona27Author Commented:
this line causes the exception:

objServiceToStart.Start()

0
jimbona27Author Commented:
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
jimbona27Author Commented:
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
jimbona27Author Commented:
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
jimbona27Author Commented:
the service is assigned to the local system account.
0
gsalierCommented:
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
jimbona27Author Commented:
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
jimbona27Author Commented:
I havent done anything with the impersonate thing as I dont really know what to do, although I know of it.
0
gsalierCommented:
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
gsalierCommented:
I did actually answer the original question here, the question grew into a bit of a Hydra...
0
jimbona27Author Commented:
hi, sorry about this.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.