无法停止本地计算机上的xxx服务

时间:2013-11-04 13:53:44

标签: c# windows-services

我有一个可以正常运行的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>

3 个答案:

答案 0 :(得分:1)

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

原因可能是:

如何初始化EventWaitHandleAutoResetManualReset以及您在线程中执行的操作以附加到它。 There你可以找到一个如何完成它的例子。

你的帖子正在耗费时间,他们need more time to shutdown properly

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

---------- --------- UPDATE

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

答案 1 :(得分:0)

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

编辑:

据我所知,您多次致电IvrApplication.Start(),因此多次调用ThreadStart ts = new ThreadStart(MainCode);。这意味着你最终会有很多线程等待ThreadEvent发出信号。 但是,当您在ThreadEvent.Set();内调用StopImmediate()时,会发生ThreadEvent信号,但只有一个线程从等待事件中释放。其他人仍在等待这一事件。

您需要的是ManualResetEvent而非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; }
}

答案 2 :(得分:0)

我遇到了同样的问题。

您需要添加方法覆盖:

protected override void OnShutdown()
{
    eventLog1.WriteEntry("On Shutdonw.");
    timer.Stop();
    //Add your code for release memory
}