<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.technet.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Notes From The Field : Active Directory</title><link>http://blogs.technet.com/notesfromthefield/archive/tags/Active+Directory/default.aspx</link><description>Tags: Active Directory</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>A Small Concern When Virtualizing Domain Controllers - Time Sync</title><link>http://blogs.technet.com/notesfromthefield/archive/2009/02/13/a-small-concern-when-virtualizing-domain-controllers-time-sync.aspx</link><pubDate>Fri, 13 Feb 2009 20:48:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3129152</guid><dc:creator>jdphilli</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.technet.com/notesfromthefield/comments/3129152.aspx</comments><wfw:commentRss>http://blogs.technet.com/notesfromthefield/commentrss.aspx?PostID=3129152</wfw:commentRss><description>I'm sure this might open a can of worms, but it's a discussion that needs to happen. As virtualization technologies come into maturity, customers are more and more leaning towards virtualizing all of their infrastructure services. This includes Active Directory. Virtualizing Domain Controllers has been going on for some time now and was at first completely unsupported and even recommended against. That stance is changing considerably now, and we're beginning to see some official recommendations addressing this issue. 
&lt;P&gt;Let me first emphasize following the guidance set forth in this article: &lt;A title=http://technet.microsoft.com/en-us/library/dd363553.aspx href="http://technet.microsoft.com/en-us/library/dd363553.aspx" mce_href="http://technet.microsoft.com/en-us/library/dd363553.aspx"&gt;http://technet.microsoft.com/en-us/library/dd363553.aspx&lt;/A&gt; which contains official recommendations when virtualizing domain controllers in Hyper-V. The big 3 “don’t dos” are: never user differencing disks, don’t clone the guest without SYSPREPing it first, and don’t copy a VHD of a previously installed DC as the base for a new one. Those are all pretty straight forward to keep you from having SID conflicts or USN rollback issues which will totally mess up your AD installation.&lt;/P&gt;
&lt;P&gt;Now, the next big issue is Time Sync. Microsoft recommends disabling host to guest time synchronization so that all DCs will use the default Windows Time service hierarchy just like a physical server. That’s not so hard, right? Just go into Hyper-V and disable that feature from the Integration Services settings. Easy. Done. &lt;/P&gt;
&lt;P&gt;But: what about DCs running virtualized on VMWare [for the sake of discussion, let’s assume the SVVP supported version]? What does VMWare recommend? According to their KB article &lt;A href="http://kb.vmware.com/selfservice/viewContent.do?language=en_US&amp;amp;externalId=1318" mce_href="http://kb.vmware.com/selfservice/viewContent.do?language=en_US&amp;amp;externalId=1318"&gt;http://kb.vmware.com/selfservice/viewContent.do?language=en_US&amp;amp;externalId=1318&lt;/A&gt;, they say to turn of Windows Time service and use their host-to-guess time sync, except for the PDC Emulator of course, but then they want you to leave that on with “NoSync” turned on.&lt;/P&gt;
&lt;P&gt;So: what is one to do?&lt;/P&gt;
&lt;P&gt;First, I’d suggest a compromise – one that may avoid some of the issues. Don’t virtualize all your DCs. In fact, this is outlined in the Microsoft article above. You should really keep at least one hardware-based copy of your domain, and it should be the PDC emulator of the root domain of the forest. Preferably, in multi-domain forests, you’d want to keep a physical server for the PDC emulator of each child domain as well. This doesn’t have to be a very large machine, unless you’re a very large organization.&lt;/P&gt;
&lt;P&gt;Now, if you virtualize all other DCs on Hyper-V (which I’d recommend not just because it’s Microsoft’s solution and I’m an employee, but because I’ve used both and Hyper-V is SO much easier to manage and configure), then the answer is clear: for DCs, leave the Windows Time service running on the guest DCs, with the root PDC Emulator’s time service configured to point to a highly-accurate external clock and disable Time Synchronization in the Integration settings. The Hyper-V hosts should then be joined to the domain. This will keep all hosts and guests synched to the proper time.&lt;/P&gt;
&lt;P&gt;For guest running on VMWare, this is a tough decision since there are competing recommendations. Anecdotally, I have heard of no particular issues with disabling time sync in the VMWare tools and leaving Windows Time to synch the DC time clocks, but I have heard of issues the other way around: letting VMWare tools manage the time sync. In my opinion, such a custom solution as VMWare recommends should only be used if you’ve experience problems with the regular way of doing things. That’s why it’s the default: it generally works well when left that way. You should also configure the hosts to retrieve their time from the physical PDC Emulator in the root domain.&lt;/P&gt;
&lt;P&gt;So, in summary, use a physical DC for at least one of your DCs per domain, and when you have to use VMWare, I’d recommend disabling the time sync from host to guest on domain controllers, and setting the hosts to obtain their time information from the root PDC Emulator. All other guests can be configured to obtain time from the host. But, as always, carefully monitor all your event logs for your servers and make sure you don’t have any issues.&lt;/P&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3129152" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/notesfromthefield/archive/tags/Hyper-V/default.aspx">Hyper-V</category><category domain="http://blogs.technet.com/notesfromthefield/archive/tags/Active+Directory/default.aspx">Active Directory</category></item><item><title>Some Easy Active Directory Scripting</title><link>http://blogs.technet.com/notesfromthefield/archive/2008/08/26/some-easy-active-directory-scripting.aspx</link><pubDate>Tue, 26 Aug 2008 21:28:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3112326</guid><dc:creator>jdphilli</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.technet.com/notesfromthefield/comments/3112326.aspx</comments><wfw:commentRss>http://blogs.technet.com/notesfromthefield/commentrss.aspx?PostID=3112326</wfw:commentRss><description>&lt;p&gt;I solved a little problem for a customer the other day and I thought I'd share a little about it with you. It involves some VBScript user manipulation in Active Directory, and yes: there will be a code sample.&lt;/p&gt;  &lt;p&gt;Let's start with the problem. For whatever reason, some users were missing some home drive information and more than half of users were not configured for roaming profiles. It was determined that this should be corrected. An easy way, of course, would be to push a group policy out which would configure something like: &lt;a href="file://servername/home/%25username%25" mce_href="file://servername/home/%25username%25"&gt;\\servername\home\%username%&lt;/a&gt; for home directory paths and &lt;a href="file://servername/profile/%25username%25" mce_href="file://servername/profile/%25username%25"&gt;\\servername\profile\%username%&lt;/a&gt; for profile paths. Well, that would have been easy if that's what the customer wanted to do, but it wasn't. Instead, they have set up a rather nice DFS root share for home drives and profile paths broken down by, lets say, users' last names. Sample paths for this would be &lt;a href="file://\\dfsroot.com\home\%x\%username%" mce_href="file://dfsroot/home/%25x/%25username%25"&gt;\\dfsroot.com\home\%x\%username%&lt;/a&gt; where %x is the user's first initial of the last name. This wouldn't be so easy with a group policy. So for this, I wrote some code.&lt;/p&gt;  &lt;p&gt;What I did was obtain a list of users who needed these properties set in display name format. This was done by extracting user information with CSVDE. The result would look something like this:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier"&gt;Smith, Bob       &lt;br /&gt;Johnson, William K.&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Once I had this file (named &lt;strong&gt;&lt;font face="courir"&gt;users.txt&lt;/font&gt;&lt;/strong&gt;), I could run my script&lt;/p&gt;  &lt;p&gt;If you'll notice, in this particular instance, the display name is &lt;strong&gt;Last, First&lt;/strong&gt;. Many corporations configure their GAL this way, and I can understand why, although at Microsoft we use the reverse order of &lt;strong&gt;First Last&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;What the script does is open a log file for writing, open the &lt;font face="Courier"&gt;&lt;strong&gt;users.txt&lt;/strong&gt;&lt;/font&gt; file for reading&lt;/p&gt;  &lt;blockquote&gt;   &lt;pre class="csharpcode"&gt;&lt;font size="1"&gt;&lt;span class="kwrd"&gt;Const&lt;/span&gt; ForWriting = 2
&lt;span class="kwrd"&gt;Const&lt;/span&gt; ForReading = 1

&lt;span class="rem"&gt;'Path for log&lt;/span&gt;
logfilepath = &lt;span class="str"&gt;&amp;quot;C:\TEMP\log.txt&amp;quot;&lt;/span&gt;

&lt;span class="rem"&gt;'Path for user list&lt;/span&gt;
userfilepath = &lt;span class="str"&gt;&amp;quot;C:\TEMP\users.txt&amp;quot;&lt;/span&gt;

&lt;span class="rem"&gt;'Base Paths&lt;/span&gt;
baseHomePath = \\dfsroot.com\home\baseProfilePath = \\dfsroot.com\profile\

&lt;span class="rem"&gt;'Setup input file&lt;/span&gt;
&lt;span class="kwrd"&gt;Set&lt;/span&gt; objFSO = CreateObject(&lt;span class="str"&gt;&amp;quot;Scripting.FileSystemObject&amp;quot;&lt;/span&gt;)
&lt;span class="kwrd"&gt;Set&lt;/span&gt; objInputFile = objFSO.OpenTextFile(userfilepath, ForReading, &lt;span class="kwrd"&gt;True&lt;/span&gt;)

&lt;span class="rem"&gt;'Setup log file&lt;/span&gt;
&lt;span class="kwrd"&gt;Set&lt;/span&gt; objFSO = CreateObject(&lt;span class="str"&gt;&amp;quot;Scripting.FileSystemObject&amp;quot;&lt;/span&gt;)
&lt;span class="kwrd"&gt;Set&lt;/span&gt; objAdLogTextFile = objFSO.OpenTextFile(logfilepath, ForWriting, &lt;span class="kwrd"&gt;True&lt;/span&gt;)

&lt;span class="rem"&gt;'Create Objects for LDAP Queries&lt;/span&gt;
&lt;span class="kwrd"&gt;Set&lt;/span&gt; rootDSE = GetObject(&lt;span class="str"&gt;&amp;quot;LDAP://RootDSE&amp;quot;&lt;/span&gt;)
DomainContainer = rootDSE.&lt;span class="kwrd"&gt;Get&lt;/span&gt;(&lt;span class="str"&gt;&amp;quot;defaultNamingContext&amp;quot;&lt;/span&gt;)

&lt;span class="kwrd"&gt;Set&lt;/span&gt; conn = CreateObject(&lt;span class="str"&gt;&amp;quot;ADODB.Connection&amp;quot;&lt;/span&gt;)
conn.Provider = &lt;span class="str"&gt;&amp;quot;ADSDSOObject&amp;quot;&lt;/span&gt;
conn.Open &lt;span class="str"&gt;&amp;quot;ADs Provider&amp;quot;&lt;/span&gt;

&lt;span class="rem"&gt;'Read in username from input file&lt;/span&gt;
&lt;span class="kwrd"&gt;Do&lt;/span&gt; &lt;span class="kwrd"&gt;Until&lt;/span&gt; objInputFile.AtEndOfStream

  strDisplayName = objInputFile.Readline

  &lt;span class="rem"&gt;'Find all users in AD using an LDAP query&lt;/span&gt;
  strLDAP = &lt;span class="str"&gt;&amp;quot;&amp;lt;LDAP://&amp;quot;&lt;/span&gt; &amp;amp; DomainContainer &amp;amp; &lt;span class="str"&gt;&amp;quot;&amp;gt;;(&amp;amp;(objectCategory=person)(objectClass=user)_&lt;br /&gt;      (anr=&amp;quot;&lt;/span&gt; &amp;amp; strDisplayName &amp;amp; &lt;span class="str"&gt;&amp;quot;*));adspath;subtree&amp;quot;&lt;/span&gt;

  &lt;span class="rem"&gt;'Get query results and output to file&lt;/span&gt;
  &lt;span class="kwrd"&gt;Set&lt;/span&gt; oComm = CreateObject(&lt;span class="str"&gt;&amp;quot;ADODB.Command&amp;quot;&lt;/span&gt;)
  oComm.ActiveConnection = conn
  oComm.CommandText = strLDAP
  oComm.Properties(&lt;span class="str"&gt;&amp;quot;Sort on&amp;quot;&lt;/span&gt;) = &lt;span class="str"&gt;&amp;quot;displayName&amp;quot;&lt;/span&gt; 
  oComm.Properties(&lt;span class="str"&gt;&amp;quot;Page size&amp;quot;&lt;/span&gt;) = 15000

  &lt;span class="kwrd"&gt;set&lt;/span&gt; rs = oComm.Execute
 
  &lt;span class="kwrd"&gt;If&lt;/span&gt; rs.recordcount = 0 &lt;span class="kwrd"&gt;then&lt;/span&gt; 
        QueryResult = &lt;span class="str"&gt;&amp;quot;User not found&amp;quot;&lt;/span&gt; 
        objAdLogTextFile.WriteLine(FoundObject.Displayname &amp;amp; &lt;span class="str"&gt;&amp;quot; | &amp;quot;&lt;/span&gt; &amp;amp; QueryResult)  
  &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt; 

  &lt;span class="kwrd"&gt;If&lt;/span&gt; rs.recordcount &amp;gt; 1 &lt;span class="kwrd"&gt;then&lt;/span&gt; 
        QueryResult = &lt;span class="str"&gt;&amp;quot;Resolved to more than one name&amp;quot;&lt;/span&gt; 
        objAdLogTextFile.WriteLine(FoundObject.Displayname &amp;amp; &lt;span class="str"&gt;&amp;quot; | &amp;quot;&lt;/span&gt; &amp;amp; QueryResult) 
  &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt; 

  &lt;span class="kwrd"&gt;If&lt;/span&gt; rs.recordcount = 1 &lt;span class="kwrd"&gt;then&lt;/span&gt; 
    &lt;span class="kwrd"&gt;While&lt;/span&gt; &lt;span class="kwrd"&gt;Not&lt;/span&gt; rs.EOF
      &lt;span class="kwrd"&gt;Set&lt;/span&gt; FoundObject = GetObject (rs.Fields(0).Value)
      fullProfilePath = baseProfilePath &amp;amp; left(FoundObject.displayName,1) &amp;amp; &lt;span class="str"&gt;&amp;quot;\&amp;quot;&lt;/span&gt; &amp;amp;_&lt;br /&gt;          FoundObject.sAMAccountName
      fullHomePath = baseHomePath &amp;amp; left(FoundObject.displayName,1) &amp;amp; &lt;span class="str"&gt;&amp;quot;\&amp;quot;&lt;/span&gt; &amp;amp;_&lt;br /&gt;          FoundObject.sAMAccountName
      objAdLogTextFile.WriteLine(FoundObject.Displayname &amp;amp; &lt;span class="str"&gt;&amp;quot; | &amp;quot;&lt;/span&gt; &amp;amp; fullHomePath &amp;amp;_&lt;br /&gt;          &lt;span class="str"&gt;&amp;quot; | &amp;quot;&lt;/span&gt; &amp;amp; fullProfilePath)
      FoundObject.profilePath = fullProfilePath
      FoundObject.homeDirectory = fullHomePath
      FoundObject.homeDrive = &lt;span class="str"&gt;&amp;quot;H:&amp;quot;&lt;/span&gt;
      FoundObject.SetInfo
      rs.MoveNext
    &lt;span class="kwrd"&gt;Wend&lt;/span&gt;
  &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt;
&lt;span class="kwrd"&gt;Loop&lt;/span&gt;
 
MsgBox &lt;span class="str"&gt;&amp;quot;Processing complete!&amp;quot;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;/blockquote&gt;

&lt;p&gt;This code helped me to set the baseline for existing users. New would then need to be created with the proper home drive and profile path. A good way to automate this is with something like ILM to provision user accounts. ILM is good for quite a lot of things and maybe one day, I'll have some tidbits to post about it.&lt;/p&gt;

&lt;p&gt;Until next time, I hope this sample will help you get started on your own scripts for your directory.&lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3112326" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/notesfromthefield/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.technet.com/notesfromthefield/archive/tags/VBScript/default.aspx">VBScript</category><category domain="http://blogs.technet.com/notesfromthefield/archive/tags/Active+Directory/default.aspx">Active Directory</category></item></channel></rss>