Microsoft's official enterprise support blog for AD DS and more
Hi, Ned here again. You may remember Mike Stephens writing about importing and exporting WMI filters back in May. A common follow up question we got from that blog post was: “Hey cool. So, uh, what are WMI filters again?”
Group Policy WMI filters were introduced with Windows XP, and are supported in Windows Server 2003, Windows Vista, and Windows Server 2008. They are not supported in Windows 2000, so if you have an all-2000 environment you’re out of luck (10 years is a long time to go without upgrading :-P).
For those still with us…
You can use WMI filters to add a decision on when to apply a given group policy. This can be very useful when users or computers are located in a relatively flat structure instead of specific OU’s, for example. Filters can also help when you need to apply certain policies based on server roles, operating system version, network configuration, or other criteria. Windows evaluates these filters in the following order of overall Group Policy Processing:
So we find all the policies that exist in the user/computer’s Local, Site, Domain, and OU hierarchy. Then we determine if the WMI filter evaluates as TRUE. Then we verify that the user/computer has Read and Apply Group permissions for the GPO. This means that WMI filters are still less efficient than hierarchical linking, but can definitely use filters to make decisions in a non-hierarchical Active Directory design.
You configure WMI filters using the WMI Filters node in GPMC.MSC.
Figure 1 – GPMC WMI Filters Node
Then you can create, delete or edit a filter.
Figure 2 – WMI Filter Editor
Then you can link the WMI filter to any GPO you like (or more than one GPO), like below:
Figure 3 – GPMC Filter Dropdown
So in this case, I created a filter (you will see more on this below) that allows a GPO to apply to operating systems earlier than Windows Vista. I linked the WMI filter to a GPO that is applied to Windows Server 2008 computers – so the GPO shouldn’t apply. If I force Group Policy processing using GPUPDATE /FORCE then run GPRESULT /R, I see:
Figure 4 – GPRESULT output
Slick!
WMI filters use a language called WQL, which will be very familiar to anyone that has ever written a SQL query. The nice thing about learning WMI queries is that it forces you to learn more about the extremely powerful WMI system as a whole and its massive repository of data within it. WMI works within a construct of Namespaces and Classes. 99% of every WQL query will operate in the CIMV2 namespace, like all of the examples below.
So let’s look at some syntax examples:
Only for certain operating systems
It is common to want Group Policy objects to apply to a computer using a specific operating system or service pack installed. Here are some examples that cover a few bases:
SELECT Version FROM Win32_OperatingSystem WHERE Version < "6"
The above WQL query returns true for any operating systems older than Vista (so Windows XP and Windows Server 2003).
SELECT Version FROM Win32_OperatingSystem WHERE Version LIKE "6.0%"
The above WQL query returns true for only Windows Vista or Windows Server 2008 operating systems.
SELECT Version FROM Win32_OperatingSystem WHERE Version = "5.1.2600"
The above WQL query returns true only if the operating system is Windows XP Service Pack 2.
SELECT * FROM Win32_OperatingSystem WHERE Version LIKE “6.0.%” AND ProductType <> “1”
The above WQL query returns true only if the computer is running Windows Server 2008 regardless of service pack. Why so complex, you ask? Remember that Windows Server2008 and Vista SP1 share the same codebase, so they actually have the same exact version. Choosing a product type not equal to 1 (which is Workstation) returns only servers or domain controllers running Windows Server 2008.
Only on Windows Server 2008 Core servers
What if you have a GPO that you want to apply only to servers running Windows Server 2008 Core installations? Here is a sample query (wrapped for readability, this should be done as a single line in the filter dialog):
SELECT OperatingSystemSKU FROM Win32_OperatingSystem WHERE OperatingSystemSKU = 12 OR OperatingSystemSKU = 39 OR OperatingSystemSKU= 14 OR OperatingSystemSKU = 41 OR OperatingSystemSKU = 13 OR OperatingSystemSKU = 40 OR OperatingSystemSKU = 29
These values map back to HEX values, which map back to:
PRODUCT_DATACENTER_SERVER_CORE 0x0000000C
Server Datacenter Edition (core installation)
PRODUCT_DATACENTER_SERVER_CORE_V 0x00000027
Server Datacenter Edition without Hyper-V (core installation)
PRODUCT_ENTERPRISE_SERVER_CORE 0x0000000E
Server Enterprise Edition (core installation)
PRODUCT_ENTERPRISE_SERVER_CORE_V 0x00000029
Server Enterprise Edition without Hyper-V (core installation)
PRODUCT_STANDARD_SERVER_CORE 0x0000000D
Server Standard Edition (core installation)
PRODUCT_STANDARD_SERVER_CORE_V 0x00000028
Server Standard Edition without Hyper-V (core installation)
PRODUCT_WEB_SERVER_CORE 0x0000001D
Web Server Edition (core installation)
If you want GPOs to apply only to computers NOT running Windows Server 2008 Core (and you can probably think of some reasons to do that), then you would change all the equal signs (=) in the above query to signs above to angled brackets (<>). (See http://msdn2.microsoft.com/en-us/library/ms724358.aspx for details and the non-CORE values.)
Only on a certain day of the week
Yes this is possible! Yes, customers have asked how to do this! No, I have no idea why! Ok, kidding about that last one, but it sure seems like an odd request at first. It turns out that some companies like to do things like set a specific message of the day for their legal notice. Or have a separate screensaver running every day of the week for their users. Different strokes for different folks, I suppose.
To do this, your WQL queries (one filter per GPO that you wanted to set, remember) would be:
Select DayOfWeek from Win32_LocalTime where DayOfWeek = 1
Select DayOfWeek from Win32_LocalTime where DayOfWeek = 2
Select DayOfWeek from Win32_LocalTime where DayOfWeek = 3
You get the idea. One is Monday, two is Tuesday, etc.
Wrapping it up
Hopefully you’ve found some new things to think about regarding WMI filters and Group Policy. A closing note: not all WMI filters are created equal. Not everything in WMI is as optimized as we’d like it to be, and some WMI queries are not as performant as we’d like. Avoid loose wildcard queries when possible as they will run slower (for example, Select * from Win32_LocalTime where DayOfWeek = 5 will run slightly slower than the samples provided above). And above all, always test before deploying to production, using the slowest hardware you can find so that you get a good idea about baseline performance.
Got a filter question or a good sample to share? Hit the comments section below.
- Ned Pyle
Hi Rob here again. I recently had a customer that needed the functionality of MoveUser.exe from the Windows 2000 Resource Kit available in Windows Vista. The customer had quite a few Windows Vista machines that were not joined to the domain but were now migrating to Active Directory. For their own business reasons they were previously unable to join the machines to the domain, instead all the users logged on with local user accounts. Since they had this new fancy Active Directory they created user accounts in AD for the users and joined the machines to the domain. They then found that they needed a way to attach the users’ existing local profile to their Active Directory user accounts so that the users would have their normal setup and desktop when they logged in-a seamless experience. Now if you have been around forever like most of us here in support in Windows 2000 and up we used a utility named MoveUser.exe to accomplish this.
Well, in Windows Vista moveuser.exe is no longer supported. However, now we expose this functionality with a new WMI provider called Win32_UserProfile, which is discussed in KB930955. This is awesome because we expose things about user profiles in WMI now… and we can also move the profile to another user as well as delete user profiles. However, once I started looking at MSDN to understand what methods were available I quickly found that MSDN has not been updated as of yet for this new class. So we did some digging into the source code to find out how this works and what is supported.
I wrote a sample script that illustrates how you can leverage this provider to move an existing user profile to another user’s profile. I know that I could have made the script smaller by not listing out all the different properties available in the provider, but the different things exposed are just way too many and if you are planning on using this provider they are just way too cool.
Please keep in mind that this is a sample script-you will need to alter it and test it in your environment and for your needs. To use:
1. Copy the below script into Notepad then save as moveuser.vbs
2. You will need to modify the following variables within the script.
3. Run the script by typing cscript moveuser.vbs
Sample Script
' This script is provided "AS IS" with no warranties, and confers no rights. ' For more information please visit ' http://www.microsoft.com/info/cpyright.mspx to find terms of use. ' Option Explicit DIM strComputer, strSourceAcct, strSourceAcctDomain, strTargetAcct DIM strTargetAcctDomain, strTargetAcctSID DIM objProfile, objCommand, objRecordSet, objConnection, objWMIService, objSID DIM dtStart, colProfiles, oSID, oUsr DIM Revision, IssueAuthorities(11), strSDDL, subAuthoritiesDIM strDomainDN
CONST ADS_SCOPE_SUBTREE=2
' This script has hard coded variables in it that must be filled out. ' strComputer = The computer name that this script needs to run against. ' With WMI the "." means this computer. ' ' strSourceAcct = user account that has the source profile on the system. ' ' strSourceAcctDomain = The domain of the source user account that the profile belongs to. ' If the source account that you want to move the profile from ' is a local computer user you put in the computers name for the domain. ' If this is another domain then you type in the domain name. ' ' strTargetAcct = The user account that the source profile should be moved to. ' ' strTargetDomain = The domain of the target user account that the profile should be moved to ' If the target account that you want to move the profile to. ' is a local computer user you put in the computers name. ' If this is another domain then you type in the domain name. ' ' strDomainDN = The Target Account Domains Distinguished Name. ' This is done for the LDAP query to be built to find the target accounts SID '
strComputer ="." strSourceAcct="User1" strSourceAcctDomain="Contoso-Vista" strTargetAcct="User1" strTargetAcctDomain="CONTOSO" strDomainDN="dc=contoso,dc=com"strTargetAcctSID="" dtStart = TimeValue(Now()) Set objConnection = CreateObject("ADODB.Connection") objConnection.Open "Provider=ADsDSOObject;" Set objCommand = CreateObject("ADODB.Command") objCommand.ActiveConnection = objConnection
' We need the proper Active Directory domain name where the user exists in a DN format. You can ' modify the strDomainDN variable to you Active Directory domain name is in DN format.
objCommand.CommandText = _ "SELECT AdsPath, cn FROM 'LDAP:// "+strDomainDN+"' WHERE objectCategory = 'user'" & _ "And sAMAccountName= '"+strTargetAcct+"'" objcommand.Properties("searchscope") = ADS_SCOPE_SUBTREE Set objRecordSet = objCommand.Execute If objRecordset.RecordCount = 0 Then WScript.Echo "sAMAccountName: " & strTargetAcct & " does not exist." ElseIf objRecordset.RecordCount > 1 Then WScript.Echo "There is more than one account with the same sAMAccountName" Else WScript.Echo "Found account: "+strTargetAcctDomain+"\"+strTargetAcct + " in the domain." objRecordSet.MoveFirst Do Until objRecordSet.EOF Set Ousr = GetObject(objRecordSet.Fields("AdsPath").Value) strTargetAcctSID = SDDL_SID(oUsr.Get("objectSID")) WScript.echo "SID for "+ strTargetAcctDomain+"\"+strTargetAcct + _ " is: "+strTargetAcctSID WScript.Echo VBNewLine WScript.Echo VBNewLine
objRecordSet.MoveNext Loop
objConnection.Close
Set objWMIService = GetObject("winmgmts:\\" & strComputer &"\root\cimv2") Set colProfiles = objWMIService.ExecQuery("Select * from Win32_UserProfile") For Each objProfile in colProfiles Set objSID = objWMIService.Get("Win32_SID.SID='" & objProfile.SID &"'") Wscript.Echo"======================================================"& VBNewLine _ &"Sid:" & objProfile.Sid & VBNewLine _ &"User Name:" & objSID.AccountName & VBNewLine _ &"User Domain:" & objSID.ReferencedDomainName & VBNewLine _ &"LocalPath:" & objProfile.LocalPath & VBNewLine _ &"Loaded:" & objProfile.Loaded & VBNewLine _ &"RefCount:" & objProfile.RefCount & VBNewLine _ &"RoamingConfigured:" & objProfile.RoamingConfigured & VBNewLine _ &"RoamingPath:" & objProfile.RoamingPath & VBNewLine _ &"RoamingPreference:" & objProfile.RoamingPreference & VBNewLine _ &"Status:" & objProfile.Status & VBNewLine _ &"LastUseTime:" & objProfile.LastUseTime & VBNewLine _ &"LastDownloadTime:" & objProfile.LastDownloadTime & VBNewLine _ &"LastUploadTime:" & objProfile.LastUploadTime & VBNewLine
' Testing to verify that the current profile handle is for the Source Account that we want to ' Move to the domain user. if UCase(objsid.referencedDomainName+"\"+objsid.AccountName)= _ UCase(strSourceAcctDomain+"\"+strSourceAcct) Then ' Making sure that the source profile is currently not in use. If it is we will bail out. If objProfile.RefCount < 1 Then WScript.echo "Change Profile for: "+ strSourceAcctDomain+"\"+ _ strSourceAcct+" to: "+ strTargetAcctDomain+"\"+strTargetAcct ' ChangeOwner method requires to String SID of Target Account and a Flag setting
' Flag 1 = Change ownership of the source profile to target account ' even if the target account already has a profile on the system.
' Flag 2 = Delete the target account Profile and change ownership ' of the source user account profile to the target account.
' To use the ChangeOwner method, both the source and ' target account profiles (If it exists) must not be loaded.
ObjProfile.ChangeOwner strTargetAcctSID,1 Else Wscript.echo "Could not move the users profile, because " + _ strSourceAcctDomain+"\"+strSourceAcct+" profile is currently loaded" End If End If Next End If Sub Init_IssueAuthorities( ) 'DIM IssueAuthorities(11) IssueAuthorities(0) = "-0-0" IssueAuthorities(1) = "-1-0" IssueAuthorities(2) = "-2-0" IssueAuthorities(3) = "-3-0" IssueAuthorities(4) = "-4" IssueAuthorities(5) = "-5" IssueAuthorities(6) = "-?" IssueAuthorities(7) = "-?" IssueAuthorities(8) = "-?" IssueAuthorities(9) = "-?"
end sub
function SDDL_SID ( oSID ) DIM Revision, SubAuthorities, strSDDL, IssueIndex, index, i, k, p2, subtotal DIM j, dblSubAuth ' ' First byte is the revision value ' Revision = "1-5"' ' Second byte is the number of sub authorities in the ' SID ' SubAuthorities = CInt(ascb(midb(oSID,2,1))) strSDDL = "S-" & Revision IssueIndex = CInt(ascb(midb(oSID,8,1))) ' ' BYtes 2 - 8 are the issuing authority structure ' Currently these values are in the form: ' { 0, 0, 0, 0, 0, X} ' ' We use this fact to retrieve byte number 8 as the index ' then look up the authorities for an array of values ' strSDDL = strSDDL & IssueAuthorities(IssueIndex) ' ' The sub authorities start at byte number 9. The are 4 bytes long and ' the number of them is stored in the Sub Authorities variable. ' index = 9 i = index for k = 1 to SubAuthorities ' ' Very simple formula, the sub authorities are stored in the ' following order: ' Byte Index Starting Bit ' Byte 0 - Index 0 ' Byte 1 - Index + 1 7 ' Byte 2 - Index + 2 15 ' Byte 3 - Index + 3 23 ' Bytes0 - 4 make a DWORD value in whole. We need to shift the bits ' bits in each byte and sum them all together by multiplying by powers of 2 ' So the sub authority would be built by the following formula: ' ' SUbAuthority = byte0*2^0 + Byte1*2^8 + byte2*2^16 + byte3*2^24 ' ' this be done using a simple short loop, initializing the power of two ' variable ( p2 ) to 0 before the start an incrementing by 8 on each byte ' and summing them all together. ' p2 = 0 subtotal = 0 for j = 1 to 4 dblSubAuth = CDbl(ascb(midb(osid,i,1))) * (2^p2) subTotal = subTotal + dblSubAuth p2 = p2 + 8 i = i + 1 next ' ' Convert the value to a string, add it to the SDDL Sid and continue ' strSDDL = strSDDL & "-" & cstr(subTotal) next SDDL_SID = strSDDL end function
Please keep in mind if you have not installed Service Pack 1 for Vista, you will need to download the MSI installer to get the new WMI Profile provider since it was released after Vista shipped.
Well, I hope that you find this functionality helpful. Happy scripting.
- Rob Greene
Rob and Mike here. We're asked, many times, why a user does not authenticate against a local domain controller in the same site when logging on across a forest. We've setup the most common scenario to help explain how domain locator works for user logons across a forest.
Let's explain the typical scenario in which we see this problem: The scenario starts with two separate Active Directory forests: contoso.com and litware.com. Each forest has a forest (i.e. kerberos) trust to the other. The contoso.com forest has one Active Directory site name CHARLOTTE. The litware.com forest contains two sites: REDMOND and CONTOSO. Administrators in the litware.com forest created the CONTOSO site and subnet to support logons for litware.com users from terminal servers in the contoso.com forest.
Figure 1 Forest trust configuration
Users from litware.com logon to a terminal server existing in the contoso.com forest. However, Users experience a slower-than-usual logon, and the LOGONSERVER environment variable shows the name of a remote domain controller in the REDMOND site rather than the domain controller from the CONTOSO site.
However, administrators from the litware.com domain expect users from their domain (logging on contoso.com terminal servers) to authenticate using the domain controller located in the CONTOSO site. The CONTOSO site is the same physical locations as the terminal server. Authentication should occur in the local site and should be fast, right?
It is important to know how a Windows computer selects a domain controller. The computer, during startup, determines the Active Directory site in which it belongs. Windows accomplishes this by examining the subnet of its current network configuration. Then, the computer queries a domain controller that hosts the computer object(using the Windows API DsGetSiteName). The domain controller answers this query with the name of the site associated with the computer's currently configured subnet. This is all done by the NetLogon service, which runs the DC Locator code at boot and periodically rechecks the domain controllers’ location.
IMPORTANT: The computer determines the site name using a domain of which the computer is a member—not the user's domain. This determination occurs during computer startup—not during user logon. Microsoft Support article 939252 (http://support.microsoft.com/default.aspx?scid=kb;EN-US;939252) describes how you can change this behavior NOTE: Windows writes the site name to the registry during each computer startup. You can view the registry to determine the site to which the computer believes it belongs. You should NOT modify this registry value. The path to this registry value is: HKLM\System\CurrentControlSet\Services\Netlogon\ Parameters\DynamicSiteName\
IMPORTANT: The computer determines the site name using a domain of which the computer is a member—not the user's domain. This determination occurs during computer startup—not during user logon. Microsoft Support article 939252 (http://support.microsoft.com/default.aspx?scid=kb;EN-US;939252) describes how you can change this behavior
NOTE: Windows writes the site name to the registry during each computer startup. You can view the registry to determine the site to which the computer believes it belongs. You should NOT modify this registry value. The path to this registry value is: HKLM\System\CurrentControlSet\Services\Netlogon\ Parameters\DynamicSiteName\
Windows will attempt to use the closest domain controller (on the same subnet) to the local computer for authentication. Windows finds the closest domain controller by using DNS and SRV resource records.
Here’s how it works: Windows first performs a DNS query to find a _ldap SRV record for the computer's current site, but using the domain name selected from the CTRL+ALT+DEL sequence – the domain name of the user. An example looks like:
_ldap._tcp.<Computer Site Name>._sites.dc._msdcs.<User Domain>.com: type SRV, class IN
The DNS server responds indicating a record by that name is not found. Windows then attempts to find any domain controller within the user's domain. Windows accomplishes this by removing the site name from the DNS query. The example similar to the one above:
_ldap._tcp.dc._msdcs.<User Domain>.com: type SRV, class IN
The DNS server's response to the above request includes a resource record for every domain controller in the user's domain. Since the client receives the list of domain controllers in no particular order this result is usually the cause as to why the domain controller locator does not use the closest domain controller for authentication.
NOTE: The Netlogon service of a domain controller is responsible for dynamically registers the _ldap service resource records with its configured DNS server. This registration includes the site specific and domain specific _ldap records.
Our scenario involves a terminal server, which allows multiple users sessions. This is a great way to take network captures of user logon related issues by sing one of the logon sessions to take the network capture. It is always best to clear the DNS and NetBIOS name caches before starting a network capture. This ensures the network capture includes name resolution. You can clear these caches by using IPConfig /FlushDNS and NbtStat –R from a command window (under an elevated command prompt for Server 2008 and Vista).
Here is a snippet of the output of the network capture.
Figure 2 Contoso.com network capture of user logon
The results of the network capture show the domain controller locator attempts to locate a domain controller in the site with the same name as the site of the computer; but in the user's domain (frame 3). The DNS server responds with no such name. This is correct. The Litware.com forest has only two sites: REDMOND and CONTOSO. Frame 4 queries for an SRV record a second time; however, this time the query does not include the site name of the computer (_ ldap._tcp.dc.msdcs.litware.com). The DNS response provides a positive answer to the second query. The answer includes a _ldap record for each domain controller in the litware.com domain (the user's domain).
We've covered the background information and the problem. Now, let's talk about how to fix it. We can accomplish this by using Active Directory Sites and Services to rename the CONTOSO site in the litware.com domain to CHARLOTTE (the name of the site hosting the computer in the contoso.com domain). Active Directory site configuration is stored in the configuration partition of Active Directory. Renaming the site creates a change and you'll want ensure this replication converges-- especially to the litware.com domain controller that is now located in the CHARLOTTE site of the litware.com domain. After Active Directory replication completes, then restart the Netlogon service on the litware.com domain controller in CHARLOTTE site (in the litware.com domain). This registers the service resource records in DNS for the domain controller, including the new site in which it belongs.
Figure 3 Forest trust configuration after site rename
Let's take another network trace of a litware.com domain user logon from the terminal server in the contoso.com domain.
Figure 4 Network capture after site rename in litware.com
The same DNS query from figure 1 appears in figure 2. Frame 3 shows the domain controller locator attempting to find a domain controller service resource record in the CHARLOTTE site of the user's domain, litware.com. However, the difference between figure 1 and figure 2 is the DNS response. Figure 1 returned a negative DNS response because a resource record for the domain controller did not exist in the CHARLOTTE site in the litware.com domain. But, figure 2 shows a positive DNS response (frame 5) for a service resource record for a domain controller in the CHARLOTTE site of the litware.com domain.
After renaming the sites so that they match in both forests, the terminal server in the contoso.com domain successfully located a domain controller covering the CHARLOTTE site for litware.com domain. Ideally, in this scenario you would also want the litware.com domain controller covering for the contoso.com CHARLOTTE site to be on the same subnet as the contoso.com terminal server. This helps expedite litware.com logon requests originating from the terminal servers. Regardless, the configuration provides a way to distinguish a specific domain controller for use with logons that span across forests.
- Rob Greene and Mike Stephens
Introduction
Hello, it’s LaNae again. A major issue I see when customers call in regarding ADAM/AD LDS is around the creation of Service Connection Points and why they are needed. Let’s take a further look into this topic and uncover the mystery of this object.
What are Service Connection Points?
Service Connection Points (SCPs) are objects in Active Directory that hold information about services. Services can publish information about their existence by creating serviceConnectionPoint objects in Active Directory. Client applications use this information to find and connect to instances of the service. ADAM/AD LDS is no exception to this. The serviceConnectionPoint object class is derived from the connectionPoint class. ServiceConnectionPoints in ADAM/AD LDS will contain some key attribute information that is needed for client application discovery. The table below lists the contents of the serviceConnectionPoint object attributes. You can also find this information by using ADSIEDIT.MSC and viewing the properties of the child object of the computer that the ADAM/AD LDS instance is installed.
For example, Exchange 2007 uses SCPs to advertise autodiscover service information. The serviceBindingInformation attribute of this object is updated during setup with the autodiscover service URL. For more information on how Exchange 2007 uses Service Connection Points see Doug Gowans blog : http://blogs.msdn.com/douggowans/archive/2007/06/28/serviceconnectionpoints.aspx
This image was taken from the Understanding ADAM service publication TechNet article.
Discovering ADAM/AD LDS with Service Connection Points
If ADAM/AD LDS is installed in a domain and the ADAM/AD LDS service account has the Create Child right on the computer object where the serviceConnectionPoint object will be created it will attempt to create a serviceConnectionPoint object in Active Directory. By default global catalogs in Active Directory contain the same information that can be found in the Keywords attribute of a SCP object. Client applications will search the SCP attributes located in the global catalog to find an ADAM/AD LDS instance. Client applications can search for:
Discovering ADAM/AD LDS without Service Connection Points
Understand that ADAM/AD LDS do not need SCPs to be published in order to function properly. ADAM/AD LDS can run with or without SCPs. If ADAM/AD LDS is installed in a workgroup environment or if the service account that ADAM/AD LDS is running under does not have the proper permissions to create SCPs then it will not create an SCP. Under these circumstances client applications will use DNS to resolve the host name of a computer that has ADAM/AD LDS installed.
Creating Service Connection Point Objects
Service Connection Point objects can be created automatically or manually. When ADAM/AD LDS is installed on a machine that is part of a domain it will attempt to create a service connection point object. This object will appear as a child object of the computer object where the ADAM/AD LDS instance is installed. If the service account that is used to run ADAM/AD LDS does not have the “Create Child Right on the computer object where the ADAM/AD LDS instance is installed it will fail to create the service connection point object. ADAM/AD LDS will then log an Event ID 2537 in the ADAM/AD LDS event log stating that it could not create the SCP due to insufficient rights.
How are SCP Objects updated?
ADAM/AD LDS checks the SCP object for changes when the instance is started and then it will review the SCP object every hour after that to make sure it is still valid. When the instance starts it will search the Global Catalog for its GUID and then use that to find the distinguished name of the SCP object. The ADAM/AD LDS instance will bind to the distinguished name of the SCP object and updates it if needed. The interval that the ADAM/AD LDS instance reviews the SCP object can be modified by adding the Server information update interval (mins) dword value to the following registry key: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\instancename\parameters. The value data will be set to the time interval in minutes that is desired.
Managing SCP Objects
You can manage the ADAM/AD LDS by creating an OU that contains the computer objects that host ADAM/AD LDS instances. Doing this will place all SCP objects in the same location and allow for ease of administration.
Modifying the SCP Object Creation Location
Earlier in this blog I stated that the SCP object is created as a child object of the computer object that holds the ADAM/AD LDS instance. This location can be changed by modifying the SCPContainer attribute located on the SCP Publication Service object. This can be done to make administration of SCP objects easier. The following steps are identical for ADAM and AD LDS with a few exceptions: in the AD LDS schema you do not have to make any modification to the msDs-SCPContainer attribute. Also, there is no separate ADSIEDIT snapin for AD LDS.
You will connect to the AD LDS instance using the ADSIEDIT.msc that is used to manage AD DS and connect to the instance on its respective port.
1. You must first open the ADAM Schema (ADAM-adsiedit.msc) and navigate to the msDS-SCPContainer attribute.
2. Right click on the attribute and select properties. Check the box next to “Allow this attribute to be shown in advanced view” and “Index this attribute in the Active Directory” and click “OK”. 3. Launch ADAM ADSIEDIT or AD DS ADIEDIT 4. Connect to the configuration container of the ADAM/AD LDS instance and navigate to “CN=Directory Service,CN=Windows NT, CN=Services,CN=Configuration, CN=GUID of Instance”.
2. Right click on the attribute and select properties. Check the box next to “Allow this attribute to be shown in advanced view” and “Index this attribute in the Active Directory” and click “OK”.
3. Launch ADAM ADSIEDIT or AD DS ADIEDIT
4. Connect to the configuration container of the ADAM/AD LDS instance and navigate to “CN=Directory Service,CN=Windows NT, CN=Services,CN=Configuration, CN=GUID of Instance”.
5. In the right pane double click on the CN=SC Publication Service object. 6. Locate the msDS-SPContainer attribute and click edit.
5. In the right pane double click on the CN=SC Publication Service object.
6. Locate the msDS-SPContainer attribute and click edit.
7. Enter the DN of the location where you would like the SCP object to be created.
Note: you will need to give the ADAM/AD LDS service account the create child object right on the object you put in the Value. This can be done by right-clicking on the DN of the SCP object and going to properties. Click on the security tab and add the ADAM/AD LDS service account to the “Create Child Object” right.
Once you have completed these steps all ADAM/AD LDS instances will create the SCP in the specified location.
Summary
I hope this blog post has given you a better understanding of what Service Connection Point objects are. You should hopefully now know why we use service connection point objects and how to administer them.
- LaNae Wade
Hi, Ned here again. Today I’m going to talk about handling compressed files in Windows Server 2008 running as a Core server. You know, that thing with no pretty graphical interface and just a big command prompt that stares at you, daring you to try some successful administration.
Core mode is pretty slick – super-small footprint on the disk, great memory utilization, and plenty of useful roles that can be installed. But sheesh – it can be a real pain in the tail if your command-line skills are rusty or if you just haven’t ever had to deal with certain operations sans GUI.
So, quick question: have you tried to zip a file on a Core server yet? It’s sorta hard… because there is no zip.
With Core, there is no Explorer, so there is no file compression functionality. What if you need to compress a file on your Core server in order to copy it over some awfully slow connection and you want to do it all locally? You have two options:
Let’s talk about pro-style cheating.
Compressing a single file with MAKECAB
MAKECAB is a tool present in all later SKU’s of Windows. While it cannot create ZIP files, it can create cabinet (CAB) files. It’s an odd little utility as it was designed for developers to package files for installs, but it works well with decent compression.
So let’s take the scenario where you are remoted into your Core server through Terminal Services, WINRM, or (yuck) Telnet. You have a single file you need to compress and copy elsewhere. In your CMD prompt session, type:
MAKECAB <source> <destination> /l <some folder path> So for example: MAKECAB c:\somefolder\somebig.fil smaller.cab /l c:\
MAKECAB <source> <destination> /l <some folder path>
So for example:
MAKECAB c:\somefolder\somebig.fil smaller.cab /l c:\
This will cab up the ‘somebig.fil’ into ‘smaller.cab’ and put that file at the root of the C: drive for easier access.
Compressing a bunch of files with MAKECAB
Things get trickier with multiple files. Remember that MAKECAB was designed for developers, so naturally it’s as complex as possible :-). Using MAKECAB for a bunch of files requires that you use a directives file. Let’s say we have a folder full of files, and we want to zip them all up into one cab:
1. CD into the folder containing your files. 2. Run: DIR /B > mycab.ddf 3. Run: MAKECAB /d cabinetnametemplate=smaller.cab /d maxdisksize=CDROM /f mycab.ddf 4. You will now have a folder called ‘Disk1’ that contains ‘smaller.cab’
1. CD into the folder containing your files.
2. Run:
DIR /B > mycab.ddf
3. Run:
MAKECAB /d cabinetnametemplate=smaller.cab /d maxdisksize=CDROM /f mycab.ddf
4. You will now have a folder called ‘Disk1’ that contains ‘smaller.cab’
So a bit tricky, but not too terrible. If you want to get fancy you can add paths in a DDF file, and can even add more directives. If you want a definite cure for insomnia, you can read everything you ever wanted to know about cab files and the Cabinet SDK by going here. This includes further tools like CABARC that add advanced cabinet features. The "maxdisksize" switch there tells makecab.exe to write to the cab file up to 660MB. If there is still data to go, it will then create a "disk2" folder, write to that cab file, and so on.
Decompressing a cab file with EXPAND
Naturally, you’re going to want a way to decompress these files. If you had just copied to a Full Windows 2008 computer, Explorer is perfectly ok at reading CAB files. But let’s say you’ve been copying these CAB files between Core servers and now need to expand the data out. Simple:
EXPAND -R <cab file> -F:* <destination folder that must exist> So using our smaller.cab from above: EXPAND –R smaller.cab –F:* c:\
EXPAND -R <cab file> -F:* <destination folder that must exist>
So using our smaller.cab from above:
EXPAND –R smaller.cab –F:* c:\
And now our file(s) in the CAB file are decompressed and ready to roll. All without any fancy Explorer shell.
Notes
Final Raymond Chen-style preemptive strike: you’re probably firing up the Comment section below to lambast the developers about leaving zip tools out of Win2008 and how this is a conspiracy to… make people not like us? The real reason there is no command-line zip in Core is because there has never been a command-line zip in Windows. IT Pros just haven’t asked for it; they had their favorite zipping tools of choice, and there was always a GUI method for the home users. In fact, there was no MAKECAB in Core mode for most of its development history, because no MS beta customer had asked for it or for zip functionality after a year of testing! Yours truly raised a (polite, professional) stink and it was added in RC1. Don’t say I never did anything for you, folks.
There were some internal issues that prevented me from getting this out for a while, but I’m hopeful to post these weekly again now. Note that much of the content that previously would have become a KB article is now ending up on TechNet, so it is possible there will be fewer KB articles being published going forward.
These are the new articles that relate to Directory Services for 9/21-9/27:
955610
You cannot connect to an ADAM instance in Windows Server 2003 by using the Secure Sockets Layer 3 protocol together with a certificate that is larger than 1024 bytes
957802
The "Slow network connection time-out for user profiles" Group Policy setting does not work for a Windows Vista Service Pack 1-based or a Windows Server 2008-based client computer
958002
File System Auditing option in the Security Templates in MMC is confusing
Ned here with a quick blurb:
The latest version of the Ultrasound tool has been released to the web. This version adds support for monitoring FRS on Windows Server 2008 and allows the use of SQL Server 2005 for hosting the Ultrasound database. No other new features have been added in this version, and it does not monitor DFSR (the older version didn't either).
The download location for the tool is the same as before - http://www.microsoft.com/downloads/details.aspx?FamilyID=61acb9b9-c354-4f98-a823-24cc0da73b50&displaylang=en. To deploy the Ultrasound WMI provider on an x64 version of Windows Server 2008, the hotfix KB954737 must be installed (this fact is also mentioned in the release notes). - Ned Pyle
This is Paul Fragale, coming to you from my little corner of the world. With the launch of Windows Server 2008, there have been several cases around Terminal Server and Terminal Server License Server. I would like to take a moment to review with you some common steps that can help you resolve these issues.
The first case:
Introducing a Windows 2008 Terminal Server into your existing Windows 2003 Environment requires a little preparation. The first main point is that a Windows Server 2008 Terminal Server can only talk to a Windows 2008 License Server. (Additional information can be found at http://technet.microsoft.com/en-us/library/cc770371.aspx) There are two ways to set up the environment to handle this requirement:
The second case:
Limiting your Client Access Licenses (CALs) issuance is a frequent concern. With the auto-discovery process any Terminal Server can search Active Directory for a license server. If it finds one, it can then use the TSLS to issue licenses, thereby possibly depleting your license pool inadvertently. To prevent this, Microsoft has introduced a new group called “Terminal Server Computers”. This group allows you to configure what servers the license server is allowed to talk to. It works in conjunction with the “License server security group” Group policy found in the following location:
Computer Configuration\Administrative Templates\Windows Components\Terminal Services\TS Licensing.
In Windows 2008, we have found that it is a good idea to add all your Terminal Servers to this group when the License server is Windows 2008. A couple of symptoms that people have reported are the following:
Once you have added the servers to the “Terminal Server Computers” group, the server will start communicating and receiving licenses from the TSL. The one catch is that the server has to have already discovered the license server.
The third case:
Upon installing a Windows 2008 TSL, you may find the following event in the System event log:
Event ID: 8195 Task Category: None Level: Warning Keywords: Classic User: N/A Computer: tsl.alpineskihouse.com Description: The computer account for the Terminal Services license server could not be added to the Terminal Server License Servers group in Active Directory Domain Services during the installation of TS Licensing. The action failed with Win32 error code 0x80072037.
This event occurs in the following situations:
(I would like to thank Rob Greene for providing this third piece of information.)
So hopefully this gives you a little insight on troubleshooting your own Terminal Server License Server issues.
Until next time,
-Paul Fragale