OS refresh fails with NTLDR can’t be found error


 

Update. As Avi pointed out in comments to this post, my script does not handle root directories that invalid in Windows FileSystem space, because FSO does not see them when enumerating. I changed it to call of “DIR” command. And now I just delete them.
Another minor (but important!) change was taking out skipping deletion of “RECYCLER” folder from the script. I got a case of invalid names under RECYCLER. Please use at your own risk.

 

If you’ve been doing XP to Wind 7 migrations in larger scale, you probably came across some computers out there that ended up tossed with NTLD missing error.

Not nice! After this happens, you’d probably boot and safe user’s data from state store, and try to figure out what the hack happened. Looking in smsts.log reveals some details:

Reporting deletion progress.
Unable to delete directory C:\Documents and Settings\***\Local Settings\Temp\OICE_43BCF28F-9C21-4A31-BC1E-52B54828BD6F.0 (0x80070091). Continuing.
Unable to delete directory C:\Documents and Settings\***\Local Settings\Temp\OICE_930D53AE-2288-434E-97DD-C56505BB49CA.0 (0x80070091). Continuing.
Unable to delete directory C:\Documents and Settings\***\Local Settings\Temp (0x80070091). Continuing.
Unable to delete directory C:\Documents and Settings\***\Local Settings (0x80070091). Continuing.

Searching on the internet is giving you some clue. Most of the posts saying it’s permissions, so you come up with the script that resets permissions, but this is still happening. 

So what’s the culprit?

Let’s see what in that folder.

 Directory of C:\Documents and Settings\***\Local Settings\Temp

02/14/2012 05:50 PM <DIR> .
02/14/2012 05:50 PM <DIR> ..
02/14/2012 05:50 PM <DIR> OICE_1ED1F44B-623B-49CB-91A9-3D5FF12339E9.0
02/14/2012 05:50 PM <DIR> OICE_450CAED0-70C4-4B0E-A799-4C20309918BE.0
0 File(s) 0 bytes

Directory of C:\Documents and Settings\***\Local Settings\Temp\OICE_1ED1F44B-623B-49CB-91A9-3D5FF12339E9.0

02/14/2012 05:50 PM <DIR> .
02/14/2012 05:50 PM <DIR> ..
02/13/2012 07:28 PM 0 108D235B.
1 File(s) 0 bytes

Directory of C:\Documents and Settings\***\Local Settings\Temp\OICE_450CAED0-70C4-4B0E-A799-4C20309918BE.0

02/14/2012 05:50 PM <DIR> .
02/14/2012 05:50 PM <DIR> ..
02/13/2012 06:12 PM 0 FE182149.
1 File(s) 0 bytes

Total Files Listed:
2 File(s) 0 bytes
8 Dir(s) 300,889,800,704 bytes free

Notice highlighted files. They got a dot at the end. 

Bingo! Look at this answer:

http://stackoverflow.com/questions/4075753/how-to-delete-a-folder-that-name-ended-with-a-dot 

Looks like OSDApplyOS does not use it to delete files, so we’re in trouble.

So what creates it? I have a guess. 

Looks like it’s related somehow with Office Isolated Conversion Environment. So, 

http://support.microsoft.com/kb/935865 

I attached the script you can run if Apply OS Image failed before running Apply OS Image again.

Quick illustration:

How to use this script

 

This script needs ztiutility.vbs from MDT and it needs setacl.exe from http://sourceforge.net/projects/setacl/files/ 

If you use MDT, I recommend creating a Custom folder under Scripts on MDT package and copying the script and SetACL.exe into it.

 

Only If you DON’T use MDT change path to ZTIUtility from parent folder to current folder in the script

<script language=”VBScript” src=”..\ZTIUtility.vbs”/>

to

<script language=”VBScript” src=”ZTIUtility.vbs”/>

Copy SetAcl.exe, ZTIUtility.vbs and the script to a separate package in Configuration Manager.

 

  1. Open your task sequence
  2. Find “Apply Operating System Image” step
  3. Go to options and select “Continue on error”
  4. Create a new group, call it “Image Failed to Apply” right below the “Apply Operating System Image” step
  5. Add a new step of type “Run Command Line” to your new group
  6. If you use MDT and followed recommendation to copy it to Scripts\Custom use this command line: cscript.exe “%DeployRoot%\Scripts\Custom\OSDApplyOSRecovery.wsf”
  7. If you’re using a separate package, just use this command line: cscript.exe “OSDApplyOSRecovery.wsf” and Check “Package” and point it to the package you created above.
  8. Call this step “Attempt to recover”
  9. Go to options and set “Continue on error”
  10. Copy “Apply Operating System Image” step and paste it under your “Attempt to Recover” step.
  11. If you’re using MDT template, you should see “Logical drive letter stored under variable” under Destination. No changes necessary.
  12. If you’re not using MDT, and it says “Next Available Partition” you should change it to Specific Disk and Partition and use a proper partition (usually partition 2 disk 0 if formatting for bitlocker)
  13. Go to options and unselect “Continue on error” only for that step
  14. Done! 🙂

TEST, TEST AND TEST

Try to create an “invalid” folder by using mkdir “\\?\C:\Screw my deployment with period at the end.”

 Set permissions on it removing  Local System and administrators. Start OS Refresh.

 Be careful with this script if you save your State Store somewhere else but \StateStore folder! Meaning – if you’re running MDT 2010 U1 or earlier integration and pick and alternative location for State Store other then C:\StateStore!
Thank you.

 

OSDApplyOSRecovery.txt


Comments (27)

  1. John says:

    Is this the SetACL.exe referenced? sourceforge.net/…/setacl

  2. Jordi S says:

    I was wondering… would this script wipe the migration task sequence if using hardlink mode?

    I believe it would… because its delenting original doc&settings files… in fact, im testing it right now on test comp… but would you give me your pov? cheers

  3. alex semi says:

    How did your test go?

    I skip statestore and _smstasksequence folders, so you should be fine.

  4. Thanks for the script, I implemented it into my TS as I ran into a similar scenario where the TS could not wipe a file with a trailling space. While I could not test the script for the same scenario, I was able to run into an instance where the Apply OS task failed and your recovery task took over, which it processed successfully. However the TS then failed duing the re-apply of the OS, stating that there are no more Volume available for use (Volume C: has already used.).

    Did you encounter this particular issue when you tested your script? And if so, what did you do to get around it?

  5. alexsemi says:

    Cha Lo – yes, if you run ApplyOS step more then once and choose "Next available partition" the second attempt will fail. Is is possible to specify the partition number?

  6. Yes, I've changed the partition to C: for my TS, thanksfully we only use one partition. I won't know if it worked until I run into it again, I'll let you know if I do though.

  7. 'Avi' says:

    Hey,

    well done taking this on, I tried this script by creating a folder with a trailing period by doing:

    mkdir "\?C:Folder with Dots…"  (example: mkdir "\?C:360safe."

    i tried to delete it manually with and failed:

    rd /s /q c:360safe.

    i tried to delete it with and succeeded:

    rd /s /q "\?c:360safe."

    so far so good, however the script you wrote uses FileSystemObject and that fso.getfolder or fso.subfolders and that does not see those folders with trailing period / dot in the end  etc.

    i tried to run the following script that uses the same object and methods and came up with "regular" folders only:

    ViewSubFolders "c:"

    Sub ViewSubFolders(strFolder)

    Set objFSO = CreateObject(&quot;Scripting.FileSystemObject&quot;)
    
    Set objFolder = objFSO.GetFolder(strFolder)
    
    For Each SubFolder in objFolder.SubFolders
    
        Wscript.Echo SubFolder.Path
    
        ViewSubFolders SubFolder
    
    Next
    
    Set objFolder = Nothing
    
    Set objFSO = Nothing
    

    End Sub

    so actually it will not delete what it intends to delete?

  8. 'Avi' says:

    Hey again,

    okay, instead of using the filesystemobject i decided to use simple DIR command in FOR loop,

    so after the apply os image fails i restart the pc and run this .bat from a package i created (can be MDT or any toolkit package)

    @echo off

    for /f "tokens=" %%i in ('dir /s /a:D /b \?C:.*^|"%~dp0"findstr /I /V /G:"%~dp0exclusion.txt"') do Call :Delete "%%i"

    :Delete

    echo found %1

    rd /s /q %1

    here's what happens:

    DIR list all directories on \?C: recursively and outputs a bare list pipe the output to findstr which exclude names found on that text file and then calls the delete command,

    to make it work with findstr in winpe i have to copy the correct version of findstr from same architecture windows 7 pc and also copy the locale file "findstr.exe.mui" to a folder i created in the package source called "en-US"

    and created the exclusion file to do what your select performed select performed,

    the file exclusion.txt contains these lines:

    boot

    userstate

    system volume information

    _smstasksequence

    thanks to you and "TheOutcaste" from this thread:

    forums.techguy.org/…/833910-solved-help-r-loop.html

    now i have a global solution to when apply os image fails,

    before your post and this solution we had to remove the disk from the failed machine and connect it to a different machine and then see what files were left over or could not be deleted, and in every office it was some other annoyance, in one it was some autorun.inf "vaccine" program the user enabled and in others it was a malware that created weird folders with a trailing period.

    hope this helps others as well.

  9. 'Avi' says:

    I forgot to mention that i also use additional xml file for USMT to prevent these folders from restoring (yes that happened even tho you won't see them in userstate store folder)

    <unconditionalExclude>

    <objectSet>

    <!– Folders to unconditionally exclude: –>

    <pattern type="File">C:*. [*]</pattern>

    </objectSet>

    </unconditionalExclude>

  10. alexsemi says:

    Avi – I updated this script. So now it does handle root folders correctly. Besides that it fixes the folders with hidden and/or system attributes set and my script still has that ACL part that always worked.

    Thank you for input and feedback.

  11. So for the script to work in a Task Sequence I need the ZTIutility.vbs and your script thats it right. What is the point of the SetACL.exe ?

  12. AlexSemi says:

    SetAcl takes ownership and resets permissions

  13. ben says:

    I'm trying to get this working… I have an MDT created TS in SCCM.

    It seems that when the apply operating system step fails, it jumps directly to "Gather Logs and StateStore on Failure" and never runs the second apply operating system image step set to _SMSTSLastActionSucceeded=false.

    Do I need to check "continue on error" in my first apply operating system image step?

  14. 'Avi' says:

    @Ben – yes the first applyOS pass should have "ContinueOnError" enabled

    followed by a group with the condition _SMSTSLastActionSucceeded=False

    that group does the following:

    -restart

    -handle the bad directories

    -restart

    -applyOS 2nd pass to drive C: (this is important if the 1st applyOS is for "next available partition")

    -restart again

  15. I'm seeing this identical scenario, with the failure rate around 20% of our target clients.  Is there a way to leverage these scripts when using SCCM without MDT integration?

  16. alexsemi says:

    @Avi – Thanks for clarifications here, some corrections –

    I don't do restarts, we don't do anything that requires restart. For next available partition, I use MDT UDI template, it uses variable OSDisk.

    @MP8167 – absolutely. Create a new package with this script and copy ZTIUtility.vbs from MDT. Change path to ZTIUtility from parent folder to current folder

    &lt;script language=&quot;VBScript&quot; src=&quot;..ZTIUtility.vbs&quot;/&gt;
    

    to

    &lt;script language=&quot;VBScript&quot; src=&quot;ZTIUtility.vbs&quot;/&gt;
    

    See Avi's comment above about "next available partition".

  17. Mugambo says:

    Hi Alex, thanks for posting this. Do you know how I can get this to work with hardlinking? As it currently deletes contents of C:UserState folder when the script is run.

  18. alexsemi says:

    It works with hardlinks. Can I ask you why your state store called C:UserState, not C:StateStore? Anyways, you can add another exception folder to the script:

    Case "minint", "system volume information", "deploy", "drivers", "_smstasksequence", "smstslog", "sysprep", "statestore", "userstate"

  19. Travis says:

    How are you getting your second (retry) apply operating system action to work?  Everytime I put a second one in it knows the drive has already been used for an apply image action and it won't use it again.  Are you using a different destination instead of the default "Next available formatted partition" option?

  20. Iam using the batch file method by Avi and created a SCCM package with the batch file and called it in a Run command line in task sequence but getting error code 1. Should it be run from pacakge share or should we copy the file to local system and run.

  21. Hi Alexsemi

    I tried your script as I have the same exact problem but still i have folders in the drive "The directory is not empty." any way to get around this issue.

    Thanks

  22. dynas2001 says:

    any tricks to having this work on a xp32bit to win764 ts AND win764 to Win764?

    I'm guessing yoru sciprt doesn't deal with the whole 32bit 64bit stuff?

  23. Basel says:

    Thank you for the script and the solution, so far so good 🙂

    but i'm using it differently, i don't wait for the Apply Operating System step to fail, i created the script step right before my one and only "Apply Operating System" step, it does not take much time so why don't we avoid failing OS step and apply the script anyway .. will fix the "next available partition" issue as well 🙂

  24. Woosel says:

    I tried running this as the first step in the Task Sequence right after an initial reboot and nothing appears to happen…the "screw my…" folder is still there. I also tried running from a command line in XP and that appeared to do nothing either. I did get the error about the referenced path not found and then corrected the path as I am using this as an SCCM package. The "if you are NOT using MDT" got me a bit confused as we are using an MDT task sequence from within SCCM.

    Pardon my ignorance, but is this designed to only run from within WinPE as part of a task sequence?

  25. Woosel says:

    Success! Set up the "screw my deployment" folder exactly as specified but placed the package and command line to run the script immediately before "Apply Operating System" just as @Basel did. Ran perfectly and the deployment finished successfully.

  26. Jim Riekse says:

    Thank you for the script! It eliminated a 10% failure rate in our migration. If it is useful to anyone, I added additional logic in the recovery steps to only activate on the specific errors of "The directory is not empty" or low disk space. The logic is:

    _SMSTSLastActionSucceeded=false AND (_SMSTSLastActionRetCode=-2147024751 or -2147024784)