Removing the 'Protect object from accidental deletion' Flag From A Bunch of OUs

I was recently conducting an experiment that involved creating a ton of Organizational Units in Active Directory.  Typically, when new OUs are created, they have a flag set on them that says "Protect object from accidental deletion."

This is normally fine, as you wouldn't want an admin to accidentally delete an entire OU full of users and computers.  But I had created a large hierarchy of OUs to conduct an experiment, and now that it was done, I wanted to get rid of all the OUs.  Like, immediately.  And I didn't want to sit in the AD Users & Computers GUI and uncheck that box on every OU, one at a time, so that it would let me delete them.

$AllOUs = Get-ADObject -Filter "ObjectClass -EQ 'organizationalUnit'" `
          -SearchBase 'OU=TestOUs,DC=CONTOSO,DC=COM' -Properties *

Foreach ($OU In $AllOUs)
{
    Set-ADOrganizationalUnit $OU.DistinguishedName `
          -ProtectedFromAccidentalDeletion $False
}

Now I can just delete the base of the tree and they'll all vanish.

ImAlive - RDP Activity Simulator

Sometimes I use Remote Desktop Protocol (RDP) to connect to machines remotely.  Good ole' mstsc.exe.  Sometimes, the remote server that I connect to has a policy that automatically disconnects idle sessions after some minutes.  This can be excruciatingly inconvenient when, for instance, I'm trying to transfer a large file to or from the server.  The file transfer may take hours, but I have to sit there and babysit the RDP session to make sure that the server doesn't disconnect me?

So that's why I made ImAlive.

Basically, this tiny program will send a "heartbeat" to all open RDP windows on your system every 10 seconds.  This keeps your RDP session in an "Active" state, even if you walk away from the keyboard for hours.  You run this program locally on your workstation, not on the remote machine.

Just launch the executable, and you will see this:

Press any key to terminate the program.  It will automatically locate all open RDP windows on your desktop, and send a "heartbeat" to them, thus keeping your session "Active," indefinitely.

Caveats and Limitations:

  • You mustn't minimize your RDP windows.  You can keep them in the background, but don't minimize them. If you minimize the RDP windows, they will not be able to receive the heartbeat messages.  It doesn't matter if the RDP session is full screen or windowed.
  • You can still use your computer to do other things while your RDP sessions are in the background, but you may see your RDP windows flash into the foreground for an instant as the heartbeats are sent to them.  After the heartbeat is sent, the program attempts to return focus to whatever window had focus before the heartbeat was sent.  If you have multiple monitors, I recommend shoving all your "idle" RDP windows to the side where they don't bother you if they briefly (like, 10 milliseconds, you may not even notice) flash to the foreground.
  • The program stops working if your workstation is locked or goes to sleep or hibernates.

If at any time I eliminate any of these bugs/limitations, I will update the program and post the updates to this page.

Download:

ImAlive.zip (90.6KB)

Windows Emergency Management Services

BSODToday we're going to talk about one of the more esoteric features of Windows.  A feature that even some seasoned sysadmins don't know about, and that almost nobody outside of kernel debuggers and device driver writers in Redmond ever use...

Emergency Management Services!

Imagine you have a Windows computer that has suffered a blue screen of death. If you want to sound more savvy, you might call it a STOP error or a bug check. Pictured is a very old example of a BSoD, but it's just so much more iconic than the pretty new Win8 one with the giant frowny face on it.

So you're sitting there staring at a blue screen on the computer's console... can you still reboot the machine gracefully?  Or even crazier, could you still run, for example, Powershell scripts on this machine even after it has suffered some massive hardware failure?

Don't reach for that power button just yet, because yes you can!

You might have thought that once a Windows computer has blue-screened, then it's done. It's stopped forever and it cannot execute any more code, period.  I thought that myself for a long time. But lo and behold, there's still a little juice left even after you've blue-screened, and all you need is a serial or USB cable.  That's where Emergency Management Services comes in.

As the name implies, EMS is typically there for when all else fails. For when your computer has already gone to hell in a handbasket. You could consider it an out-of-band management solution.

Of course you need to have already enabled it beforehand, not after a bug check has already occurred. You'd enable it on Vista/2008 and above like so:

Bcdedit.exe /EMS ON /EMSSETTINGS BIOS

If using a USB port, or

Bcdedit.exe /EMS ON /EMSSETTINGS EMSPORT:COM2 EMSBAUDRATE:9600

If using an RS-232 serial port. (How quaint.)

Now that it's enabled, you can connect to the Special Administration Console (SAC.)

SAC Special Administration Console

From here, you can launch a command prompt (Cmd.exe,) and from there, you can launch Powershell.exe!  All over a serial or USB cable connection. If the regular SAC mode cannot be entered for some reason, then EMS will put you in !SAC mode, where you can still at least read the event logs and reboot the server in a more graceful manner than just pulling the plug.

Mark Russinovich has this to say about the Windows boot up process as it concerns EMS:

"At this point, InitBootProcessor enumerates the boot-start drivers that were loaded by Winload and calls DbgLoadImageSymbols to inform the kernel debugger (if attached) to load symbols for each of these drivers. If the host debugger has configured the break on symbol load option, this will be the earliest point for a kernel debugger to gain control of the system. InitBootProcessor now calls HvlInit System, which attempts to connect to the hypervisor in case Windows might be running inside a Hyper-V host system’s child partition. When the function returns, it calls HeadlessInit to initialize the serial console if the machine was configured for Emergency Management Services (EMS)."
Mark Russinovich, David Solomon, Alex Ionescu, Windows Internals 6th Ed.

So there you have it. Even when faced with a BSoD, if you have an opportunity to shut down or reboot the machine in a more graceful manner than just pulling the electricity from it, then you should do it.

My Powershell Profile Just Went Full-Glitz

My cat woke me up extremely early this Saturday morning with the incessant meowing and carpet-scratching that signals either her boredom, or an empty food dish.

So I got up, made some coffee, put some meat crackers into kitty's bowl, and then started tinkering with my Powershell profile... now it looks like this every time I launch PS: 

Powershell Profile

It all started a couple weeks ago when I watched a Channel9 video where Jeffrey Snover was playing with Powershell, and I noticed that he had changed his error text color to green. I'm guessing like so:

$Host.PrivateData.ErrorForegroundColor = "Green"

I don't know why he configured his error messages to be green. Maybe it's just because it's easier to see than the default red.  But I like to imagine the idea is to promote positive feedback... like elementary school teachers marking their student's incorrect homework answers with another color of pen besides a red pen... because red ink makes the kids feel bad.

Anyway, as I started playing with text colors and title bar text and whatnot, it occured to me that all these settings would just revert to defaults after I closed this Powershell session. So how do we make such changes permanent?

The Powershell Profile!

Just type $Profile into Powershell right now, and it will tell you the full path of your very own PS profile. It should be something like this:

C:\Users\Ryan\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

That script gets executed first thing every time you launch PS. It may not exist yet - you have to create it.  Just type Notepad $Profile and Notepad will open that file up, or prompt you to create it if it doesn't already exist.

I'm still thinking of more neat gizmos to throw in here, but this is good for now. The  weather information comes from the Yahoo Weather web API, and the ServerFault rep information comes from the StackExchange API. *Swoon...* REST APIs are so dreamy...

The StackExchange API gives you 300 anonymous calls per day per IP (more if you authenticate.)  There is a basic amount of error handling so that if you can't connect to one or the other of the web APIs to get the data for whatever reason, it will just replace the appropriate string with [Error connecting to weather API], and so on. You'd want to put a short timeout on the API calls too... Powershell doesn't need any help being slow to load!

And without further ado, here's the code:

Set-StrictMode -Version Latest
[String]$WOEID           = "2355944" # Where on earth ID for Arlington TX
[String]$WelcomeName     = "Ryan"
[Xml]$WeatherAPIResponse = $Null
$StackExAPIResponse      = $Null
[String]$WelcomeBanner   = [String]::Empty
[String]$WeatherString   = [String]::Empty
[String]$StackExString   = [String]::Empty

Try
{
    $WeatherAPIResponse = Invoke-WebRequest http://weather.yahooapis.com/forecastrss?w=$WOEID -TimeoutSec 3 -ErrorAction Stop
    If($WeatherAPIResponse -NE $Null -AND $WeatherAPIResponse.PSObject.Properties.Match('rss').Count)
    {
        $WeatherString = "Current weather in $($WeatherAPIResponse.rss.channel.location.city), $($WeatherAPIResponse.rss.channel.location.Region): $($WeatherAPIResponse.rss.channel.item.condition.temp)°, $($WeatherAPIResponse.rss.channel.item.condition.text), $($WeatherAPIResponse.rss.channel.atmosphere.humidity)% humidity"
    }
    Else
    {
        Throw
    }
}
Catch
{
    $WeatherString = "[Error connecting to weather service.]"
}

Try
{
    $StackExAPIResponse = Invoke-WebRequest https://api.stackexchange.com/users/104624?site=serverfault -TimeoutSec 3 -ErrorAction Stop
    If($StackExAPIResponse -NE $Null -AND $StackExAPIResponse.PSObject.Properties.Match('Content'))
    {
        $StackExString = "Current ServerFault rep: $($(ConvertFrom-Json $StackExAPIResponse.Content).Items.Reputation) total,  $($(ConvertFrom-Json $StackExAPIResponse.Content).Items.reputation_change_day) today, $($(ConvertFrom-Json $StackExAPIResponse.Content).Items.reputation_change_week) this week"
    }
    Else
    {
        Throw
    }
}
Catch
{
    $StackExString = "[Error connecting to StackExchange.  ]"
}


$WelcomeBanner      = @"
            .ooooooo            Welcome back, $WelcomeName!
          oooooooooooo          $WeatherString
        ooooo      ooooo        $StackExString
       oooo          oooo       
       ooo            .oo       
   oooooooooo          ooo      
  ooooooo.oooo.        oo.      
 ooo        .o.        ooooo    
ooo                    ooooooo  
oo                    .oooooooo 
oo                    oo     ooo
ooo                           oo
.oo                          ooo
 oooo                        oo.
  .oo myotherpcisacloud.com oo 
    .oooooooooooooooooooooooo  

"@

Write-Host $WelcomeBanner -ForegroundColor Cyan

So Long, TechNet Subscription.

It's been fun.  Got the email this afternoon.  I'm not sure that I'll be able to do much lab stuff any more.  Which means less content for this blog.  Less ability to answer questions on Server Fault through having the ability to quickly verify things.  Less ability for me take the things I've learned and tested and use them for the benefit of my employers.  Less ability to try out the extremely atypical scenarios that I'd get asked in the usual tricky Microsoft exam yet never see in a production environment.

I guess I can still get stuff from TechNet Evaluation Center, but as far as I can tell I'll have to promptly rebuild my entire lab every 6 months, which makes me less inclined.

I'll think of something.  Man, I never thought I'd be saying this, but sometimes I feel like things would be a lot easier on me if I just specialized in Linux stuff.