0

I am developing an automation tool which is reading the file path from an Excel workbook and after launching the application I am firing print job using SendKeys.SendWait() for Ctrl+P and Enter key. Now the Problem is, I am facing synchronization issue for launching the application and handling the print procedure keys. Sometimes Applications are launching little late(like Excel and MsWord files), so at that time I am not able to find till how long I have to wait for a successful launch of the Application. Anybody have any Idea how to check this waiting time till how long I should wait to fire CTRL+P and then after getting PrintDialog ENTER button ?

Any help will be appreciate. Thanks in advance.

SharpUrBrain
  • 3,180
  • 5
  • 38
  • 56
  • How about something like this: [http://stackoverflow.com/questions/854693/printing-excel-using-interop][1] [1]: http://stackoverflow.com/questions/854693/printing-excel-using-interop – Douglas Anderson Oct 21 '11 at 16:39
  • yes, Its cool. But still here we are only printing Excel worksheet, what about to make printing for all kind of documents like pdf, msWord etc... – SharpUrBrain Oct 24 '11 at 05:34

2 Answers2

2

I initially read the question as only printing MS type files. If you want to print all kinds of files then I would first leverage Windows 'PrintTo' function.

You can call the commands directly by searching the Registry for PrintTo and you should see commands for PrintTo and also Print. Hit the web for specifics for each application.

The other option that is probably the simplest is to use the PrintTo verb with ShellExecute and let Windows handle the behind the scenes.

System.Diagnostics.Process print = new System.Diagnostics.Process();
print.StartInfo.FileName = @"c:\test\test.pdf";
print.StartInfo.Verb = "PrintTo";
print.StartInfo.CreateNoWindow = True;
print.StartInfo.Arguments = printerName;
print.StartInfo.UseShellExecute = True;
print.Start();
print.WaitForExit();

PrintTo should allow you to specify the printer while the verb "Print" should just send to the default device.

Keep in mind that not all filetypes support these verbs.

Douglas Anderson
  • 4,652
  • 10
  • 40
  • 49
  • +1 for prividing the solution and not just answering the question. – Wesley Long Oct 24 '11 at 14:11
  • @Douglas Anderson: Thanks a lot for the help, but it will print directly, which I do not want. I want to open the application and handle the "Print" button of the Print dialogue. – SharpUrBrain Oct 24 '11 at 14:49
  • @SharpUrBrain: So you want to Print Dialog to come up and then press Enter? Doesn't this achieve the same result? Or do you want the user to then intervene? – Douglas Anderson Oct 24 '11 at 15:14
  • @Douglas Anderson: No, it doesn't achieve same result because I am hooking the printer driver for getting print info to update one xml file, So if I am printing the document directly then I am not able to hook the printer driver and I am not able to get the Print info. And also I am not able to lunch web application and print them too. – SharpUrBrain Oct 24 '11 at 15:33
  • am using this for "print to pdf", so is there a way to suppress the save dialog box? – Sid133 May 18 '22 at 15:29
0

In order to determine whether or not the application to automate is ready to accept user input (key strokes) you have to search for the window of the application processing the key strokes you will send. There is quite a bit interop necessary to accomplish the task. Below you will find a small example automating the task of printing an excel document (all error handling details omitted). I've copied the interop signatures from pinvoke.net.

First, let me describe the necessary steps:

  1. Search for the excel main window using the class name of the excel main window. Use a tool like spy++ to determine the class name.
  2. Bring the excel main window to the foreground.
  3. Send CTRL+C to the main window to open the print dialog.
  4. Wait for the print dialog to appear.
  5. Send ENTER to the print dialog.

Second, let me show you a small code example:

private enum WindowShowStyle : uint    
{     
  Hide = 0,
  ShowNormal = 1,
  ShowMinimized = 2,
  ShowMaximized = 3,
  Maximize = 3,
  ShowNormalNoActivate = 4,
  Show = 5,
  Minimize = 6,
  ShowMinNoActivate = 7,
  ShowNoActivate = 8,
  Restore = 9,
  ShowDefault = 10,
  ForceMinimized = 11
}

[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, WindowShowStyle nCmdShow);

[DllImport("user32.dll")]
private static extern bool BringWindowToTop(IntPtr hWnd);

[DllImport("kernel32.dll")]
private static extern uint GetCurrentThreadId();

[DllImport("user32.dll")]
private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);

[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();       

[DllImport("user32.dll", SetLastError = true)]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

private static void BringWindowToForeground(IntPtr hWnd)
{
  uint foregroundThread, currentThread;

  uint pid;
  foregroundThread = GetWindowThreadProcessId(GetForegroundWindow(), out pid);
  currentThread    = GetCurrentThreadId();

  if (foregroundThread != currentThread)
  {
    AttachThreadInput(foregroundThread, currentThread, true);

    BringWindowToTop(hWnd);
    ShowWindow(hWnd, WindowShowStyle.ShowMaximized);                
    AttachThreadInput(foregroundThread, currentThread, false);
  }
  else
  {
    BringWindowToTop(hWnd);
    ShowWindow(hWnd, WindowShowStyle.ShowMaximized);
  }
}

private void button1_Click(object sender, EventArgs e)
{
   // Find excel window.
   IntPtr hWnd;
   while (true) 
   {
     hWnd = FindWindow("XLMAIN", null); // XLMAIN is the class name
                                        // of the main excel window.
     if (hWnd != IntPtr.Zero)
       break;
   }

   BringWindowToForeground(hWnd);
   SendKeys.SendWait("^p"); // Send CTRL+P to main excel window

   // Find print dialog.
   while (true)
   {
     hWnd = FindWindow("bosa_sdm_XL9", null); // bosa_sdm_XL9 is the class name
                                              // of the print dialog.
     if (hWnd != IntPtr.Zero)
       break;
   }

   BringWindowToForeground(hWnd);

   SendKeys.SendWait("~"); // Send ENTER to print dialog.
 }

The button_click methods includes the steps to wait for the Excel windows to appear. If the specified window is found the keys are sent.

Hope, this helps.

Hans
  • 12,902
  • 2
  • 57
  • 60