Introduction
This is a "workaround" solution to enable programmatic changes to the Windows Parental Controls of a user whether or not they are logged on, and even if the machine is a standalone with no domain.
The Story...
I was trying to have one of my VB.NET programs change the Parental Control settings for a named user on a local standalone system with no domain. Every piece of code I could find worked for the current logged-on user, but, no matter how I tried, I could not get it to work for any user who was not logged on at the time. The problem is that, whilst there are several ways we can address the settings, to do so we need either a logon token (only available for logged on users), a UPN (only available from an active domain), or to know the SID for each username whose WPC settings we need to access. Turning the username into a SID gives much the same problems. So...
I'd found a code-snippet that worked nicely for any user I knew the SID for (Not very well formatted - Sorry!):
Dim searcher As New ManagementObjectSearcher("root\CIMV2\Applications\WindowsParentalControls", "SELECT * FROM WpcUserSettings")
If queryObj("SID") = "S-1-5-21-666666666-444444444-7777777777-1001" Then
queryObj("AppRestrictions") = True
queryObj("HourlyRestrictions") = True
queryObj("LoggingRequired") = False
queryObj("LogonHours") = False
queryObj("OverrideRequests") = False
queryObj("WpcEnabled") = True
queryObj.Put()
End If
I then tried all ways and for hours to get the machine to give me the SID of the account from the username, but all attempts failed, for similar reasons to why the other ways of querying the WPC settings failed.
Finally, I realised that I already had a piece of code that worked the other way around: i.e. it gives the username for any given SID. Hence, all I had to do was to generate a list of ALL the SID's for a machine , and then run a simple If/Then loop to find the right one. It turns out that getting all the SID's from a machine is quite easy.
Here's what we end up with. Quick note here: If you're copying and pasting this code, remember the "Imports" lines, and to set the references to them in your project. ("Coding 101 - Egg Sucking for grandmothers", I know, but we all forget sometimes!)
Imports System
Imports System.Collections.Generic
Imports System.Management
Imports System.Text
Module Module1
Sub Main()
Console.WriteLine("Starting Module")
Dim SidString As String = ""
Dim AccountName As String = ""
Dim FullName As String = Environment.MachineName & "\YOUR ACCOUNT NAME"
Try
Dim searcher As New ManagementObjectSearcher("root\CIMV2\Applications\WindowsParentalControls",
"SELECT * FROM WpcUserSettings")
Console.WriteLine("Path to the Parental Control settings - " & searcher.ToString)
For Each queryObj As ManagementObject In searcher.[Get]()
SidString = queryObj("SID")
Console.WriteLine("SID - " & SidString)
AccountName = New SecurityIdentifier(SidString).Translate(GetType(NTAccount)).ToString
Console.WriteLine(AccountName & " is " & FullName)
If AccountName = FullName Then
Console.WriteLine(queryObj("SID"))
queryObj("AppRestrictions") = True
queryObj("HourlyRestrictions") = True
queryObj("LoggingRequired") = False
queryObj("LogonHours") = False
queryObj("OverrideRequests") = False
queryObj("WpcEnabled") = True
queryObj.Put()
Else
Console.WriteLine(AccountName & " is not " & FullName)
End If
Next
Catch e As ManagementException
Console.WriteLine("An error occurred setting the WMI data: " + e.Message)
End Try
Console.ReadKey()
End Sub
End Module
So, there you have it. A way to change Parental Control permissions for any account from any account... well, almost... You need Administrator rights to run it... Sorry kids!
I started programming Algol in 1974, when my school obtained precious processing "windows" on the university mainframe. After a brief foray into Fortran, I settled into the "new" language of Basic, at college in 1978, and became the resident college "hacker", managing to annoy several other students by corrupting their workspaces during (eventually successful)attempts to get the teletype terminals to talk to each other. I believe that my little 1978 Basic application was the world's first ever IM!
Since then, I spent about 30 years in the music business, but recently came back to coding in VB.NET (completely missing out VB). I'm now working on software projects for the music and hospitality industries, but still perform as Lead Tenor in "History, The Musical" at the Tenerife Magma convention centre.