My current PowerShell script:
$document = "C:\\test.doc"
$word = ne开发者_JAVA百科w-object -comobject word.application
$word.Visible = $false
$word.DisplayAlerts = "wdAlertsNone"
$word.AutomationSecurity = "msoAutomationSecurityForceDisable"
$doc = $word.Documents.Open($document)
$word.ActivePrinter = "\\http://ptr-server:631\pdf-printer"
$background = $false
$doc.PrintOut([ref]$background)
$doc.close([ref]$false)
$word.quit()
But it results in an alert box The macros in this project are disabled. Please refer to the online help or documentation of the host application to determine how to enable macros.
How can I open the document without it running the AutoOpen
macro or displaying any sort of dialog prompt?
Environment Details:
- Word 2003 SP3
- Windows Server 2003 R2 - Standard Edition - Service Pack 2
- Powershell Version 1.0
Turns out this is MUCH easier to do in VB.NET than in C# (which I never could figure out). But all you would need to do is create, say, a console application with a single routine. Here are the instructions:
Code
Imports word = Microsoft.Office.Interop.Word
Module Module1
Sub Main()
Dim args() As String = Environment.GetCommandLineArgs
Dim path = args(1)
Dim printer = args(2)
Dim wordApp As word.Application = New word.Application
wordApp.WordBasic.DisableAutoMacros(1)
wordApp.Visible = False
Dim doc As word.Document = wordApp.Documents.Open(path)
wordApp.ActivePrinter = printer
Dim background As Object = False
doc.PrintOut(background)
doc.Close(False)
wordApp.WordBasic.DisableAutoMacros(0)
wordApp.Quit()
End Sub
End Module
Steps to recreate solution:
- Open VS2008 and create a new Console Application in VB.NET.
- Set a reference to Microsoft.Office.Interop.Word (version 11)
- Delete any code in
Module1
and insert the code above. - Save the project and name it "wordprinter". Build the project.
- Nav to the Release folder and grab the "wordprinter.exe" and put it anywhere you like. This will be your
$wordprinterpath
. - Note the paths to your document and printer. This will be your
$doc
and$printer
, respectively. - Enter the following in PS:
$wordprinterpath = "C:\\path\\wordprinter.exe" $doc ="""C:\\Users\\me\\Documents\\Your doc.doc""" $printer = "\\http://ptr-server:631\pdf-printer" Invoke-Expression "$wordprinterpath $doc $printer" | out-Null
You should be good to go after this. I haven't tested the printing part of this, so that may need some work, but disabling of the auto-macros and opening the doc works.
The issue you're experencing is documented at KB-886633 (Nevermind that it is talking about Office for Mac - the same applies on PCs):
Additionally, if a macro tries to open a file that contains a macro, the attempt will fail if both of the following conditions are true:
- The Application.AutomationSecurity property option is set to
msoAutomationSecurityForceDisable.- The attempt to open the file is made through an Office API macro. This includes macros that are written in VBA, XLM in Excel, and WordBasic in Word.
Both bullet points apply to your script.
The only way I know to get around it is to go old-school - with WordBasic - to disable all Auto Macros (AutoOpen
, AutoExec
, etc.). Insert $word.WordBasic.DisableAutoMacros
right before $word.AutomationSecurity = "msoAutomationSecurityForceDisable"
. Note that there is no equivalant to this routine in VBA.
To disable the macros in C# I finally settled on the following and it seems to work for me..
wordApp = new Microsoft.Office.Interop.Word.Application();
wordApp.Application.AutomationSecurity = MsoAutomationSecurity.msoAutomationSecurityForceDisable;
Now I would love to be able to trigger a compile check (without sendkeys) but that is another question ;)
I do not know if this will work, just an idea: Could you download and use Wordviewer? This does not execute macros, so probably would not show a warning. However, I do not know if it can be called via API.
I tried a few different things ...
You're supposed to be able to use $word.WordBasic.DisableAutoMacros(1)
but PowerShell is miserable at COM, because you can't (really) cast to interfaces in PowerShell, and so, casting a COM object to the IDispatch interface that you need seems hopeless, and I can't see a way to do this. Brandon (BSonPosh) and I just gave up on this for a networking interface he was trying to use and resorted to Add-Type to embed some C# to make the method call in his case. That would most likely work here too...
What WOULD work (I am sure) is automating clicking on the button. You can use System.Windows.UIAutomation or the PowerShell WASP module to do that pretty simply.
Thanks for the pointers above. I was able to resolve this issue even in C# using the new dynamic feature of .NET 4. All I did was this:
var word = new Microsoft.Office.Interop.Word.Application();
word.WordBasic.DisableAutoMacros();
Obviously there is no intellisense support giving a hint for DisableAutoMacros() since WordBasic is dynamic. But this worked for me; all the error messages that popped up because of some error in some macro disappeared.
精彩评论