• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1882
  • Last Modified:

ManagementObject.SetPropertyValue fails to change Service property

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
rberrett
Asked:
rberrett
  • 4
  • 4
1 Solution
 
DabasCommented:
Hello rberrett,

Can you please post your code as a snippet?

Regards,

Dabas
0
 
rberrettAuthor Commented:
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
 
DanRollinsCommented:
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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
rberrettAuthor Commented:
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
 
DanRollinsCommented:
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
 
rberrettAuthor Commented:
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
 
DanRollinsCommented:
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
 
DanRollinsCommented:
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
 
rberrettAuthor Commented:
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

Nothing ever in the clear!

This technical paper will help you implement VMware’s VM encryption as well as implement Veeam encryption which together will achieve the nothing ever in the clear goal. If a bad guy steals VMs, backups or traffic they get nothing.

  • 4
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now