C# 将控制台应用程序转换为 Windows 服务
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19558801/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Converting Console app to Windows Service
提问by Murali Uppangala
Am trying to convert my console application, which generates pdf reports, into a windows service. My code is as follows. Am I on the right direction? I installed this service and start/stop works fine but no report is generated! The console app alone works fine to generate Output.pdf. My aim is to Generate ouput when the service starts.
我正在尝试将生成 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();
}
}
采纳答案by cstruter
I would advise that you move the code in your OnStart event to a separate thread, since your service will need to start in a timely matter, else it can potentially time out on start up.
我建议您将 OnStart 事件中的代码移动到一个单独的线程,因为您的服务需要及时启动,否则它可能会在启动时超时。
E.g
例如
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
}
}
}
You might also want to check if the executing user (user context in which the service runs) has rights to the folder you're writing to etc.
您可能还想检查执行用户(服务运行所在的用户上下文)是否有权访问您正在写入的文件夹等。
You will also need to write your errors to the event log instead of writing them to the console window like seen in your snippet (your code is swallowing exceptions at the moment thats why you cant pin point whats going wrong)
您还需要将错误写入事件日志,而不是像您的代码片段中看到的那样将它们写入控制台窗口(此时您的代码正在吞咽异常,这就是为什么您无法指出出了什么问题)
Read more over here: C# Basics: Creating a Windows Service
在此处阅读更多信息: C# 基础知识:创建 Windows 服务
回答by T. Nielsen
Yes and no, what you should do is to define what OperationContract you are in the process of exposing by defining an interface.
是和不是,您应该做的是通过定义接口来定义您在公开过程中的操作合同。
For instance see this on channel 9:
http://channel9.msdn.com/Shows/Endpoint/Endpoint-Screencasts-Creating-Your-First-WCF-Service
例如,在频道 9 上看到这个:http:
//channel9.msdn.com/Shows/Endpoint/Endpoint-Screencasts-Creating-Your-First-WCF-Service
you should define this service is a separate library assembly (because tomorrow you'll want to host this service somewhere else and very likely while developing, in a console application).
你应该定义这个服务是一个单独的库程序集(因为明天你会想在其他地方托管这个服务,很可能在开发时,在控制台应用程序中)。
consuming the service you need to consider if it should be from an asp.net web page, a windows forms program or a console utility, really depending on your consumer scenario you'd want to externalize the actual pdf functionality in a separate class (in same library assembly) so that the day you want to just be able to do that in one of you other programs, it will not have to communicate with a wcf service somewhere on the network, though such a thing is nifty in itself it affects performance to integrate across process to a limited degree.
使用您需要考虑的服务是否应该来自 asp.net 网页、windows 窗体程序或控制台实用程序,实际上取决于您的消费者场景,您希望在单独的类中外部化实际的 pdf 功能(在相同的库程序集),以便您希望能够在其中一个其他程序中执行此操作的那一天,它不必与网络上某处的 wcf 服务进行通信,尽管这样的事情本身很漂亮,但它会影响性能在有限的程度上跨流程整合。