我开发了c#application,其中apllication输出类型是Console Applicatiuon.我想将此应用程序作为服务运行.当我从visual studio运行它或只需双击.exe时,Environment.UserInteractive始终为true.
以下是我的代码
static void Main(string[] args)
{
// Get the version of the current application.
Assembly assem = Assembly.GetExecutingAssembly();
AssemblyName assemName = assem.GetName();
Version ver = assemName.Version;
// Console.WriteLine("{0}, Version {1}", assemName.Name, ver.ToString());
Console.WriteLine("{0} version {1}", assemName.Name, ver.ToString());
TouchService touchService = new TouchService();
if (Environment.UserInteractive)
{
bool show_help = false;
bool install_service = false;
bool uninstall_service = false;
string servicename = "";
OptionSet p = new OptionSet()
.Add("h|?|help", delegate(string v) { show_help = v != null; })
.Add("s|servicename=", "name of installed service", delegate(string v) { servicename = v; })
.Add("i|install", "install program as a Windows Service. A valid servicename is needed.", delegate(string v) { install_service = v != null; })
.Add("u|uninstall", "uninstall program from Windows Services. A valid servicename is needed.", delegate(string v) { uninstall_service = v != null; });
List<string> extra;
try
{
extra = p.Parse(args);
}
catch (OptionException e)
{
Console.Write("TouchServer: ");
Console.WriteLine(e.Message);
Console.WriteLine("Try `TouchServer --help' for more information.");
return;
}
if (show_help)
{
ShowHelp(p);
return;
}
else if (install_service)
{
IntegratedServiceInstaller Inst = new IntegratedServiceInstaller();
Inst.Install(servicename, null, "Provides XML data over HTTP for Touch clients",
System.ServiceProcess.ServiceAccount.NetworkService,
System.ServiceProcess.ServiceStartMode.Manual);
return;
}
else if (uninstall_service)
{
IntegratedServiceInstaller Inst = new IntegratedServiceInstaller();
Inst.Uninstall(servicename);
return;
}
// start and run the server,
// and receive commands from the console
else
{
touchService.OnStart(args);
while(true)
{
Console.Write("TouchServer>");
string commandLine = Console.ReadLine().ToLower();
if (commandLine == "exit" || commandLine == "x")
{
break;
}
if (commandLine == "quit" || commandLine == "q")
{
break;
}
else if(commandLine == "version" || commandLine == "v")
{
Console.WriteLine("{0} version {1}", assem.GetName().Name, assem.GetName().Version.ToString());
}
else if (commandLine == "list" || commandLine == "l")
{
TouchServer.showURLs = (TouchServer.showURLs == false) ? true : false;
Console.WriteLine("List URLs: {0}", (TouchServer.showURLs ? "active" : "inactive"));
}
else if (commandLine == "status" || commandLine == "s")
{
Console.WriteLine("{0,-20} {1,8}", "Name", "Sessions");
Console.WriteLine("----------------------------");
foreach (Site site in TouchServer.siteCollection.All)
{
Console.WriteLine("{0,-20} {1,8}", site.Name, site.AllSessions.Length);
}
Console.WriteLine();
}
}
touchService.OnStop();
}
}
**else
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new TouchService()
};
ServiceBase.Run(ServicesToRun);
}**
Run Code Online (Sandbox Code Playgroud)
我如何将其作为服务运行,请帮助我.在此先感谢sangita
Art*_*fin 16
使用文件 - >新建项目 - > Visual C# - > Windows-> Windows服务,
并将您的主要代码添加到OnStart()和OnStop()事件处理程序,然后将其安装为服务:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
namespace MyWindowsService
{
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
}
protected override void OnStop()
{
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我使用的解决方案,它在Visual Studio 2012和.NET 4.5下运行得很好.当我在控制台模式下运行时,它运行正常,当我作为服务运行使用时installutil.exe
,它完美地运行.
档案MainPayload.cs
.您可以忽略所有其他文件,并将长时间运行的代码插入此文件中.请注意CancellationTokenSource
,这样服务可以在服务停止时快速退出.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
//using Gurock.SmartInspect; // Only used if we are logging using SmartInspect (see www.SmartInspect.com).
namespace Demos___Service_Plus_Console
{
/// <summary>
/// Main entry point for both console and Windows service.
/// </summary>
public class MainPayload
{
private readonly CancellationTokenSource _cancellationTokenSource;
/// <summary>
/// Constructor; do not block in this call; it is for setup only.
/// </summary>
public MainPayload(CancellationTokenSource cancellationTokenSource)
{
// Do not block in this call; it is for setup only.
_cancellationTokenSource = cancellationTokenSource;
}
/// <summary>
/// Long running task here.
/// </summary>
public void Run()
{
while (_cancellationTokenSource.IsCancellationRequested == false)
{
//SiAuto.Main.LogMessage(".");
Console.WriteLine(".");
// This will break every N seconds, or immediately if on cancellation token.
_cancellationTokenSource.Token.WaitHandle.WaitOne(TimeSpan.FromSeconds(1));
}
//SiAuto.Main.LogMessage("Exited Run().");
Console.WriteLine("Exited Run().");
Thread.Sleep(500); // If we remove this line, then we will miss the final few writes to the console.
}
}
}
Run Code Online (Sandbox Code Playgroud)
档案EntryPoint.cs
.这是控制台应用程序和服务的入口点.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
//using Gurock.SmartInspect; // Only used if we are logging using SmartInspect (see www.SmartInspect.com).
namespace Demos___Service_Plus_Console
{
internal static class EntryPoint
{
// Run in console mode.
private static readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
private static Task _task;
/// <summary>
/// The main entry point for the application.
/// </summary>
public static void Main(string[] args)
{
//SiAuto.Si.Connections = "pipe(reconnect=\"true\", reconnect.interval=\"10\", backlog.enabled=\"true\", backlog.flushon=\"debug\", backlog.keepopen=\"true\")";
//SiAuto.Si.Enabled = true;
if (Environment.UserInteractive)
{
// Make sure that we can write to the console.
StreamWriter standardOutput = new StreamWriter(Console.OpenStandardOutput()) {AutoFlush = true};
Console.SetOut(standardOutput);
// If Ctrl-C is pressed in the console, we get to here.
Console.CancelKeyPress += new ConsoleCancelEventHandler(myHandler);
MainPayload myMain = new MainPayload(_cancellationTokenSource); // Pass the token into the task.
_task = Task.Run(() => myMain.Run());
// Wait for the payload task to finish.
while (_cancellationTokenSource.IsCancellationRequested == false)
{
// This will break every N seconds, or immediately if cancellation token is pinged.
_cancellationTokenSource.Token.WaitHandle.WaitOne(TimeSpan.FromSeconds(10));
}
}
else
{
// Run as Windows Service.
var ServicesToRun = new ServiceBase[]
{
new ServiceController()
};
ServiceBase.Run(ServicesToRun);
}
_task.Wait(TimeSpan.FromSeconds(10)); // Delay for console to write its final output.
}
static void myHandler(object sender, ConsoleCancelEventArgs args)
{
_cancellationTokenSource.Cancel();
//SiAuto.Main.LogMessage("CtrlC pressed.");
Console.WriteLine("CtrlC pressed.");
}
}
}
Run Code Online (Sandbox Code Playgroud)
档案ProjectInstaller.cs
.这是该服务的安装程序.
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Linq;
using System.Threading.Tasks;
namespace Demos___Service_Plus_Console
{
[RunInstaller(true)]
public partial class ProjectInstaller : System.Configuration.Install.Installer
{
public ProjectInstaller()
{
InitializeComponent();
}
private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e)
{
}
private void serviceProcessInstaller1_AfterInstall(object sender, InstallEventArgs e)
{
}
}
}
Run Code Online (Sandbox Code Playgroud)
档案ServiceController.cs
.这包含服务的方法Start()
和Stop()
方法.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Demos___Service_Plus_Console
{
/// <summary>
/// When running in service mode.
/// </summary>
public partial class ServiceController : ServiceBase
{
public ServiceController()
{
InitializeComponent();
}
readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
// Initialize payload.
private MainPayload myMain;
protected override void OnStart(string[] args)
{
myMain = new MainPayload(cancellationTokenSource); // Pass the token into the task.
Task.Run(() => myMain.Run());
}
protected override void OnStop()
{
cancellationTokenSource.Cancel();
}
}
}
Run Code Online (Sandbox Code Playgroud)
要将其安装为Windows服务,请使用installutil.exe ServiceName.exe
.要卸载,请使用installutil.exe ServiceName.exe -u
.这意味着,你将不得不打开一个Visual Studio 2012 x32 command prompt
是下Visual Studio Tools
的Start Menu
.如果要在32位模式下进行编译,请使用32位命令提示符,如果要在64位模式下进行编译,请打开64位命令提示符(这意味着路径设置正确,并且installutil.exe
具有单独的版本取决于它的32位还是64位).
打开Services
面板,然后查找名为的新服务ServiceController
.当你启动它时,如果你打开了一个日志记录框架,那么你会看到每秒都会记录到日志中的消息.
它看起来像很多代码,但它都基于Windows Service
Visual Studio 2012中的项目模板.我创建了一个新的Windows服务,然后用于Environment.UserInteracive
在控制台或服务之间切换.我添加了CancellationTokens以确保如果服务停止,任务也会快速停止(即使它是一个延迟).
唯一的另一个技巧是右键单击"Service1.cs"页面的灰色背景,然后单击"添加安装程序",添加安装程序.如果你不这样做,那么installutil.exe
会给你一个错误.
您还必须右键单击serviceProcessInstaller1
然后选择Properties
并设置Account
为LocalService
,否则它将在您安装服务时询问您的用户名凭据.
以下是所需的额外引用(使用模板创建新的Windows服务时会自动添加这些引用):
你会注意到Gurock.SmartInspect
和的引用SiAuto
.如果要观察正在运行的服务创建的日志,可以使用此或其他内容,如NLog或log4net.
仅当Environment.UserInteractive实际作为服务运行时,它才为false.双击它或从Visual Studio启动它时; 它作为普通的控制台应用程序运行,桌面可用,因此Environment.UserInteractive为true.
您可以从Squiggle代码库的 ConsoleService类派生您的类,以创建一个也可以作为Windows服务运行的控制台应用程序.
public class ConsoleService : ServiceBase
{
public void RunConsole(string[] args)
{
Trace.Listeners.Add(new ConsoleTraceListener());
OnStart(args);
Trace.WriteLine(this.ServiceName + " running... Press any key to stop");
Trace.WriteLine("");
Console.ReadKey();
OnStop();
}
public static void Run<TService>(string[] args) where TService : ConsoleService, new()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
if (Environment.UserInteractive)
{
try
{
string option = args.Length > 0 ? args[0].ToUpperInvariant() : String.Empty;
switch (option)
{
case "-I":
case "/I":
ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetCallingAssembly().Location });
break;
case "-U":
case "/U":
ManagedInstallerClass.InstallHelper(new string[] { "/U", Assembly.GetCallingAssembly().Location });
break;
default:
new TService().RunConsole(args);
break;
}
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.Message);
}
}
else
{
ServiceBase[] servicesToRun = new ServiceBase[] { new TService() };
ServiceBase.Run(servicesToRun);
}
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
if (e.ExceptionObject is Exception)
Trace.WriteLine(((Exception)e.ExceptionObject).Message);
}
}
Run Code Online (Sandbox Code Playgroud)
我刚刚在Visual Studio 2013中对此进行了测试,并且可以正常工作。
这是我的Program.cs的样子:
static class Program
{
/// <summary>
/// </summary>
static void Main()
{
if (!Environment.UserInteractive)
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
}
else
{
Console.Write("Hit any key to continue...");
Console.ReadKey();
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以像这样添加服务安装
您可以使用以下命令安装服务: installutil.exe /i YouExeName.exe
您可以使用以下命令来卸载服务: installutil.exe /u YouExeName.exe
归档时间: |
|
查看次数: |
38910 次 |
最近记录: |