您的位置:首页 > 其它

以 Console 方式运行、调试、编译 .Net 编写的 Windows 服务

2006-04-17 02:23 585 查看
经常看到一些人在调试 Windows 服务时,很执著的在附加进程后调试!

其实 .Net 编写的 Windows 应用程序,包括 Windows 服务都可以编译成 Console 程序!

甚至于 ASP.Net ASPX 的 codebehind 里加个 Main 函数,编译成 Console 也未尝不可!

万事万物皆Console!(学自《thinking in java》万事万物皆对象!有点牵强,表笑偶)

利用 Visual Studio .Net 2003 创建的 "Windows 服务" 项目默认不是 Console,

你可以在项目属性中:

把 "通用属性->常规->输出类型->应用程序" 强行指定为 "控制台应用程序"

把 "配置属性->调试->启动选项->命令行参数" 指定为任意字符串,如: "/cxxx"

然后将生成的 C# 服务代码,如: Service.cs 的 Main 函数改为如下代码

static void Main(string[] args )

接下来就可以 F5 运行了,如果有客户端调用,且你设了断点,自然就可以断点调试了!

这个程序即可以服务方式运行,也可以在运行时指定命令行参数以 Console 运行!

绝不不影响 InstallUtil 部署该服务!

我在 程序代码 里经常加些 System.Console.WriteLine 的提示信息!

再多说几句:

Visual Studio 生成的服务程序代码比较多,并不是所有的代码都是必要的!

其实实现一个最简单的 Windows 服务,用不了太多的代码,

Service 的 Installer 的最关键代码是 ServiceName 要一致!

下面就是一个 SimpleService 的简单例子

namespace Microshaoft

请用命令行编译:

csc service1.cs

编译生成 service1.exe ,其实就是一个 Console!

如果编译时加上 /debug 还可以结合 DbgCLR.exe 工具进行断点调试!

用命令行:

InstallUtil.exe service1.exe

安装成服务!

或者在 cmd 命令行状态,运行如下命令行:

service1.exe /xxx

就可以 Console 运行该 "服务"!

如果你有 System.Console.WriteLine 的提示信息,看着多爽!

有些时候 "服务" 方式启动不了时,用 Console 运行还可以很轻易的发现错误!

我个人现在工作中,基本不写大量代码!

因此基本不用 Visual Studio,很少写 WinForm、WebForm,只写 Console!

只是使用 EditPlus + SDK + DbgCLR 编写、调试一些功能简单的测试代码!

接下来吐血●●●推荐下载我强大的 EditPlus:

http://microshaoft.googlepages.com/EditPlus.v2.21.b381.zip

注意: 解压后请复制到你的D盘根目录,即目录为 D:\EditPlus

如果你想放在其他盘或目录下,请打开 EditPlus 目录下的一些 INI 文件,并替换路径,保存!

可以编写、编译:

C#、Java、C/C++ 等

并集成了一些有用的 .Net 命令行工具,如: wsdl.exe、installutil、regasm、tlbimp 等

(如果命令行工具的路径不对,请自行打开 tool.ini 文件替换你自己的相应路径)

收集了一些有用的代码片断,

欢迎使用,提意见!

namespace Microshaoft
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Security.Principal;
using System.ServiceProcess;
using Microshaoft.Win32;
public class WindowsServiceHost : ServiceBase
{
static void Main(string[] args)
{
Console.WriteLine(Environment.CommandLine);
WindowsServiceHost service = new WindowsServiceHost();
int l = 0;
bool needFreeConsole = false;
if (args != null)
{
l = args.Length;
}
if (l > 0)
{
if (args[0].ToLower() == "/console")
{
needFreeConsole = true;
Console.Title = "Service Run as Console ...";
Console.WriteLine("Alloc Console ...");
NativeMethods.AllocConsole();
service.OnStart(args);
Console.ReadLine();
return;
}
}
Console.WriteLine("Service");
ServiceBase.Run(service);
if (needFreeConsole)
{
Console.WriteLine("Free Console ...");
NativeMethods.FreeConsole();
}
}
public WindowsServiceHost()
{
CanPauseAndContinue = true;
}
protected override void OnStart(string[] args)
{
Console.WriteLine("[{0}]", string.Join(" ", args));
Console.WriteLine("Current User Identity: {0}", WindowsIdentity.GetCurrent().Name);
Console.WriteLine(".Net Framework version: {0}", Environment.Version.ToString());
}
}
[RunInstallerAttribute(true)]
public class ProjectInstaller : Installer
{
private ServiceInstaller _serviceInstaller;
private ServiceProcessInstaller _processInstaller;
public ProjectInstaller()
{
_processInstaller = new ServiceProcessInstaller();
_serviceInstaller = new ServiceInstaller();
// Service will run under system account
_processInstaller.Account = ServiceAccount.LocalSystem;
// Service will have Start Type of Manual
_serviceInstaller.StartType = ServiceStartMode.Manual;
//_serviceInstaller.ServiceName = WindowsServiceHost.serviceName;
Installers.Add(_serviceInstaller);
Installers.Add(_processInstaller);
}
public override void Install(IDictionary stateSaver)
{
SetServiceName();
base.Install(stateSaver);
}
public override void Uninstall(IDictionary savedState)
{
SetServiceName();
base.Uninstall(savedState);
}
private void SetServiceName()
{
var parameters = Context.Parameters;
var parametersKeys = parameters.Keys;
//foreach (KeyValuePair<string, string> kvp in parameters)
foreach (string s in parametersKeys)
{
var k = s.Trim().ToLower();
if (k == "servicename")
{
//var serviceName = kvp.Value;
var serviceName = parameters[k];
_serviceInstaller.ServiceName = serviceName;
_serviceInstaller.DisplayName = serviceName;
break;
}
}
}
}
}
namespace Microshaoft.Win32
{
using System.Runtime.InteropServices;
public class NativeMethods
{
/// <summary>
/// 启动控制台
/// </summary>
/// <returns></returns>
[DllImport("kernel32.dll")]
public static extern bool AllocConsole();
/// <summary>
/// 释放控制台
/// </summary>
/// <returns></returns>
[DllImport("kernel32.dll")]
public static extern bool FreeConsole();
}
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: