A reader, Paul, dropped me a note to ask about a script he'd written. He wanted to duplicate what had ben a manual process up to that point, including:
- Opening the Security Templates MMC snap-in
- Creating a template
- Expanding the "system services" node and double-clicking a service
- Defining the startup mode for that service as Disabled
- Editing the security (using the default of Admins, System having Full Control, and Interactive having Read)
- Repeating these steps for each service they needed to secure
- Saving the template
- Running the Security Configuration and Analysis MMC snap-in
- Creating a new Security Database using the saved template
- Applying the configuration to the computer.
No wonder he wanted to automate it! He decided to create a text file containing the equivalent of the security template, run SecEdit.exe to create the database, and SecEdit again to apply the template. Here's the PowerShell code:
# create database
$arguments =
"/c secedit.exe /import /cfg "
+ $TemplateFile +
" /db "
+ $TheDBFile +
" /overwrite /quiet"
[diagnostics.process]::start(
"cmd.exe"
, $arguments).waitforexit() | Out-Null
sleep -Seconds 2
# apply template
$arguments =
"/c secedit.exe /configure /cfg "
+ $TemplateFile +
" /db "
+ $TheDBFile +
" /overwrite /log "
+ $TheLogFile +
" /quiet"
[diagnostics.process]::start(
"cmd.exe"
, $arguments).waitforexit() | Out-Null
sleep -Seconds 2
His question was, "is there a better way to do this?"
I don't think so. Obviously, Get-WmiObject, Invoke-WmiMethod, and the Win32_Service class' Change() method could be used to change the startup mode - but not to apply the permissions they're using. I think Paul's probably hit on exactly the right way to do this for his organization.
Granted, what Paul's doing isn't a "pure PowerShell" solution. But you know what? It doesn't matter. There are, as I like to say, no points for style in this business - only points for what works, and Paul's solution works. I'm sure there are other ways Paul could solve this problem - but I couldn't identify any that were markedly better.
I've heard folks from Microsoft often asked, "why should I switch from ____ to PowerShell," and their usual answer is "don't." They didn't create PowerShell to force you to use it or switch from it; if you've got something else - a command-line tool in this case - that works, keep using it. PowerShell is designed to give you capabilities you didn't have before, in a more consistent and broad-reaching environment, but it isn't designed to necessarily replace anything you already have. In this example, Paul's using PowerShell to launch external command-line utilities, superbly illustrating the shell's ability to work with, and to integrate, existing tools and technologies.
I might suggest some very minor syntactic improvements:
$arguments = "/c secedit.exe /configure /cfg $TemplateFile /db $TheDBFile /overwrite /log $TheLogFile /quiet"
[diagnostics.process]::start("cmd.exe", $arguments).waitforexit() | Out-Null
sleep -Seconds 2
All I've done there is remove the string concatenation - in double quotes, PowerShell will replace a $variable with its contents, so you can avoid some of the ugliness of string concatenation. Paul, if you're reading this you'll have to double-check the syntax - the original you sent me in e-mail had is formatting a little whacked, so I may have missed a space or parameter. In addition, I might have used Start-Process instead of the static Start() method of the Process class; that cmdlet has a -wait parameter and I think you could accomplish everything you're after, here, using that cmdlet. Doing so would make the script a bit more readable for more folks. But again, these are minor syntactic points - and as I said, there are no points for style!
0 comments
Hide comments