0

我有一个运行良好的 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>
4

3 回答 3

1

您没有发布所有代码,并且很难理解错误。

原因可能是:

你如何初始化你的 EventWaitHandle:AutoReset或者ManualReset你在你的线程中做了什么来附加到它。在那里你可以找到一个应该如何做的例子。

您的线程正在做一些耗时的事情,他们需要更多时间才能正确关闭

protected override void OnStop()
{
   this.RequestAdditionalTime(10000);
   IvrApplication.StopImmediate();
}

- - - - - 更新 - - - - -

在您记录错误后,我可以打赌您没有将所有依赖 dll 放在您服务所在的文件夹中。

于 2013-11-04T14:26:38.297 回答
0

我的猜测是你在StopImmediate()被调用之后仍然有线程运行。

编辑:

根据我从您的评论中了解到,您IvrApplication.Start()多次调用,因此ThreadStart ts = new ThreadStart(MainCode);也被多次调用。这意味着您最终会遇到很多线程都在等待ThreadEvent发出信号。但是,当您ThreadEvent.Set();在内部调用StopImmediate()时,ThreadEvent会发出信号,但只有一个线程从等待事件中释放。其他人仍在等待事件。

您需要的是 aManualResetEvent而不是 an AutoResetEvent,以便在调用Set()时释放所有等待线程,而不仅仅是第一个线程。

代替

private static AutoResetEvent s_ThreadEvent = new AutoResetEvent(false);

采用

private static ManualResetEvent s_ThreadEvent = new ManualResetEvent(false);
public static ManualResetEvent ThreadEvent
{
   get { return s_ThreadEvent; }
}
于 2013-11-04T14:06:32.283 回答
0

我面临着同样的问题。

您需要添加方法覆盖:

protected override void OnShutdown()
{
    eventLog1.WriteEntry("On Shutdonw.");
    timer.Stop();
    //Add your code for release memory
}
于 2018-07-10T21:34:33.187 回答