Link to home
Start Free TrialLog in
Avatar of z07924
z07924

asked on

ShellExecute

how do I print a document using ShellExecute to a specific printer.(more like drag and drop) I used the following ,

x = ShellExecute(hwnd, "printto", z_file, "'Acrobat Distiller'", z_path, 0)

but this doesn't work. Anyhelp would be highly appreciated. thanks.

waiting....
ASKER CERTIFIED SOLUTION
Avatar of orbitaltech
orbitaltech

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
if you want to switch to a non default printer, you can list them in a listbox and then set the printer to the one you choose like this:

Dim prnt As Printer
For Each prnt In Printers
    List1.AddItem prnt.DeviceName
Next

to set:
Set Printer = Printers(List1.ListIndex)
Avatar of GivenRandy
GivenRandy

Another way of setting the current printer is if you know its name:

---
Dim P As Printer
   
For Each P In Printers
    If (P.DeviceName = "HP C LaserJet 4500-PS") Then
        Set Printer = P
        Exit For
    End If
Next
---
The following is a quick and dirty way to print a file:

---
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long

ShellExecute Me.hWnd, "Print", "TheFileName", 0&, 0&, vbMinimized
---
Avatar of z07924

ASKER

Comment accepted as answer
Avatar of z07924

ASKER

My default printer is something else (HP LaserJet 4M Plus). So this prints to that default printer. My objective is to print the file to a specific printer(Acrobat distiller) without changing the default printer.

any ideas to do this...thanks in advance
? But you already accepted an answer.  Did it not really answer your question?  I'm just confused.
Avatar of z07924

ASKER

This is my first time in this group. SO i didn't know how to respond to his suggestion. Sorry abt that.

Anyways, his approach didn't work because it prints to the default printer. Any ideas to print a file to a
specific printer without changing the default. thanks.
Avatar of z07924

ASKER

This is my first time in this group. SO i didn't know how to respond to his suggestion. Sorry abt that.

Anyways, his approach didn't work because it prints to the default printer. Any ideas to print a file to a
specific printer without changing the default. thanks.
z07924 - who's code did you use to enumerate the printers? I would like to give them 1/2 of the points since you used both our code...

thanks
Avatar of z07924

ASKER

to be frank, my problem is not yet solved with both the approaches.
This is what I am using. But it is always printing to the default printer...

Dim P As Printer
     
For Each P In Printers
If (P.DeviceName = "Acrobat Distiller") Then
     Set Printer = P
      Exit For
   End If
Next

x = ShellExecute(hwnd, "print", z_file, "'Acrobat Distiller'", z_path, 0)
Use AzraSound's way of doing it. Let the user select a printer to print with.

Or you use the commondialog box's print method, then pass the printer name to the shellSexcute statement

letme know how it goes.. these points are not all mine
Avatar of z07924

ASKER

Problem is it is a batch process. No user interaction.
The batch process prints some pdf files to the Acrobat distiller and finally merge all of the output files together and print it to the default printer.

The problem comes when multiple instances of this batch process starts to run....That is why I was looking for a way to print to a specific printer, without user interaction & without changing the default printer.

pleaseeeeeeeeeeeeeee help me....I really appreciate that.
well, without user interaction or a printer specified at runtime, the program doesn't kow which printer you want to print to.. Mabye you can popup a dialog box at the beginning of the programs process(if it's not an ActiveX control or DLL) to alert the user that they cannot continue until they select a printer.

Could you limit the program to only run one instance or is that not an option?
Avatar of z07924

ASKER

I know the printer name at runtime. It is always going to be "Acrobat Distiller". The problem is ShellExecute doesn't work when I specify a printer name to print. It always prints to the default printer...

>>Could you limit the program to only >>run one instance or is that not an >>option?

It is an option. This batch process is run by another another application on which I don't have any control.
so how do I do this. thanks.


For detecting multiple instances:
http://www.mvps.org/vbnet/code/system/appprevinst.htm


It prints to the defuault printer because I am sure the "Acrobat Distiller" is not the name that windows uses to define the printer.

ShellExecute will not allow you to change the printer.
What you can do it change the default printer before you print and change it back after you print.

Here's how:
http://www.mvps.org/vbnet/code/system/defprinternt.htm
Avatar of z07924

ASKER

This is exactly what I am doing. It works fine as long as you have single instance of the application. When you have multiple instances the application goes crazy and prints to the default printer at that moment...This si the problem I am having and still I don't know how to solve it...
For detecting multiple instances:
http://www.mvps.org/vbnet/code/system/appprevinst.htm 

Check this code out and let me know what comes of it. I used it in aprogram I wrote and it works great
Avatar of z07924

ASKER

I don't want to prevent multiple instances instead I want the next instance to wait for the previous instance to be over before it starts runing. Is it possible to implement within the batch process? thanks.
what kind of program is it? ActiveX control, ActiveX Exe??

Does the program automatically shutoff and close itself upon finishing the task?

How does it load?
Avatar of z07924

ASKER

It is a simple VB application. It automatically shuts off upon finishing the task. A separate application loads
this by passing parameters for each report. (that cause multiple instances...) thanks.
In the application that passes the parameters, you can use your shell execte to execute the report with parameters (which you have done) and the wait for that report to close before starting another instance. How does that sound.

-Now, declare these:
Public Const GW_HWNDFIRST = 0
Public Const GW_HWNDNEXT = 2
Public Const GW_CHILD = 5

Public Declare Function GetWindow Lib "user32" _
  (ByVal hwnd As Long, _
   ByVal wCmd As Long) As Long
 
Public Declare Function GetDesktopWindow Lib "user32" () As Long

Public Declare Function GetWindowThreadProcessId Lib "user32" _
  (ByVal hwnd As Long, _
   lpdwProcessId As Long) As Long
   

-What we can do is get the hwnd from the report's Process/Thread using the function below

Public Function GethWndFromProcessID(hProcessIDToFind As Long) As Long

    Dim hWndDesktop As Long
    Dim hWndChild As Long
    Dim hWndChildProcessID As Long
   
    On Local Error GoTo GethWndFromProcessID_Error
   
   'get the handle to the desktop
    hWndDesktop = GetDesktopWindow()
   
   'get the first child under the desktop
    hWndChild = GetWindow(hWndDesktop, GW_CHILD)
   
   'hwndchild will = 0 when no more child windows are found
    Do While hWndChild <> 0
   
       'get the ThreadProcessID of the window
        Call GetWindowThreadProcessId(hWndChild, hWndChildProcessID)
       
       'if it matches the target, exit returning that value
        If hWndChildProcessID = hProcessIDToFind Then
            GethWndFromProcessID = hWndChild
            Exit Do
        End If
       
       'not found, so get the next hwnd
        hWndChild = GetWindow(hWndChild, GW_HWNDNEXT)
       
    Loop
   
Exit Function

-Your shell execute function will look like this
Dim hProcessID As Long
Dim ReportHwnd as Long
   
   hProcessID = ShellExecute(sApplication, vbNormalFocus)
   
   ReportHwnd = GethWndFromProcessID(hProcessID)

'I don't recommend doing this loop function, but it shows you what's going on  
   Do:DoEvents:Loop Until ReportHwnd = 0

Avatar of z07924

ASKER

This idea sounds excellent. But the only bottlenech is I don't have control over the application that calls the report process. It is a third party product developed using developer 2000.
That product is customized to call this report process by passing the report number.
My only option is to play around with this report process to achieve my goal.

Can you please tell me how to detect any running applications?

I am thinking of creating a separate application that would act like a report manager to control all the report process instances. SO when the VERY first instance of the report process starts it will start the report manager. This manager inturn will look for all the instance of the report process to be over before start printing all the reports created by all the report process instances.

to do this I need to know a way to detect all the running report process from report manager application.

thanks in advance.

ok, I am confused. Can you give me a layout of how the program  interacts with your program? Which is Which?

I thought the reson you wanted the ShelLExecute function was to open the report program with parameters. you should be able to send a command to open 1 report at a time right??