欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Device information in Windows 8 store apps windowsc#metro

程序员文章站 2022-06-04 11:38:12
...
Our Sticker Tales game tracks var­i­ous activ­i­ties via Google Ana­lyt­ics using code that grew into our CSharp­An­a­lyt­ics open source project.

But we also want to add some sys­tem met­rics that could help us answer other questions:

When is it time to exploit fea­tures of an OS update?
Do peo­ple on tablets play longer than peo­ple on laptops?
How long do var­i­ous timed activ­i­ties take by CPU?
Does not hav­ing a phys­i­cal key­board affect pur­chase flow completion?
To do this we want to record:

Proces­sor architecture
Device man­u­fac­turer, model and form fac­tor (category)
Win­dows ver­sion number
On Win­dows Phone and .NET this infor­ma­tion is eas­ily avail­able but in Win­dows Store apps it is not. Microsoft have made this dif­fi­cult because your appli­ca­tion should not change it’s behav­ior based on this infor­ma­tion.

The fol­low­ing code uses the PnPOb­ject API to best-guess these things. It is not bullet-proof and could eas­ily fail on machines with cus­tom HAL dri­vers (I haven’t seen one of those in years) or on other lan­guage edi­tions of Win­dows (not yet tried).

It is good enough in my opin­ion for ana­lyt­ics, log­ging or trou­bleshoot­ing and for noth­ing more.

To use it simply:

var windowsVersion = await SystemInfoEstimate.GetWindowsVersionAsync();
var processor = await SystemInfoEstimate.GetProcessorArchitectureAsync();
using System;
using System.Linq;
using System.Threading.Tasks;
using Windows.Devices.Enumeration.Pnp;
using Windows.System;
 
public class SystemInfoEstimate
{
  const string ItemNameKey = "System.ItemNameDisplay";
  const string ModelNameKey = "System.Devices.ModelName";
  const string ManufacturerKey = "System.Devices.Manufacturer";
  const string DeviceClassKey = "{A45C254E-DF1C-4EFD-8020-67D146A850E0},10";
  const string PrimaryCategoryKey = "{78C34FC8-104A-4ACA-9EA4-524D52996E57},97";
  const string DeviceDriverVersionKey = "{A8B865DD-2E3D-4094-AD97-E593A70C75D6},3";
  const string RootContainer = "{00000000-0000-0000-FFFF-FFFFFFFFFFFF}";
  const string RootQuery = "System.Devices.ContainerId:=\"" + RootContainer + "\"";
  const string HalDeviceClass = "4d36e966-e325-11ce-bfc1-08002be10318";
 
  public static async Task<ProcessorArchitecture> GetProcessorArchitectureAsync()
  {
    var halDevice = await GetHalDevice(ItemNameKey);
    if (halDevice != null && halDevice.Properties[ItemNameKey] != null) {
      var halName = halDevice.Properties[ItemNameKey].ToString();
      if (halName.Contains("x64")) return ProcessorArchitecture.X64;
      if (halName.Contains("ARM")) return ProcessorArchitecture.Arm;
      return ProcessorArchitecture.X86;
    }
    return ProcessorArchitecture.Unknown;
  }
 
  public static Task<string> GetDeviceManufacturerAsync()
  {
    return GetRootDeviceInfoAsync(ManufacturerKey);
  }
 
  public static Task<string> GetDeviceModelAsync()
  {
    return GetRootDeviceInfoAsync(ModelNameKey);
  }
 
  public static Task<string> GetDeviceCategoryAsync()
  {
    return GetRootDeviceInfoAsync(PrimaryCategoryKey);
  }
 
  public static async Task<string> GetWindowsVersionAsync()
  {
    // There is no good place to get this.
    // The HAL driver version number should work unless you're using a custom HAL... 
    var hal = await GetHalDevice(DeviceDriverVersionKey);
    if (hal == null || !hal.Properties.ContainsKey(DeviceDriverVersionKey))
      return null;
 
    var versionParts = hal.Properties[DeviceDriverVersionKey].ToString().Split('.');
    return string.Join(".", versionParts.Take(2).ToArray());
  }
 
  private static async Task<string> GetRootDeviceInfoAsync(string propertyKey)
  {
    var pnp = await PnpObject.CreateFromIdAsync(PnpObjectType.DeviceContainer,
              RootContainer, new[] { propertyKey });
    return (string)pnp.Properties[propertyKey];
  }
 
  private static async Task<PnpObject> GetHalDevice(params string[] properties)
  {
    var actualProperties = properties.Concat(new[] { DeviceClassKey });
    var rootDevices = await PnpObject.FindAllAsync(PnpObjectType.Device, 
        actualProperties, RootQuery);
 
    foreach (var rootDevice in rootDevices.Where(d => d.Properties != null && d.Properties.Any())) {
        var lastProperty = rootDevice.Properties.Last();
        if (lastProperty.Value != null)
           if (lastProperty.Value.ToString().Equals(HalDeviceClass))
              return rootDevice;
    }
    return null;
  }
}
相关标签: windows c# metro