1

I wrote a C# program that converts a 1997 - 2003 .DOC Word Documents into TEXT FILES. I am running the program from the Command Line. I have to convert over 300,000 documents. Every document takes from 0.7 to 1.5 seconds to process. The program works fine. I am using library:

  • Microsoft.Office.Interop.Word

The problem here is that few Word Documents are corrupted, some have macros enabled, some are lock for editing etc. I am able to handle most of those errors, except for one.

A similar problem that I am having can be found on this link (except for the fact that I am converting into TXT): Microsoft Interop saveAs command failed

Here is my problem; I get an error once every 25 - 35 minutes. And something is in that library, that catches the error and generates a POP-UP saying "An error was encountered with the file. Command Failed", and the pop-up has only an 'OK' BUTTON.

When that warning message window pops up, the program pauses until someone manually hits 'RETURN', or click on the 'OK' button.

How can I write a program that runs in the background and simulates someone pressing the RETURN button? This way the pop-up generated within the command line will be gone, and my program resumes.

class Program
{

    public static object refTrue = true;
    public static object refFalse = false;
    public static object refMissing = Type.Missing;

    static void Main(string[] args)
    {

        Word._Application word = null;
        Word.Documents documents;
        string dirpath = "C:\\Blobs\\directory\\";

        String msserver = "SERVER";
        String msdatabase = "DB";
        String msconnstring = String.Format("Data Source={0};Trusted_Connection=yes;Database={1};MultipleActiveResultSets=true", msserver, msdatabase);

        using (System.Data.SqlClient.SqlConnection con = new System.Data.SqlClient.SqlConnection(msconnstring))
        {
            //open connection
            con.Open();
            System.Data.SqlClient.SqlCommand cmdtest = con.CreateCommand();
            cmdtest.CommandText = "select f.filenamedoc from dbo.tb_worddtl_txt_ f left join  dbo.tb_worddtl_txt p on f.filenamedoc = p.filenamedoc where p.filenamedoc is null ";
            cmdtest.CommandType = CommandType.Text;
            cmdtest.CommandTimeout = 60;

            List<string> Filestoprocesstest = new List<string>();

            SqlDataReader missingFiles = cmdtest.ExecuteReader();

            while (missingFiles.Read())
            {
                Filestoprocesstest.Add(missingFiles[0].ToString().Trim());
            }

            //Will process missing files:
            foreach (string value in Filestoprocesstest)
            {
                Console.WriteLine(value);

                word = new Word.Application();
                documents = word.Documents;

                String file2p = dirpath.Trim() + value.Trim();

                Object filename = file2p;
                object newRefTargetFile = file2p.Replace(".doc", ".txt");

                if (File.Exists(file2p))
                {
                /** converts .DOC into .TXT **/
                    try
                    {
                        Word.Document document = documents.OpenNoRepairDialog(
                               ref filename,
                               ref refTrue,
                               ref refFalse,
                               ref refFalse,
                               ref refMissing,
                               ref refMissing,
                               ref refMissing,
                               ref refMissing,
                               ref refMissing,
                               ref refMissing,
                               ref refMissing,
                               ref refTrue,
                               ref refFalse,
                               ref refMissing,
                               ref refMissing,
                               ref refMissing);

                        if (document == null)
                            throw new Exception("Could not read " + filename);

                        word.Visible = false;
                        word.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone;

                        object wdFormatDOSText = Word.WdSaveFormat.wdFormatDOSText;

                        word.Options.SavePropertiesPrompt = false;
                        word.Options.SaveNormalPrompt = false;

                        word.ActiveDocument.SaveAs(ref newRefTargetFile, ref wdFormatDOSText,
                            ref refMissing, ref refMissing, ref refMissing,
                            ref refMissing, ref refMissing, ref refMissing,
                            ref refMissing, ref refMissing, ref refMissing,
                            ref refMissing, ref refMissing, ref refMissing,
                            ref refMissing, ref refMissing);

                        word.Quit();
                        Thread.Sleep(500);
                        word = null;
                    }
                    catch (System.Runtime.InteropServices.COMException exception)
                    {
                        Console.WriteLine("An error was encountered with file: " + exception.Message);
                    }
                    finally
                    {
                        if (word != null)
                        {
                            word.Quit();
                        }
                        word = null;
                    }

                    /** Reads TXT **/
                    String filecontents = "";
                    try
                    {
                        using (StreamReader sr = new StreamReader((String)newRefTargetFile))
                        {
                            filecontents += sr.ReadToEnd();
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("The file could not be read:");
                        Console.WriteLine(e.Message);
                    }

                    /** Inserts TXT back into Database **/
                    System.Data.SqlClient.SqlCommand cmd = con.CreateCommand();
                    cmd.CommandText = "Insert into dbo.tb_worddtl_txt values (@filename, @sourcefile, @filetext)";
                    cmd.CommandType = CommandType.Text;
                    cmd.CommandTimeout = 60;

                    System.Data.SqlClient.SqlParameter param = cmd.Parameters.Add("@filename", SqlDbType.Text);
                    param.Value = file2p.Substring(20).Replace("doc", "txt");
                    param.Direction = ParameterDirection.Input;

                    param = cmd.Parameters.Add("@sourcefile", SqlDbType.Text);
                    param.Direction = ParameterDirection.Input;
                    param.Value = value;

                    param = cmd.Parameters.Add("@filetext", SqlDbType.Text);
                    param.Direction = ParameterDirection.Input;
                    param.Value = filecontents;

                    Console.Write("Processed: " + filename + "\r\n");

                    cmd.ExecuteNonQuery();
                }

            }

            con.Close();
            //OdbcConn.Close();
        }
Community
  • 1
  • 1
Salva
  • 312
  • 2
  • 11
  • 1
    Have a look at either [Options.WarnBeforeSavingPrintingSendingMarkup](http://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.options.warnbeforesavingprintingsendingmarkup(v=office.14).aspx) or [Application.DisplayAlerts](http://msdn.microsoft.com/en-us/library/microsoft.office.interop.word._application.displayalerts(v=office.14).aspx) – Adriaan Stander Dec 13 '14 at 04:23
  • 1
    I may sound very lame here. Are you talking about this line of code MessageBox.Show("An error was encountered with file: " + exception.Message);? If so, just remove this line. – Ahuman Dec 13 '14 at 04:58
  • In fact, I put that line trying to work around with the message. My program does not have that line. I will fix it. -- And I know it, because the ": " does not appear in the pop up window. – Salva Dec 13 '14 at 05:04
  • You would actually be better to use something like [AutoHotKey](http://www.autohotkey.com/) rather then write logic in a program to do this. – Icemanind Dec 15 '14 at 22:20

2 Answers2

1

You can use the SendKeys class

SendKeys.Send("{ENTER}");

you can have a look at the msdn for more info

Patrick
  • 736
  • 9
  • 27
  • 1
    This is sort of half an answer.... he won't be able to just use that method.... from a shell. I would also take a strong look at this solution.... you will need to point your key strokes at a specific window. http://stackoverflow.com/questions/2604898/net-sendkeys-to-calculator – Scott Stevens Dec 13 '14 at 04:36
1

I figured out the problem. After trying to quit Word instance with word.Quit();, the process WINWORD.EXE was still running in the background. Some Word Documents had VB Macros with them and some others used MS Word extension (.dot), that caused WINWORD.EXE process instances not to be released, and some cases it generated pop ups (such as the one described above, and some others like "Do you want to modify the .dot extension"). Also, when I physically opened Word, I had documents "Saved from the last session". Basically, all my problems went away when used the line Marshal.ReleaseComObject(documents); after quitting MS Word. This line released the WINWORD.EXE instance process for that iteration, and my program is running very smooth.

finally
{
    if (word != null)
    {
        word.Quit();
    }
    word = null;
}

Marshal.ReleaseComObject(documents);
Salva
  • 312
  • 2
  • 11