Advertisements

Archive for the ‘Scripting’ Category

Powershell Script to Locate Windows Services Running as Domain users

Ever had to change a domain administrator’s password and had the sinking feeling that some bozo had setup a Windows service to run as that user.   If you only have a couple servers it isn’t that big a deal to check each manually, but if you have a lot it can be a problem.  I’ve seen a lot of admins just use the scream test to figure out what broke, but sometimes it isn’t obvious until the server is rebooted.  We run into this situation frequently as we take over new clients.

Recently we had to make a change for a customer with 50+ Windows servers and I knew the account had been used for services. I just didn’t know where.  So I built the below powershell script.  I definitely owe a few people props as I used a number of different websites to figure out the WMI piece. Unfortunately, it has been too long since I remember who.  But the next best thing is to put this script out there for other to use.  So I have posted the script and a readme file to GitHub (a new experience for me, but way better than how I published my scripts previously).

https://github.com/Deadtired78/Find-DomainUserServices.ps1/

Hope this helps out.  This is provided “as-is” and while I’ve used in several environments I can’t guarantee it will work everywhere.  Feel free to leave respectful comments.

Advertisements

Remote Desktop Services “Drain mode” PowerShell script

If you’ve ever had to put a large number of 2008+ Windows Terminal/Remote Desktop servers in “drain mode” using the gui admin tool, you know it can be slow and tedious.  Faced with doing this on a Saturday night for about 30 servers I decided to make life a little quicker and easier by building a powershell script.   While my long term goal is to figure out how to drain an entire farm, for now I’m pretty satisfied to be able to do it from PowerShell pretty quickly.

There are two scripts.  Drain-RDserver.ps1 and Undrain-RDserver.ps1. Both require a single parameter “-RDserver” followed by the server name.  Drain changes the “User logon mode” to “Allow reconnections, but prevent new logons.” This could be changed to the “Allow reconnections, but prevent new logons until the server is restarted” by modifying the script.   Undrain puts the server back in “Allow all connections” mode.

Big thanks to SourceDaddy’s article which got me started on the right path. (http://sourcedaddy.com/windows-7/preparing-server-maintenance.html)

Here is the code:


###Drain-RDServer
# Input computer name
param (
[string]$RDServer = $(throw "-RDserver is required")
)
$RDSH = Get-WmiObject -Class "Win32_TerminalServiceSetting" -Namespace "root\CIMV2\terminalservices" -ComputerName $RDServerdra -Authentication PacketPrivacy -Impersonation Impersonate
$RDSH.SessionBrokerDrainMode=1
$RDSH.put() > $null
Write-Host "$RDServer is set to:"
switch ($RDSH.SessionBrokerDrainMode)
{
0 {"Allow all connections."}
1 {"Allow incoming reconnections but prohibit new connections."}
2 {"Allow incoming reconnections but until reboot prohibit new connections."}
default {"The user logon state cannot be determined."}
}


###Undrain-RDServer
# Input computer name
param (
[string]$RDServer = $(throw "-RDserver is required")
)
$RDSH = Get-WmiObject -Class "Win32_TerminalServiceSetting" -Namespace "root\CIMV2\terminalservices" -ComputerName $RDServer -Authentication PacketPrivacy -Impersonation Impersonate
$RDSH.SessionBrokerDrainMode=0
$RDSH.put() > $null
Write-Host "$RDServer is set to:"
switch ($RDSH.SessionBrokerDrainMode)
{
0 {"Allow all connections."}
1 {"Allow incoming reconnections but prohibit new connections."}
2 {"Allow incoming reconnections but until reboot prohibit new connections."}
default {"The user logon state cannot be determined."}
}

And here is a link to the scripts in a zip file.

Set Owner with PowerShell: “The security identifier is not allowed to be the owner of this object”

I’ve written several PowerShell scripts to help customers adjust permissions to their directory structures when migrating from other file servers(Linux/Samba, Novell OES/Netware, etc).  Part of these scripts includes assigning ownership for the user.  While this tends to take a long time quotas and file reporting are worthless if the administrator that copied everything is assigned as the owner.

Recently I tried to adapt one of these scripts for a customer, but when I ran it it failed with the error: “The security identifier is not allowed to be the owner of this object”

A quick internet search found lots of people saying basically this can’t be done with PowerShell.  What!!! I know for a fact these scripts had worked before.  What’s the deal?   After a lot of testing and beating my head against the wall I figure out I was trying to do something different.  Previously I had run my scripts against the UNC path (eg. \\servername\share\directory), but this time I was trying to run it on a local directory using the drive path (E:\Share\Directory).

Could it be that simple? Yes.  I ran the command again using the UNC path and the script worked as it did before.

Here is an example script to set the owner of a directory or file to test the above:

function pathPrompt {

$tempPath = $null
$tempPath = Read-Host ‘Please enter the path of thedirectory (e.g. “\\file\vol1\users\example”‘
return $tempPath
}

$username=”exampleuser”
$domain=”domain”
$ID = new-object System.Security.Principal.NTAccount($domain, $username)

$path = pathPrompt

write-host $path

$acl = get-acl $path
$acl.SetOwner($ID)
set-acl -path $path -aclObject $acl

Save the above to a file with a .PS1 extension, change the $username and $domain variables, and run it (make sure you set-executionpolicy to unrestricted and PowerShell as administrator). It will prompt for a path. It will then write the path to powershell and then set the owner if it can.

Below is an example of running it against a local path and a UNC path.

VBScript to create a My Documents Variable

I was recreating a login script for a client that mapped a drive to the location of their redirected My Documents.  Because they were in the middle of a migration the My Documents could be in a different spot depending on if a user had been migrated to a new environment or not. So I needed to be able to query the current location of the My Docs, much like the %userprofile% shows the path to the current profile.

Below is a chunk of VBScript I cobbled together from a variety of sources including ActiveXperts that reads the appropriate registry key value of the user that runs the script.  This chunk just outputs the path to the command line but the myDocsPath variable could also be used to map a drive.

(Please note that the line that starts “Set oReg=GetObject….” and the line below it need to be a single line)

—-Copy Everything Below—–

const HKEY_CURRENT_USER = &H80000001
const HKEY_LOCAL_MACHINE = &H80000002
strComputer = "."
Set StdOut = WScript.StdOut
 
Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer &
 "\root\default:StdRegProv")

strKeyPath = "Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders"
strValueName = "Personal"
oReg.GetExpandedStringValue HKEY_CURRENT_USER,strKeyPath,strValueName,myDocsPath
StdOut.WriteLine "Current My Docs path is: " & myDocsPath

 —-Copy Everything Above—–

Advertisements