如标题所示,如何查看用户安装的 DirectX 版本?检查 FeatureLevel 是不够的,因为我的应用程序可以在功能级别 10.0 上运行,但需要安装 DirectX 11.1。
为什么这不是重复的:
- How to code to get direct X version on my machine in C#?
- 这个问题的第一个答案是“如果是 Windows 7,DirectX = 11,如果是 Windows Vista,DirectX = 10”。这是错误的,因为 Vista 支持 DirectX 10 和 11,而 Windows 7 支持 DirectX 11 和 11.1。
- 第二个答案引用了一个仅适用于 DirectX 9 及更低版本的注册表项。即使在安装了 DirectX 11.1 的 Windows 7 系统上,此注册表项也永远不会指示安装的版本高于 9.0c
- .NET How to detect if DirectX 10 is supported?
- 此问题的答案再次引用了相同的注册表项,仅适用于 DirectX 9 及更低版本。
我需要一个适用于 DirectX 10 安装及更高版本的答案。这意味着确定它们的版本是 10、10.1、11 还是 11.1。
最佳答案
另一种可能性是直接使用 IDxDiagProvider
COM 对象并浏览它产生的 IDxDiagContainer
层次结构 - 这就是 dxdiag.exe
在内部所做的.它也需要一些时间才能完成,因此它也不是一个快速的解决方案,但至少您不需要创建或解析原始文件。
显然,此功能以前包含在 Microsoft.DirectX.Diagnostics
中的托管 DirectX 程序集中。 ,因为它们与 COM 对象提供的接口(interface)非常相似,但是这些程序集已经过时并且不能在 .NET Core 中工作,所以让我们自己包装这些 COM 对象吧!有关方法的文档,您仍然可以引用上面链接的文档。
首先,您需要 IDxDiagProvider
接口(interface)和 DxDiagProvider
组件类以及传递给提供程序的 DXDIAG_INIT_PARAMS
:
[ComImport]
[Guid("A65B8071-3BFE-4213-9A5B-491DA4461CA7")]
public class DxDiagProvider { }
[Guid("9C6B4CB0-23F8-49CC-A3ED-45A55000A6D2")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDxDiagProvider
{
void Initialize(ref DXDIAG_INIT_PARAMS pParams);
void GetRootContainer(out IDxDiagContainer ppInstance);
}
[StructLayout(LayoutKind.Sequential)]
public struct DXDIAG_INIT_PARAMS
{
public int dwSize;
public uint dwDxDiagHeaderVersion;
public bool bAllowWHQLChecks;
public IntPtr pReserved;
};
您还需要包装 IDxDiagContainer
类:
[Guid("7D0F462F-4064-4862-BC7F-933E5058C10F")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDxDiagContainer
{
void EnumChildContainerNames(uint dwIndex, string pwszContainer, uint cchContainer);
void EnumPropNames(uint dwIndex, string pwszPropName, uint cchPropName);
void GetChildContainer(string pwszContainer, out IDxDiagContainer ppInstance);
void GetNumberOfChildContainers(out uint pdwCount);
void GetNumberOfProps(out uint pdwCount);
void GetProp(string pwszPropName, out object pvarProp);
}
现在我们开始使用我们的包装器并且必须执行以下操作来检索版本信息:
- 通过创建 coclass 并将其转换为接口(interface)来实例化提供者。
- 使用初始化参数初始化提供者。
- 获取根容器。
- 获取 DxDiag_SystemInfo 子容器。
- 阅读 DirectX 版本属性。
正确清理 COM 资源的代码如下所示:
IDxDiagProvider provider = null;
IDxDiagContainer rootContainer = null;
IDxDiagContainer systemInfoContainer = null;
try
{
// Instantiate and initialize the provider.
provider = (IDxDiagProvider)new DxDiagProvider();
DXDIAG_INIT_PARAMS initParams = new DXDIAG_INIT_PARAMS
{
dwSize = Marshal.SizeOf<DXDIAG_INIT_PARAMS>(),
dwDxDiagHeaderVersion = 111
};
provider.Initialize(ref initParams);
// Get the Root\SystemInfo container.
provider.GetRootContainer(out rootContainer);
rootContainer.GetChildContainer("DxDiag_SystemInfo", out systemInfoContainer);
// Read the DirectX version info.
int versionMajor = GetProperty<int>(container, "dwDirectXVersionMajor");
int versionMinor = GetProperty<int>(container, "dwDirectXVersionMinor");
string versionLetter = GetProperty<string>(container, "szDirectXVersionLetter");
bool isDebug = GetProperty<bool>(container, "bDebug");
}
finally
{
if (provider != null)
Marshal.ReleaseComObject(provider);
if (rootContainer != null)
Marshal.ReleaseComObject(rootContainer);
if (systemInfoContainer != null)
Marshal.ReleaseComObject(systemInfoContainer);
}
如您所见,我创建了一个小型实用程序 GetProperty
方法,用于从 COM 接口(interface)返回的 VARIANT
值中检索正确类型的属性:
private static T GetProperty<T>(IDxDiagContainer container, string propName)
{
container.GetProp(propName, out object variant);
return (T)Convert.ChangeType(variant, typeof(T));
}
关于c# - 检查安装了哪个版本的 DirectX,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17130764/