DFS Replication Validation Script…

2017-07-27T00:01:04+00:00 December 12th, 2012|Uncategorized|

The other day, while at the enterprise-level customer with whom I’m currently working, I ran into a situation where I needed to validate that certain parts of a DFS hierarchy were properly being replicated across the customer’s AD domain controllers.  As the administrators applied normal, routine DFS changes, the changes sometimes didn’t replicate properly across the enterprise — causing some segments of the DFS structure to not be visible or available. 

Apparently, the DFS problem was a result of using VMware guests as AD DCs.  I understand (from the customer) that a Microsoft hotfix is in the last stages of testing (at the time of this writing) and will be available for release “soon.”   It seemed that even though the DCs in question did not synchronize time with the ESX host upon which they reside, there is a default behavior in VMware Tools that assigns the host time value to the guest — at least up until the “do not sync” routine is processed during startup; after which the guest is then allowed to find its own time.  During this brief time window, the DFS Namespace service sometimes completes assembling its DFS target list and can find itself behind in time, relative to links it has been given by PDCE; which makes no sense to it, and it removes them from its listing.  And as a result, people can’t find their mapped drives or browse some of the DFS Tree.  (Note: I cannot take credit for this timing behavior investigation and results; and while I’d love to credit the folks who are due, I’m not permitted to.)  The customer remedied the situation with a temporary fix, but the real fix is the up-coming aforementioned patch.

Anyway, while the symptoms were being analyzed, I was working on other things and needed to work around the issue as much as possible while the solution was being chased.  So, I whipped up a simple little DOS script to go out and validate the top-levels of the DFS hierarchy across all domain controllers that carry them, in order to find out what would or wouldn’t be properly resolved.

For what it’s worth, I thought I’d pass the script along to you.  Here it is:


@set AdDomain=MyAdDomain.local
@set DirQuantity=17
@set DestPath=h:DcList.txt
@REM This requires elevated credentials, otherwise will fail...
@ipconfig /flushdns
@REM First we build the input file...
@nslookup %AdDomain% |findstr 
[0-9].*.[0-9].*|findstr /V /C:"Address: " > %DestPath% @ECHO As of 20121212, there should be %DirQuantity% DFS dirs on each server (actual, plus the "." and ".." items). @REM Now loop through the input file and check the DFS at the destination... @For /F "tokens=*" %%Q in (%DestPath%) Do @( @set MYDC=%%Q @set MYDC=!MYDC:Addresses: =! for /f "tokens=* delims=" %%A in ('dir /A:D \!MYDC!Corp ^|findstr /C:"Dir(s)"') do @set MYDIR=%%A for /f "tokens=* delims= " %%G in ("!MYDIR!") do @set MYDIR=%%G @REM Options A: Use this line if you wish to see all DFS sources: @ECHO For: !MYDC! !MYDIR:~0,9! @REM Option B: Use this line if you wish to see only those in violation @REM (note: there's a space and tab separator for spacing alignment): @REM @ECHO For: !MYDC! !MYDIR:~0,9! |findstr /V /C:"%DirQuantity% Dir(s)" )

What it does:

The script builds a domain controller list in a static, external file, then iterates through the list, attempting to quantify the available DFS path branches against a numeric count that you supply in another variable.  I provided two different “ends” to the script (one of them commented out), in order to give you a couple different ways to present the results.  Make sure to “set” the variables in the first few lines, to your locally-relevant information; especially the number of *expected* DFS hierarchies.

Of course, I wanted to write it to do more, but I pretty much ran up against the limits of what I *should* do in a DOS script.  I’ll make another version in PowerShell some day that iterates down the hierarchy and validates the entire structure, instead of just the top level… 

…Unless you beat me to it…  😉

There you go; enjoy!




Scripted Home Folder Management with PowerShell Pt. 6 – The Script!

2017-07-27T00:01:07+00:00 October 3rd, 2012|Uncategorized|

This is the last post in my series on scripting user and Home Folder management (see Part 1, Part 2, Part 3, and Part 4 and Part 5 for reference) — it was a lot of ground to cover, but we did it!  Thanks for hanging in there with me.  We’ve created the user and attributes, built the folder, set permissions, added the Home Folder attribute on the user object; all with PowerShell.  You don’t get much more real-world than that!

Now, as promised, it’s time to pull it all together into one example script.

Of course, now that we’re putting all the concepts from the previous posts together, we need to be smart and add a few smart/standard script things; like good use of variables, error checking, and so forth.  Specifically, the new things I’m introducing in this post are:

  • Use of variables  – To make the script portable and easily modifiable
  • Use of command line arguments – To accept the new user’s name as input arguments
  • Use of SubString – To generate a “UserName” (a.k.a. SamAccountName) from a first and last name
  • Check for pre-existing – To make sure we don’t attempt to create an already-existing user name

All of the items above are in the first section of the script below, and the remaining sections are where I pull in the concepts from the previous posts to get it all done.  I don’t want to go into great detail on these new items, but they are necessary to make the script flow correctly and be usable right away as-is.

So, here you go.  You can paste this right into a file (something like provisionNewUser.ps1), launch a PowerShell session, and run it with the new user’s First Name and Last Name on the command line (as explained early in the body of the script). 

And here’s my warning: Don’t ever do what people on the Internet tell you to do; if this script is scary to you, don’t run it.  In fact, only run this in a test lab, until you are comfortable with the specifics.  So there.

# Home Folder Provisioning Demo Script
# Jeremy Pavlov, Coretek Services, 20121003
# Execute in a powershell session, with the new user's First and Last names after the command, like this:
# .provisionNewUser.ps1 Jeremy Pavlov
# # Make sure you run this if not already loaded, for AD-based commands Import-Module ActiveDirectory # # Read in the first name and last name from command line inputs $FirstName = $args
[0] $FirstInitial = $FirstName.Substring(0,1) $LastName = $args[1] $LastInitial = $LastName.Substring(0,1) $UserName = "$FirstInitial$LastName" $MyDomain = "CoretekServices.local" $HomePrefix = "\$MyDomainCorpHomes" $DefaultUserOu = "ou=New Users,dc=CoretekServices,dc=local" # write "First name will be: $FirstName" write "Last name will be: $LastName" write "User name will be: $UserName" write "Home Folder will be: $HomePrefix$LastInitial$UserName" write "" # # See if the user exists $CheckUser = Get-ADUser -ldapFilter "(SamAccountName=$UserName)" # #If user exists, exit! if ($CheckUser -ne $Null) { write "User $UserName already exists! Exiting..." write "" exit } # write "Creating $UserName..." write "" New-ADUser -Path "$DefaultUserOu" -SamAccountName "$UserName" -Enabled $true -Name "$FirstName $LastName" -GivenName "$FirstName" -Surname "$LastName" -AccountPassword (ConvertTo-SecureString –AsPlaintext "ChangeMe123!" –Force) -ChangePasswordAtLogon $true # write "Create $HomePrefix$LastInitial$UserName ..." write "" New-Item -type directory -path $HomePrefix$LastInitial$UserName # write "Setting permissions on the $HomePrefix$LastInitial$UserName ..." write "" $acl = Get-Acl $HomePrefix$LastInitial$UserName $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$MyDomain$UserName", "DeleteSubdirectoriesAndFiles, Modify, Synchronize", "ContainerInherit, ObjectInherit", "None", "Allow") $acl.AddAccessRule($rule) Set-Acl $HomePrefix$LastInitial$UserName $acl # write "Setting the Home Folder attribute for $UserName" write "" Set-ADUser -identity "$UserName" -homeDrive h: -homeDir "$HomePrefix$LastInitial$UserName" # write "...Complete!" write "" #

…and there you have it.  Now, of course, I could have dumped in a lot of other good practice stuff like input validations and things, or other additional neat features, but I’m only trying to demonstrate the core concepts here from our previous posts in this series.  I don’t want to over-whelm the example and make it difficult or — heaven forbid — boring (gasp!) to read.

But please, if you have a better way of doing it, make sure to drop a comment or two and help out others…

Now go create some users!



Scripted Home Folder Management with PowerShell Pt. 3

2017-07-27T00:01:07+00:00 September 12th, 2012|Uncategorized|

In this post, I’m following up on Part 1 and Part 2 of this series where I showed you how to create users (and set a few attributes) with PowerShell.  Now that you have your user created and configured, I’m going to show you a bit about Home Folder creation and permission assignment.  Remember that all of these basics are leading toward a single, simplified, scripted elements method of managing Home Folders in the Enterprise.

So let’s create a folder.  Of course, you know how to do that already, so I won’t belabor the point too much.  Picking up where we left off in the last post, you already have a PowerShell session going, with network access to the shares where the folders will be created.  And since PowerShell has native access to the filesystem via its own object paths, you can actually skip the fancy stuff and just do a good ol’ md:

md \serverShare$JPavlov

…or if you’re using a DFS structure, something like this…

md \MyCompany.orgDFSPathHomesJPavlov

I know, I know.  That’s not PowerShell.  So if you really want to use the benefit of PowerShell, you would use the New-Item command like this (sticking with our DFS structure from above):

New-Item -type directory -path \MyCompany.orgDFSPathHomesJPavlov

Okay, great.  At this point, we have a folder, but no permissions yet for the person who will use it.  In order to set the permissions, we’ll stick with PowerShell and…

1.) Build a variable with the existing permissions with the Get-Acl command:

$acl = Get-Acl \MyCompany.orgDFSPathHomesJPavlov

2.) Add-on the permission we want (your permissions may vary!):

$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("CoretekServicesJPavlov", "DeleteSubdirectoriesAndFiles, Modify, Synchronize", "ContainerInherit, ObjectInherit", "None", "Allow")

3.) And then stuff it all back on the folder with the Set-Acl command:

Set-Acl \MyCompany.orgDFSPathHomesJPavlov $acl

There you have it!  We’ve created the soon-to-be Home Folder for the user we created previously, and added permission we want.  So it’s out there if the user can browse around and find it…  But let’s help them out a little bit and deliver it as a mapped drive in the next post.

Next time…  Assigning this folder as the user’s Home Folder via the AD attribute.  See you then!



Scripted Home Folder Management with PowerShell Pt. 2

2017-07-27T00:01:07+00:00 September 5th, 2012|Uncategorized|

In this post, I’m following up on Part 1 of this series where I showed you how to create users (and set a few attributes) the basic way with Powershell.  Now, I’m going to show you an easier way to create users thanks to the new(ish) Powershell modules that came along in Windows Server 2008 R2.  In the up-coming parts of this series, we’ll continue on to Home Folder creation/management concepts and automation.  But for now, let’s get that user created…

To be honest with you, I have to admit that most of the time when I’m building a script loop and just need an easy output that looks nice, I’d just do the DSAdd tool like this:

dsadd user "cn=Jeremy Pavlov,ou=Demo,dc=CoretekServices,dc=local" -samId JPavlov -disabled no -fn Jeremy -ln Pavlov -pwd ChangeMe123! -mustchpwd yes

…but the future is here, and the future is PowerShell; and you and I have to get over it.  Powershell gives us better portability, variable management, etc., etc…  So onward and upward. 

And with recent versions of Windows 2008 R2, Microsoft provides the new “ActiveDirectory” module; making user creation/management activities as easy to do as the DSAdd/DSMod tools.  Here’s what I mean…

Open a Powershell session, and import the ActiveDirectory module like this:

Import-Module ActiveDirectory

Note: You need to have network access to an Active Directory server running AD Web Services for this module to work. 

Loading this module is the equivalent of launching the “Active Directory Module for Windows PowerShell” option on Windows 7 and Server 2008, but if you’re scripting you’ll want to make sure you load the module explicitly.  And, as a result, you have a ton of new AD tools available to you. 

You can get a good look at the majority of the new AD tools by using this command:

Get-Command *-AD*

Finally, using the New-ADUser command, we create that user with what is pretty much the equivalent of the DSAdd above (I used the same options to help clarify):

New-ADUser -Path "ou=Demo,dc=CoretekServices,dc=local" -SamAccountName "JPavlov" -Enabled $true -Name "Jeremy Pavlov" -GivenName "Jeremy" -Surname "Pavlov" -AccountPassword (ConvertTo-SecureString –AsPlaintext "ChangeMe123!" –Force) -ChangePasswordAtLogon $true

And that’s it!  You have a new user with your standard attributes set correctly.  I like this one-line method because it looks much cleaner when you are building import scripts that must be distributed to other folks, or when you want to insert some other command between each line (if you’re looping), etc.; it’s neat.

On a side note, there’s also a way to read in the contents of a formatted CSV, and pump it into the New-ADUser command; but my goal here is to show you concepts that ultimately can be combined into an multifaceted script.

Next time…  Home Folder creation and permission assignment.  See you then!



DOS Batch File Error Level Checking Tricks…

2012-06-27T23:01:24+00:00 June 27th, 2012|Uncategorized|

Fellow Coreteker Paul and I were chatting today about capturing post-execution error codes in Windows.  Paul was looking to grab the error code resulting from a script (VBscript, if I recall), and he was looking for the best way.  He found a handy way to handle it (pun intended); but it left me thinking about how one might capture error codes *within* a DOS batch file, and how that might be tricky.  So I tossed a few notes together and I thought I’d pass them along to you… 

First things first: the DOS post-execution error code is stored in the dynamic variable %errorlevel%

One of the important things to remember when trying to grab error codes from DOS batch files is that each executed line of the batch file will produce its own error code result, as well as the fact that you have the capability to grab the error code of the script as a whole (by issuing an EXIT /B command).  Note that one must never hard-set an error level, as you’ll break the shell’s ability to dynamically manage the variable.

 So, if you have multiple lines in your script and wish to capture the error codes from some of the lines, here are a few suggestions…


…this will grab your error code and just for fun set your %RESULT% to the now-famous trademarked “Storage Wars” catch phrase (minus the exclamation point for legal).  You’d typically run this line after the previous line from which you wanted to capture the code.  Error code of zero almost always means that it is operating as intended. 

However, to catch unintended errors in either of these cases,


…they will both will grab the error code, check to see if it’s not equal to zero, and set the %RESULT% variable with the code it grabbed.  Note that the second line — while checking for a value of 1 — is actually checking for 1 or more; this is default behavior.

After grabbing the error code and evaluating it, you can have the script have success/failure-specific condition statements act upon the condition (send notice, add to the event log, exit, etc.).

I hope that helps!


Load More Posts