Visual Studio Development Bookmark and Share   
 index > Visual Studio Tools for Office > How to check if Word Doc opened remotely?
 

How to check if Word Doc opened remotely?

HI everyone,

We've come across an issue. in C# .NET 2.0. We have a program which goes through folders replacing the template files of each word document. The basic gist of our program is:

1) get the folder

2) get all the files in the folder and store in an array

3) for each file, open the file, replace the template, close the file.

These documents are located on a server, so while running our program users could have the document open remotely.

When a document is open, we get the following pop-up prompt box from Word:
FILE IN USE
file.doc is locked for editing by user <whoever>
Do you want to:
* Open a read only copy
* create a local copy and merge your changes later
* receive notification when the original copy is available

How the heck do we programmatically go through and disable this? When this box pops up, the program halts. We can't check for the hidden tmp files because it is extremely possible that a user could open up a document in the folder after we've obtained all the file names.

Also, these folders could have thousands of files, so it makes no sense for us to have to loop through and check if there are tmp files (to see if it's open) for each main file we come across. That would just take too long.

Below is the code we have.

Any ideas? Thanks!

        //Settings for when working on the Word documents. 
        private object missing = System.Reflection.Missing.Value;
        private object dotNormal = @"Normal.dot";
        private object newPasswd = "";
        private object oldPasswd = "ccad";
        private object docVisible = false;
        private object;
        private object saveChanges = Word.WdSaveOptions.wdSaveChanges;


try
            {   //Get all the files in the current folder. 
                string[] arrFiles = Directory.GetFiles(folderPath, "*.doc");

                //Need the following to disable Macros so documents prompt for data/input.
                wordApp.AutomationSecurity = Microsoft.Office.Core.MsoAutomationSecurity.msoAutomationSecurityForceDisable;

                //Loop through all the files...
                for (int x = 0; x < arrFiles.Length; x++)
                {   // ... getting each file ...
                    object docName = (object)arrFiles[x];
                    try
                    {   // ... open the document, replace the template, save it, close, update counter.
//IT IS THIS NEXT LINE WHERE PROCESSING HALTS UNTIL THE USER RESPONSE TO THE PROMPT. HOW TO GET AROUND THIS???
                        newDoc = wordApp.Documents.Open(ref docName, ref missing, ref readOnly, ref missing, ref oldPasswd, ref oldPasswd, ref missing, ref missing, ref missing, ref missing, ref missing, ref docVisible, ref missing, ref missing, ref missing, ref missing);
                        newDoc.set_AttachedTemplate(ref dotNormal);
                        newDoc.Save();
                        newDoc.Close(ref saveChanges, ref missing, ref missing);
                        intNumFilesProcessed[intThreadNum] += 1;
                    }
                    catch (Exception)
                    {   //If we couldn't open the file for some reason, increment the associated counter
                        //and save the path for writing to the log file.
                        if (!dSkippedFiles.ContainsKey(docName.ToString()))
                            dSkippedFiles.Add(docName.ToString(), (int)intThreadNum);

                        intNumFilesSkipped[intThreadNum] += 1;
                    }
                }

                //Successfully processed all the files in the folder. 
                intNumFoldersProcessed[intThreadNum] += 1;

                //Clean up local array
                Array.Clear(arrFiles, 0, arrFiles.Length);
                arrFiles = null;
            }
            catch (Exception)
            {   //If we couldn't open the folder for some reason, increment the associated counter
                //and save the path for writing to the log file.
                if (!dSkippedFolders.ContainsKey(folderPath))
                    dSkippedFolders.Add(folderPath, (int)intThreadNum);

                intNumFoldersSkipped[intThreadNum] += 1;
            }
            finally
            {   //Clean up all the objects this thread was using.
                wordApp.Quit(ref saveChanges, ref missing, ref missing);
                newDoc = null;
                wordApp = null;
            }
FireMyst  Wednesday, October 14, 2009 3:40 AM

Hello FireMyst,

I could provide a sample of doing this, just for your reference:

 private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {

            Object filename = @"D:\ShareDocument\New Microsoft Office Word Document.docx";
            appWord = Application;
            appWord.Visible = true;

                   
            bw = new BackgroundWorker();
            bw.DoWork += new DoWorkEventHandler(bw_DoWork);
            bw.WorkerSupportsCancellation = true;
            bw.RunWorkerAsync();


            try
            {
                docWord = appWord.Documents.Open(ref filename, ref ConfirmConversions, ref ReadOnly,
                ref AddToRecentFiles, ref PasswordDocument, ref PasswordTemplate,
                ref Revert, ref WritePasswordDocument, ref WritePasswordTemplate,
                ref Format, ref Encoding, ref Visible, ref missing, ref missing, ref missing, ref missing);
            }
            catch
            {

            }
            finally
            {
                bw.CancelAsync();
            }
          }          

 [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern int FindWindow(String className, String windowName);

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hwnd, uint wMsg, int wParam, int lParam);
        public const uint WM_SYSCOMMAND = 0x0112;
        public const int SC_CLOSE = 0xF060;

        void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            while (bw.CancellationPending == false)
            {
                try
                {
                    IntPtr handle = (IntPtr)FindWindow("bosa_sdm_Microsoft Office Word 12.0", "File In Use");
                    SendMessage(handle, WM_SYSCOMMAND, SC_CLOSE, 0);
                }
                catch
                {
                }
            }
            e.Cancel = true;
        }

As Cindy said, above stuff is out of scope in VSTO forum, the code I gave is a skeleton that give you a idea to get across this situation.

Thanks.

Tim Li

MSDN Subscriber Support in Forum

If you have any feedback on our support, please contact EMAIL GONE


Please remember to mark the replies as answers if they help and unmark them if they provide no help.
  • Marked As Answer byFireMyst Monday, October 19, 2009 3:58 AM
  •  
Tim Li  Thursday, October 15, 2009 9:02 AM

Hello FireMyst,

Welcome to MSDN forums!

The key to your problem is how to work around the File In Use dialog when the document you're opening is already opened by another user, right?

As far as I know, in Word Object Model we could not reach this dialog, also we could not avoid this from  happening if we try to open the document via Object Model.

However, there is a work around out of Word Object Model. Before we perform Documents.Open method we could first check if the file is in use by File.OpenWrite Method:

  using (File.OpenWrite(filename.ToString()))
            {
           
            }
If the document is already in use above method will fail.

And this is not a perfect work around, because if a user opens the document just after File.OpenWrite method, and just before Documents.Open method, the prompt still pops up.

To avoid this happen, another way is start a background before Documents.Open method, and timely check if the dialog is pop-up by Windows API FindWindow method, if the dialog exist, we could close it by using SendMessage method.

If you have any further question, please feel free to follow up.

Thanks.

Tim Li

MSDN Subscriber Support in Forum

If you have any feedback on our support, please contact msdnmg @ microsoft.com


Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Tim Li  Wednesday, October 14, 2009 10:14 AM
Hi Tim,

Yes, you've summarized our problem.

"To avoid this happen, another way is start a background before Documents.Open method, and timely check if the dialog is pop-up by Windows API FindWindow method, if the dialog exist, we could close it by using SendMessage method."

I've quoted the above because I'm not quite sure how to go about what you suggest. Do you mean have some sort of background thread running that's always checking for pop-up windows? If so, what do we look for in order to identify that one specific window?

You're delving into parts of programming that we haven't had experience with yet, so your guidance would be helpful. Skeleton code perhaps?

Thanks!
FireMyst  Wednesday, October 14, 2009 10:29 AM
Your question is off-topic in the VSTO forum. VSTO is essentially an extension of the Office applications to provide the .NET developer easier access to interact with the user. General Office automation, such as you're doing, is not part of the VSTO technology. You'll find some links for non-VSTO, Office-related questions in the forum's Please Read First message.

FWIW I don't think there's any way, short of checking for temp files, to determine whether a file is locked before trying to open it. You could test whether setting Application.DisplayAlerts to "off" helps with this error message, but if it does not I know of no other possibility. You can try asking in a group that specializes in the Word application (the links I mention,above). Given the admiinistrative nature of what you're doing, however, it might make sense to schedule this during non-working hours and block access to the folder a while before that. I know that's what a company I worked for, some 15 years ago, did when they needed to do maintenance.
Cindy Meister, VSTO/Word MVP
Cindy Meister  Wednesday, October 14, 2009 1:05 PM

Hello FireMyst,

I could provide a sample of doing this, just for your reference:

 private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {

            Object filename = @"D:\ShareDocument\New Microsoft Office Word Document.docx";
            appWord = Application;
            appWord.Visible = true;

                   
            bw = new BackgroundWorker();
            bw.DoWork += new DoWorkEventHandler(bw_DoWork);
            bw.WorkerSupportsCancellation = true;
            bw.RunWorkerAsync();


            try
            {
                docWord = appWord.Documents.Open(ref filename, ref ConfirmConversions, ref ReadOnly,
                ref AddToRecentFiles, ref PasswordDocument, ref PasswordTemplate,
                ref Revert, ref WritePasswordDocument, ref WritePasswordTemplate,
                ref Format, ref Encoding, ref Visible, ref missing, ref missing, ref missing, ref missing);
            }
            catch
            {

            }
            finally
            {
                bw.CancelAsync();
            }
          }          

 [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern int FindWindow(String className, String windowName);

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hwnd, uint wMsg, int wParam, int lParam);
        public const uint WM_SYSCOMMAND = 0x0112;
        public const int SC_CLOSE = 0xF060;

        void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            while (bw.CancellationPending == false)
            {
                try
                {
                    IntPtr handle = (IntPtr)FindWindow("bosa_sdm_Microsoft Office Word 12.0", "File In Use");
                    SendMessage(handle, WM_SYSCOMMAND, SC_CLOSE, 0);
                }
                catch
                {
                }
            }
            e.Cancel = true;
        }

As Cindy said, above stuff is out of scope in VSTO forum, the code I gave is a skeleton that give you a idea to get across this situation.

Thanks.

Tim Li

MSDN Subscriber Support in Forum

If you have any feedback on our support, please contact EMAIL GONE


Please remember to mark the replies as answers if they help and unmark them if they provide no help.
  • Marked As Answer byFireMyst Monday, October 19, 2009 3:58 AM
  •  
Tim Li  Thursday, October 15, 2009 9:02 AM

Hi,

I am writing to check the status of the issue on your side. Could you please let me know if the suggestion works for you or not? If you have any questions or concerns, please feel free to let me know. I will be more than happy to be of assistance.

Tim Li

MSDN Subscriber Support in Forum

If you have any feedback on our support, please contact msdnmg@microsoft.com


Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Tim Li  Monday, October 19, 2009 2:30 AM
Hi Tim,

Thanks for your suggestion!

Unfortunately, we're unable to try it at this stage as our code had to be released into Production for use (I didn't receive an alert that you had posted a code sample).

I do hope to get back to it sometime before year's end when I have time to play. :-)

We're using Office 11 and were thinking we'd somehow have to go through Windows Shared Services.

But again many thanks for your suggestion! I'll let you know how things pan out when we get time to play again.

For now, I'm going to mark is as the answer since you went through that trouble (which we really appreciate!). :-)
FireMyst  Monday, October 19, 2009 3:57 AM

You can use google to search for other answers

Custom Search

More Threads

• Access Denied starting MS Outlook from Windows Service
• Modifying Built-in Ribbon Controls - Newbie Question
• Using Copies of an Excel Workbook that has VSTO Customization
• VSTOR wit XP Home Edition and Office student version
• BeginUpdate/EndUpdate on excel list object
• Determine SharePoint Readonly Word document
• Infopath TaskPane Addin
• WebService as DataSource for ListObjects
• vsto 3.0 runtime
• AttachmentRead Event