将控制台应用程序转换为Windows服务

6

我想将生成PDF报告的控制台应用程序转换为Windows服务。我的代码如下。我是在正确的方向上吗?我安装了这个服务,启动/停止都正常,但没有生成报告!单独使用控制台应用程序可以成功地生成Output.pdf。我的目的是在服务启动时生成输出。

class Program : ServiceBase
{
    public Program()
    {
        this.ServiceName = "My PdfGeneration";
    }
    static void Main(string[] args)
    {

        ServiceBase.Run(new Program());
    }
    protected override void OnStart(string[] args)
    {
        EventLog.WriteEntry("My PdfGeneration Started");
        //base.OnStart(args);
        //Customise parameters for render method
        Warning[] warnings;
        string[] streamIds;
        string mimeType = string.Empty;   //"application/pdf";
        string encoding = string.Empty;
        string filenameExtension = string.Empty;
        string deviceInfo = "<DeviceInfo>" + "<OutputFormat>PDF</OutputFormat>" + "<PageWidth>15in</PageWidth>" + "<PageHeight>11in</PageHeight>" + "<MarginTop>0.5in</MarginTop>" + "<MarginLeft>0.5in</MarginLeft>" + "<MarginRight>0.5in</MarginRight>" + "<MarginBottom>0.5in</MarginBottom>" + "</DeviceInfo>";

        //Create a SqlConnection to the AdventureWorks2008R2 database. 
        SqlConnection connection = new SqlConnection("data source=localhost;initial catalog=pod;integrated security=True");

        //Create a SqlDataAdapter for the Sales.Customer table.
        SqlDataAdapter adapter = new SqlDataAdapter();

        // A table mapping names the DataTable.
        adapter.TableMappings.Add("View", "Route_Manifest");

        // Open the connection.
        connection.Open();
        Console.WriteLine("\nThe SqlConnection is open.");

        // Create a SqlCommand to retrieve Suppliers data.
        SqlCommand command = new SqlCommand("SELECT TOP 10 [RouteID],[FullTruckID],[DriverID],[DriverName],[StopID],[CustomerID],[CustomerName],[InvoiceID],[last_modified],[Amount] FROM [pod].[dbo].[Route_Manifest]", connection);
        command.CommandType = CommandType.Text;

        // Set the SqlDataAdapter's SelectCommand.
        adapter.SelectCommand = command;
        command.ExecuteNonQuery();

        // Fill the DataSet.
        DataSet dataset = new DataSet("Route_Manifest");
        adapter.Fill(dataset);

        //Set up reportviewver and specify path
        ReportViewer viewer = new ReportViewer();
        viewer.ProcessingMode = ProcessingMode.Local;
        viewer.LocalReport.ReportPath = @"C:\Documents and Settings\xxxxx\My Documents\Visual Studio 2008\Projects\PdfReportGeneration\PdfReportGeneration\Report.rdlc";

        //specify the dataset syntax = (datasetofreport.rdlc,querydataset); 
        viewer.LocalReport.DataSources.Add(new ReportDataSource("podDataSet_Route_Manifest", dataset.Tables[0]));


        //Now render it to pdf
        try
        {
            byte[] bytes = viewer.LocalReport.Render("PDF", deviceInfo, out mimeType, out encoding, out filenameExtension, out streamIds, out warnings);
            //output to bin directory 
            using (System.IO.FileStream fs = new System.IO.FileStream("output.pdf", System.IO.FileMode.Create))
            {
                //file saved to bin directory
                fs.Write(bytes, 0, bytes.Length);
            }
            Console.WriteLine("\n YEP!! The report has been generated:-)");

            /*           //Save report to D:\ -- later
                         FileStream fsi = new FileStream(@"D:\output.pdf", System.IO.FileMode.Create);
            */
        }
        catch (Exception e)
        {
            Console.WriteLine("\n CHEY!!!this Exception encountered:", e);
        }


        // Close the connection.
        connection.Close();
        Console.WriteLine("\nThe SqlConnection is closed.");
        Console.ReadLine();

    }
    protected override void OnStop()
    {
        EventLog.WriteEntry("My PdfGeneration Stopped");
            base.OnStop();
    }

}

关于为上述代码编写Onstart和Onstop日志记录的问题已经正确地记录到日志中。同时,render方法的日志记录“YEP!! The report has been generated:”也已被记录! - Murali Uppangala
2个回答

11

我建议您将OnStart事件中的代码移动到一个单独的线程中,因为您的服务需要及时启动,否则可能会在启动时超时。

例如:

using System.ServiceProcess;
using System.Threading;

namespace myService
{
    class Service : ServiceBase
    {
        static void Main()
        {
            ServiceBase.Run(new Service());
        }

        public Service()
        {
            Thread thread = new Thread(Actions);
            thread.Start();
        }

        public void Actions()
        {
            // Do Work
        }
    }
}

你可能还需要检查执行用户(服务运行的用户上下文)是否有权访问你正在写入的文件夹等。

同时,你还需要将错误信息写入事件日志而不是像代码片段中显示的那样写入控制台窗口(当前代码吞噬异常,这就是为什么你无法确定出错原因)。

在此处阅读更多信息:C#基础:创建Windows服务


-2

是和不是,你应该定义正在公开的OperationContract,通过定义一个接口。

例如,请参见Channel 9上的内容:
http://channel9.msdn.com/Shows/Endpoint/Endpoint-Screencasts-Creating-Your-First-WCF-Service

你应该将此服务定义为单独的库程序集(因为明天你可能想在其他地方托管此服务,在开发时很可能是在控制台应用程序中)。

使用服务时,你需要考虑它是否应该来自ASP.NET网页、Windows窗体程序或控制台实用程序,真正取决于你的消费者场景,你希望将实际的PDF功能外部化到一个单独的类中(在同一库程序集中),这样当你想要在其他程序中执行此操作时,它将不必与网络上的WCF服务通信,尽管这样做本身很棒,但跨进程集成会影响性能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接