7

Windows サービスを使用しており、サービスの開始時に .html ページを印刷したいと考えています。私はこのコードを使用していますが、うまく印刷されています。しかし、印刷ダイアログ ボックスが表示されます。印刷ダイアログ ボックスなしで印刷するにはどうすればよいですか?

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

印刷ダイアログボックスを表示せずにこれを印刷する他の方法があります。

前もって感謝します、Anup Pal

4

3 に答える 3

14

ここに聖杯があります。

StaTaskScheduler を利用する (Parallel Extension Extras (コード ギャラリーのリリース) から取得)。

機能: 印刷の完了を待つ、印刷設定を表示しない、できれば信頼できる。

制限: C# 4.0 が必要、既定のプリンターを使用、印刷テンプレートを変更できない

    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;
            }
        }
    }
}
于 2010-09-12T22:14:43.043 に答える
1

Vadim の制限に加えて、次を使用して、印刷する前にデフォルトのプリンターを設定できます。

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

PrintHtml メソッドを次のように少し変更します。

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


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

デフォルトのプリンターを頻繁に変更すると同時実行性の問題が発生する可能性があることを考えると、重い印刷環境でそれがどのように公平になるかはわかりません。しかし、これまでのところ、この制限を修正するために思いついたのはこれが最善です。

于 2010-10-20T04:56:16.127 に答える
-2

Windows サービスでは、Microsoft Web ブラウザ コントロールが機能していません。私はそのコードを使用していましたが、Windowsアプリケーションでは正常に動作していますが、Windowsサービス内で使用していると、プログラムがこの行で動かなくなります

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

返信ありがとう、Anup Pal

于 2009-01-06T12:58:04.770 に答える