我想从 C# 调用 DISM API 来找出安装了哪些可选的 Windows 功能。DISM 功能不会出现在著名的 pinvoke.net 网站上,因此我开始使用 P/Invoke Interop Assistant 工具来解决这个问题。
问题涉及一个这样开始的结构:
[StructLayout(LayoutKind.Sequential)]
public struct DismFeatureInfo
{
/// PCWSTR->WCHAR*
[MarshalAs(UnmanagedType.LPWStr)]
public string FeatureName;
/// DismPackageFeatureState
[MarshalAs(UnmanagedType.I4)]
public DismPackageFeatureState FeatureState;
/// PCWSTR->WCHAR*
[MarshalAs(UnmanagedType.LPWStr)]
public string DisplayName;
我有一个指向 unmanaged 的指针DismFeatureInfo
。当我使用时,Marshal.PtrToStructure
我得到了一个FatalExecutionEngineError
例外。
如果我从后面注释掉所有字段DisplayName
(仅保留前两个),那么它可以工作,并且我会在FeatureName
.
如果我使用调试器内存窗口检查结构地址处的内存,它会按预期布局。我在 64 位运行,它开始:
[ 8 bytes ] // pointer to a string containing the feature name
[ 4 bytes ] // enum value
[ 8 bytes ] // pointer to a string containing the display name
更重要的是,如果我手动执行偏移来读取指针,然后从中获取字符串:
var featureName = Marshal.PtrToStringUni(Marshal.ReadIntPtr(featureInfoPtr));
var displayName = Marshal.PtrToStringUni(Marshal.ReadIntPtr(featureInfoPtr, 8 + 4));
效果很好 -displayName
包含显示名称。
这一切都表明enum DismPackageFeatureState
正在编组为错误的大小。从检查原始内存来看,它绝对应该是 4 个字节。我已经设置了一个属性说它应该是I4
.
如果我将FeatureState
字段更改为:
public UInt32 FeatureState;
然后我仍然得到异常。那么发生了什么?
(注意。我对 P/Invoke 方面特别感兴趣,而不是我原来的问题。从那以后,我通过更轻松地找到了我需要的信息,new ManagementClass("Win32_OptionalFeature")
但仍然对我在尝试使 P/Invoke 工作时发现的内容感到困惑,并且想知道发生了什么。)