Solved

ManagementObject.SetPropertyValue fails to change Service property

Posted on 2008-10-17
11
1,643 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
3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

 

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
 
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

3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

Question has a verified solution.

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

Suggested Solutions

For those of you who don't follow the news, or just happen to live under rocks, Microsoft Research released a beta SDK (http://www.microsoft.com/en-us/download/details.aspx?id=27876) for the Xbox 360 Kinect. If you don't know what a Kinect is (http:…
More often than not, we developers are confronted with a need: a need to make some kind of magic happen via code. Whether it is for a client, for the boss, or for our own personal projects, the need must be satisfied. Most of the time, the Framework…
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…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

803 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