domingo, 16 de dezembro de 2012

DFS-R Replication problems: Event ID 6002


today morning, while applying windows updates into one of mine DFS-R and DFS-N servers, I found a strange ID, 6002:

The DFS Replication service detected invalid msDFSR-Subscriber object data while polling for configuration information.

Additional Information:
Object DN: CN=<removed>,CN=DFSR-LocalSettings,CN=<removed>,OU=<removed>,OU=<removed>,OU=<removed>,OU=<removed>,DC=<domain name>,DC=com
Attribute Name: msDFSR-MemberReference
Domain Controller: <DC hostname>
Polling Cycle: 60 minutes

After seeing this error I filtered mine alerts, and found that for 3 days these alerts were being shown, just a few each day. So, let´s do what every SysAdmin does: google it!

I had the feeling that this was related to conflicts or orphan entries in LDAP DB that contains the entire DFS configuration, and the feeling became true.

My Domain is  based on Windows Server 2008 R2 with 2008 R2 Functional Level.

I found some interesting entries: (fix only for 2k3 R2 - other problem)

and here the details about the ms-DFSR-MemberReference attribute (Windows):

But, after the links and the intro, what was the solution?

Before going to the solution, I need to add one more thing: this error stopped replication for ALL folders and groups. So this is a very critical problem. I created some Diag Reports and create some test files to see them replicated, but nothing happened for hours.

Steps taken:

1. Get the errors (look in all involved servers from your DFS-R farm, if you replicate folders from A to B, look on A and B for 6002 errors - filter the event viewer)

2. Go to your Domain Controller (I am assuming you have DFS deployed in a Domain), open the ADSIEdit.msc console (this tool allows you to browse the LDAP structure from your domain, including all attributes from the objects, allowing a RW view... be careful when editing this, this is only required for advanced procedures)

3. In the ADSIEdit console, connect to your DC/Domain and navigate to the key informed in the error. Open the details for the key, there you will find the replicated folder name.

4. Do the same in the other servers. Verify in all the servers the replicated folder name

5. Do not remove the entry yet. Go back to your DFS Management snap-in and delete the affected replicated group.

6. Wait for the changes to propagate, to speedup run in an elevated prompt dfsrdiag PollAD /Member:<your  DC hostname>

7. Wait up to 1h to see the changes propagated. For me, after removing the conflicting Replication Group from the DFS-R Management (not removing from view, but deleting the RG totally) the DFS replication started to work properly again (yes!!!). But the conflicted still existed in MSIEdit.

8. To stop the 6002 errors, I deleted the entries from LDAP DB and restarted DFS-R service. After that everything was OK.

So, one more problem solved and documented so you can also benefit from this. Please comment

domingo, 29 de julho de 2012

Convert thousands of files from .Doc to .Html with Powershell (The Saga!)

Hello! After so long I am coming again after a 2-day battle against Powershell and Office assemblies. So, first, what I wanted to do (and actually did :) )...

Convert thousands of Word .doc files to .html for a customer project. Well, first option: do by hand was out of scope... as they were really thousands of .doc files. So let´s go forward for a smart function.

Then I found this amazing piece of code at Technet:
1:  param([string]$docpath,[string]$htmlpath = $docpath)  
2:  $srcfiles = Get-ChildItem $docPath -filter "*.doc"  
3:  $saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], "wdFormatFilteredHTML");  
4:  $word = new-object -comobject word.application  
5:  $word.Visible = $False  
6:  function saveas-filteredhtml  
7:    {  
8:      $opendoc = $$doc.FullName);  
9:      $opendoc.saveas([ref]"$htmlpath\$doc.fullname.html", [ref]$saveFormat);  
10:      $opendoc.close();  
11:    }  
12:  ForEach ($doc in $srcfiles)  
13:    {  
14:      Write-Host "Processing :" $doc.FullName  
15:      saveas-filteredhtml  
16:      $doc = $null  
17:    }  
18:  $word.quit();  


OK, perfect, right? Not yet. After copying and saving as a .ps1 file, the errors started...

Unable to find type [Microsoft.Office.Interop.Word.WdSaveFormat]: make sure that the assembly containing this type is l
At c:\path\Doc2Html.ps1:5 char:73
+ $saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat] <<<< , "wdFormatFilteredHTML");
    + CategoryInfo          : InvalidOperation: (Microsoft.Offic...rd.WdSaveFormat:String) [], RuntimeException
    + FullyQualifiedErrorId : TypeNotFound

Ops... something is not good here. So, let´s troubleshoot. 

1. Download and install the Office Interop Assemblies for your Office version ( for Office 2007 the download link is here (

2. Very important: run the Script from a directory in the PATH. For example, after I installed the Interop Assembly I still got the same errors. Than I realized that I was trying to run the script from a USB drive. I copied the file to %SystemRoot% (C:\Windows\system32) in my case. 

So, now it ran yes? Not yet :( again strange errors:

Method invocation failed because [System.__ComObject] doesn't contain a method named 'SaveAS'.

What now? After Googling (or Binging...) I found that this error is related with regionalization and language settings. Mine Office is Portuguese-Brazil, but my PC has Win7 Enterprise - English. I found a simmilar error on this thread that had a link to the a MS page saying that this  is really a BUG:;en-us;320369

OK, so now just add the hint in the blog to my Powershell code? No. The hint is for C# so I had to search for the Powershell version. Finally found here:

$currentThread = [System.Threading.Thread]::CurrentThread
$culture = [System.Globalization.CultureInfo]::InvariantCulture
$currentThread.CurrentCulture = $culture
$currentThread.CurrentUICulture = $culture

Added the lines above to the script and finally the conversion started and converted in the first test 50 docs perfectly to html.

Now mine final code, with regionalization settings:

1:  # Convert .doc to .html  
2:  param([string]$docpath,[string]$htmlpath = $docpath)  
3:  $srcfiles = Get-ChildItem $docPath -filter "*.doc"  
4:  $saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], "wdFormatFilteredHTML");  
5:  $word = new-object -comobject word.application  
6:  $word.Visible = $False  
7:  function saveas-filteredhtml  
8:    {  
9:       $name = $doc.basename  
10:       $savepath = "$htmlpath\" + $name + ".html"  
11:       write-host $name  
12:       Write-Host $savepath  
13:      $opendoc = $$doc.FullName);  
14:      $opendoc.saveas([ref]$savepath, [ref]$saveFormat);  
15:      $opendoc.close();  
16:    }  
17:  ForEach ($doc in $srcfiles)  
18:    {  
19:      Write-Host "Processing :" $doc.FullName  
20:      saveas-filteredhtml  
21:      $doc = $null  
22:    }  
23:  $word.quit();  

I hope this piece of code helps someone... pls comment!