#184106 - 2007-12-21 02:37 AM
Re: enum services running as specific user
[Re: Gargoyle]
|
Glenn Barnas
KiX Supporter
   
Registered: 2003-01-28
Posts: 4401
Loc: New Jersey
|
Well, that post could handle your scheduled tasks.. but there's a UDF on my site that makes service management simple. Not as comprehensive as the UDF that Chris wrote, but (in my opinion) easier to use for Quick-n-dirty scripts.
The UDF on my site is called WMISvcMgr(). Here's some Pseudo-Code to put in a loop where $Computer has the name of the current computer to query.
; Get a list of services on the named computer
$Services = WMISvcMgr('List', , , $Computer)
; enumerate the list of services, looking for those that use the old admin account
For Each $Service in $Services
$SvcInfo = WMISvcMgr('Query', $Service, , $Computer)
If $SvcInfo[8] = 'OldUserName' ; if the service account is the old user
$SvcInfo[8] = 'NewUserName' ; update the new userID and password
$SvcInfo[9] = 'NewPassword'
; stop the service
$ = WMISvcMgr('Stop', $Service, , $Computer)
; write the updated config info back to the service database
$ = WMISvcMgr('Modify', $Service, $SvcInfo, $Computer)
; restart the service with the new credentials
$ = WMISvcMgr('Start', $Service, , $Computer)
Next
Realize that this is untested, PSEUDOCODE! It's damn close to working Kix code, but you should add some error checking and such.
Glenn
_________________________
Actually I am a Rocket Scientist!
|
|
Top
|
|
|
|
#184147 - 2007-12-21 04:29 PM
Re: enum services running as specific user
[Re: Glenn Barnas]
|
brewdude6
Hey THIS is FUN
Registered: 2000-10-21
Posts: 280
Loc: Nashville, TN
|
That is actually how I was testing, but thought the the split could be done on the array. Thanks for explaining that.
I am having a problem with "modify". I'm using your code like this:
$computer = 'mycomputer'
; Get a list of services on the named computer
$Services = WMISvcMgr('List', , , $Computer)
; enumerate the list of services, looking for those that use the old admin account
For Each $Service in $Services
$Service = Split($Service, ',')[0]
$SvcInfo = WMISvcMgr('Query', $Service, , $Computer)
If $SvcInfo[8] = '.\administrator' ; if the service account is the old user
$SvcInfo[8] = '.\administrator'
$SvcInfo[9] = 'password'
; stop the service
$ = WMISvcMgr('Stop', $Service, , $Computer)?@SERROR
; write the updated config info back to the service database
$ = WMISvcMgr('Modify', $Service, $SvcInfo, $Computer)?@SERROR
; restart the service with the new credentials
$ = WMISvcMgr('Start', $Service, , $Computer)?@SERROR
EndIf
Next
This produces this output. I'm sure it's the "$SvcInfo" section of the command, but I'm not sure how that should be formatted.
The operation completed successfully. The parameter is incorrect.50 The operation completed successfully.
_________________________
I could have made a neat retort but didn't, for I was flurried and didn't think of it till I was downstairs. -Mark Twain
|
|
Top
|
|
|
|
#184150 - 2007-12-21 05:38 PM
Re: enum services running as specific user
[Re: brewdude6]
|
Glenn Barnas
KiX Supporter
   
Registered: 2003-01-28
Posts: 4401
Loc: New Jersey
|
OK - I have a temporary fix for you. For some reason, you can change the service description, binary, user, and password, but I'm getting errors on the other values. I probably need to translate the strings into specific values - gotta head back to the documentation for the other parameters.
For now, your solution is to replace the entire MODIFY section in the UDF with the following code. The only real change(s) is that I commented out the original line and replaced it with a line that updates only the 4 string values. I verified that this works on my server.
; ==============================
Case $_Action = 'Modify'
If VarType($_SvcData) < 8192 Exit 87 EndIf ; exit if service data array is not defined
If UBound($_SvcData) <> 9 Exit 87 EndIf ; exit if service data array is invalid
; Change(DisplayName, PathName, ServiceType, ErrorControl, StartMode, DesktopInteract, StartName, StartPassword,
; next 3 unsupported...
; LoadOrderGroup, LoadOrderGroupDependencies, ServiceDependencies)
For Each $_oItem in $_cItems
;$_R = $_oItem.Change($_SvcData[1],$_SvcData[2],$_SvcData[3],$_SvcData[4],$_SvcData[5],$_SvcData[6],,$_SvcData[8],$_SvcData[9])
$_R = $_oItem.Change($_SvcData[1],$_SvcData[2],,,,,$_SvcData[8],$_SvcData[9])
$_E = @ERROR
Next
Just copy this, locate the corresponding section in your copy of the UDF, select the text and paste this over the original. You should be good to go. Just don't ask to change the service type or error control values (yet!). Should not be a problem now for changing user ID or password.
Also - I changed the code slightly to stop/start the service only if it was originally in a Running state:
; stop the service
If Left($SvcInfo[7], 1) = 'R'
$ = WMISvcMgr('Stop', $Service, , $Computer)
@SERROR ?
EndIf
; write the updated config info back to the service database
$ = WMISvcMgr('Modify', $Service, $SvcInfo, $Computer)
@SERROR ?
; restart the service with the new credentials
If Left($SvcInfo[7], 1) = 'R'
$ = WMISvcMgr('Start', $Service, , $Computer)
@SERROR ?
EndIf
FYI - the "?" is a shortcut for a carriage return + line feed, and generally should come AFTER the text you print, not before. It's different from BASIC, where it's a shortcut for the PRINT statement and comes first.
Glenn
_________________________
Actually I am a Rocket Scientist!
|
|
Top
|
|
|
|
#184157 - 2007-12-21 08:51 PM
Re: enum services running as specific user
[Re: Glenn Barnas]
|
Glenn Barnas
KiX Supporter
   
Registered: 2003-01-28
Posts: 4401
Loc: New Jersey
|
Here's the updated version, including the code you need to enumerate the services on a defined computer. You'll need to change the definitions at the top of the script to match your requirements. This is also the latest version of the UDF with the validation processing. The only item I can't resolve is the "Interact with Desktop" flag, which should not be an issue.
$ = SetOption('NoMacrosInStrings', 'On')
Break On
$Computer = 'computer'
$OldUser = 'oldUID'
$NewUser = 'newUID'
$NewPass = 'password'
; Get a list of services on the named computer
$Services = WMISvcMgr('List', , , $Computer)
; enumerate the list of services, looking for those that use the old admin account
For Each $Service in $Services
$Service = Split($Service, ',')[0] ; get the short service name
'Querying ' $Service ?
$SvcInfo = WMISvcMgr('Query', $Service, , $Computer)
If $SvcInfo[8] = $OldUser ; if the service account is the old user
$SvcInfo[8] = $NewUser
$SvcInfo[9] = $NewPass
'Settings: '
$SvcInfo[0] ?
$SvcInfo[1] ?
$SvcInfo[2] ?
$SvcInfo[3] ?
$SvcInfo[4] ?
$SvcInfo[5] ?
$SvcInfo[6] ?
$SvcInfo[7] ?
$SvcInfo[8] ?
$SvcInfo[9] ?
; stop the service
If Left($SvcInfo[7], 1) = 'R'
$ = WMISvcMgr('Stop', $Service, , $Computer)
@SERROR ?
EndIf
; write the updated config info back to the service database
$ = WMISvcMgr('Modify', $Service, $SvcInfo, $Computer)
@SERROR ?
; restart the service with the new credentials
If Left($SvcInfo[7], 1) = 'R'
$ = WMISvcMgr('Start', $Service, , $Computer)
@SERROR ?
EndIf
Quit 0
EndIf
Next
;;
;;======================================================================
;;
;;FUNCTION WMISvcMgr()
;;
;;ACTION Manage windows services
;;
;;AUTHOR Glenn Barnas
;;
;;VERSION 1.0 / 2007/10/15
;; Written as a replacement for SvcList() & SvcCtl(), which uses XNET.exe
;;
;;SYNTAX WMISvcMgr(Action, [Service] [, SvcData] [, Computer] [, AuthPtr])
;;
;;PARAMETERS Action - REQUIRED, Action to perform - must be one of:
;; Status# - return WMI_Service status message
;; List - list all services and their status
;; Start - start the named service
;; Stop - stop the named service
;; *Create - create the named service using the supplied configuration array (*unimplemented)
;; Modify - modify the named service using the supplied configuration array
;; Delete - delete the named service
;; Query - return current service data in the configuration array
;;
;; Service - OPTIONAL, Name of service to act upon
;;
;; SvcData - OPTIONAL, Array of service parameters
;; 0 - service short name (Read Only)
;; 1 - DisplayName Long service name
;; 2 - PathName Path to executable
;; 3 - ServiceType Own Process / Share Process
;; 4 - ErrorControl 0/Ignore, 1/Normal, 2/Severe, 3/Critical
;; 5 - StartMode Disabled, Manual, or Automatic
;; 6 - DesktopInteract (Read Only)
;; 7 - State (only when reading, ignored when writing)
;; 8 - StartName User ID
;; 9 - StartPassword (only when writing, always returned empty)
;;
;; Computer - OPTIONAL, Name of computer to query
;;
;; AuthPtr - OPTIONAL - pre-authenticated WMI object pointer
;; Use WMIAuthentication() udf to create the AuthPtr value
;; AuthPtr is not needed if user has admin rights
;;
;;REMARKS Used to manipulate & query services on a local or remote system
;;
;;
;;RETURNS Depends upon action
;; List - Array of comma-delimited strings: short name,display name,status
;; Start - WMI_Service status code
;; Stop - WMI_Service status code
;; Create - WMI_Service status code
;; Modify - WMI_Service status code
;; Delete - WMI_Service status code
;; Query - Array of service information (SvcData array format)
;;
;;DEPENDENCIES WMI
;;
;;TESTED WITH W2K, WXP, W2K3, Vista, x64
;;
;;EXAMPLES $Status = WMISvcMgr('Start', 'UPS', , $Computer)
;; WmiSvcMgr($Status) ? ; Display the message based on status code
;
Function WMISvcMgr($_Action, OPTIONAL $_Service, OPTIONAL $_SvcData, OPTIONAL $_Target, OPTIONAL $_pAuth)
Dim $_objWMI, $_cItems, $_oItem ; WMI object vars
Dim $_Line ; line string
Dim $_aTmp[0], $_I ; return array, index
Dim $_ ; temp var
Dim $_BTime, $_CTime ; boot and current times from target system
Dim $_E, $_R ; error and result vars to be returned
; If a numeric value was provided for Action, return the WMI_Service status/error message string
If $_Action = Int($_Action)
Select
Case $_Action = 0 $WMISvcMgr = 'Service Control Request completed successfully'
Case $_Action = 1 $WMISvcMgr = 'Not Supported'
Case $_Action = 2 $WMISvcMgr = 'Access Denied'
Case $_Action = 3 $WMISvcMgr = 'Start failed - dependent service(s) not running'
Case $_Action = 4 $WMISvcMgr = 'Invalid Service Control Request'
Case $_Action = 5 $WMISvcMgr = 'Service cannot accept the requested control'
Case $_Action = 6 $WMISvcMgr = 'Service Not Active'
Case $_Action = 7 $WMISvcMgr = 'Service Request Timeout'
Case $_Action = 8 $WMISvcMgr = 'Unknown failure when starting service'
Case $_Action = 9 $WMISvcMgr = 'Path not found'
Case $_Action = 10 $WMISvcMgr = 'Service Already Running'
Case $_Action = 11 $WMISvcMgr = 'Service Database Locked'
Case $_Action = 12 $WMISvcMgr = 'Service Dependency Deleted'
Case $_Action = 13 $WMISvcMgr = 'Service Dependency Failure'
Case $_Action = 14 $WMISvcMgr = 'Service Disabled'
Case $_Action = 15 $WMISvcMgr = 'Service Logon Failure'
Case $_Action = 16 $WMISvcMgr = 'Service Markded for Deletion'
Case $_Action = 17 $WMISvcMgr = 'No Service Execution Thread'
Case $_Action = 18 $WMISvcMgr = 'Circular Dependency'
Case $_Action = 19 $WMISvcMgr = 'Duplicate Name'
Case $_Action = 20 $WMISvcMgr = 'Invalid Name'
Case $_Action = 21 $WMISvcMgr = 'Invalid Service Parameter(s)'
Case $_Action = 22 $WMISvcMgr = 'Invalid Service Account'
Case $_Action = 23 $WMISvcMgr = 'Service Exists'
Case $_Action = 24 $WMISvcMgr = 'Already Paused'
Exit 0
EndIf
; insure we have a valid target name, without any "\"
$_Target = IIf($_Target, $_Target, '.')
If InStr($_Target, '\') $_Target = Join(Split($_Target, '\'), '') EndIf
; If we pre-authenticated via WMIAuth, use that WMIobject instead, otherwise instantiate an object reference
If $_pAuth
$_objWMI = $_pAuth
Else
$_objWMI = GetObject('winmgmts:{impersonationLevel=impersonate}!\\' + $_Target + '\root\cimv2')
If @ERROR Exit Val('&' + Right(DecToHex(@ERROR), 4)) EndIf
EndIf
; Verify that the Service name is provided for actions that require it
If InStr('-Start-Stop-Create-Modify-Delete-Query-', '-' + $_Action + '-')
If $_Service = '' Exit 87 EndIf
EndIf
; Create the collection of all services, or one specific one, depending on action
If InStr('-List-Create-', '-' + $_Action + '-')
$_cItems = $_objWMI.ExecQuery('Select * from Win32_Service')
Else
; All remaining Actions require a service name - either exit if not definee or query WMI
$_cItems = $_objWMI.ExecQuery('Select * from Win32_Service WHERE Name = "' + $_Service + '"')
EndIf
; validate the action and required arguments, perform the defined task
Select
; ==============================
Case $_Action = 'List'
$_I = -1
For Each $_oItem in $_cItems
$_I = $_I + 1
ReDim Preserve $_aTmp[$_I]
$_aTmp[$_I]= $_oItem.name + ',' + $_oItem.DisplayName + ',' + $_oItem.State
Next
$WMISvcMgr = $_aTmp
$_cItems = 0
Exit 0
; ==============================
Case $_Action = 'Create'
If VarType($_SvcData) < 8192 Exit 87 EndIf ; exit if service data array is not defined
Exit 1
; TBD - future release
; ==============================
Case $_Action = 'Modify'
If VarType($_SvcData) < 8192 Exit 87 EndIf ; exit if service data array is not defined
If UBound($_SvcData) <> 9 Exit 87 EndIf ; exit if service data array is invalid
; Change(DisplayName, PathName, ServiceType, ErrorControl, StartMode, DesktopInteract, StartName, StartPassword,
; next 3 unsupported at this time... (feel free to code/test on your own!)
; LoadOrderGroup, LoadOrderGroupDependencies, ServiceDependencies)
; Need to convert ServiceType strings to proper value
Select
Case Left($_SvcData[3], 3) = 'Own'
$_SvcData[3] = 16
Case Left($_SvcData[3], 3) = 'Sha'
$_SvcData[3] = 32
EndSelect
; Need to convert ErrorControl strings to values
Select
Case $_SvcData[4] = 'Ignore'
$_SvcData[4] = 0
Case $_SvcData[4] = 'Normal'
$_SvcData[4] = 1
Case $_SvcData[4] = 'Severe'
$_SvcData[4] = 2
Case $_SvcData[4] = 'Critical'
$_SvcData[4] = 3
EndSelect
For Each $_oItem in $_cItems
$_R = $_oItem.Change($_SvcData[1],$_SvcData[2],$_SvcData[3],$_SvcData[4],,,$_SvcData[8],$_SvcData[9])
$_E = @ERROR
If Not @ERROR And $_R = 0
If $_SvcData[5]
$_R = $_oItem.ChangeStartMode($_SvcData[5])
$_E = @ERROR
EndIf
EndIf
Next
; ==============================
Case $_Action = 'Query'
ReDim $_aTmp[9]
For Each $_oItem in $_cItems
$_aTmp[0] = $_oItem.Name ; Service Name (not modifiable)
$_aTmp[1] = $_oItem.DisplayName ; Display Name
$_aTmp[2] = $_oItem.PathName ; Binary Path
$_aTmp[3] = $_oItem.ServiceType ; type of service
$_aTmp[4] = $_oItem.ErrorControl ; 0:Ignore, 1:Normal, 2:Severe, 3:Critical
$_aTmp[5] = $_oItem.StartMode ; Start Mode
$_aTmp[6] = $_oItem.DesktopInteract ; Bool - true if service can interact with desktop (Read Only)
$_aTmp[7] = $_oItem.State ; Current state (Read Only)
$_aTmp[8] = $_oItem.StartName ; Service User Account
$_aTmp[9] = '' ; Service password (not readable, return null)
Next
$WMISvcMgr = $_aTmp
Exit @ERROR
; ==============================
Case $_Action = 'Start'
For Each $_oItem in $_cItems
$_R = $_oItem.StartService
$_E = @ERROR
Next
; ==============================
Case $_Action = 'Stop'
For Each $_oItem in $_cItems
$_R = $_oItem.StopService
$_E = @ERROR
Next
; ==============================
Case $_Action = 'Delete'
For Each $_oItem in $_cItems
$_R = $_oItem.DeleteService
$_E = @ERROR
Next
EndSelect
$WMISvcMgr = $_R ; return the status value
Exit $_E
EndFunction
Glenn
_________________________
Actually I am a Rocket Scientist!
|
|
Top
|
|
|
|
#184158 - 2007-12-21 08:55 PM
Re: enum services running as specific user
[Re: brewdude6]
|
NTDOC
Administrator
   
Registered: 2000-07-28
Posts: 11628
Loc: CA
|
|
|
Top
|
|
|
|
Moderator: Jochen, Allen, Radimus, Glenn Barnas, ShaneEP, Ruud van Velsen, Arend_, Mart
|
0 registered
and 874 anonymous users online.
|
|
|