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