我有一个运行良好的 Windows 服务,但是当我尝试从服务控制台停止它时,它会引发此错误:
--------------------------- Services --------------------------- Windows could not stop the xxx service on Local Computer. The service did not return an error. This could be an internal Windows error or an internal service error. If the problem persists, contact your system administrator.
我的代码:
protected override void OnStop()
{
// TODO: Add code here to perform any tear-down necessary to stop your service.
IvrApplication.StopImmediate();
}
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Text;
using VoiceElements.Common;
using VoiceElements.Client;
using System.Threading;
using System.IO;
using System.Net.Sockets;
using System.Configuration;
namespace VoiceApp
{
public class IvrApplication
{
private static object s_SyncVar = new object();
// private static ObjectPool<InboundLine> _linepool = new ObjectPool<InboundLine>(() => new InboundLine());
//private static int _maxLineInstances = 0;
public static object SyncVar
{
get { return IvrApplication.s_SyncVar; }
}
private static Log s_Log;
public static Log Log
{
get { return s_Log; }
}
private static State s_State;
public static State State
{
get { return s_State; }
}
private static Thread s_MainCodeThread;
public static Thread MainCodeThread
{
get { return s_MainCodeThread; }
}
private static AutoResetEvent s_ThreadEvent = new AutoResetEvent(false);
public static AutoResetEvent ThreadEvent
{
get { return s_ThreadEvent; }
}
private static string s_WorkingFolder = null;
public static string WorkingFolder
{
get { return s_WorkingFolder; }
}
static IvrApplication()
{
// Constructor
s_Log = new Log("IvrApplication.Log");
Log.Write("IvrApplication Constructor Complete");
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
if (e.ExceptionObject is Exception)
{
Log.WriteException((Exception)e.ExceptionObject, "Domain Level Unhandled Exception");
}
else
{
Log.Write("Domain Level Unhandled Exception - No Exception Object");
}
}
public static void Start()
{
lock (SyncVar)
{
if (State == State.Stopped)
{
s_State = State.Starting;
ThreadStart ts = new ThreadStart(MainCode);
s_MainCodeThread = new Thread(ts);
s_MainCodeThread.Name = "IvrApplication";
s_MainCodeThread.Start();
Log.Write("IvrApplication Starting...");
}
else
{
Log.Write("IvrApplication is in the " + State.ToString() + " state. Cannot start IvrApplication at this time.");
}
}
}
public static void StopImmediate()
{
lock (SyncVar)
{
if (State == State.Running || State == State.StoppingControlled)
{
s_State = State.StoppingImmediate;
ThreadEvent.Set();
Log.Write("IvrApplication StoppingImmediate.");
}
else
{
Log.Write("IvrApplication is in the " + State.ToString() + " state. Cannot stop IvrApplication at this time.");
}
}
}
public static void StopControlled()
{
lock (SyncVar)
{
if (State == State.Running)
{
s_State = State.StoppingControlled;
ThreadEvent.Set();
Log.Write("IvrApplication StoppingControlled.");
}
else
{
Log.Write("IvrApplication is in the " + State.ToString() + " state. Cannot stop IvrApplication at this time.");
}
}
}
public static TelephonyServer s_TelephonyServer = null;
public static void MainCode()
{
try
{
s_WorkingFolder = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
Log.Write("IvrApplication::MainCode() Starting...");
// Start Other Threads...
try
{
// UPDATE YOUR SERVER ADDRESS HERE
System.Net.IPAddress[] ips = System.Net.Dns.GetHostAddresses(ConfigurationManager.AppSettings["veserver"]);
if (ips == null || ips.Length == 0) throw new Exception("Error: Could not resolve Telephony Server specified!");
string sIpaddress = @"gtcp://" + ips[0].ToString() + ":54331";
Log.Write("Connecting to: {0}", sIpaddress);
// CHANGE YOUR USERNAME AND PASSWORD HERE
s_TelephonyServer = new TelephonyServer(sIpaddress, "username", "password");
//create object pool for line instance object that get used in the Newcall Event handler
// CHANGE YOUR CACHE MODE HERE
//
// Client Session mode means that the server will stream and cache the files to/from your client machine.
// Files are flushed after you disconnect.
//
// Server mode means that the files reside on the server and will use the full path name to find them there.
// Server mode can only be used on your own dedicate VE server.
//s_TelephonyServer.CacheMode = VoiceElements.Interface.CacheMode.ClientSession;
s_TelephonyServer.CacheMode = VoiceElements.Interface.CacheMode.Server;
// SUBSCRIBE to the new call event.
s_TelephonyServer.NewCall += new VoiceElements.Client.NewCall(s_TelephonyServer_NewCall);
s_TelephonyServer.RegisterDNIS();
// Subscribe to the connection events to allow you to reconnect if something happens to the internet connection.
// If you are running your own VE server, this is less likely to happen except when you restart your VE server.
s_TelephonyServer.ConnectionLost += new ConnectionLost(s_TelephonyServer_ConnectionLost);
s_TelephonyServer.ConnectionRestored += new ConnectionRestored(s_TelephonyServer_ConnectionRestored);
}
catch (Exception ex)
{
try
{
if (s_TelephonyServer != null)
{
s_TelephonyServer.Dispose();
}
}
catch (Exception) { }
Log.Write("IvrApplication::MainCode() Exception: " + ex.Message + "\r\n" + ex.StackTrace);
throw ex;
}
Log.Write("VoiceElementsClient Version: {0}", s_TelephonyServer.GetClientVersion());
Log.Write("VoiceElementsServer Version: {0}", s_TelephonyServer.GetServerVersion());
lock (SyncVar)
{
s_State = State.Running;
}
Log.Write("IvrApplication::MainCode() Running...");
while (true)
{
// Waits for some asyncronous event.
ThreadEvent.WaitOne(10000, false);
// At this point you are in control. You can farm out calls from a database,
// or you could code the IvrInteractive Form and create a GUI for handling you calls.
// Follow the example from the Sampler on how to make an outbound class for new calls.
lock (SyncVar)
{
if (State != State.Running) break;
}
}
s_TelephonyServer.Dispose();
s_TelephonyServer = null;
// Must be shutting down...
if (State == State.StoppingControlled)
{
Log.Write("IvrApplication::MainCode() StoppingControlled...");
}
if (State == State.StoppingImmediate)
{
Log.Write("IvrApplication::MainCode() StoppingImmediate...");
}
lock (SyncVar)
{
s_State = State.Stopped;
Log.Write("IvrApplication::MainCode() Stopped.");
}
}
catch (Exception ex)
{
Log.Write("IvrApplication::MainCode() Exception" + ex.Message + "\r\n" + ex.StackTrace);
s_State = State.Stopped;
}
finally
{
s_MainCodeThread = null;
}
}
static void s_TelephonyServer_ConnectionRestored(object sender, ConnectionRestoredEventArgs e)
{
// When the connection is restored you must reset your cache mode and re-register the DNIS.
s_TelephonyServer.CacheMode = VoiceElements.Interface.CacheMode.ClientSession;
//s_TelephonyServer.CacheMode = VoiceElements.Interface.CacheMode.Server;
s_TelephonyServer.RegisterDNIS();
Log.Write("The Connection to the server was successfully restored!");
}
static void s_TelephonyServer_ConnectionLost(object sender, ConnectionLostEventArgs e)
{
// You could also send an email to yourself to let you know that the server was down.
Log.Write("The Connection to the server was lost.");
}
static void s_TelephonyServer_NewCall(object sender, VoiceElements.Client.NewCallEventArgs e)
{
// Handle The New Call Here
//Object Pool ***************************************************
//if (_linepool.PoolCount() > _maxLineInstances)
//{
// _maxLineInstances++;
// Log.Write("");
// Log.Write("Max Object Pool Size:{0}", _linepool.PoolCount().ToString());
// Log.Write("");
//}
//InboundLine s_InboundLine = _linepool.GetObject();
//********************************************************
InboundLine s_InboundLine = new InboundLine();
s_InboundLine.TServer = s_TelephonyServer;
s_InboundLine.Channel_Resource = e.ChannelResource;
s_InboundLine.log = Log;
s_InboundLine.RunScript();
// _linepool.PutObject(s_InboundLine); //Object Pool
//Threads per object ************************************
//ThreadStart its = new ThreadStart(s_InboundLine.RunScript);
//Thread s_InboundLineThread = new Thread(its);
//s_InboundLineThread.Name = "Port"+e.ChannelResource.PortIndexer.ToString();
//s_InboundLineThread.Start();
//*********************************************************
}
}
}
我试图在 OnStop 中捕获异常。我发现事件视图中的详细信息是:
Log Name: Application
Source: IvrService
Date: 11/4/2013 11:57:23 AM
Event ID: 0
Task Category: None
Level: Error
Keywords: Classic
User: N/A
Computer: xxx.corporate.my.com
Description:
Failed to stop service. System.IO.FileNotFoundException: Could not load file or assembly 'VoiceElementsCommon, Version=8.3.12.111, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
File name: 'VoiceElementsCommon, Version=8.3.12.111, Culture=neutral, PublicKeyToken=null'
at VoiceApp.IvrService.OnStop()
at System.ServiceProcess.ServiceBase.DeferredStop()
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
Running under executable C:\source\VoiceApp\obj\Debug\VoiceApp.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = NT AUTHORITY\SYSTEM
LOG: DisplayName = VoiceElementsCommon, Version=8.3.12.111, Culture=neutral, PublicKeyToken=null
(Fully-specified)
LOG: Appbase = file:///C:/source/VoiceApp/obj/Debug/
LOG: Initial PrivatePath = NULL
Calling assembly : VoiceApp, Version=1.0.0.0, Culture=neutral, PublicKeyTok...
Event Xml:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="IvrService" />
<EventID Qualifiers="0">0</EventID>
<Level>2</Level>
<Task>0</Task>
<Keywords>0x80000000000000</Keywords>
<TimeCreated SystemTime="2013-11-04T16:57:23.000000000Z" />
<EventRecordID>45872</EventRecordID>
<Channel>Application</Channel>
<Computer>xxx-desk.corporate.my.com</Computer>
<Security />
</System>
<EventData>
<Data>Failed to stop service. System.IO.FileNotFoundException: Could not load file or assembly 'VoiceElementsCommon, Version=8.3.12.111, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
File name: 'VoiceElementsCommon, Version=8.3.12.111, Culture=neutral, PublicKeyToken=null'
在 VoiceApp.IvrService.OnStop() 在 System.ServiceProcess.ServiceBase.DeferredStop()
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
Running under executable C:\source\VoiceApp\obj\Debug\VoiceApp.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = NT AUTHORITY\SYSTEM
LOG: DisplayName = VoiceElementsCommon, Version=8.3.12.111, Culture=neutral, PublicKeyToken=null
(Fully-specified)
LOG: Appbase = file:///C:/VoiceApp/obj/Debug/
LOG: Initial PrivatePath = NULL
Calling assembly : VoiceApp, Version=1.0.0.0, Culture=neutral, PublicKeyTok...</Data>
</EventData>
</Event>