System.MissingMethodException - 仅在设备启动时
System.MissingMethodException - only on device startup
我们的 C# 2.0 CF (CompactFramework) 应用程序针对旧设备 运行 Windows CE 5.0 和 6.0。该项目构建了许多 DLL 以提供 RS-232 通信等功能。
在 Windows CE 5.0 设备上,抛出 MissingMethodException
,引用这些 DLL 之一。这发生在应用程序启动过程的早期,并且仅在电源循环之后立即发生。如果我们终止应用程序并重新启动,则不会抛出异常并且应用程序可以正常运行。如果我们使用 Visual Studio 进行调试部署(无一例外),结果相同。
在 Windows CE 6.0 设备上没有抛出异常。
由于这只会在电源循环后立即发生并且我们无法调试项目,我可以尝试找出导致问题的位置和原因吗?
更新
josef
的回答很有用。在具有以下子系统之一的 CE 5.0 上使用 IsAPIReady
:
const uint SH_GDI_CE5 = 16; // Most useful
const uint SH_WMGR_CE5 = 17; // Most useful
const uint SH_SHELL_CE5 = 21; // Most useful
const uint SH_WNET_CE5 = 18;
const uint SH_COMM_CE5 = 19;
const uint SH_FILESYS_APIS_CE5 = 20;
const uint SH_DEVMGR_APIS_CE5 = 22;
const uint SH_TAPI_CE5 = 23;
const uint SH_PATCHER_CE5 = 24;
const uint SH_SERVICES_CE5 = 26;
或在具有以下子系统之一的 CE 6.0 上使用 WaitForAPIReady
:
const uint SH_GDI_CE6 = 80; // Most useful
const uint SH_WMGR_CE6 = 81; // Most useful
const uint SH_SHELL_CE6 = 85; // Most useful
const uint SH_WNET_CE6 = 82;
const uint SH_COMM_CE6 = 83;
const uint SH_FILESYS_APIS_CE6 = 84;
const uint SH_DEVMGR_APIS_CE6 = 86;
const uint SH_TAPI_CE6 = 87;
const uint SH_DDRAW_CE6 = 91;
const uint SH_D3DM_CE6 = 92;
但是,令人尴尬的是,实际问题并不是一个低级别的 OS/CLR 问题,而是应用程序在开机时意外启动了两次。第一次是使用 HKLM\init
注册表项,但某些(未知)用户已将快捷方式添加到 Startup
文件夹。这两个实例一个接一个地启动得如此之快,我一开始没有注意到。这是第二个崩溃的实例。
解决方案是使用 CreateToolhelp32Snapshot
检查应用程序的多个实例的启动。如果检测到第二个实例,应用程序将中止。
将为关注的任何人保留此问题...
当设备启动时,并非所有 API 都准备好从一开始就可以使用,因为它们是异步加载的。为此WinCE提供了isApiReady函数:https://docs.microsoft.com/en-us/previous-versions/windows/embedded/ms885686%28v%3dmsdn.10%29
在设备启动时,它加载驱动程序、服务,最后根据 init 注册表项的顺序加载 shell。您的代码可能使用了尚未加载的 API,因此失败。
可以在 https://github.com/hjgode/RAC_switch/blob/master/RAC_switch/WinAPIReady.cs
找到 isApiReady 使用的示例
我们的 C# 2.0 CF (CompactFramework) 应用程序针对旧设备 运行 Windows CE 5.0 和 6.0。该项目构建了许多 DLL 以提供 RS-232 通信等功能。
在 Windows CE 5.0 设备上,抛出 MissingMethodException
,引用这些 DLL 之一。这发生在应用程序启动过程的早期,并且仅在电源循环之后立即发生。如果我们终止应用程序并重新启动,则不会抛出异常并且应用程序可以正常运行。如果我们使用 Visual Studio 进行调试部署(无一例外),结果相同。
在 Windows CE 6.0 设备上没有抛出异常。
由于这只会在电源循环后立即发生并且我们无法调试项目,我可以尝试找出导致问题的位置和原因吗?
更新
josef
的回答很有用。在具有以下子系统之一的 CE 5.0 上使用 IsAPIReady
:
const uint SH_GDI_CE5 = 16; // Most useful
const uint SH_WMGR_CE5 = 17; // Most useful
const uint SH_SHELL_CE5 = 21; // Most useful
const uint SH_WNET_CE5 = 18;
const uint SH_COMM_CE5 = 19;
const uint SH_FILESYS_APIS_CE5 = 20;
const uint SH_DEVMGR_APIS_CE5 = 22;
const uint SH_TAPI_CE5 = 23;
const uint SH_PATCHER_CE5 = 24;
const uint SH_SERVICES_CE5 = 26;
或在具有以下子系统之一的 CE 6.0 上使用 WaitForAPIReady
:
const uint SH_GDI_CE6 = 80; // Most useful
const uint SH_WMGR_CE6 = 81; // Most useful
const uint SH_SHELL_CE6 = 85; // Most useful
const uint SH_WNET_CE6 = 82;
const uint SH_COMM_CE6 = 83;
const uint SH_FILESYS_APIS_CE6 = 84;
const uint SH_DEVMGR_APIS_CE6 = 86;
const uint SH_TAPI_CE6 = 87;
const uint SH_DDRAW_CE6 = 91;
const uint SH_D3DM_CE6 = 92;
但是,令人尴尬的是,实际问题并不是一个低级别的 OS/CLR 问题,而是应用程序在开机时意外启动了两次。第一次是使用 HKLM\init
注册表项,但某些(未知)用户已将快捷方式添加到 Startup
文件夹。这两个实例一个接一个地启动得如此之快,我一开始没有注意到。这是第二个崩溃的实例。
解决方案是使用 CreateToolhelp32Snapshot
检查应用程序的多个实例的启动。如果检测到第二个实例,应用程序将中止。
将为关注的任何人保留此问题...
当设备启动时,并非所有 API 都准备好从一开始就可以使用,因为它们是异步加载的。为此WinCE提供了isApiReady函数:https://docs.microsoft.com/en-us/previous-versions/windows/embedded/ms885686%28v%3dmsdn.10%29
在设备启动时,它加载驱动程序、服务,最后根据 init 注册表项的顺序加载 shell。您的代码可能使用了尚未加载的 API,因此失败。
可以在 https://github.com/hjgode/RAC_switch/blob/master/RAC_switch/WinAPIReady.cs
找到 isApiReady 使用的示例