Some nice one-liners

  • Restart the computer you are logged on to immediately, forcing all applications to close:
    shutdown.exe /r /t 0 /f
  • The same for a remote computer:
    shutdown.exe /r /t 0 /f /m \<computer>
  • Add someone to the local Administrators groups:
    net localgroup Administrators /add <user or group>
  • Enable Remote Desktop on a remote system:
    reg add “\<computername>HKLMSYSTEMCurrentControlSetControlTerminal Server” /v fDenyTSConnections /d 0 /t REG_DWORD /f
  • Schedule a reboot of the system you are logged on to (works on Windows Server 2003):
    schtasks.exe /Create /RU “NT AUTHORITYSYSTEM” /SC ONCE /TN “Restart” /TR “%systemroot%system32shutdown.exe /r /t 0 /f” /ST 22:00 /Z
  • Schedule a reboot of the system you are logged on to (works on Windows Server 2008 and later):
    schtasks.exe /create /TN “Restart” /SC Once /ST 23:00 /TR “%windir%system32shutdown.exe /r /t 0 /f” /RU “SYSTEM”

Some Active Directory Migration Tool (ADMT) Notes

The good old Active Directory Migration Tool (ADMT) has reached version 3.2 making it compatible with Windows 7/Server 2008 R2 and x64. ADMT started it’s Microsoft life as licensed software from One point. I’ve been using this baby since version 2.0. It offers what you need to perform intra or inter-forest Active Directory migrations/restructures, but it is very basic. The most annoying thing is that Microsoft have yet to implement PowerShell support in ADMT.

Here are some observations I have made about the use of ADMT over the course of many years:

  • No version of ADMT translates security for Remote Desktop (Terminal Server) Roaming Profiles.
    It will translate Local Profiles using the User Profiles option in the Computer Account Migration wizard, and regular Roaming Profiles using the Translate Roaming Profiles option in the User Account Migrationwizard, but it will not touch the Remote Desktop profile. This seems very strange to me since we are just talking about reading another attribute in Active Directory and doing the same thing as you are already doing with Roaming Profiles. Beats me…(Just to be clear, the regular Roaming Profile is specified on the Profile tab of the user in Active Directory Users and Computers (ADUC), and is stored in the profilePath attribute. The Remote Desktop Services Roaming profile is specified on the Remote Desktop Services Profile tab in ADUC and is stored in the userParameters attribute data blob. In the Windows Server 2008 Active Directory schema; Microsoft have created a new attribute called msTSProfilePath that is meant to store this setting in the future.)
  • ADMT needs Full Control NTFS permissions to translate a profile, roaming or local.
    Translating a profile means updating the NTFS permissions on all the files in the profile directory, but also loading the user’s registry hive; the NTUSER.DAT file, and translating the registry permissions set on all the keys in it. I have written about manually performing this process here.If you have not changed the default settings Windows will create roaming profiles with the following ACL/Owner:
    – SYSTEM – Full Control
    user_name – Full Control
    – Owner = user_name
    Obviously these permissions will not let ADMT, which connects to the computer as the user running it (it does not have a service), translate the profile. To work around this you can either enable a Group Policy setting called Computer ConfigurationPoliciesAdministrative TemplatesSystemUser ProfilesAdd the Administrators security group to the roaming user profiles, before the profile is created or you can grant the Administrators local group (or any other user/group you prefer) Full Control permissions to the profile folder and all its files and subfolders. The easiest way to do the latter, in my opinion, is to use PsExec from Sysinternals to start a command shell as SYSTEM and then use CACLS.EXE/XCACLS.EXE/ICACLS.EXE, or any other ACL editor, to add the Administrators group to the files/folders. Here’s an example using CACLS.EXE (which is included in every version of Windows since Windows 2000):
    1. Start the shell as SYSTEM: psexec.exe -i -s cmd.exe
    2. Change the permissions with CACLS.EXE: cacls.exe <root of profile share> /T /E /C /G Administrators:F
  • ADMT uses Server Message Block (SMB)  and Remote Procedure Calls (RPC) respectively, to install and communicate with it’s agents on machines when performing computer migrations or security translations.
    This means that you need to allow traffic from the ADMT machine to all the computers that you are going to migrate or translate security on, on these ports:
  • Traffic Port Notes
    RPC Endpoint mapper 135 TCP The endpoint mapper is like the RPC address book. Whenever an RPC connection is to be made; the client, in this case the ADMT machine, first connects to the endpoint mapper to find out which dynamic port the service it needs to talk to is listening on. It then makes a connection to that port.
    RPC Dynamic Ports Up to Windows Server 2008/Vista:
    1024 – 65535 TCPWindows Server 2008/Vista and later:
    49152 – 65535 TCP
    Any service using RPC talks to the RPC subsystem on the system where it is starting and asks for a port(s). This operation is performed each time the service starts and thus the port can potentially change on every service startup.
    Server Message Block (SMB) SMB Direct Hosting:
    445 TCPNetBIOS Over TCP/IP: 137/UDP
    137/TCP
    138/UDP
    138/TCP
    ADMT connects to the ADMIN$ share on computers it will either migrate or perform security translation on, and copies its files to the %windir%OnePointDomainAgent folder. It also installs a service on the machine called Active Directory Migration Service.
  • ADMT Agent source files
    Are stored in %windir%ADMTNT4Agent for Windows NT machines, or %windir%ADMTW2kAgent for Windows 2000 and above.
  • ADMT cannot migrate a user object that has child objects
    This is true for both inter and intra-forest migrations. Trying to do so will give you this error:
    ERR2:7422 Failed to move source object <RDN of user being migrated>. hr=0x8007208c  The operation cannot be performed because child objects exist. This operation can only be performed on a leaf object.
    The only case where I have found child objects for users are with Exchange Active Sync partnerships. These are stored in a sub container, called ExchangeActiveSyncDevices, as objects of class msExchActiveSyncDevice. Each device the user has an active partnership with has its own object. A typical name of the device object is iPhone§Appl690509FTA4S. It contains attributes of the device, ID, firmware, protocol version etc.You will have to get rid of these one way or the other if you want to migrate the user. If you just delete them, the user needs to set up sync on their devices from scratch once they are migrated. This is usually not a major problem if the users are warned beforehand that this will happen. Another way is to export the sub container and all the device objects, delete it (leaving the user as a leaf object), migrating, and finally importing the device objects back under the migrated user. This last solution requires that you change the distinguishedName attribute when you import the data, and it is probably not supported by Microsoft…at all. Here are some commands using LDIFDE.EXE to export and import the data. You can use this in a script before and after user migration with ADMT:
    Export:
    ldifde.exe –s <source domain DC> –f <export file> –d <DN of the ExchangeActiveSyncDevices container> -l * -o objectGUID
    Note that I have excluded the objectGUID attribute and included all others (-l *). When you import an object into Active Directory it will be assigned a new GUID. Importing a GUID, potentially causing two objects to have the same GUID, is a security violation, and the DC will refuse to perform it.
    Import:
    ldifde.exe -i –f <import file> –c <<old DN> replace with <new DN> (see LDIFDE help for more info)>
    Now, one thing about this. The device object has an attribute called msExchUserDisplayName. It has a value in the form of e.g.: <domain DNS name>/OU/OU/<user>. In other words an LDAP canonical name. If you perform and export/import as I have shown here, this attribute will contain the canonical name the user had in the source domain, i.e. the OLD canonical name. I know for a fact that this will break remote wipe and the Get-ActiveSyncDeviceStatistics cmdlet on Exchange 2007, and probably Exchange 2010. However, the device will continue to sync. (On a side note, this problem also occurs if you move a user within a domain. The msExchUserDisplayName attribute is not updated; breaking wipe and the cmdlet.) To work around this you can try to exclude the attribute when exporting with LDIDFE.EXE or implement code that changes it before you import it back into your target domain. I have not, as of now, tried any of these yet, but I am thinking that if I use PowerShell instead of LDIFDE.EXE to export the objects it would be easy to replace the old canonical name with the new one. I also do not know if removing the attribute from the device object will break the sync partnership. Another problem though, is the device. It stores the domain and username when you set up the account and usually won’t let you change it. The only thing you get to change is the password. So all this work may be for nothing, since users must update the account information on their devices anyway. Damn!
  • Inter-forest migrations do not exclude any attributes (except the SID…sort of)
    According to the ADMT documentation a system attribute exclusion list is created the very first time you run a user migration. The attributes in the list always include the attributes mail and proxyAddresses. I addition, says the docs, the objectGUID, objectSID and legacyExchangeDn attributes are also always excluded even if they are not on the system attribute exclusion list. However, when you do intra-forest migrations ALL attributes are copied. You can examine the system attribute exclusion list with this script, found in KB937537:
    Set o = CreateObject(“ADMT.Migration”)
    WScript.Echo o.SystemPropertiesToExclude
    When I ran this on an ADMT machine used for intra-forest migrations it returnes exactly zero attributes. Examining the migrated objects also verified that indeed all attributes had been copied. The mail, proxyAddressesobjectGUID and legacyExchangeDN were the same. The object had been given a new SID, which it had to because it was now living in a domain with a different domain SID, but the old SID had been copied into the sIDHistory attribute. Neat!

I will probably update this post with more info in the future. For now; Happy migrating!

Some SID Filtering Notes

  • SID Filtering is also known as Quarantine, Domain Quarantine, or SID Filtering Quarantine.
  • SID Filtering only applies to trusts, it cannot be enabled within a domain.
  • SID Filtering, by default, is not active on automatically created trusts within a forest. You can enable it, but not if the forest functional level is below Windows Server 2003. Doing so on any trust within a forest breaks replication. Additionally, if the forest functional level is Windows Server 2003 or higher; users with universal group memberships from other domains in the forest may loose access to resources if you enable SID Filtering on any of your trusts.
  • You can check the status of SID Filtering with the netdom.exe (Windows Domain Manager) command:
    • To verify the status of SID Filtering between two domains:
      netdom trust <TrustingDomainName> /domain: <TrustedDomainName> /quarantine
      Example output:
      SID filtering is not enabled for this trust. All SIDs presented in an authentication request from this domain will be honored.
      This is the default setting between domains in the same forest.
    • To verify the status of SID Filtering between two forests:
      netdom trust <TrustingDomainName> /domain: <TrustedDomainName> /enablesidhistory
      Example output:
      SID history is disabled for this trust.
      This is the default setting between trusting forests.
    • As you can see the two commands are nearly identical, but /quarantine applies only to domain trusts and /enablesidhistory is only valid for an outbound forest trust. They also output totally different messages making it hard to see that they actually apply to the same thing.
  • More info:

AdminSDHolder, Protected Groups, SDProp and moving mailboxes in Exchange

When you move a mailbox in Exchange 2000 or newer, you sometimes encounter an error saying that you have insufficient permissions to move the mailbox. Although that may be the case, usually this error is caused by the user object associated with the mailbox you are trying to move not having inheritable permissions enabled in Active Directory. This is also known as that the DACL is protected, i.e. it is special and should not be changed. But why is it protected?

Usually it is protected because the user was once a member of one of the protected administrative groups in Active Directory. (Notice the word ‘once’, it will be important later!) These groups are (per Windows Server 2008 R2):

  • Enterprise Admins
  • Schema Admins
  • Domain Admins
  • Administrators
  • Account Operators
  • Server Operators
  • Print Operators
  • Backup Operators
  • Cert Publishers

Any user who is a direct or indirect member of any of these groups will get a protected DACL (inheritable permissions turned off) and the attribute adminCount set to 1. SDProp, or the Security Descriptor Propagator, thread within the LSASS.EXE process is responsible for checking and applying these settings once an hour. Any change you make to a protected object will be reset within the hour.

So back to moving mailboxes.

If the user is a member of any of the protected groups, the move mailbox process completes successfully since Exchange is aware of how to handle that scenario. But if the user has been removed from all protected groups the move process fails (remember I said “once a member of”).

The reason is that the user still has a protected DACL and the adminCount attribute set to 1. SDProp does not reverse its changes when you remove a user from a protected group. This is a scenario that Exchange does not know how to handle and so throws the insufficient permissions error. The easiest way to resolve the problem is to go into the Security tab of the user object, select Advanced and hit the Restore Defaults button. That will enable inheritance of permissions and remove any ACEs that SDProp (or any other process) has set explicitly. One important thing to know is that the Restore Defaults button does not reset the adminCount attribute back to 0, so you still have a user object in a non-consistent state (it is inheriting permissions, but still flagged as a special object). The best practice would be to manually clear adminCount with you favorite DS tool when you also enable permission inheritance.

Now that we know this it would be a good idea to find all the users that would fail when we tried to move them. To do this we would need to construct a query with the following criteria:

  • Not a member of any of the protected groups
  • Has a mailbox
  • Has a protected DACL

My choice would be PowerShell. Here is an example using the Quest Active Directory cmdlets:

  1. Put all the known protected groups in an array:
    $ADProtectedGroups = @(“Enterprise Admins”,”Schema Admins”,”Domain Admins”,”Administrators”,”Account Operators”,”Server Operators”,”Print Operators”,”Backup Operators”,”Cert Publishers”)
  2. Find all the users and put them in an array:
    $mismatchedUsers = Get-qaduser -sizelimit 0 -securitymask DACL –NotIndirectMemberOf $ADProtectedGroups -IncludedProperties homeMDB | Where-Object {(($_.DirectoryEntry.PSBase.ObjectSecurity.AreAccessRulesProtected) –
    and ($_.homeMDB -ne $null))}
  3. View the users if you like:
    $mismatchedUsers | ft
  4. Fix the users:
    $mismatchedUsers | ForEach { Set-QADObjectSecurity $_ –UnLockInheritance | Set-QADObject -ObjectAttributes @{adminCount=$null} }

Note: You may also want to include adminCount=1 in your search to see which objects have it set, but you could then get back users that have been fixed before by pressing Restore Defaults or enabling inheritable permissions.

To search for users with adminCount=1:

$admincountUsers = Get-qaduser -sizelimit 0 -NotIndirectMemberOf $ADProtectedGroups -IncludedProperties homeMDB,adminCount | Where-Object {(($_.adminCount -eq 1) -and ($_.homeMDB -ne $null))}

Or to just find everything with adminCount=1:

Get-ADObject –LDAPFilter “(adminCount=1)”

“A certificate cloud not be found that can be used with this Extensible Authentication Protocol” error in IAS

After issuing a new certificate for a Windows Server 2003 running IAS this error presented itself in the IAS console when trying to configure EAP with the new certificate:

image

“A certificate could not be found that can be used with this Extensibel Authentication Protocol.”

This was accompanied by these two events in the System Log:

image

image

This was the new certificate, based on the default Computer template in Windows:

image

Notice the empty subject field, IAS/NPS does not accept certificates with empty subject names for use with EAP or Smart Cards. The certificate template that had been used for this certificate was a duplicate of the default Computer template. The template looked like this:

image

After creating a new template from the default Computer template, now with Subject name format set to Common name, and issuing a new certificate; IAS worked fine.

So don’t use certificate with blank subjects for your IAS/NPS servers…

An overview of groups used by Active Directory Certificate Services

This is a quick list of the groups associated with Active Directory Certificate Services.

CERTSVC_DCOM_ACCESS

Purpose: Grant DCOM access to Certificate Authority.

Default description: This group has no default description.

Group type: Local/Domain Local Security group.

Default members: Everyone/Domain Users and Domain Computers.

This group is created when Windows Server 2003 Service Pack 1 is installed on a Certificate Authority. If the CA is a member server (or in a workgroup); CERTSVC_DCOM_ACCESS is a computer local group, if the CA is a DC; CERTSVC_DCOM_ACCESS is a domain local group. Also when you install a Certificate Authority (CA) on a Windows Server 2003 machine that already has Service Pack 1 (or later); this group is created.

All security principals that need to enroll certificates from the CA must be a member, direct or indirect, of this group. If the CA is a member server; the Everyone security group is added to CERTSVC_DCOM_ACCESS. If the CA is a DC; the Domain Users and Domain Computers groups are added to CERTSVC_DCOM_ACCESS.

Only domains with a CA installed on a DC have this group, and only members servers with a CA have it as a computer local group. If you have several domains in your forest, only computers and users in the domain where the CA resides can request certificates. If other domains in the forest need to enroll certificates, security principals from those domains must be added to the group.

In Windows Server 2008 this group was replaced by the Certificate Service DCOM Access group (see own group into below).

More info:

  • Description of the changes to DCOM security settings after you install Windows Server 2003 Service Pack 1
  • Error message when a client computer requests a certificate from a computer that is running Windows Server 2003 with Service Pack 1: “The wizard cannot be started because of one or more of the following conditions”Certificate Service DCOM Access

    Purpose: Grant DCOM access to Certificate Authority.

    Default description: Members of this group are allowed to connect to Certification Authorities in the enterprise.

    Group type: Builtin Local Security Group.

    Default members: Authenticated Users.

    This group serves the same purpose as CERTSVC_DCOM_ACCESS, but is created in Windows Server 2008 domains. It grants access to Certificate Authorities, but is a Builtin local group as opposed to CERTSVC_DCOM_ACCESS, which is a Local or Domain Local group.

    Sometimes you will se both CERTSVC_DCOM_ACCESS and Certificate Service DCOM Access in a domain.

    Cert Publishers

    Purpose: Publish certificates to Active Directory.

    Default description: Enterprise certification and renewal agents

    Group Type: Global Security Group (Windows 2000)/Domain Local Security Group (Windows Server 2003 or later)

    Default members: Certificate Authority computer account from same domain as group.

    This group is created when an Active Directory domain is created. In Windows 2000 it is created as a Global Security Group, but in Windows Server 2003 or later it is created as a Domain Local Security Group.

    If a Windows 2000 domain is upgraded to Windows Server 2003 or later, this group remains as a Global Security Group; it is not automatically updated to Domain Local scope. To change the group scope you can run this command:

  • dsmod group CN=Cert Publishers,CN=Users,<domain DN> -scope lSometimes you cannot change the group scope directly to Domain Local. In this case, you have to run 2 commands:
  • dsmod group CN=Cert Publishers,CN=Users,<domain DN> -scope u
    (This command changes the global group into a universal group.)
  • dsmod group CN=Cert Publishers,CN=Users,<domain DN> -scope l
    (This changes the group scope to Domain Local.)This group is granted Read userCertificate and Write userCertificate on all user and computer accounts in the domain where it resides. If the same domain contains a Certificate Authority the CA is added to this group, thus allowing it to publish certificates to the user or computer.

    The permissions granted to the Cert Publishers group in a domain are defined on the AdminSDHolder container located in <domain>/System. Changing the Cert Publishers group’s permissions on AdminSDHolder will change the permissions that Cert Publishers have on all objects in the domain.

    In a multi-domain forest, the CA computer account(s) must be added to this group in all the domains where you want the CA to be able to publish certificates.

    If you have a multi-domain forest the PowerShell script below will display the group scope and members of all the Cert Publishers groups in the forest:

    #
    # EnumerateAllCertPublishersMembers2.ps1
    # by Morgan Simonsen, Atea
    #
    # List the group type, scope and members of the Cert Publishers group
    # in every domain in a forest.
    #
    # More info:
    #
    http://morgansimonsen.wordpress.com/2012/01/24/an-overview-of-groups-used-by-active-directory-certificate-services/
    #

    $colCertPublishersGroups = @()

    $forest = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()

    Write-Host “Getting forest-wide membership of Cert Publishers groups…”

    # Get members of ‘Cert Publishers’ for forest-root domain
    $objTemp = New-Object System.Object
    $objTemp | Add-Member -type NoteProperty -name “Domain” -value $forest.name

    $group = Get-QADGroup -Identity ( $forest.name + “/users/Cert Publishers” ) -Service $forest.pdcroleowner #-ea silentlycontinue

    $objTemp | Add-Member -type NoteProperty -name “Group Name” -value $group.name
    $objTemp | Add-Member -type NoteProperty -name “Group Type” -value $group.grouptype
    $objTemp | Add-Member -type NoteProperty -name “Group Scope” -value $group.groupscope

    $members = Get-QADGroupMember -Identity ( $forest.name + “/users/Cert Publishers” ) -Service $forest.pdcroleowner #-ea silentlycontinue

    $objTemp | Add-Member -type NoteProperty -name “Members” -value $members

    If ( $members -ne $null )
    {
    ForEach ( $member in $members )
    {
    #Nothing
    }
    }
    $colCertPublishersGroups += $objTemp

    $domain = $null
    $group = $null
    $members = $null
    $objTemp = $null

    # Get members of ‘Cert Publishers’ for child domains
    $forest.children | ForEach `
    {
    $objTemp = New-Object System.Object
    $mydomain = Get-QADObject -Identity $_.name #-ea silentlycontinue

        $objTemp | Add-Member -type NoteProperty -name “Domain” -value $mydomain.name

        $group = Get-QADGroup -Identity ( $_.name + “/users/Cert Publishers” ) -Service $_.pdcroleowner #-ea silentlycontinue

        $objTemp | Add-Member -type NoteProperty -name “Group Name” -value $group.name
    $objTemp | Add-Member -type NoteProperty -name “Group Type” -value $group.grouptype
    $objTemp | Add-Member -type NoteProperty -name “Group Scope” -value $group.groupscope

        $members = Get-QADGroupMember -Identity ( $_.name + “/users/Cert Publishers” ) -Service $_.pdcroleowner #-ea silentlycontinue

        $objTemp | Add-Member -type NoteProperty -name “Members” -value $members

        If ( $members -ne $null )
    {
    ForEach ( $member in $members )
    {
    #Nothing
    }
    }
    $colCertPublishersGroups += $objTemp

        $domain = $null
    $group = $null
    $members = $null
    $objTemp = $null

    }

    $colCertPublishersGroups

    More info:

  • Certification Authority configuration to publish certificates in Active Directory of trusted domain
  • Cert Publishers scope changed from Global to Domain Local in Windows Server 2003
  • Enterprise CA May Not Publish Certificates from Child Domain or Trusted Domain

Error when trying to reset a password when Fine Grained Password Policies (FGPP) are in effect

I had created a Fine Grained Password Policy (FGPP) which, among other things, turned off the requirement for complex passwords. I had applied this policy to users through a group. When I tried to reset the password of one of the users for which this FGPP applied, Active Directory Users and Computers would give me this error:

—————————
Active Directory Domain Services
—————————
Windows cannot complete the password change for <user> because:

The password does not meet the password policy requirements. Check the minimum password length, password complexity and password history requirements.

—————————
OK
—————————

Originally I though that my password did in fact violate my FGPP, but after testing this further I concluded that it was something else. After a bit of looking I discovered that this domain was in Windows Server 2003 Functional Mode. A requirement for FGPP is at least Windows Server 2008 Functional Mode. After changing it to Windows Server 2008, the FGPP took effect and I could reset my passwords.

Perhaps the *-ADFineGrainedPasswordPolicy cmdlets should check the domain functional level. At least New-ADFineGrainedPasswordPolicy should display a warning if the domain is not at the required level. The requirement is listed in the Step-by-Step guide (thank you PTS), but I didn’t catch that this time.

References:

Windows Live stuff #1

Here are a few tips I picked up regarding using the Windows Live Essentials 2011 suite and the Hotmail mail service. I use Hotmail to host my email with my own vanity domain, which I think works great (and it’s free!). Don’t know if these things work exactly like this if you use another mail service or have other default programs.

  1. The Inbox button in Windows Live Messenger will open Windows Live Mail if Windows Live Mail is set to automatically sign in to Windows Live.
    image
    To stop this behavior; select Stop signing in, in Windows Live Mail (Options->Connections):
    image
    This will open your default browser instead and navigate to Hotmail when you hit the Inbox button.
  2. To get the new cool Jump List and notifications when you pin Hotmail to the Windows 7 Taskbar; first navigate to your Hotmail Inbox, then drag the tab down to the Task Bar. If you do it from the Windows Live Home page you will not get these cool features.
    image

Customizing Office 2010 Setup with OCT: Adding/Removing files

The Office 2010 Office Customization Tool (OCT) can add and remove files to/from a computer that is installing Office. These are the steps in the OCT where you can add and remove files:

image

image

Notice the text in the Add files step; Specify files to add to the user’s computer during installation. When you exit this tool, copies of the files are saved in the Setup customization file. Notice also the Location column; [AppDataFolder]Microsoft…

So in the example above the normal.dotm and Word.officeUI files will be added to the MSP (Windows Install Patch) file.

When you deploy Office to a computer the files are copied from the MSP file into the [INSTALLLOCATION]Microsoft OfficePatchFiles and renamed with GUIDs as their names:

image

Now, looking back at the Location column in the Add files step in the OCT we can see that the files in this example are to be copied into the [AppDataFolder]Microsoft… etc. A user’s AppData folder is stored in the %APPDATA% environment variable and it’s usually something like: c:Users%username%AppDataRoaming. But since all users who log on to the computer, not just the one installing Office, needs these files they are copied from the PatchFiles folder into the AppDataRoaming folder for each new user who starts one of the Office applications. This feature also works the same way when Office is installed by the SYSTEM account, and not a user; the files are copied from the MSP file into the PatchFiles folder and from there to the user’s AppData folder.

Office 2010 Professional Plus fails with unexpected restart on Windows XP

The Situation

Office 2010 Professional Plus (32-bit) deployed to Windows XP Professional Service Pack 3 (32-bit) clients with System Center Configuration Manager (SCCM) 2007 R2 (64-bit). Office 2010 configured with Office Customization Tool (OCT) according to Microsoft guidelines.

The Problem

Upon completion the installation would initiate a forced reboot without prompting the user or giving any warning. After the reboot the Office 2010 installation would continue, but since it already completed before the reboot, this would be interpreted as a modification, prompting the user to select Add/Remove components, change product key etc. This, however, was not visible to the user since the program was configured to run without user interaction in SCCM. The result was that the Configuration Client (CcmExec) would wait for setup.exe for the maximum allowed run time and then terminate setup.exe, logging the installation as a failure. The whole process looked like this in the SCCM Advertisement Status report:

Time Message State Name Message Name Message ID Record ID
10.11.2011 12:37 Accepted Program received 10002 1164453
10.11.2011 12:37 Waiting Waiting for content 10035 1164454
10.11.2011 12:54 Running Program started 10005 1164461
11.11.2011 08:24 Failed Program failed (unexpected restart) 10021 1165171
11.11.2011 08:29 Running Program started 10005 1165174
11.11.2011 13:28 Failed Program failed (run time exceeded) 10070 1165445

Screenshot from SCCM

At 11.11.2011 08:29 Office 2010 restarts the installation after the reboot, even though it actually succeeded before the reboot, and the reboot is just to complete the installation. This is interpreted as a modification to the existing install and setup.exe prompts the user for what modifications to make. The user cannot see this, however, because he cannot interact with the program. CcmExec lets setup.exe run until the max run time is reached and then terminates setup.exe (11.11.2011 13:28) logging the install as a failure.

The Office 2010 setup log, located in %systemroot%System32Temp indicates that the install is successful, but that a restart is needed.

The Solution

To work around this problem it is necessary to suppress the reboot. This is done by adding the following to the MSP file in OCT (or the equivalent to config.xml):

image

With this setting in the MSP file the installation of Office 2010 will not be “fooled” by its own restart and complete successfully. You will first receive a status of Program completed successfully (reboot pending), until you initiate a restart on your own. After this restart the status will change to Program completed with success. Office 2010 seems to be fully functional even without performing this restart immediately, but the advertisement status in SCCM will not change until you restart.

Notes

Reports from other who have experiences similar issues indicate that the forced restart only happens on Windows XP computers, not Windows 7. I have not tested this myself.

References

Information wants to be free!