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 使用的示例