2009-01-06 23 views
6

Estoy usando un servicio de Windows y quiero imprimir una página .html cuando se inicie el servicio. Estoy usando este código y está imprimiendo bien. Pero aparece un cuadro de diálogo de impresión, ¿cómo puedo imprimir sin el cuadro de diálogo Imprimir?Imprimir documento html desde el Servicio de Windows en C# sin imprimir el cuadro de diálogo

public void printdoc(string document) 
{ 
    Process printjob = new Process(); 
    printjob.StartInfo.FileName = document; 
    printjob.StartInfo.UseShellExecute = true; 
    printjob.StartInfo.Verb = "print"; 
    printjob.StartInfo.CreateNoWindow = true; 
    printjob.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; 

    printjob.Start(); 
} 

¿Hay alguna otra manera de imprimir esto sin mostrar el cuadro de diálogo de impresión?

Gracias de antemano, Anup Pal

+0

UseShellExecute y CreateNoWindow se contradicen entre sí en este caso. Solo puedes configurar uno de ellos. Para imprimir documentos en lugar de iniciar programas, UseShellExecute debe ser verdadero. –

Respuesta

-1

En servicio de Windows el control del navegador web de Microsoft no está funcionando. Había usado ese código, funciona bien en la aplicación de Windows, pero cuando estoy usando un servicio de Windows, el programa se atasca en esta línea

axWebBrowser1.Navigate (@ "C: \ mydoc.html", ref empty, ref vacío, ref vacío, ref vacío);

gracias por la respuesta, Anup Pal

13

Aquí está el Santo Grial.

Aprovechando StaTaskScheduler (tomado de Parallel Extension Extras (release on Code Gallery)).

Características: espera la finalización de la impresión, no muestra configuraciones de impresión, con suerte es confiable.

Limitaciones: Requiere C# 4.0, utiliza la impresora por defecto, no se deja de cambiar la plantilla de impresión

TaskScheduler Sta = new StaTaskScheduler(1); 
    public void PrintHtml(string htmlPath) 
    { 
     Task.Factory.StartNew(() => PrintOnStaThread(htmlPath), CancellationToken.None, TaskCreationOptions.None, Sta).Wait(); 
    } 

    void PrintOnStaThread(string htmlPath) 
    { 
     const short PRINT_WAITFORCOMPLETION = 2; 
     const int OLECMDID_PRINT = 6; 
     const int OLECMDEXECOPT_DONTPROMPTUSER = 2; 
     using(var browser = new WebBrowser()) 
     { 
      browser.Navigate(htmlPath); 
      while(browser.ReadyState != WebBrowserReadyState.Complete) 
       Application.DoEvents(); 

      dynamic ie = browser.ActiveXInstance; 
      ie.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER, PRINT_WAITFORCOMPLETION); 
     } 
    } 

//-------------------------------------------------------------------------- 
// 
// Copyright (c) Microsoft Corporation. All rights reserved. 
// 
// File: StaTaskScheduler.cs 
// 
//-------------------------------------------------------------------------- 

using System.Collections.Concurrent; 
using System.Collections.Generic; 
using System.Linq; 

namespace System.Threading.Tasks.Schedulers 
{ 
    /// <summary>Provides a scheduler that uses STA threads.</summary> 
    public sealed class StaTaskScheduler : TaskScheduler, IDisposable 
    { 
     /// <summary>Stores the queued tasks to be executed by our pool of STA threads.</summary> 
     private BlockingCollection<Task> _tasks; 
     /// <summary>The STA threads used by the scheduler.</summary> 
     private readonly List<Thread> _threads; 

     /// <summary>Initializes a new instance of the StaTaskScheduler class with the specified concurrency level.</summary> 
     /// <param name="numberOfThreads">The number of threads that should be created and used by this scheduler.</param> 
     public StaTaskScheduler(int numberOfThreads) 
     { 
      // Validate arguments 
      if (numberOfThreads < 1) throw new ArgumentOutOfRangeException("concurrencyLevel"); 

      // Initialize the tasks collection 
      _tasks = new BlockingCollection<Task>(); 

      // Create the threads to be used by this scheduler 
      _threads = Enumerable.Range(0, numberOfThreads).Select(i => 
      { 
       var thread = new Thread(() => 
       { 
        // Continually get the next task and try to execute it. 
        // This will continue until the scheduler is disposed and no more tasks remain. 
        foreach (var t in _tasks.GetConsumingEnumerable()) 
        { 
         TryExecuteTask(t); 
        } 
       }); 
       thread.IsBackground = true; 
       thread.SetApartmentState(ApartmentState.STA); 
       return thread; 
      }).ToList(); 

      // Start all of the threads 
      _threads.ForEach(t => t.Start()); 
     } 

     /// <summary>Queues a Task to be executed by this scheduler.</summary> 
     /// <param name="task">The task to be executed.</param> 
     protected override void QueueTask(Task task) 
     { 
      // Push it into the blocking collection of tasks 
      _tasks.Add(task); 
     } 

     /// <summary>Provides a list of the scheduled tasks for the debugger to consume.</summary> 
     /// <returns>An enumerable of all tasks currently scheduled.</returns> 
     protected override IEnumerable<Task> GetScheduledTasks() 
     { 
      // Serialize the contents of the blocking collection of tasks for the debugger 
      return _tasks.ToArray(); 
     } 

     /// <summary>Determines whether a Task may be inlined.</summary> 
     /// <param name="task">The task to be executed.</param> 
     /// <param name="taskWasPreviouslyQueued">Whether the task was previously queued.</param> 
     /// <returns>true if the task was successfully inlined; otherwise, false.</returns> 
     protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) 
     { 
      // Try to inline if the current thread is STA 
      return 
       Thread.CurrentThread.GetApartmentState() == ApartmentState.STA && 
       TryExecuteTask(task); 
     } 

     /// <summary>Gets the maximum concurrency level supported by this scheduler.</summary> 
     public override int MaximumConcurrencyLevel 
     { 
      get { return _threads.Count; } 
     } 

     /// <summary> 
     /// Cleans up the scheduler by indicating that no more tasks will be queued. 
     /// This method blocks until all threads successfully shutdown. 
     /// </summary> 
     public void Dispose() 
     { 
      if (_tasks != null) 
      { 
       // Indicate that no new tasks will be coming in 
       _tasks.CompleteAdding(); 

       // Wait for all threads to finish processing tasks 
       foreach (var thread in _threads) thread.Join(); 

       // Cleanup 
       _tasks.Dispose(); 
       _tasks = null; 
      } 
     } 
    } 
} 
+0

¿Cómo nadie ha votado aún? ¡Esto funciono muy bien para mi! – JasonRShaver

+0

¿De dónde viene la "Tarea"? –

+0

https://msdn.microsoft.com/en-us/library/system.threading.tasks.task(v=vs.110).aspx –

1

Para añadir a la limitación de Vadim puede configurar la impresora predeterminada antes de imprimir mediante el uso de:

static void SetAsDefaultPrinter(string printerDevice) 
    { 
     foreach (var printer in PrinterSettings.InstalledPrinters) 
     { 
      //verify that the printer exists here 
     } 
     var path = "win32_printer.DeviceId='" + printerDevice + "'"; 
     using (var printer = new ManagementObject(path)) 
     { 
      printer.InvokeMethod("SetDefaultPrinter", 
           null, null); 
     } 

     return; 
    } 

Y changeing ligeramente el método PrintHtml con:

public void PrintHtml(string htmlPath, string printerDevice) 
    { 
     if (!string.IsNullOrEmpty(printerDevice)) 
      SetAsDefaultPrinter(printerDevice); 


     Task.Factory.StartNew(() => PrintOnStaThread(htmlPath), CancellationToken.None, TaskCreationOptions.None, _sta).Wait(); 
    } 

Ahora no sé h Esto será justo en un entorno de impresión pesado, ya que podría haber problemas de concurrencia al cambiar mucho la impresora predeterminada. Pero hasta ahora esto es lo mejor que se me ocurrió para arreglar esta limitación.

Cuestiones relacionadas