• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2456
  • Last Modified:

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.
0
biroadam
Asked:
biroadam
1 Solution
 
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
Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
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
 
ContactRKCommented:
not soloved our problem.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now