2

I have seen some other questions on here which has solutions, however even direct cast and garbage collection won't get rid of the ambiguity warning or stop my program trying to use a document that is apparently already in use.

The below code is part of an application to completely rebrand some Word documents (changing headers, templates and logos etc). MergeDocument isn't disposing of the word application or document (a template file that other methods need access too).

The WaitForIt method is simply a timer delay of two seconds, in hope that it was a timing issue in regards to accessing the template file. Most of the other methods don't get a chance to do anything before the try/catch in GrabLogoFromTemplate is hit when it tries to use the same template that MergeDocument has used.

Unfortunately it isn't and I'm now out of ideas as what to do to combat this, direct casting as mentioned in the title didn't rectify what I assume is the issue with the Introp Word Application and Document Close and Quite methods. The same as reported in this question, and hereI tried the solution of garbage collection noted in the latter, but it didn't solve my issue. Both Close() and Quit() are ambiguous, like the issue in the first question, but even disposing (think I have done this correctly) doesn't free the template for the other methods to use.

Has anyone come across this before?

Merge Button:

private void Merge_btn_Click(object sender, EventArgs e)
{
    Rebrand rb = new Rebrand();
    progressBar1.Increment(+1);
    rb.FolderCreation();
    Microsoft.Office.Interop.Word.Application wordApp = new Microsoft.Office.Interop.Word.Application();

    progressBar1.Increment(+24);
    string[] fileArray = Directory.GetFiles(currentFolder_tb.Text);

    for (int i=0; i < fileArray.Length; i++)
    {
        string tmpTemplate = rb.GetTempTemplateLocationn(template_tb.Text,i);

        string newDocumentPath = rb.MergeDocument(fileArray[i], newLocation_tb.Text, tmpTemplate, wordApp);
        // ambiguous 
        foreach(Word.Document d in wordApp.Documents)
        {
            d.Close(ref missing, ref missing, ref missing);
        }
        rb.WaitForIt();
        rb.GrabLogoFromTemplate(tmpTemplate);
        rb.WaitForIt();
        if (newDocumentPath != "false")
            rb.ReplaceImageInHeader(newDocumentPath);
    }

    object missing = System.Reflection.Missing.Value;
    ((Microsoft.Office.Interop.Word.Application)wordApp).Quit(ref missing, ref missing, ref missing);
    // the above has ambiguity warning
    GC.Collect();// doesn't solve

    if (progressBar1.Value == 99)
        progressBar1.Increment(+1);
        MessageBox.Show("File(s) ReBranded!");
    progressBar1.Value = 0;
}

Merge Document:

public string MergeDocument(string oldDoc, string newDoc, string tmplt, Microsoft.Office.Interop.Word.Application wordApp)
{
    try
    {
        object missing = System.Reflection.Missing.Value;
        //Microsoft.Office.Interop.Word.Application wordApp = new Microsoft.Office.Interop.Word.Application();
        Microsoft.Office.Interop.Word.Document aDoc = null;
        object readOnly = false;
        object isVisible = false;
        wordApp.Visible = false;
        object oldfile = oldDoc;
        // keep the old document's filename
        object newfile = newDoc + @"\" + Path.GetFileName(oldDoc);
        object template = tmplt;
        // add new template
        aDoc = wordApp.Documents.Add(ref template, ref missing, ref missing, ref missing);
        // open existing document you wish to merge
        aDoc = wordApp.Documents.Open(ref oldfile, ref missing, ref readOnly, ref missing, ref missing,
            ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref isVisible,
            ref missing, ref missing, ref missing, ref missing);
        aDoc.Activate();
        aDoc.set_AttachedTemplate(template);
        aDoc.UpdateStyles();
        aDoc.SaveAs(ref newfile, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
            ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);

        // close the document, ambiguity warning
        ((Microsoft.Office.Interop.Word.Document)aDoc).Close(ref missing, ref missing, ref missing);
        return newfile.ToString();
    }
    catch
    {
        return "false";
    }

}
Community
  • 1
  • 1
PurpleSmurph
  • 2,055
  • 3
  • 32
  • 52

2 Answers2

1

I had a problem batch processing PowerPoint slides. The only solution was to close, quit and then run GC twice!

  GC.Collect();
  GC.WaitForPendingFinalizers();

  GC.Collect();
  GC.WaitForPendingFinalizers();
Peter Smith
  • 5,528
  • 8
  • 51
  • 77
  • Thanks for the idea, tad over-kill, but then again so is what I've done just now and it seems to be working. Involving looping through the word app to close all documents at the mergedocument method and before the template grabloogofromtemplate method. Also through in if not null ReleasComObject for good measure. Nuking a house spider, but hey, if it works. – PurpleSmurph Jan 21 '16 at 12:39
1

I don't fully understand why this works, but it was the solution for me, essentially destroying objects twice.

Over-the-top, as essentially I'm disposing of the same object multiple times, but it does the trick.

The ambiguity is still present, which is probably why I needed to 'double tap' each object.

Within MergeDocument() underneath close() I added:

if(aDoc != null)
    System.Runtime.InteropServices.Marshal.ReleaseComObject(aDoc);
    aDoc = null;

Before GrabLogoFromTemplate() I added a loop to destroy all Document types remaining in my Application instance:

foreach(Word.Document d in wordApp.Documents)
{
    d.Close(ref missing, ref missing, ref missing);
}

Finally, just before I call the GC I made sure that the Application instance is set to null and release the Introp ComObject:

if(wordApp != null)
    System.Runtime.InteropServices.Marshal.ReleaseComObject(wordApp);
    wordApp = null;
PurpleSmurph
  • 2,055
  • 3
  • 32
  • 52