如何从C#桌面应用程序中调用Windows 8的WinRT API- WinRT 图表

[原文发表地址]  How to call WinRT APIs in Windows 8 from C# Desktop Applications – WinRT Diagram

[原文发表时间] 2012-10-12 5:45

我曾试着访问一些运行在Windows 8 操作系统、内置于Intel Ultrabook的传感器。然而,尽管在Windows 7或者更高版本中支持定位传感器内置在.NET 4 库中, 但我想访问完整的内置在Windows 8自身中的传感器和定位平台。这些API 通过COM可用,而且我可以通过COM调用它们,但是通过WinRT层来调用它们就更好了。这就是WinRT存在的原因.

这让我思考WinRT以及它的意义。我在数月前发表了一篇博文真正弄清楚了一些东西,但是我总觉得所有试图解释事情如何协同的各种各样的图表说明方式太复杂

免责声明:所有图表就其性质而言过于简单化。我的工作是有关Web方面的,而不是Windwos 方面,所以这都是我自己的意见和推测。我不为Windows组织工作,我只是一个试图为新手编写一个应用程序的家伙。

我想它并不像这些图表那么复杂。 我画这个是为了帮助自己理解。

WinRT Diagram

就像C 语言有一个C运行时为它提供一系列功能支持及功能的调用约定,Windows 运行时(WinRT)为Windows和它的语言也是如此。这些API和运行时包含有调用约定的元数据,这些约定使得调用WinRT API比调用COM更容易。

在图表中,看出我是如何从.NET CLR中调用任何API的吗?在我想调用传感器API的情况下,当它们是Win32 API或者 COM API, 我想使用最高层的调用约定来调用它们,这是一个非常友好的Windows RT 。

从C# 桌面应用程序中调用WinRT API

我喜欢使用小型的控制台应用程序来做测试,但是这些不是“Windows商店应用程序”。所以我被允许从我的桌面或者控制台应用程序中调用WinRT吗?

当然可以。在MSDN文档中有一章节列出了所有可以从桌面调用的针对Windows 8的WinRT API。 我可以明确地在文档中确认LightSensor 类,并且确保它是允许被桌面应用程序调用的。

LightSensor is allowed to be called from Desktop Apps

虽然没有明确定义,但是有文档描述了如何在非Windows商店应用程序中添加WinRT引用.

从一个桌面应用程序中添加WinRT引用

文档说的 有些隐晦

在桌面项目中,Core选项卡默认不会显示。用户可以选择针对Windows Runtime编写代码,通过打开项目节点的快捷菜单,选择Unload Project(不加载项目),添加以下代码片段,再次打开项目节点的快捷菜单,然后选择Reload Project(重新加载项目)。现在,当用户从项目中激活引用管理器对话框时,Core选项卡就会显示了。

 <PropertyGroup>
  <TargetPlatformVersion>8.0</TargetPlatformVersion>
</PropertyGroup>

我将会制作一个.NET 4.5 C#的控制台应用程序。我将修改.csproj 文件,添加TargetPlatformVersion行。我将会从解决方案资源管理器节点的上下文菜单中选择Add Reference(添加引用)。

Windows Core References

我将会添加一小段代码来检查我笔记本上的光传感器的状态:

 LightSensor light = LightSensor.GetDefault();
if (light != null)
{
    uint minReportInterval = light.MinimumReportInterval;
    uint reportInterval = minReportInterval > 16 ? minReportInterval : 16;
    light.ReportInterval = reportInterval;

    light.ReadingChanged += light_ReadingChanged; //event hander
}

然而,当我编译应用程序时,我得到了一个错误,错误出现在我试着挂钩一个事件处理器的那一行。用“+=”语言添加多点传送委托无法工作。

Error 1 Property, indexer, or event 'Windows.Devices.Sensors.LightSensor.ReadingChanged' is not supported by the language; try directly calling accessor methods 'Windows.Devices.Sensors.LightSensor.add_ReadingChanged (Windows.Foundation.TypedEventHandler<Windows.Devices.Sensors.LightSensor, Windows.Devices.Sensors.LightSensorReadingChangedEventArgs>)' or 'Windows.Devices.Sensors.LightSensor.remove_ReadingChanged (System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken)'

为了解决这个问题,并且将适当的应用程序集加载到我的应用程序来支持从我的桌面应用程序调用WinRT,我需要添加引用System.Runtime 和 System.Runtime.InteropService.WindowsRuntime.dll. 它在我系统的C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5目录下。

System.Runtime.InteropServices.WindowsRuntime.dll in C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5

现在编译我的应用程序。我甚至可以将委托改写成lambda表达式这种样式。

 light.ReadingChanged += (s, a) =>
{ 
   Console.WriteLine(String.Format("There was light! {0}", a.Reading.IlluminanceInLux));
};

现在我能够运行我的小型控制台应用程序了,感知光线并且检测它的操作。以下是一个截图,显示了一束光照在我笔记本电脑的结果。你可以看到Ambient LightSensor检测到它,并且输出到控制台。

The ambient light sensor reacting

现在在Visual Studio中,非Windows商店应用程序调用Windows RT 应用程序所需的就是一点手动操作,它的基本功能和运行时很适合我。 希望这几个手动操作步骤在未来某天能变成复选框。

看到MSDN文档包含有关哪些API能够真正被桌面和Windows商店应用程序调用的详细内容也让人感到高兴。