0

I am trying to process a folder (or even one) Word.docx files from C#. I have lots of C# code that works with OPEN word documents, but I have never tried to open a Word document programmatically in C#.

The code below is simple, and behaves the same as a standalone Windows Form app or running under a Visual Studio test case as shown below. The problem is that the code (or Word) copies the original Word document (which comes from a Trusted Location in the Trust Center options of Word) into a temp folder (shown in the code). The folder of Word documents contains documents that have many internal styles and macros.

Am I doing something wrong in my code? Is there any way to open Word documents (with macros in them) in C# so that I can process them using C#? (In this case, the processing is simply to export them as PDFs, but I do frequently use C# to perform operations on open Word docs.)

I have seen many other questions here on SO about opening Word docs using C#, but none of them talk about macros, security, trusted locations, or overcoming the issue I am facing with a temporary file location. A Microsoft Security Warning notice pops up and requires manual intervention, which won't really work for the automated processing of a folder of files.

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Application = Microsoft.Office.Interop.Word.Application;  // MS Word 16.0 Object Library

namespace HsMicrophoneTests;

[TestClass]
public class WordPdfTests
{
 
  [TestMethod]
  public void MakePdf() {
    var folder = @"h:\my\folder";
    var docName = "MyWord Document.docx";
    var nameNoSuffix = docName.FilenameNoSuffix();
    var docPath = Path.Combine(folder, docName);
    var pdfPath = Path.Combine(folder, $"{nameNoSuffix}.pdf");

    // this dies because Word disables macros from untrusted locations
    // C:\Users\me\AppData\Local\Microsoft\Windows\INetCache\Content.Word\~WRC3582.tmp
    // var appWord = new Application();

    // UPDATE: This works to open Word itself. Then connecting to it
    // through COM and asking it to open my document might work.
    // var exePath = @"C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE";
    // Process.Start(exePath);

    // UPDATE 2 - Start Word manually and then automate the docs
    // Assume: Word is running. Get a reference to the running instance.
    var wapp = Marshal2.GetActiveObject("Word.Application") as Application;

    // These lines could be in a loop to process all docs in a folder.
    var wordDocument = wapp.Documents.Open(wordPath);
    wordDocument.ExportAsFixedFormat("foo.pdf", WdExportFormat.wdExportFormatPDF);
    wapp.ActiveDocument.Close(null); // ** do not save changes

    // appWord.Quit();
  }
}


// MARSHAL2
///   My Marshal2 code came from the Microsoft reference code on GitHub,
///   via the StackoverFlow post here
///   https://stackoverflow.com/questions/58010510/
///   no-definition-found-for-getactiveobject-from-system-runtime-interopservices-mars
///   in response to my question here
///   https://stackoverflow.com/questions/70483656
///   /net-5-replacement-for-marshall-getactiveobject-in-net-framework
Kevin
  • 1,548
  • 2
  • 19
  • 34
  • 2
    Read this: https://learn.microsoft.com/en-us/office/client-developer/integration/considerations-unattended-automation-office-microsoft-365-for-unattended-rpa. You can't expect Office apps to ever run unattended successfully. You can open the documents (using the OpenXML SDK, fie example), but not using Office apps – Flydog57 Mar 26 '23 at 17:40
  • Here's another one: [Considerations for server-side Automation of Office](https://support.microsoft.com/en-us/topic/considerations-for-server-side-automation-of-office-48bcfe93-8a89-47f1-0bce-017433ad79e2) – Tu deschizi eu inchid Mar 26 '23 at 17:51
  • Thank you for that link - it was right on target for general unattended automation, especially for automation that involves multiple clients, servers, and so on. I had hoped to find a way (as a single client, on a single machine, working with trusted documents in trusted folders) to programmatically start Word from C#. Note that the security warning comes from Word itself before it ever sees the pathname to load. Probably the Normal.dot has macros that trigger Word? But I use Word all the time with my Normal.dot... – Kevin Mar 26 '23 at 17:51
  • 100% I would use OpenXML – Leandro Bardelli Mar 26 '23 at 20:19
  • Thank you, everyone. The problem to solve is bigger than just PDFs. I just chose the PDF operation as a simple example for this post. The bigger problem involves calling the macros inside the documents to do various things. Thus OpenXML won't work either - I need to have Word alive and working to do the operations. At least for my problems, starting Word with Process.Start() and then connecting to it via COM lets me do what I need to do. – Kevin Mar 27 '23 at 03:24

0 Answers0