如何使用C#自动化一堆打印作业?

时间:2011-10-21 11:20:59

标签: c# vb.net visual-studio printing automation

我正在开发一个自动化工具,它从Excel工作簿中读取文件路径,在启动应用程序后,我使用SendKeys.SendWait() Ctrl+PEnter key使用CTRL+P启动打印作业。现在问题是,我正面临启动应用程序和处理打印过程密钥的同步问题。有时应用程序启动时间很晚(如Excel和MsWord文件),所以那时我无法找到等待成功启动应用程序多长时间。任何人都有任何想法如何检查这个等待时间,直到我等待PrintDialog,然后在获得ENTER {{1}}按钮后等待多长时间?

任何帮助都将不胜感激。提前谢谢。

2 个答案:

答案 0 :(得分:2)

我最初将该问题视为仅打印MS类型文件。如果你想打印各种文件,那么我首先会利用Windows的'PrintTo'功能。

您可以通过在Registry for PrintTo中搜索来直接调用命令,您应该看到PrintTo和Print的命令。点击网页查看每个应用程序的详细信息。

可能最简单的另一个选项是使用带有ShellExecute的PrintTo动词,让Windows处理幕后。

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应允许您指定打印机,而动词“打印”应该只发送到默认设备。

请记住,并非所有文件类型都支持这些动词。

答案 1 :(得分:0)

为了确定自动化应用程序是否已准备好接受用户输入(击键),您必须搜索处理您将发送的击键的应用程序窗口。完成任务需要相当多的互操作。下面您将找到一个自动执行打印Excel文档任务的小示例(省略所有错误处理细节)。 我已经复制了pinvoke.net的互操作签名。

首先,让我描述一下必要的步骤:

  1. 使用excel主窗口的类名搜索excel主窗口。使用像spy ++这样的工具来确定类名。
  2. 将excel主窗口置于前台。
  3. CTRL + C 发送到主窗口以打开打印对话框。
  4. 等待打印对话框出现。
  5. ENTER 发送到打印对话框。
  6. 其次,让我向您展示一个小代码示例:

    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.
     }
    

    button_click方法包括等待Excel窗口显示的步骤。如果找到指定的窗口,则发送密钥。

    希望,这有帮助。