Hidden run of a third party application (silent print from Adobe Reader)

I would like to run a third party application (Adobe Reader 9) completely hidden, without displaying the splash screen, application window, taskbar button etc.

The background story: I have to print PDF files from my application, the Adobe Reader 9 with the /t command line switch does it fine, but the Reader window pops up while printing, which is very annoying and unprofessional (the same thing happens with the ActiveX control). I didn't consider using third party PDF applications (as recommended on Experts-Exchange before) due to various reasons (press quality transparency flattening is needed, done well only by Adobe products).

Therefore the only solution I see is to manage somehow to hide the Reader window. Here are the things I've tried so far:

1. CreateProcess with the SW_HIDE switch specified -- works fine with other apps, Adobe ignores it.

2. Calling ShowWindow(Handle, SW_HIDE) right after the Reader window is created (I have even installed a shell hook for that), but the window appears for a moment on the screen, of if called with the /t switch, it even stays there until the print operation completes (apparently the message loop is blocked while it prints).

3. Starting it as a different user: the window will still appear on the active desktop.

My further ideas are to launch Reader on a different desktop or a different window station, but Ive never used them before and have no idea whether they will work or not. Any other ideas for hiding Acrobat or printing silently in any other way are welcome.
biroadamAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

2266180Commented:
use createprocess and in the startupinfo structure use the dwX and dwY members to move the window out of the screen.

not tested, and it might not work, because it could be that the splash window is created after the main window and displayed before it.

if this is indeed the case, then the only practical solution would be to hook showwindow api function and not show that window at all :)
there might be other workable solutions too, but it all depends on how the slash screen is created and whether some values are forced or not in that window.
0
biroadamAuthor Commented:
Hi Ciuly,

Thanks for the comment. The results:

1. dwX and dwY members are ignored, the Reader uses instead he position values saved in the registry (in a key called SDI). Setting these values out of the screen has no effect, it will take care to keep the window entirely on the screen.

2. "Hook showwindow api function and not show that window at all" -- how exactly would you do this? As I said, I managed to install a shell hook that notified me when the Acrobat window has been created, but I couldn't see a way to block displaying the window.

3. Don't worry about the splash screen, there is a bDisplayedSplash registry item, setting it to 1 will hide it (it only appears on the first launch after installation anyway, as far as I see).

So we should concentrate on hiding the main form or displaying it somewhere (other desktop, other window station) where nobody can see it. Any suggestions?

Regards,
Adam
0
2266180Commented:
can you give me more info on 2) ? like what things you have available in your callback function. if you have access to the windows handle right after creation and before displaying it, then you can move that off screen.

my hook idea requires code injection. I'd leave that as a last resort.
0
Fundamentals of JavaScript

Learn the fundamentals of the popular programming language JavaScript so that you can explore the realm of web development.

swiatloCommented:
I had the same problem. Poping up Acrobat at printing PDF.
Because I had to print a batch of PDF I have noticed that acrobat stays/displays itself only for the first document in the loop. Other documents from the batch went behind. I can imagnie that could be some sort of a trace to investigate.
I had to rewrite the part of my application that generated PDF, to print directly to the file instead, and then I printed that file not PDF. But I have a control over it and you seem to be fixed with PDF, don't you.
0
biroadamAuthor Commented:
Hi everyone,

It seems that in the meanwhile I've found the solution, though it needs a bit more work. My multiple desktop idea seems to work fine: I create a new desktop called 'HideAcrobat', and will create the Acrobat process on that desktop. The result: there is absolutely no interaction with the current desktop, not even the printer icon will appear in the system tray (which would have happened if I would have just hide the main window).

The code is something like this:

procedure SilentPrint(FileName, PrinterName: string);
var Desk: cardinal; si: TStartupInfo; pi: TProcessInformation; AcrobatCmd: string;
begin
  AcrobatCmd := '"C:\Program Files\Adobe\Reader 9.0\Reader\AcroRd32.exe" /t "' +
    FileName + '" ' + PrinterName;
  Desk := Windows.CreateDesktop(PChar('HideReader'), nil, nil, 0, MAXIMUM_ALLOWED, nil);
  zeromemory(@si, sizeof(si));
  si.cb := SizeOf(TStartupInfo);
  si.lpDesktop := 'HideReader';
  CreateProcess(nil, pchar(AcrobatCmd), nil, nil, false, 0, nil, nil, si, pi);
  ... then wait for the file to be printed, close the Reader, and close the desktop
end;

The solution isn't yet 100% working, we're experiencing the following problems:

1. If there is a Reader already running on the current desktop, a second Reader will be started on the second desktop, but won't print.

2. While a Reader prints on the second desktop, the Reader cannot be started on the current desktop.

3. If I don't close the reader on the second desktop, then the next print operation will crash -- the only cure for this seems to be to close the Reader after printing.

4. On Vista Home Basic, the CreateDesktop function will only work after a registry key is defaulted (see MSDN documentation of CreateDesktop).

Possible idea to cure problems 1-3: to start the Reader not just on a different desktop, but also as a different user.

Any ideas, comments, test results are welcome.

Regards,
Adam
0
biroadamAuthor Commented:
Hi everyone,

I have developed a solution that seems to work perfectly: Acrobat Reader will print in the background, without affecting instances opened in the user accounts. The difference from the solution presented above is that the Reader runs not just on a different desktop, but also in the SYSTEM account, this will ensure that it will have no interference with other Reader instances running in user accounts. The Reader in the System account uses a different set of settings, and can be started-stopped independently from the Reader instances running in user accounts.

Here is what has to be done:

1. To get consistent results that do not depend on the current user settings of the Reader (e.g. fit to page), the registry settings of Acrobat Reader needs to be copied into the .DEFAULT user (which is used by the SYSTEM account), and then modified according to your needs (e.g. fit to page turned off). You may also set the \AdobeViewer\Launched value to TRUE (to avoid first time launch problems).
Source:
HKEY_CURRENT_USER\Software\Adobe\Acrobat Reader\9.0
Destination:
HKEY_USERS\.DEFAULT\Software\Adobe\Acrobat Reader\9.0.

2. Set up printers for the SYSTEM account, so then applications running in the system account can use the printers installed in the system. For this, you'll have to copy three registry keys:
Source:
HKEY_CURRENT_USER\Software\Microsoft\Windows NT\Current Version\Devices
HKEY_CURRENT_USER\Software\Microsoft\Windows NT\Current Version\PrinterPorts
HKEY_CURRENT_USER\Software\Microsoft\Windows NT\Current Version\Windows
Destination:
HKEY_USERS\.DEFAULT\Software\Microsoft\Windows NT\Current Version\Devices
HKEY_USERS\.DEFAULT\Software\Microsoft\Windows NT\Current Version\PrinterPorts
HKEY_USERS\.DEFAULT\Software\Microsoft\Windows NT\Current Version\Windows.

3. Restart the spooler:
command line: "net stop spooler /y", then "net start spooler".

4. Run the following code FROM THE SYSTEM ACCOUNT(!):

procedure SilentPrint(FileName, PrinterName: string);
var Desk: cardinal; si: TStartupInfo; pi: TProcessInformation; AcrobatCmd: string;
begin
  AcrobatCmd := '"C:\Program Files\Adobe\Reader 9.0\Reader\AcroRd32.exe" /t "' +
    FileName + '" ' + PrinterName;
  Desk := Windows.CreateDesktop(PChar('HideReader'), nil, nil, 0, MAXIMUM_ALLOWED, nil);
  zeromemory(@si, sizeof(si));
  si.cb := SizeOf(TStartupInfo);
  si.lpDesktop := 'HideReader';
  CreateProcess(nil, pchar(AcrobatCmd), nil, nil, false, 0, nil, nil, si, pi);
end;

The safest way to run the Reader from the system account is to install a system service, and then run the code above from that system service. It will do the job even from Vista with UAC. You can send the parameters (FileName and PrinterName) through a mailslot from your application.

I hope it will be useful.

Regards,
Adam
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
ContactRKCommented:
not soloved our problem.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.