Microsoft MCM and MCA Certifications Are Dead

First they trash TechNet subscriptions, and now I'm hearing that Microsoft Certified Master and Architect certifications are officially dying now as well. (Note: the following email was not sent to me. It came from this guy.) 

We are contacting you to let you know we are making a change to the Microsoft Certified Master, Microsoft Certified Solutions Master, and Microsoft Certified Architect certifications. As technology changes so do Microsoft certifications and as such, we are continuing to evolve the Microsoft certification program. Microsoft will no longer offer Masters and Architect level training rotations and will be retiring the Masters level certification exams as of October 1, 2013. The IT industry is changing rapidly and we will continue to evaluate the certification and training needs of the industry to determine if there's a different certification needed for the pinnacle of our program.

As a Microsoft Certified Master, Microsoft Certified Solutions Master, or Microsoft Certified Architect, you have earned one of the highest certifications available through the Microsoft Certification program. Although individuals will no longer be able to earn these certifications, you will continue to hold the credential and you will not be required to recertify your credential in the future. You will continue to have access to the logos through the MCP site, and your certifications will continue to show in the appropriate section of your transcript, according to Microsoft technology retirement dates. If you are a Charter Member, you will continue to hold the Charter Member designation on your transcript.

Also as a Microsoft Certified Master, Microsoft Certified Solutions Master, or Microsoft Certified Architect, you are a member of an exclusive, highly technical community and you've told us this community is one of the biggest benefits of your certification. We encourage you to stay connected with your peers through the main community distribution lists. Although we won't be adding more people to this community, you continue to be a valued member of it. Over time, Microsoft plans to transition the distribution lists to the community, and, with your consent, will include your information so that it can continue to be a valuable resource for your ongoing technical discussions.

Within the coming weeks, you will receive invitations to an updated community site. This community site will require you to sign in with a Microsoft Account and will replace the need for a Microsoft Partner account as is required today. From this site, you will be able to manage service requests for the Masters and Architects communities – such as ordering welcome kits and managing your contact information for the distribution lists and directory - and accessing training rotation and other community content (if applicable).

If you have not ordered your Welcome Kit, the last day to do so is October 31, 2013. To order your Welcome Kit, please contact the Advanced Cert team at advcert@microsoft.com.

We thank you for your commitment to Microsoft technologies.

This is extraordinarily depressing for me, as Microsoft Certified Master certification has been one of my biggest goals for the past three years. And now that's no longer a possibility.

I don't know why Microsoft would make such a decision, or if there will ever be a new equivalent certification to take the place of the MCM and MCA.

Microsoft, many of us do not understand your recent decisions that appear to be squarely anti-IT Pro. Microsoft Certified Masters and Architects were your strongest supporters and evangelists. They help advocate your products to customers and drive sales for you, Microsoft.  They spent the time and effort on that Masters or Architect certification because of a sincere passion for your products. I can't think of any other reason for you to make this decision unless you just don't want highly skilled and trained people advocating your products.

There are pockets of activism showing up already.  Here is a petition of sorts on Microsoft Connect that you can participate in. If you find any other similar petitions, please let me know.

Anatomy of a Powershell Advanced Function

This is the template I'm using for my Powershell 301: Anatomy of a Powershell Advanced Function class. In this online virtual class, I'll be discussing the Powershell Advanced Function feature line by line. Hopefully this will help instill good scripting techniques for scripters who are new to Advanced Functions or Powershell in general.

 

#Requires -Version 3
#Requires -Module ActiveDirectory
Function New-Cmdlet
{
<#
.SYNOPSIS
	This Cmdlet uses an approved verb from Get-Verb, comment-based help, #Requires
    statements, and it follows the format of an advanced Powershell function.
.DESCRIPTION
	This Cmdlet uses an approved verb from Get-Verb, comment-based help, #Requires
    statements, and it follows the format of an advanced Powershell function.
    This Cmdlet is designed only as a teaching tool to show good form for 
    writing Powershell v3 Cmdlets, also known as "Advanced Functions."
.PARAMETER ComputerName
    This describes the ComputerName parameter. If there are any defaults or extra
    attributes of the parameter as listed in the Param() block below, they will
    automatically be populated here. Notice that we use ComputerName here, and not
    ComputerNames or Hostname. That's because every other Cmdlet uses the parameter
    ComputerName with no S, even if we intend to supply multiple names, so we should
    stay consistent with that. Make it feel as much like an official Powershell
    Cmdlet as you can.
.EXAMPLE
    Get-Content C:\Hosts.txt | New-Cmdlet -Verbose

    This runs New-Cmdlet on each hostname in the Hosts.txt file.
.EXAMPLE
    "Server1","Server2","Server3" | New-Cmdlet

    This runs New-Cmdlet on Server1, Server2 and Server3.
.EXAMPLE
    New-Cmdlet -ComputerName Server1,Server2 -WhatIf -Verbose

    This tells what would happen if you ran New-Cmdlet on Server1 and Server2.
.INPUTS
    System.String[]

    This should be an array (a list) of one or more computer hostnames that you
    want to run this Cmdlet on. Pipeline input is accepted.
.OUTPUTS
    Nothing... yet!
.LINK
    If any relevant links, put 'em here.
.NOTES
    Notes. Author, date, whatever. You don't have to include every single one of 
    these event-based help categories, but it never hurts.
#>
	[CmdletBinding(SupportsShouldProcess=$True)]
	Param([Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)][ValidateLength(3,30)][String[]]$ComputerName)

    BEGIN
    {
        # Run one-time set-up tasks here, like defining variables, etc.
        Set-StrictMode -Version Latest
        Write-Verbose -Message "Cmdlet is starting. You won't see this message unless you used -Verbose."
    }
    PROCESS
    {
        # The process block can be executed multiple times as objects are passed through the pipeline into it.
        ForEach($computer In $ComputerName)
        {
            If($PSCmdlet.ShouldProcess($computer))
            {
                Write-Verbose -Message "Beginning Process block on $computer"          
                $computer
            }        
        }
    }
    END
    {        
        # Finally, run one-time tear-down tasks here.
        Write-Verbose -Message "Running End block."
    }
}

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

SRV Record for NTP? In *MY* Active Directory?

Howdy fellow IT goons. I am probably not going to talk about Powershell today... but no promises.

Good ole' RFC 2782, the great fireside reading that it is, spells out the concept behind DNS SRV records and using them to locate services within a domain. The Microsoft article "How DNS Support for Active Directory Works", which is also more than just a heart-warming story but is also required reading if you're a Windows admin, mentions that Active Directory is pretty much, more or less, compliant with the aforementioned RFC:

"When a domain controller is added to a forest, a DNS zone hosted on a DNS server is updated with the Locator DNS resource records for that domain controller. For this reason, the DNS zone must allow dynamic updates (RFC 2136), and the DNS server hosting that zone must support the SRV resource records (RFC 2782) to advertise the Active Directory directory service."

It goes _<service>._<protocol>.domain.com, so if I wanted to locate LDAP services in a domain I'd issue a DNS query for _ldap._tcp.domain.com, or if I wanted to find Kerberos service I'd do _kerberos._tcp.domain.com.

But no one ever said that Active Directory uses every type of SRV there is by default. Not even close. Take NTP, Network Time Protocol, as an example.  Given the above logic I might issue a DNS query for _ntp._udp.domain.com, searching for NTP time service in that domain. Assuming I'm in a Microsoft Active Directory domain, odds are that I will not find it.

An SRV record is not created by default for the NTP service.  This is because Windows clients connecting to an AD domain already know to use domain controllers for time service in an AD domain, and the domain controllers already have their own SRV records, so separate NTP records would be redundant and unnecessary.

In fact, the only Microsoft-centric scenario I know of where the SRV record _ntp._udp.domain.com comes in to play is smart phones and devices using Microsoft Office Communicator or Lync - and even then it's optional since they'll fail back to time.windows.com if the SRV record is not found. You can find those examples here and here. If you know of any other situations where Windows-based applications use such an SRV record, please let me know.

But maybe you have a heterogeneous IT environment and you may want to add these records for yourself in order to support Unix/Linux clients and their applications that are making such DNS queries.  It's very easy:

  • Open the DNS Manager console/MMC snap-in.
  • Drill down into your Forward Lookup Zones.
  • Locate the _udp subdomain, since the NTP service operates over the UDP protocol.
  • You should see a list of _kerberos and _kpasswd SRV records there already, that represent the domain controllers currently in your domain.
  • Right-click in that white space and choose "Other New Records..."
  • Select "Service Location (SRV)" from the list.
  • Configure your new record like this screenshot:

SRV record

Mind the underscores, and notice the trailing period at the end of your domain name. You will probably want to add one of these for each domain controller you have, and you can play around with the weights and priorities however you like. NTP uses port 123 of course. There will be some options in the drop down list that they give you as examples. Don't confuse it with _nntp, unless you host the News Network Transfer service in your domain too.