Blog - Title

February, 2010

  • Strict Replication Consistency - Myth versus Reality

    Hi, David here again. Having worked numerous lingering object cases, I find a common misunderstanding about Windows Server 2003 (or later) and its ability to automatically enforce Strict Replication Consistency. Strict Replication Consistency is a registry value that prevents destination domain controllers (DC) from replicating in lingering objects. Lingering objects are objects that have been deleted on one DC but replication failures prevent a partner DC learning of the deletion. The result is those deleted objects remain “live” on the replication partners. If the replication failure persists for longer than tombstone lifetime but is later corrected, the DC that failed to inbound replicate the deletions will continue to have “live”/lingering objects in its copy of the AD database. When one or more attributes are modified on these “live” objects, that object must replicate outbound. DCs that don’t have Strict Replication Consistency enforced will replicate in these formerly deleted objects, re-animating them.

    Note: for the sake of readability, when I say “Windows Server 2003” in the document, I mean Windows Server 2003 or later. Windows Server 2008 and Windows Server 2008 R2 behave the same in this respect.

    A Windows Server 2003 server can automatically configure Strict Replication Consistency during the domain controller promotion process certain conditions have to be true. There are some myths and badly worded documents out there that imply Windows Server 2003 DC’s always configure themselves for strict replication , so this blog post aims to set the record straight.

    Forests originally created on Windows 2000 Server - but later upgraded to Windows Server 2003 require an additional step to automatically enable strict replication consistency on newly promoted domain controllers. While Windows Server 2003 DCs tend to quarantine themselves if they have not replicated for greater than Tombstone Lifetime, failure to implement this step will leave all newly promoted Windows Server 2003 DCs configured for Loose Replication Consistency; leaving them at risk of re-animating lingering objects from Windows 2000 replica DCs or Windows Server 2003 DCs that have had Allow Replication With Divergent and Corrupt Partner set but have not been cleaned of lingering objects first.

    If you want new domain controllers added to the forest to have strict replication consistency automatically enabled, you can import the Operational GUID cited below to the Configuration directory partition using Ldifde.exe. The presence of this object in the Configuration partition causes dcpromo.exe to enable Strict Replication Consistency on any Windows Server 2003 domain controller that is promoted into the forest.

    1. Start notepad.exe and copy in the sample LDF text below. Edit both lines containing DC=<domain>,DC=<com> to match your forest root domain.

    Example: If your forest root domain were contoso.com the DN would be DC=contoso,DC=com

    dn: CN=94fdebc6-8eeb-4640-80de-ec52b9ca17fa,CN=Operations,CN=ForestUpdates,CN=Configuration,DC=<domain>,DC=<com>
    changetype: add
    objectClass: container
    showInAdvancedViewOnly: TRUE
    name: 94fdebc6-8eeb-4640-80de-ec52b9ca17fa
    objectCategory: CN=Container,CN=Schema,CN=Configuration,DC=<domain>,DC=<com>

    2. Once the DN has been modified correctly save the file as StrictRepl.ldf.

    3. Open a command prompt with Enterprise Administrator credentials and issue this command:

          Ldifde.exe -i -f StrictRepl.ldf

    It’s important to note that just adding this object to the CN=Operations container will not cause existing Windows Server 2003 DCs to configure themselves for Strict Replication Consistency. For existing DCs you must add the Strict Replication Consistency registry value and set it to 1 before they will enforce strict replication. The good news is this can be done remotely using repadmin.exe from a command prompt opened with Enterprise Admin credentials. The command to run is:

    repadmin.exe /regkey <dcname> +strict

    If you want to make certain this is configured on all DCs in the forest you can pass a wildcard to repadmin.exe like this,:

    repadmin.exe /regkey * +strict

    If you are running this against all DCs in the forest you should pipe this out to a text file and verify all DCs have been contacted and the value has been set correctly.

    Warning: Before you implement this change forest-wide it is important to understand that all replication between the source DC and the destination DC will stop for any partition that has a lingering object in it. Replication will only be restored once the lingering object is removed. This could cause forest-wide authentication issues until replication is restored.

    For more information about this operational GUID see Technet.

    Hopefully this will clear up the common misconception that all Windows Server 2003 domain controllers will always enforce strict replication consistency and will lead to closer examination of current configurations before lingering objects start causing issues.

    David “buster” Everett

  • Friday Mail Sack – Not USMT Edition

    Hi all, Ned here again. Just like last Friday, today I’m sharing some emails we’ve gotten recently. Enjoy.

    Question:

    I am creating a custom schema extension for AD LDS (aka ADAM). Do I need to obtain and register my OID with Microsoft?

    Answer:

    It's not as critical as an AD forest but still highly recommended - once you get a root OID it can be used for your entire company. You absolutely must register with MS if you intend on creating a product that will be given to third parties to extend their AD LDS schemas. If you don't get an ISO-provided root OID, don't register with MS, then provide that schema to your customers then you could damage your customers. Without registration you are ineligible for the Certified for Windows logo, which is a deal breaker for certain classes of applications within many companies.

    If your AD LDS schema is never going anywhere and there’s no risk of it synchronizing with an AD schema, we have a script for generating a safe internal OID here. I really recommend that you get a registered OID though, as once you duplicate an OID in an environment, fixing the issue ranges from extremely difficult to impossible.

    Question:

    I can manage 2008 R2 DNS fine from RSAT on Windows 7, but accessing from DNS Management mmc on Server 2003 R2 returns “access is denied”. If I install the 2003 R2 Admin Pack on an XP Pro PC it the symptom is the same, Access Denied.

    Answer:

    This is expected behavior, starting with Windows Server 2008 a few years ago. RPC Integrity required by W2K8 R2 DNS Servers is not supported by the Win2000 and Win2003 versions of DNSMGMT.MSC (or DNSCMD.EXE). For the most secure experience, W2K8 R2 DNS servers should be administered from operating systems that can execute the Windows Server 2008 or later versions of DNSMGMT.MSC. So Vista RSAT, Win 7 RSAT, Win 2008, Win 2008 R2 – all running DNSMGMT.MSC.

    If you wanted to de-secure your Win2008/R2 DNS servers though – obviously this is highly discouraged – you can run the following command on your Win2008 R2 DNS servers to allow down-level connectivity:

    dnscmd.exe /Config /RpcAuthLevel 0

    If you do this you are exposing your Win2008/Win2008 R2 DNS servers to same kind of named-pipe sniffing ‘man in the middle’ attacks that Win2003/2000 DNS administration are vulnerable to. Ideally for security, all of your DNS servers would be instead upgraded to Win2008 R2. More info here.

    Question:

    Why is your manager such a hugely inappropriate bull in a china shop that never knows when not to say exactly what he is thinking?

    Answer:

    He’s from St John’s, Newfoundland.

     

    Have a great weekend folks!

    - Ned “now to work on my midyear review” Pyle

  • USMT, OST, and PST

    Ned here again. Do you remember time before email in the office? It’s been a while now. Email isn’t an option these days any more than a phone. And since Exchange has reached around 65% market share, odds are decent that you’re using some version of Outlook. If you’re planning on migrating to Windows 7 with USMT 4.0, you likely have two questions:

    1. How can I get Outlook OST’s to migrate?
    2. How can I get Outlook PST’s to migrate?

    Updated April 16, 2012 to be more complete 

    OST migration

    I am just going to rip the bandage off here, so grit your teeth: you cannot migrate Outlook OST files with USMT. USMT makes no special allowances for OST files because the Outlook team does not support those files moving between computers; they were never designed for portability and Outlook’s developers don’t want anyone copying them around. The only supported way to get an OST file is for Outlook to create it.

    If you create a custom Include XML file that copies over OST files then Outlook may state the OST is invalid or that it cannot be opened. Please don’t call us asking for workarounds: this is expected behavior and there is absolutely nothing that the USMT or Outlook support teams can do. The OST may appear to work also; you got lucky for now, but there may be buried badness in that file that rises up someday like a mail-enabled Dracula – no one knows.

    And it's not just me saying this: http://technet.microsoft.com/en-us/library/cc179110.aspx#BKMK_MigrationConsiderations

    PST migration

    By default, USMT 4.0 migrates PST files that are linked to a user’s Outlook profile. This is done through internal USMT functions named SetPstPathInMapiStruct and UpdateMvBinaryMapiStruct which is called from within migapp.xml.

    What this means is that PST files which are simply stored on the drive but not actually connected to Outlook might not migrate when using /i:migapp.xml and /i:migdocs.xml.  For example, if a user has a PST file store in their c:\users\someuser\appdata\local\microsoft\outlook folder: USMT doesn't just copy that folder's contents willy-nilly; after all, those are mostly local per-computer settings and data, and just blasting them onto another computer could cause problems.

    It’s very possible a user is keeping those around for archive purposes, though. Migdocs.xml will gather customer folder contents from the roots of drives with little though to their contents, but you may need some XML to target PSTs appropriately and surgically. Consider this scenario, where the archive.pst and nov2009on.pst are not attached to Outlook, and are just loose files on the computer:

    image

    If you just wanted the c:\pst copy, you get it for free as long as you use migdocs.xml. In order to migrate  all of those PST files though, you’ll need to use a custom XML override. Here is a sample that will gather all PST files from all fixed drives, regardless of their location:

    <?xml version="1.0" encoding="utf-8" ?>
    <migration urlid="http://www.microsoft.com/migration/1.0/migxmlext/pst">
      <component type="Documents" context="UserAndSystem">
        <displayName>All PST migrated from all fixed drives, regardless of location</displayName>
        <role role="Data">
          <rules>
            <include>
              <objectSet>
                <script>MigXmlHelper.GenerateDrivePatterns ("* [*.pst]", "Fixed")</script>
              </objectSet>
            </include>
          </rules>
        </role>
      </component>
    </migration>

    Paste that into Notepad and save as PST.XML into your USMT folder. When you add that to your scanstate and loadstate command-lines with /i:pst.xml then all fixed drive PST files will be migrated. You could also paste it into Visual Studio 2008 Express, nudge nudge.

    Here's another sample XML, which has the added bonus of not accidentally copying PST files that a user connected to Outlook through a UNC path (which is unsupported except for one small scenario, by the way - http://support.microsoft.com/kb/297019):

    <?xml version="1.0" encoding="utf-8" ?>
    <migration urlid="http://www.microsoft.com/migration/1.0/migxmlext/pst">
      <!-- This component migrates .PSTs except for ones on the network-->
      <component type="Documents" context="UserAndSystem">
        <displayName>All PST files migrated from all fixed, no PST’s migrated from network, regardless of context or outlook registry catalog settings</displayName>
        <role role="Data">
          <rules>
            <unconditionalExclude>
              <objectSet>
                <script>MigXmlHelper.GenerateDrivePatterns ("* [*.pst]", "Remote")</script>
              </objectSet>
            </unconditionalExclude>
            <unconditionalExclude>
              <objectSet>
                <pattern type="File">\\* [*.pst]</pattern>
              </objectSet>
            </unconditionalExclude>
            <include>
              <objectSet>
                <script>MigXmlHelper.GenerateDrivePatterns ("* [*.pst]", "Fixed")</script>
              </objectSet>
            </include>
          </rules>
        </role>
      </component>
    </migration>

    Side note: the migXmlHelper.GenerateDrivePatterns option allows me to avoid hard coding paths, drive letters, or non-fixed storage. It’s something you should get comfortable with as it’s extremely useful in environments with non-standard images and users roaming freely with USB thumb drives. Since you’re going to Windows 7, don’t forget about “BitLocker to go” for those scenarios!

    Another side note: Make sure you are using latest USMT 4.0 so that you capture Outlook 2010 settings correctly! http://support.microsoft.com/kb/2023591

     

    Until next time.

    - Ned “ends in t” Pyle

  • USMT Custom XML the Free and Easy Way

    Ned here again. XML is used to configure all aspects of USMT 4.0 migration and is especially important when customizing. Unfortunately most IT staffers are not familiar with XML – why should they be? It’s barely used within Windows and is mainly an applications-specific file store. Maybe you noticed that group policy ADMX files are XML – did you care, since you were using the GP editor to make changes?

    Unfortunately, there’s no USMT XML editor. What’s more, XML follows programming conventions– tags must be closed; nesting must be complete; rules are case-sensitive. And any mistake in the XML will cause the migration to fail or skip crucial steps.

    XML, like any programming file format, has rules. This means that there are tools that can examine that file and see if the rules are being broken – programmers are not super human. One such tool is Visual Studio 2008 Express. It has an excellent suite of XML authoring and validation options – and it’s free :).

    Let’s come up with a scenario that requires custom XML, create our file, and then validate it.

    The Scenario

    End users love wallpaper. I mean they love it, in a manner usually reserved for grandkids, puppies, and their first car. So when you find that USMT doesn’t migrate wallpaper from XP to Windows 7, you know they won’t be pleased.

    After some Internet exploration, you find all the wallpaper settings from XP and the default wallpaper locations are made up of a few registry settings and folders. You have examined our various references, including:

    Now you want to bang out a custom XML file. Most folks are not familiar with VS2008 so I’ll go through this step-by step.

    Authoring

    1. Download and install Visual Studio 2008 Express Edition (.Net), then start it up.

    image

    2. Choose File, New Project, and select “Empty Project”. Call it USMT.

    image

    3. In your new project, select Add then New Item.

    image

    Select XML file and give it a name like “wallpaper.xml”, then add it.

    image

    Click File menu, then Save All. Save your project and files somewhere.

    4. Paste in the following sample that migrates wallpaper and background settings. It’s wrapped for readability:

    <migration urlid="http://www.microsoft.com/migration/externalUserDocs">

      <!-- This component migrates wallpaper settings -->
      <component type="System" context="User">
        <displayName>Wallpapers</displayName>
        <role role="Settings">
          <rules>
            <include>
              <objectSet>
                <pattern type="Registry">HKCU\Control Panel\Desktop [Pattern]</pattern>
                <pattern type="Registry">HKCU\Control Panel\Desktop [PatternUpgrade]</pattern>
                <pattern type="Registry">HKCU\Control Panel\Desktop [TileWallpaper]</pattern>
                <pattern type="Registry">HKCU\Control Panel\Desktop [WallPaper]</pattern>
                <pattern type="Registry">HKCU\Control Panel\Desktop [WallpaperStyle]</pattern>
                <pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Themes [SetupVersion]</pattern>
                <pattern type="Registry">HKCU\Software\Microsoft\Internet Explorer\Desktop\General [BackupWallpaper]</pattern>
                <pattern type="Registry">HKCU\Software\Microsoft\Internet Explorer\Desktop\General [TileWallpaper]</pattern>
                <pattern type="Registry">HKCU\Software\Microsoft\Internet Explorer\Desktop\General [Wallpaper]</pattern>
                <pattern type="Registry">HKCU\Software\Microsoft\Internet Explorer\Desktop\General [WallpaperFileTime]</pattern>
                <pattern type="Registry">HKCU\Software\Microsoft\Internet Explorer\Desktop\General [WallpaperLocalFileTime]</pattern>
                <pattern type="Registry">HKCU\Software\Microsoft\Internet Explorer\Desktop\General [WallpaperStyle]</pattern>
                <content filter="MigXmlHelper.ExtractSingleFile(NULL, NULL)">
                  <objectSet>
                    <pattern type="Registry">HKCU\Control Panel\Desktop [WallPaper]</pattern>
                    <pattern type="Registry">HKCU\Software\Microsoft\Internet Explorer\Desktop\General [BackupWallpaper]</pattern>
                    <pattern type="Registry">HKCU\Software\Microsoft\Internet Explorer\Desktop\General [Wallpaper]</pattern>
                  </objectSet>
                </content>
              </objectSet>
            </include>
          </rules>
        </role>
      </component>

      <!-- This component migrates wallpaper files -->
      <component type="Documents" context="System">
        <displayName>Move JPG and BMP</displayName>
        <role role="Data">
          <rules>
            <include>
              <objectSet>
                <pattern type="File"> %windir% [*.bmp]</pattern>
                <pattern type="File"> %windir%\web\wallpaper [*.jpg]</pattern>
                <pattern type="File"> %windir%\web\wallpaper [*.bmp]</pattern>
              </objectSet>
            </include>
          </rules>
        </role>
      </component>
    </migration>

    It will now look much better, which is one important advantage of using VS 2008 to work with USMT XML: many mistakes can be avoided just by the visual cues of colored letters and proper formatting.

    image

    5. Click the XML menu and choose Schemas… (note that if you don’t select an XML document tab, the menu won’t appear).

    image

    Add in the MIGXML.XSD from your USMT folder. This file defines the schema of USMT XML and will allow Visual Studio to point out further errors.

    image

    6. Open the View menu and select Error List:

    image

    Now you will see all syntax errors in your XML file in real time, both with an underline squiggle, a la MS Word, as well as in the error window below. The sample I gave to paste in is (of course!) perfection, so you have no errors yet.

    Validation

    Let’s create some intentional mistakes to show how Visual Studio can help:

    • Change <component type="System" context="User"> to <component type="System" context="user"> . Note how the lower-case “user” is now underlined and the error list shows “The ‘context’ attribute is invalid.” XML tags are case-sensitive and a lower case user no longer matches the schema defined name of “User”, so an error is raised. Change it back.
    • Change <component type="System" context="User"> to <component type="System" context="SystemAndUser"> . Since the real value must be “UserAndSystem”, the context attribute is invalid. Change it back.
    • Change any <include> tag to <include . The next line will show an underline and “Expecting ‘>’” will appear with a line number. Change it back.
    • Delete any </include> tag. Now you will see an error “Tag was not closed” and “Expecting end tag </include>”. Change it back.

    See how much easier this is than using Notepad? :) The right tool for the job makes all the difference and didn’t cost you a dime. Take a few more of the examples included in Exclude Files and Settings and Include Files and Settings, paste them into some new XML files in your project, and start tinkering. Repetition breeds familiarity. Everything above also works with Visual Studio 2008 Professional of course.

    Save your Wallpaper.XML to the USMT folder and fire up scanstate in a test environment with /i:wallpaper.xml . Your users can now have their old wallpapers migrated free of charge. I’m sure they will thank you. Riiiiiiight.

    Update October 29 2010: If using Visual Studio Express 2010, make sure you click "Tools --> Settings --> Expert Settings" in order to see the XML menu and other feateures described above. We buried a lot in this version...

    Until next time.

    Ned “bliss.bmp” Pyle

  • New Directory Services KB Articles/Blogs 1/31-2/6

    KB

    No new DS-related KBs this week.

    Blogs

    Friday Mail Sack – First Attempt Edition

    Inventorying Computers with AD PowerShell

    Categorizing LDAP searches - inefficient vs. expensive?

    What GP-settings should I roll out in my environment?

    Announcing the Remote Desktop Protocol Performance Improvements in Windows Server 2008 R2 and Windows 7 white paper

    Active Directory (and ADAM/ADLDS) Tombstone Lifetime

    GP Editorial: Group Policy Best Practices

    Windows 7 BranchCache™ User Experience

    Updated management pack monitors DFS namespaces

    Server Core Roles and Features in 2008 R2

    How to get going with PowerShell in Server Core R2

    Windows 7 RC Users, You're About to Become Lost

    Two Minute Drill – WMI Code Creator

    Virtual Machine Manager 2008 (R2) listening ports

    Top 10 changes to Windows Server 2008 R2

    The PowerShell management module for Hyper-V

    Group Policy setting(s) of the week 12 – Prevent changing desktop background & Desktop Wallpaper

    Enterprise Domain Controllers Group and Group Policies

    Using File Classification Infrastructure (FCI) and AD RMS to automatically protect sensitive information

  • GP Editorial on the Group Policy blog

    Ned here. Mike Stephens has a short editorial on the GP development team blog. It addresses the fallacy of group policy "best practices" and is a good read for philosophy majors as well as IT staff. Here's a snippet:

    "Yes, there might be settings common to “locking down a computer”, but what does “locking down” mean? Everyone is likely to have a different answer.

    Read the rest and leave some comments.

    - Ned "Descartes" Pyle

  • Friday Mail Sack – First Attempt Edition

    Hi all, Ned here again. Today I will share some recent questions we’ve gotten offline that never ended up as full blown blog posts. Naturally any names have been changed to protect the innocent and things are often paraphrased. This post starts a new series that will appear every Friday, barring some kind of disaster such as me being out sick, me taking the day off, or me just not feeling like it (so nyyyaaahhh).

    Onward.

    Question:

    Is there any risk running Windows disk defrag on a DC? I need to defrag my drives and I’m worried about NTDS.DIT corruption.

    Answer:

    Nothing to worry about. In fact, starting in Windows Server 2008 and continuing in R2, you have been running a disk defrag every Wednesday at 1 AM whether you knew it or not. This is default behavior, even on domain controllers.

    image

    Note that the task is designed to run in idle state though, so if things stay really busy on a DC all night long, the automatic defrag may be preempted. The Task Scheduler Help has more info on what “Idle” means.

    Question:

    When I search AD for old computer accounts by using the whenChanged attribute that computers seem to be constantly “new”. How can I find old unused computer accounts using PowerShell?

    Answer:

    The attribute you want to use in this scenario is lastLogonTimeStamp; Warren wrote up a pretty comprehensive treatise in this older post. You can search for these inactive accounts using things like AD PowerShell’s cmdlet search-adaccount. For example, this would find all computers in the domain that have not logged into AD in a year:

    Search-ADaccount -AccountInactive -Timespan 365 -ComputersOnly

    Avoid looking at stale passwords, as password changes can be disabled. And before acting upon inactive accounts, make triple sure it’s really inactive. Cluster virtual computer objects don’t necessarily “logon” but if you arbitrarily get rid of them there will be heck to pay. Automating the removal is generally a bad idea.

    Question:

    I am trying to use the Delegate Control wizard within DSA.MSC. When I use a custom task delegation for User Objects I can’t specify certain attributes like Office, E-Mail, City, State, or Country. How can I get these?

    Answer:

    Choose the inetOrgPerson object class instead of User – this will get you the granularity you need with the delegation wizard. Chalk this up to vagaries of snap-in, schema, class, and inheritance.

    image  image

    Question:

    Application X doesn’t seem to work correctly with Read-Only Domain Controllers, and I am not finding anything online that says it is compatible. What should I do?

    Answer:

    Find out who created that application and talk to their support staff. If it’s a Microsoft application or Windows component, open a support case and ask to speak that particular specialty. If not MS, call that vendor. If internal to your company, find that developer! There’s no way for the AD developers test everything against RODC’s – not even within the MS-developed gamut of applications, which is huge. They have to rely on application developers to add it to their test harnesses. If the conversation with the vendor starts with “What’s an RODC?”, they probably don’t test it. :)

    No matter who you talk to, once it’s established that an RODC is or isn’t supported, make them document it publically; even if it’s just a blog post, you are helping out your fellow IT humans.

    Question:

    Hey, I think I found an error in KB article Y. Can you fix it?

    Answer:

    You betcha. Just tell us exactly what you think is wrong, making sure to give us repro steps. If we confirm it as factual error  the KB should be corrected within a few weeks. If it comes down to semantics or a difference of opinion…well, as my wife says “we’ll just have to agree to disagree” (i.e. Ned is wrong, Lisa is right, and there’s nothing Ned can do about it).

    Question:

    I need some deeper support than this blog is set up for and time is not an issue, but I am a bit strapped for cash. Is there anywhere reputable I can go?

    Answer:

    Our community forums are an excellent place to ask deeper specific questions. These are moderated by MS support engineers and MVP’s. Many questions can be answered quickly and reliably by trustworthy folks.

    If time and live support is critical though, open a support case. Time is money.

    I reckon that’s enough for today. Have a nice weekend folks.

    - Ned ‘going postal’ Pyle

  • Inventorying Computers with AD PowerShell

    Hi, Ned here again. Have you ever had to figure out what operating systems are running in your domain environment so that you can plan for upgrades, service pack updates, or support lifecycle transitions? Did you know that you don’t have to connect to any of the computers to find out? It’s easier than you might think, and all possible once you start using AD PowerShell in Windows Server 2008 R2 or Windows 7 with RSAT.

    Get-ADComputer

    The cmdlet of choice for inventorying computers through AD is Get-ADComputer. This command automatically searches for computer objects throughout a domain, returning all sorts of info.

    As I have written about previously my first step is to fire up PowerShell and import the ActiveDirectory module:

    image

    Then if I want to see all the details about using this cmdlet, I run:

    Get-Help Get-ADComputer -Full

    Getting OS information

    Basics

    Now I want to pull some data from my domain. I start by running the following:

    Important note: in all my samples below, the lines are wrapped for readability.

    Another important note (thanks dloder): I am going for simplicity and introduction here, so the -Filter and -Property switches are not designed for perfect efficiency. As you get comfortable with AD PowerShell, I highly recommend that you start tuning for less data to be returned - the "filter left, format right" model described here by Don Jones.

    Get-ADComputer -Filter * -Property * | Format-Table Name,OperatingSystem,OperatingSystemServicePack,OperatingSystemVersion -Wrap –Auto

    image

    This command is filtering all computers for all their properties. It then feeds the data (using that pipe symbol) into a formatted table. The only attributes that the table contains are the computer name, operating system description, service pack, and OS version. It also automatically sizes and wraps the data. When run, I see:

    image

    It looks like I have some work to do here – one Windows Server 2003 computer needs Service Pack 2 installed ASAP. And I still have a Windows 2000 server that is going to move quickly and replace that server.

    Server Filtering

    Now I start breaking down the results with filters. I run:

    Get-ADComputer -Filter {OperatingSystem -Like "Windows Server*"} -Property * | Format-Table Name,OperatingSystem,OperatingSystemServicePack -Wrap -Auto

    I have changed my filter to find all the computers that are running “Windows Server something”, using the –like filter. And I stopped displaying the OS version data because it was not providing me anything unique (yet!).

    image

    Cool, now only servers are listed! But wait… where’d my Windows 2000 server go? Ahhhh… sneaky. We didn’t start calling OS’s “Windows Server” until 2003. Before that it was “Windows 2000 Server”. I need to massage my filter a bit:

    Get-ADComputer -Filter {OperatingSystem -Like "Windows *Server*"} -Property * | Format-Table Name,OperatingSystem,OperatingSystemServicePack -Wrap -Auto

    See the difference? I just added an extra asterisk to surround “Server”.

    image

    As you can see, my environment has a variety of Windows server versions running. I’m interested in the ones that are running Windows Server 2008 or Windows Server 2008 R2. And once I have that, I might just want to see the R2 servers – I have an upcoming DFSR clustering project that requires some R2 computers. I run these two sets of commands:

    Get-ADComputer -Filter {OperatingSystem -Like "Windows Server*2008*"} -Property * | Format-Table Name,OperatingSystem,OperatingSystemServicePack -Wrap -Auto

    Get-ADComputer -Filter {OperatingSystem -Like "Windows Server*r2*"} -Property * | Format-Table Name,OperatingSystem,OperatingSystemServicePack -Wrap -Auto

    image

    image

    Starting to make sense? Repetition is key; hopefully you are following along with your own servers.

    Workstation Filtering

    Okeydokey, I think I’ve got all I need to know about servers – now what about all those workstations? I will simply switch from -Like to -Notlike with my previous server query:

    Get-ADComputer -Filter {OperatingSystem -NotLike "*server*"} -Property * | Format-Table Name,OperatingSystem,OperatingSystemServicePack -Wrap -Auto

    And blammo:

    image

    Family filtering

    By now these filters should be making more sense and PowerShell is looking less scary. Let’s say I want to filter by the “family” of operating system. This can be useful when trying to identify computers that started having a special capability in one OS release and all subsequent releases, and where I don’t care about it being server or workstation. An example of that would be BitLocker – it only works on Windows Vista, Windows Server 2008, and later. I run:

    Get-ADComputer -Filter {OperatingSystemVersion -ge "6"} -Property * | Format-Table Name,OperatingSystem,OperatingSystemVersion -Wrap -Auto

    See the change? I am now filtering on operating system version, to be equal to or greater than 6. This means that any computers that have a kernel version of 6 (Vista and 2008) or higher will be returned:

    image

    If I just wanted my Windows Server 2008 R2 and Windows 7 family of computers, I can change my filter slightly:

    Get-ADComputer -Filter {OperatingSystemVersion -ge "6.1"} -Property * | Format-Table Name,OperatingSystem,OperatingSystemVersion -Wrap -Auto

    image

    Getting it all into a file

    So what we’ve done ‘til now was just use PowerShell to send goo out to the screen and stare. In all but the smallest domains, though, this will soon get unreadable. I need a way to send all this out to a text file for easier sorting, filtering, and analysis.

    This is where Export-CSV comes in. With the chaining of an additional pipeline I can find all the computers, select the attributes I find valuable for them, then send them into a comma-separated text file that is even able to read the weirdo UTF-8 trademark characters that lawyers sometimes make us put in AD.

    Hey, what do you call a million lawyers at the bottom of the ocean? A good start! Why don’t sharks eat lawyers? Professional courtesy! What do have when a lawyer is buried up to his neck in sand? Not enough sand! Haw haw… anyway:

    Get-ADComputer -Filter * -Property * | Select-Object Name,OperatingSystem,OperatingSystemServicePack,OperatingSystemVersion | Export-CSV AllWindows.csv -NoTypeInformation -Encoding UTF8

    image

    Then I just crack open the AllWindows.CSV file in Excel and:

    image

    What about the whole forest?

    You may be tempted to take some of the commands above and tack on the necessary arguments to search the entire forest. This means adding:

    -searchbase “” –server <domain FQDN>:3268

    That way you wouldn’t have to connect to a DC in every domain for the info – instead you’d just ask a single GC. Unfortunately, this won’t work; none of the operating system attributes are replicated by global catalog servers. Oh well, that’s not PowerShell’s fault. All the data must be pulled from domains individually, but that can be automated – I leave that to you as a learning exercise.

    Conclusion

    The point I made above about support lifecycle is no joke: 2010 is a very important year for a lot of Windows products’ support:

    Hopefully these simple PowerShell commands make hunting down computers a bit easier for you.

    Until next time.

    - Ned “bird dog” Pyle