我使用.NET编写的代码只有在作为Windows服务安装时才会失败。失败不允许服务甚至启动。我无法弄清楚如何进入OnStart方法。
How to: Debug Windows Service Applications 给出了一个诱人的线索:
附加到服务的过程允许您调试大多数但不是所有服务的代码;例如,因为服务已经启动,所以无法以这种方式调试服务的OnStart方法中的代码,或者用于加载服务的Main方法中的代码。 解决此问题的一种方法是在服务应用程序中创建临时的第二个服务,该服务仅用于帮助调试。您可以安装这两个服务,然后启动此“虚拟”服务以加载服务进程。一旦临时服务启动了该过程,您就可以使用Visual Studio中的“调试”菜单附加到服务进程。
但是,我不清楚你应该如何创建虚拟服务来加载服务进程。
答案 0 :(得分:94)
作为临时解决方法,您可以做的一件事是将调试器作为OnStart中的第一行代码启动
System.Diagnostics.Debugger.Launch()
这将提示您输入要使用的调试器。只需在Visual Studio中打开解决方案,然后从列表中选择该实例。
答案 1 :(得分:10)
我倾向于添加这样的方法:
[Conditional("DEBUG")]
private void AttachDebugger()
{
Debugger.Break();
}
它只会在你项目的Debug版本上被调用,它会暂停执行并允许你附加调试器。
答案 2 :(得分:8)
使用installutil.exe
安装服务后,如果服务已启动,您可以更改Start Parameters
以跳转到调试器:
当您使用参数-debugWithVisualStudio
(或简称-d
)手动启动服务时,它将自动检测正确的项目,并在Visual Studio中启动交互式调试器:
要支持此功能,请更改服务的OnStart()
功能:
/// <summary>
/// Executed when the service is started.
/// </summary>
/// <param name="args">Command line arguments.</param>
protected override void OnStart(string[] args)
{
try
{
//How to debug when running a Windows Service:
// 1. Right click on the service name in Windows Service Manager.
// 2. Select "Properties".
// 3. In "Start Parameters", enter "-d" (or "-debugWithVisualStudio").
// 4. Now, when you start the service, it will fire up Visual Studio 2012 and break on the line below.
// 5. Make sure you have UAC (User Access Control) turned off, and have Administrator privileges.
#if DEBUG
if (((ICollection<string>)args).Contains("-d")
|| ((ICollection<string>)args).Contains("-debugWithVisualStudio"))
{
Debugger.Launch(); // Launches VS2012 debugger.
}
#endif
ShellStart(args);
base.OnStart(args);
}
catch (Exception ex)
{
// Log exception here.
}
}
(可选)如果要缩小服务引发错误的确切代码行,请从Visual Studio菜单DEBUG .. Exceptions
启用异常。当你继续调试时,它将在抛出异常的确切行上中断。
答案 3 :(得分:7)
一切正常!
protected override void OnStart(string[] args)
{
System.Diagnostics.Debugger.Launch();
}
答案 4 :(得分:5)
上述选项似乎无法在Windows 8上运行。
我添加了Thread.Sleep(15000);进入我的OnStart()方法并在代码的下一行设置断点。这让我在启动服务后将VS调试器附加到我的进程15秒,并允许我很好地调试OnStart()方法。
答案 5 :(得分:4)
您可以添加一行代码:
System.Diagnostics.Debugger.Break()
将弹出一个窗口,提示您选择要用于调试的调试器,例如允许您使用Visual Studio附加并进入代码。
请参阅:
http://msdn.microsoft.com/en-us/library/system.diagnostics.debugger.break.aspx
答案 6 :(得分:2)
可以将Windows配置项目设置为作为控制台应用程序运行的Windows服务,但可以使用Reflection访问服务方法。有关详细信息和示例,请参阅此处:http://ryan.kohn.ca/articles/how-to-debug-a-windows-service-in-csharp-using-reflection/。
答案 7 :(得分:2)
在服务OnStart方法中使用以下代码:
System.Diagnostics.Debugger.Launch();
从弹出消息中选择Visual Studio选项。请记住以管理员身份运行Visual Studio。
注意:要仅在调试模式下使用它,可以使用#if DEBUG编译器指令,如下所示。这样可以防止生产服务器上的发布模式中的意外或调试。
#if DEBUG
System.Diagnostics.Debugger.Launch();
#endif
答案 8 :(得分:2)
正如其他人所指出的那样,你必须在OnStart-Method中添加一个调试器中断:
#if DEBUG
System.Diagnostics.Debugger.Break()
#endif
同时以管理员身份启动VisualStudio,并允许其他用户自动调试进程(如here所述):
reg add "HKCR\AppID\{E62A7A31-6025-408E-87F6-81AEB0DC9347}" /v AppIDFlags /t REG_DWORD /d 8 /f
(我在这里也解释过:https://stackoverflow.com/a/35715389/5132456)
答案 9 :(得分:1)
我知道这已经晚了,但这就是我们处理Windows服务的方法
首先创建一个充当服务的类。
添加适当的启动,停止,暂停等方法......
将一个Windows窗体添加到服务项目中。
在服务代码中创建上面创建的服务类,并在ServiceBase类中进行启动和停止服务所需的调用
打开Program.cs并添加以下内容
#if DEBUG
[STAThread]
#endif
static void Main()
{
try
{
#if DEBUG
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new DebugForm());
#else
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new YourWindowsService()
};
ServiceBase.Run(ServicesToRun);
#endif
}
catch (Exception e)
{
logger.Error(DateTime.Now.ToString() + " - " + e.Source + " - " + e.ToString() + "\r\n------------------------------------\r\n");
}
}
当您在DEBUG模式下运行时,Windows窗体将启动。只需记住在完成后构建Release模式。当然,条件编译变量可以是你喜欢的任何东西。您甚至可以创建单独的项目,因此调试表单是它自己的项目。
希望这有帮助
答案 10 :(得分:1)
您还可以尝试 System.Diagnostics.Debugger.Launch()方法。它有助于将调试器指针指向指定的位置,然后您可以调试代码。
在此步骤之前,请使用Visual Studio命令提示符的命令行安装service.exe - installutil projectservice.exe
然后从控制面板 - &gt;启动您的服务管理工具 - &gt;计算机管理 - &gt;服务和应用 - &gt;服务 - &gt;您的服务名称
答案 11 :(得分:1)
如果在OnStart方法中添加Debugger.Launch()并且它不起作用,则可能会遇到同样的问题,即构造函数中发生异常,因此从未调用OnStart。 (头颅)
(对不起,如果这应该是对其他人的答案的评论,但我没有足够的信誉来发表评论)
答案 12 :(得分:0)
尝试在有问题的方法中添加Debugger.Break。当服务启动时,将抛出异常,寡妇应该提供使用visual studio进行调试。
答案 13 :(得分:0)
我通常有一个假装成SCM的控制台应用程序,例如调用Start,Stop然后我可以将F5插入到我的主要编码/调试目的,并在通过SCM安装和启动服务时使用Debugger.Break进行调试。
这意味着要开始做更多的工作,我有一个包含所有服务代码的类库,其中一个类公开了Windows服务类和控制台应用程序都可以调用的Start和Stop。
马特
答案 14 :(得分:0)
在我进入主题之前,我建议一下。如果您是服务器端开发人员,请始终使用日志。因为在Visual Studio中调试代码时可能无法生成某些特定条件。
回到主题,我使用Envoirnment.UserInteractive标志,这非常方便,请看下面的代码
public static void Main(string[] args)
{
if (System.Environment.UserInteractive)
{
string parameter = string.Concat(args);
switch (parameter)
{
case "--install":
ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetExecutingAssembly().Location });
break;
case "--uninstall":
ManagedInstallerClass.InstallHelper(new string[] { "/u", Assembly.GetExecutingAssembly().Location });
break;
default:
WindowsService service = new WindowsService();
service.OnStart(args);
Console.ReadKey();
service.OnStop();
break;
}
}
else
{
ServiceBase.Run(new WindowsService());
}
}
从visual studio中你将获得UserInteractive标志设置,所以我将它作为控制台应用程序运行,除此之外,即使你可以通过双击它并附加调试器来运行产品构建,如果你想测试它。
答案 15 :(得分:0)
我有一个有趣的方法,我添加另一个名为DebugNoService的配置
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugNoService|AnyCPU' ">
<OutputPath>.\</OutputPath>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>DEBUG;TRACE;DEBUGNOSERVICE</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>true</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<NoStdLib>false</NoStdLib>
<NoWarn>
</NoWarn>
<Optimize>false</Optimize>
<RegisterForComInterop>false</RegisterForComInterop>
<RemoveIntegerChecks>false</RemoveIntegerChecks>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<DebugType>full</DebugType>
<ErrorReport>prompt</ErrorReport>
<UseVSHostingProcess>false</UseVSHostingProcess>
</PropertyGroup>
我使用#if指令。 ProjectInstaller.cs
#if !DEBUGNOSERVICE
static void Main()
{
System.ServiceProcess.ServiceBase[] ServicesToRun;
.....
}
#endif
我添加了一个窗体,我还将窗体包装在
中#if DEBUGNOSERVICE
...
static void Main()
{
Form form;
Application.EnableVisualStyles();
Application.DoEvents();
form = new <the name of the form>();
Application.Run(form);
}
...
#endif
根据所选的配置,代码可以作为可以轻松调试的Windows窗体应用程序运行,也可以作为服务运行。
如果看似很多工作,但它始终有效,并使调试代码非常容易。您可以将各种输出添加到表单中,以便您可以观看它的运行。