2009-01-06 18 views
6

Używam usługi systemu Windows i chcę wydrukować stronę .html, gdy usługa zostanie uruchomiona. Używam tego kodu i dobrze się drukuje. Ale pojawia się okno dialogowe drukowania, w jaki sposób mogę drukować bez okna dialogowego drukowania?Wydrukuj dokument HTML z usługi systemu Windows w języku C# bez okna dialogowego drukowania

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(); 
} 

Istnieje inny sposób drukowania tego bez wyświetlania okna dialogowego drukowania.

Dzięki z góry, Anup Pal

+0

W tym przypadku UseShellExecute i CreateNoWindow zaprzeczają sobie nawzajem. Możesz ustawić tylko jedną z nich. Aby drukować dokumenty, a nie uruchamiać programy, parametr UseShellExecute musi być prawdziwy. –

Odpowiedz

-1

W usługi windows kontrola przeglądarki internetowej Microsoft nie pracuje. Użyłem tego kodu, który działa dobrze w aplikacji Windows, ale kiedy używam w usłudze Windows, program utknął w tej linii

axWebBrowser1.Navigate (@ "C: \ mydoc.html", ref puste, ref pusty, ref pusty, ref pusty);

dzięki za odpowiedzi, Anup Pal

13

Oto Święty Graal.

Wykorzystanie funkcji StaTaskScheduler (pobranej z dodatków rozszerzenia równoległego (release on Code Gallery)).

Funkcje: czeka na zakończenie drukowania, nie wyświetla ustawień drukowania, miejmy nadzieję, że jest niezawodny.

Ograniczenia: wymaga C# 4.0, wykorzystuje drukarkę domyślną, nie pozwala, aby zmienić szablon drukującej

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

Jak nikt jeszcze nie wznowił tego? To zadziałało dla mnie świetnie! – JasonRShaver

+0

Skąd pochodzi "zadanie"? –

+0

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

1

Aby dodać do ograniczenia Vadima można ustawić domyślną drukarkę przed drukowaniem za pomocą:

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

I zmiana spowoduje lekko metodę PrintHtml z:

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


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

teraz nie wiem h O to będzie sprawiedliwe w ciężkim środowisku drukowania, biorąc pod uwagę, że mogą pojawić się problemy z współbieżnością z dużą zmianą domyślnej drukarki. Ale jak dotąd to najlepsze, co wymyśliłem, aby naprawić to ograniczenie.

Powiązane problemy