Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent child process from creating visible windows?

I'm trying to use Office Automation (PIA) to convert some .pptx documents into some other formats. However, PowerPoint insists on showing a progress bar even the main window is hidden.

Is there any way I can prevent PowerPoint from ever displaying any Windows to the main desktop?

Extra information:

I am mainly using C#, COM PIA for Office interop. But I'm not afraid to dig into C++ :P

I start PowerPoint using PIA like this

var app = new PowerPoint.Application();
var ppt = app.Presentations.Open("my.pptx");

// This line will show a progress dialog
ppt.SaveAs("out.pdf",
    PowerPoint.PpSaveAsFileType.ppSaveAsPDF,
    MsoTriState.msoTrue);

app.Quit();
like image 789
kizzx2 Avatar asked Oct 12 '22 15:10

kizzx2


2 Answers

You can use the CreateDesktop call to create an alternate desktop before invoking the powerpoint process. This will ensure that windows created by powerpoint are not visible. However, there are a number of caveats here:

  • You will need to do this in an alternate thread; you do not want to change the desktop on your main GUI thread
  • It's probably best to initialize powerpoint once, on a dedicated thread with an alternate desktop, and keep it on that same thread until you terminate. This ensures it won't be confused by being called from multiple desktops.
  • If powerpoint pops up any kind of dialog, the user will not be able to answer it unless you switch them to the alternate desktop to interact with powerpoint.
  • If powerpoint is an out-of-process server, bad things may happen (powerpoint loads on alternate desktop, then user tries to open powerpoint manually, at which point powerpoint's main UI loads on the invisible alternate desktop). This is probably something you'll need to test carefully. This problem may be avoidable by creating an alternate Window Station as well, but as window stations are process-global, you'd need to spawn a helper child process to deal with interactions with powerpoint in this case.

You could also try using a Windows Message Hook to determine when the window is created and keep it invisible. This also has a number of caveats:

  • You'll have to find some reliable way of identifying the window of interest (window class name?)
  • If powerpoint is an out-of-process server, there will be a window in which your hook is active and might hide the wrong progress dialog (ie, one belonging to another process). To minimize this chance, test to see if powerpoint is in-process (in which case program the hook to only affect your own process), and if not, arrange for the hook to only be active for the minimum amount of time necessary to suppress the progress window.
  • Future powerpoint releases may break whatever method you use to identify the window of interest. There's little you can do about this one.
like image 186
bdonlan Avatar answered Oct 21 '22 02:10

bdonlan


You can try to leave Application.Visible property with it's default value and pass MsoTriState.msoFalse to WithWindow paremeter when you open a presentation:

var application = new Application();
var document = application.Presentations.Open(fileName, MsoTriState.msoFalse, MsoTriState.msoFalse, 
    WithWindow: MsoTriState.msoFalse);

If you explicitly set Application.Visible property to MsoTriState.msoFalse you will get "Hiding the application window is not allowed" error.

like image 39
opewix Avatar answered Oct 21 '22 03:10

opewix