首页 > 解决方案 > 为什么从 unity3d 插件 dll 调用时为 System.ServiceProcess.ServiceController.GetServices() 提供空引用

问题描述

我正在尝试实现ServiceController,它是 Windows API 的一部分,以从 Unity3d 中的 ac# dll 插件检查 Windows 服务的状态。当我从 Unity Editor 运行 dll 时,结果会根据天气是否存在服务正确给出。但是,当我进行构建并尝试作为 exe 运行时,它会出现以下错误:

  NullReferenceException: Object reference not set to an instance of an object
  at (wrapper unknown) System.ServiceProcess.Win32ServiceController/ENUM_SERVICE_STATUS_PROCESS:PtrToStructure (intptr,object)
  at (wrapper managed-to-native) System.Runtime.InteropServices.Marshal:PtrToStructure (intptr,System.Type)
  at System.ServiceProcess.Win32ServiceController.GetServices (System.String machineName, SERVICE_TYPE serviceType, System.String group) [0x00000] in <filename unknown>:0 
  at System.ServiceProcess.Win32ServiceController.GetServices () [0x00000] in <filename unknown>:0 
  at System.ServiceProcess.ServiceController.GetServices (System.String machineName) [0x00000] in <filename unknown>:0 
  at System.ServiceProcess.ServiceController.GetServices () [0x00000] in <filename unknown>:0 

这是我从 Unity3d 代码调用的 dll 中的静态方法:

public static bool isServicePresent(string serviceName)
{
    bool serviceExists = false;
    foreach (ServiceController sc in ServiceController.GetServices())
    {
        if (sc.ServiceName == serviceName)
        {
            //service is found
            serviceExists = true;
            break;
        }
    }
    return serviceExists;
}

虽然错误来自部分GetService()但如果我尝试使用下面提到的功能,则不会为独立和编辑器生成错误。我确实知道它可能与new关键字有关,但我完全没有得到证实。

public static int GetServiceControllerStatus(string serviceName)
{

    try
    {
        if(serviceController == null)
            serviceController = new ServiceController(serviceName);
    }
    catch (ArgumentException)
    {
        //return "Invalid service name."; // Note that just because a name is valid does not mean the service exists.
        return 0;
    }

    using (serviceController)
    {
        try
        {
            serviceController.Refresh(); // calling sc.Refresh() is unnecessary on the first use of `Status` but if you keep the ServiceController in-memory then be sure to call this if you're using it periodically.
            return (int)serviceController.Status;
        }
        catch (Win32Exception ex)
        {
            // A Win32Exception will be raised if the service-name does not exist or the running process has insufficient permissions to query service status.
            // See Win32 QueryServiceStatus()'s documentation.
            //return "Error: " + ex.Message;
            return -1;
        }
    }
}

所以关于上述结果,我有几个问题:

我没有任何使用 Windows API 的经验。任何有关这方面的帮助,我将不胜感激。

标签: c#unity3dwinapiservicesystem

解决方案


推荐阅读