B
Bug Repro
I am running into a scenario where Document.Merge is applying changes to the
wrong document. When I first saw it I thought it was just that the revisions
were showing up on the wrong document, so I had created a post on
ShowRevisions. However, looks like this is a bug with Merge and since I can't
change the title of the other post I am creating a new one.
I have pasted the repro code below. In order to use the code, create a
simple c# VSTO
app which adds a command bar in Word using the code from here
http://msdn.microsoft.com/en-us/library/scff9c7c(VS.80).aspx.
Change the ButtonClick to create an instance of BugRepro class and call
BugRepro.button1_Click.
Now do the following.
1. Ensure there is no word process running.
2. Start Word. Add some content to the blank document and save it. Don't
close the window. (Doc1)
3. Create a new blank document. This will create a new word window (Doc2)
4. Switch to Doc1 window and click button 1.
5. You will get a FileOpen message box. Select an existing word document in
the message box.
6. You will now get a prompt which will simple call out the fullFileName of
Doc1. Click OK.
7. Now quickly switch to Doc2's window. Note that you have only 10 secs to
make the switch.
After 10 secs, the code which executes in response to clicking button1 will
do a merge and show the changes. Changes will show up in the wrong window. If
you look at the code you will notice that I am using the ActiveDocument
property only once to get the wordDoc to begin with.
//---------------------------------------
class BugRepro
{
private string fileName;
private Document wordDoc;
public void button1_Click(object sender, EventArgs e)
{
// Ask the user to select a file to merge from
OpenFileDialog selectFileDilaog = new OpenFileDialog();
DialogResult result = selectFileDilaog.ShowDialog();
if (result == DialogResult.Cancel)
{
return;
}
wordDoc = ThisAddIn.Addin.Application.ActiveDocument;
string sourceFile = wordDoc.FullName;
MessageBox.Show(sourceFile);
fileName = selectFileDilaog.FileName;
// Get the currently active object and start a timer which will
// merge the file
Timer timer = new Timer();
timer.Interval = 10000;
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
ThisAddIn.Addin.secondButton.Caption = "Wait 10";
}
void timer_Tick(object sender, EventArgs e)
{
// stop the timer
Timer timer = sender as Timer;
timer.Stop();
ThisAddIn.Addin.secondButton.Caption = "merge";
// Do the merge
DoMerge();
}
List<Revision> revisions;
private void DoMerge()
{
// Normal merge
//
try
{
Document sourceDocument = wordDoc;
sourceDocument.ShowRevisions = true;
// Copy the file to a temp file
//
string tempFile = Path.GetTempFileName();
if (File.Exists(tempFile))
{
File.Delete(tempFile);
}
File.Copy(fileName, tempFile);
sourceDocument.ShowRevisions = true;
// Merge documents
//
RunMethod<object>(
sourceDocument,
"Merge",
new object[]
{
tempFile,
1, // wdMergeTargetCurrent
true, // DetectFormattingChanges
1, // wdFormattingFromSelected
false // AddToRecentFiles
}, true);
// Add in the revisions that were generated
//
revisions = new List<Revision>();
Revisions revisionsObject = sourceDocument.Revisions;
for (int i = 1; i <= revisionsObject.Count; i++)
{
revisions.Add(revisionsObject);
}
// Wait for some time
Timer waitTimer = new Timer();
waitTimer.Interval = 5000;
ThisAddIn.Addin.secondButton.Caption = "display Rev";
waitTimer.Tick += new EventHandler(waitTimer_Tick);
waitTimer.Start();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK);
}
}
void waitTimer_Tick(object sender, EventArgs e)
{
Timer timer = sender as Timer;
timer.Stop();
wordDoc.Repaginate();
foreach (Revision rev in revisions)
{
rev.Accept();
}
wordDoc.Repaginate();
wordDoc.Repaginate();
wordDoc.ShowRevisions = false;
ThisAddIn.Addin.secondButton.Caption = "Completed";
}
public static T RunMethod<T>(object obj, String name, object[] args,
bool throwException)
{
try
{
return (T)obj.GetType().InvokeMember(name,
BindingFlags.InvokeMethod | BindingFlags.Public, null, obj,
args);
}
catch
{
if (throwException)
{
throw;
}
return default(T);
}
}
}
wrong document. When I first saw it I thought it was just that the revisions
were showing up on the wrong document, so I had created a post on
ShowRevisions. However, looks like this is a bug with Merge and since I can't
change the title of the other post I am creating a new one.
I have pasted the repro code below. In order to use the code, create a
simple c# VSTO
app which adds a command bar in Word using the code from here
http://msdn.microsoft.com/en-us/library/scff9c7c(VS.80).aspx.
Change the ButtonClick to create an instance of BugRepro class and call
BugRepro.button1_Click.
Now do the following.
1. Ensure there is no word process running.
2. Start Word. Add some content to the blank document and save it. Don't
close the window. (Doc1)
3. Create a new blank document. This will create a new word window (Doc2)
4. Switch to Doc1 window and click button 1.
5. You will get a FileOpen message box. Select an existing word document in
the message box.
6. You will now get a prompt which will simple call out the fullFileName of
Doc1. Click OK.
7. Now quickly switch to Doc2's window. Note that you have only 10 secs to
make the switch.
After 10 secs, the code which executes in response to clicking button1 will
do a merge and show the changes. Changes will show up in the wrong window. If
you look at the code you will notice that I am using the ActiveDocument
property only once to get the wordDoc to begin with.
//---------------------------------------
class BugRepro
{
private string fileName;
private Document wordDoc;
public void button1_Click(object sender, EventArgs e)
{
// Ask the user to select a file to merge from
OpenFileDialog selectFileDilaog = new OpenFileDialog();
DialogResult result = selectFileDilaog.ShowDialog();
if (result == DialogResult.Cancel)
{
return;
}
wordDoc = ThisAddIn.Addin.Application.ActiveDocument;
string sourceFile = wordDoc.FullName;
MessageBox.Show(sourceFile);
fileName = selectFileDilaog.FileName;
// Get the currently active object and start a timer which will
// merge the file
Timer timer = new Timer();
timer.Interval = 10000;
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
ThisAddIn.Addin.secondButton.Caption = "Wait 10";
}
void timer_Tick(object sender, EventArgs e)
{
// stop the timer
Timer timer = sender as Timer;
timer.Stop();
ThisAddIn.Addin.secondButton.Caption = "merge";
// Do the merge
DoMerge();
}
List<Revision> revisions;
private void DoMerge()
{
// Normal merge
//
try
{
Document sourceDocument = wordDoc;
sourceDocument.ShowRevisions = true;
// Copy the file to a temp file
//
string tempFile = Path.GetTempFileName();
if (File.Exists(tempFile))
{
File.Delete(tempFile);
}
File.Copy(fileName, tempFile);
sourceDocument.ShowRevisions = true;
// Merge documents
//
RunMethod<object>(
sourceDocument,
"Merge",
new object[]
{
tempFile,
1, // wdMergeTargetCurrent
true, // DetectFormattingChanges
1, // wdFormattingFromSelected
false // AddToRecentFiles
}, true);
// Add in the revisions that were generated
//
revisions = new List<Revision>();
Revisions revisionsObject = sourceDocument.Revisions;
for (int i = 1; i <= revisionsObject.Count; i++)
{
revisions.Add(revisionsObject);
}
// Wait for some time
Timer waitTimer = new Timer();
waitTimer.Interval = 5000;
ThisAddIn.Addin.secondButton.Caption = "display Rev";
waitTimer.Tick += new EventHandler(waitTimer_Tick);
waitTimer.Start();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK);
}
}
void waitTimer_Tick(object sender, EventArgs e)
{
Timer timer = sender as Timer;
timer.Stop();
wordDoc.Repaginate();
foreach (Revision rev in revisions)
{
rev.Accept();
}
wordDoc.Repaginate();
wordDoc.Repaginate();
wordDoc.ShowRevisions = false;
ThisAddIn.Addin.secondButton.Caption = "Completed";
}
public static T RunMethod<T>(object obj, String name, object[] args,
bool throwException)
{
try
{
return (T)obj.GetType().InvokeMember(name,
BindingFlags.InvokeMethod | BindingFlags.Public, null, obj,
args);
}
catch
{
if (throwException)
{
throw;
}
return default(T);
}
}
}