Solved

ManagementObject.SetPropertyValue fails to change Service property

Posted on 2008-10-17
11
1,608 Views
Last Modified: 2012-05-05
I am using System.Management.ManagementObject in VB.NET to change the "StartName" property of a service.  If I check the property in the program immediately after changing it to "LocalSystem" it appears to have been changed.  Yet once I exit the program and check the service via the "Services" utility, the property has not changed.  Is there some programmatic "commit" required, or perhaps (heaven forbid) a reboot?

Thanks for any help!
0
Comment
Question by:rberrett
  • 4
  • 4
11 Comments
 
LVL 27

Expert Comment

by:Dabas
ID: 22751691
Hello rberrett,

Can you please post your code as a snippet?

Regards,

Dabas
0
 

Author Comment

by:rberrett
ID: 22760400
I've attached it here.  I tried doing the "Put" in hopes that was my problem, but it still doesn't change the "StartName" property.  Thanks for any help.
Imports System.ServiceProcess

Imports System.Management
 

Module Module1

    'Public Shared Function GetServices() As ServiceController()

    Sub Main()

        Dim scServices() As ServiceController

        scServices = ServiceController.GetServices()
 

        ' Loop through services currently running on this computer.

        Console.WriteLine("Local Computer Services :")
 

        Dim scTemp As ServiceController

        For Each scTemp In scServices
 

            'If scTemp.Status = ServiceControllerStatus.Running Then

            If scTemp.DisplayName = "ClipBook" Then

                ' Write the service name and the display name

                ' for each running service.

                Console.WriteLine()

                Console.WriteLine("  Service :        {0}", scTemp.ServiceName)

                Console.WriteLine("    Display name:    {0}", scTemp.DisplayName)
 

                ' Query WMI for additional information about this service.

                ' Display the start name (LocalSytem, etc) and the service

                ' description.

                Dim wmiService As ManagementObject

                wmiService = New ManagementObject("Win32_Service.Name='" + scTemp.ServiceName + "'")

                wmiService.Get()

                Console.WriteLine("    Start name:      {0}", wmiService("StartName"))

                Console.WriteLine("    Description:     {0}", wmiService("Description"))

                'Console.WriteLine("    StartPassword:     {0}", wmiService("StartPassword"))

                wmiService.SetPropertyValue("StartName", "LocalSystem")

                'wmiService.SetPropertyValue("StartPassword", "")

                Console.WriteLine("    Start name2:      {0}", wmiService("StartName"))

                Dim PutOptionsVal As PutOptions = New PutOptions

                PutOptionsVal.Type = PutType.UpdateOnly

                wmiService.Put(PutOptionsVal)

            End If
 

        Next scTemp
 

    End Sub
 

End Module

Open in new window

0
 
LVL 49

Expert Comment

by:DanRollins
ID: 22845885
My first thought is that you might need to remove the service (from the Service Manager's internal database) and then add it back using the new name.
However, I then saw this:

   Service Login -- API to Change it?
   http://bytes.com/forum/thread236775.html
It seems that there is a method (as opposed to a property) that you can use to affect this change.
    Change Method of the Win32_Service Class
    http://msdn.microsoft.com/en-us/library/aa384901(VS.85).aspx
0
 

Author Comment

by:rberrett
ID: 22870314
Thanks for the info!  Unfortunately when I try doing the change to "StartName" it still doesn't work (see snippet).  However, now I at least get a return value.  The value returned is 22 which is "Invalid Service Account".  So I tried using other account names and it always returns 22 unless I just try to change to the current account in which case it returns 0.  So I guess I may have a little more insight but still no luck.  When I used my previous code then check the value immediately after it appeared to have changed, but upon program exit it really had not changed.  With this code using a method it just errors (22) and when I check has not changed even temporarily.  Any further ideas? (thanks again for the help thus far)

Imports System.ServiceProcess

Imports System.Management
 
 

Module Module1

    'Public Shared Function GetServices() As ServiceController()

    Sub Main()

        Dim scServices() As ServiceController

        Dim inParams As ManagementBaseObject

        Dim options As New InvokeMethodOptions

        Dim returnValue As ManagementBaseObject
 

        'Dim svrc As New ManagementObject("\\.\root\cimv2")

        'inParams = svrc.GetMethodParameters("Change")

        'inParams("StartName") = "LocalService"
 
 

        scServices = ServiceController.GetServices()
 

        ' Loop through services currently running on this computer.

        Console.WriteLine("Local Computer Services :")
 

        Dim scTemp As ServiceController

        For Each scTemp In scServices
 

            'If scTemp.Status = ServiceControllerStatus.Running Then

            If scTemp.DisplayName = "ClipBook" Then

                ' Write the service name and the display name

                ' for each running service.

                Console.WriteLine()

                Console.WriteLine("  Service :        {0}", scTemp.ServiceName)

                Console.WriteLine("    Display name:    {0}", scTemp.DisplayName)
 

                ' Query WMI for additional information about this service.

                ' Display the start name (LocalSytem, etc) and the service

                ' description.

                Dim wmiService As ManagementObject

                wmiService = New ManagementObject("Win32_Service.Name='" + scTemp.ServiceName + "'")

                wmiService.Get()

                Console.WriteLine("    Start name:      {0}", wmiService("StartName"))

                Console.WriteLine("    Description:     {0}", wmiService("Description"))
 

                ''Console.WriteLine("    StartPassword:     {0}", wmiService("StartPassword"))

                'wmiService.SetPropertyValue("StartName", "LocalSystem")

                ''wmiService.SetPropertyValue("StartPassword", "")

                'Console.WriteLine("    Start name2:      {0}", wmiService("StartName"))

                'Dim PutOptionsVal As PutOptions = New PutOptions

                'PutOptionsVal.Type = PutType.UpdateOnly

                'wmiService.Put(PutOptionsVal)
 

                inParams = wmiService.GetMethodParameters("Change")

                inParams("StartName") = "LocalSystem"

                returnValue = wmiService.InvokeMethod("Change", inParams, options) 'System.Management.InvokeMethodOptions.InfiniteTimeout)

                Console.WriteLine("    ReturnValue:     {0}", System.Convert.ToInt32(returnValue.Properties("ReturnValue").Value))

                Console.WriteLine("    Start name:      {0}", wmiService("StartName"))

                'Dim svrc As New ManagementObject("\\.\root\cimv2")

                'inParams = svrc.GetMethodParameters("Change")

                'inParams("StartName") = "LocalService"
 

            End If
 

        Next scTemp
 

    End Sub
 

End Module

Open in new window

0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 49

Expert Comment

by:DanRollins
ID: 22871649
There might be underlying constraints; for instance, different parts of the system probably cache service names and have no direct way to update the cache -- short of a system reset.  
In general, the system probably assumes that a service will never change its name once it has been added to the Service Manager's database -- why should it?  
Of course, any service that has a dependancy of any kind would not be a good target for testing.   For instance, lots of subsystems might depend on a service named "ClipBook".  I suggest testing using a very simple Service that no other systems use.
One other thought:  In your code, you are cycling though the services and then changing one of them.  If WMI queries are similar to DBMS queries, then you have an "open recordset" which could cause failure of an update.  What if you omit the looping and just get the one record and invoke it's Change function?
0
 

Author Comment

by:rberrett
ID: 22900410
Thanks for the ideas.  The property I'm trying to change is actually the "StartName" which is the account under which the service starts.  I tried a different service (with no dependencies) and also to excute the change directly rather than in the loop, but unfortunately I get the same result.

I think the issue may lie in the "Invalid Service Account" error, but I can't seem to find out just why I get that error.  I've tried several accounts, as well as the string "LocalSystem", all to no avail.

Anyway, any further ideas would be appreciated!  This is a tough one.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 22914470
Invalid Service Account
The account which this service is to run under is not valid, or it lacks the permissions to run the service.
Can you use manual means to do this?  For instance, use the ControlPanel Services applet or
   net stop (et. al)
or the
   SC
command to change service settings using your current login?  I know I can, but I use an administrative account when doing these things.
0
 
LVL 49

Accepted Solution

by:
DanRollins earned 500 total points
ID: 22914488
Another thought:  Notice the different syntac used in the Change() function on this page of examples:
http://msdn.microsoft.com/en-us/library/aa394602(VS.85).aspx

Use the Win32_Service class and the Change method. 
 

strComputer = "."

Set objWMIService = GetObject("winmgmts:" _

    & "{impersonationLevel=impersonate}!\\" _

    & strComputer & "\root\cimv2")

Set colServiceList = objWMIService.ExecQuery _

    ("Select * from Win32_Service")

For Each objservice in colServiceList

    If objService.StartName = ".\netsvc" Then

        errReturn = objService.Change( , , , , , , , "password")  

    End If 

Next

Open in new window

0
 

Author Comment

by:rberrett
ID: 22935845
That last thing, modified to change the StartName, did the trick!  It took me a bit to realize I need to run it as a vbscript with "cscript" but that seems to work.  Thank you, thank you!
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Suggested Solutions

Creating an analog clock UserControl seems fairly straight forward.  It is, after all, essentially just a circle with several lines in it!  Two common approaches for rendering an analog clock typically involve either manually calculating points with…
The ECB site provides FX rates for major currencies since its inception in 1999 in the form of an XML feed. The files have the following format (reducted for brevity) (CODE) There are three files available HERE (http://www.ecb.europa.eu/stats/exch…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

705 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

20 Experts available now in Live!

Get 1:1 Help Now