Using PowerShell to recursively disable specific services

I'm on a bit of a mission to disable unneeded services in Windows Server 2016 (of which there are many!) in order to improve the woeful overall performance of the OS, so I have a powershell script that goes through and disables various things.  I've come across so-called "Per-user services" which are difficult to disable fully, because there's a host service, e.g. OneSyncSvc, and then when someone logs in, this spawns another service, called OneSyncSvc_##### - where ##### is always a randomly-generated 5-character hex string. There are several services that do this, namely...

CDPUserSvc
OneSyncSvc
PimIndexMaintenanceSvc
UnistoreSvc
UserDataSvc
WpnUserService

Some of the above are not visible in services.msc, and even the ones are are not able to be disabled from the snap-in, so putting a Start=4 in the registry for these is the only option.

Anyway, the way to disable any of these services with PowerShell is...

Get-Item HKLM:\SYSTEM\CurrentControlSet\Services\<service-name>   {I add this line just to record in the transcript what the value was before I changed it}
reg add HKLM\SYSTEM\CurrentControlSet\Services\<service-name> /v Start /t REG_DWORD /d 4 /f

So what I need is a short script that does the following...

1. Gets the first name on the service list above
2. Then finds all reg keys within HKLM\SYSTEM\CurrentControlSet\Services that begins with that name
3. Then runs the 'Get-Item' and 'reg add' commands above for every reg key that it finds in 2.  {or if you prefer to change the 'reg add' to the native powershell command then feel free}
4. Then repeats 1. 2. & 3. for all the other names on the above service list.

Could anyone do this for me?  Sorry that my PowerShell is not (yet!) good enough to do this recursive bit.

Many thanks.
meirionwylltSenior Desktop EngineerAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

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

Hasin Ahmed ChoudharyExchange AdministratorCommented:
Kindly provide all the steps you have written so far. Will try to do for looping and point 2 and update here.
meirionwylltSenior Desktop EngineerAuthor Commented:
Hi Hasin, the only steps I've done for this is the two lines I mentioned before, namely...

Get-Item HKLM:\SYSTEM\CurrentControlSet\Services\<<service-name>>
reg add HKLM\SYSTEM\CurrentControlSet\Services\<<service-name>> /v Start /t REG_DWORD /d 4 /f

also the 'stems' of the service names, namely...

CDPUserSvc
OneSyncSvc
PimIndexMaintenanceSvc
UnistoreSvc
UserDataSvc
WpnUserService


Thank you.
oBdACommented:
Try this; it's in test mode and will only display which keys it would process; remove the -WhatIf in line 13 to run it for real:
$regKey = 'HKLM:\SYSTEM\CurrentControlSet\Services'
$services = @(
	'CDPUserSvc'
	'OneSyncSvc'
	'PimIndexMaintenanceSvc'
	'UnistoreSvc'
	'UserDataSvc'
	'WpnUserService'
)
ForEach ($Service in $services) {
	Get-ChildItem -Path $regKey |
		Where-Object {$_.PSChildName -match "\A$($service)(\Z|_)"} |
		Set-ItemProperty -Name Start -Value 4 -Force -WhatIf
}

Open in new window

oBdACommented:
Sorry, missed the part about you wanting to see the old value; as before, in test mode (line 15):
$regKey = 'HKLM:\SYSTEM\CurrentControlSet\Services'
$services = @(
	'CDPUserSvc'
	'OneSyncSvc'
	'PimIndexMaintenanceSvc'
	'UnistoreSvc'
	'UserDataSvc'
	'WpnUserService'
)
ForEach ($Service in $services) {
	Get-ChildItem -Path $regKey |
		Where-Object {$_.PSChildName -match "\A$($service)(\Z|_)"} |
		ForEach-Object {
			"$($_.PSChildName) old: $((Get-ItemProperty -Path $_.PSPath).Start)"
			Set-ItemProperty -Path $_.PSPath -Name Start -Value 4 -Force -WhatIf
			"$($_.PSChildName) new: $((Get-ItemProperty -Path $_.PSPath).Start)"
		}
}

Open in new window

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
meirionwylltSenior Desktop EngineerAuthor Commented:
Thanks oBdA!  I've tested that and it works excellently well - just what I needed.  I'm glad I asked the question, because I could have been looking at this for weeks and still not manage to do it.  Cheers.
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
Powershell

From novice to tech pro — start learning today.