Created
February 3, 2016 06:20
-
-
Save harujoh/f05f263e90ae51c2f26f to your computer and use it in GitHub Desktop.
USBカメラのシリアルIDをDXDiagを使って取得する。8秒程かかり非常に低速だが、汎用性は高い。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Diagnostics; | |
using System.Dynamic; | |
using System.IO; | |
using System.Linq; | |
using System.Xml; | |
using System.Xml.Linq; | |
namespace ConsoleApplication3 | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
dynamic doc = new DynamicXml(XDocument.Parse(RunDxDiag())); | |
var test = doc.VideoCaptureDevices.VideoCaptureDevice; | |
for (int i = 0; i < test.Count; i++) | |
{ | |
Console.WriteLine(test[i].FriendlyName); | |
Console.WriteLine(test[i].Parent.ToString().Split('\\')[2]); | |
Console.WriteLine(""); | |
} | |
Console.Read(); | |
} | |
static private string RunDxDiag() | |
{ | |
var psi = new ProcessStartInfo(); | |
if (IntPtr.Size == 4 && Environment.Is64BitOperatingSystem) | |
{ | |
// Need to run the 64-bit version | |
psi.FileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows),"sysnative\\dxdiag.exe"); | |
} | |
else { | |
// Okay with the native version | |
psi.FileName = Path.Combine(Environment.SystemDirectory,"dxdiag.exe"); | |
} | |
string path = Path.GetTempFileName(); | |
try | |
{ | |
psi.Arguments = "/x " + path; | |
using (var prc = Process.Start(psi)) | |
{ | |
prc.WaitForExit(); | |
if (prc.ExitCode != 0) | |
{ | |
throw new Exception("DXDIAG failed with exit code " + prc.ExitCode); | |
} | |
} | |
return File.ReadAllText(path); | |
} | |
finally | |
{ | |
File.Delete(path); | |
} | |
} | |
} | |
public class DynamicXml : DynamicObject | |
{ | |
XElement element; | |
/// <summary> | |
/// XElement を与えて初期化。 | |
/// </summary> | |
/// <param name="element">読み取り対象の XElement。</param> | |
public DynamicXml(XElement element) { this.element = element; } | |
/// <summary> | |
/// XDocument を与えて初期化。 | |
/// ルート要素を読み出し。 | |
/// </summary> | |
/// <param name="doc">読み取り対象の XDocument。</param> | |
public DynamicXml(XDocument doc) : this(doc.Root) { } | |
/// <summary> | |
/// ファイルのパスを与えて初期化。 | |
/// </summary> | |
/// <param name="uri">読み取り対象の XML ファイル名。</param> | |
public DynamicXml(string uri) : this(XDocument.Load(uri)) { } | |
public override bool TryGetMember(GetMemberBinder binder, out object result) | |
{ | |
var name = binder.Name; | |
// 属性値は _属性名 で取得。文字列として返す。 | |
if (name.StartsWith("_")) | |
{ | |
var attName = name.Substring(1); | |
result = this.element.Attribute(attName).Value; | |
return true; | |
} | |
var subElements = this.element.Elements(name).ToList(); | |
// 要素がないときは null 返す。 | |
if (subElements.Count == 0) | |
{ | |
result = (string)null; | |
return true; | |
} | |
// 要素が1個だけの時は素直にその要素を返す。 | |
if (subElements.Count == 1) | |
{ | |
var e = subElements[0]; | |
result = new DynamicXml(e); | |
return true; | |
} | |
// 要素が複数ある時はリストで要素一覧を返す。 | |
var es = subElements.Select(x => new DynamicXml(x)); | |
result = es.ToList(); | |
return true; | |
} | |
public override bool TryConvert(ConvertBinder binder, out object result) | |
{ | |
// string へのキャストで、要素の値を取得。 | |
if (binder.Type == typeof(string)) | |
{ | |
result = this.element.Value; | |
return true; | |
} | |
// int へのキャストで int.Parse。 | |
// Parse できないときは例外丸投げ。 | |
if (binder.Type == typeof(int)) | |
{ | |
result = int.Parse(this.element.Value); | |
return true; | |
} | |
// 要素単体に対して foreach やっちゃったときでもエラーにならないように、IEnumerable へのキャストを定義。 | |
// これやっとかないと、元々複数要素あったのに XML を修正して要素が1個だけになった時に挙動おかしくなる。 | |
if (binder.Type == typeof(System.Collections.IEnumerable)) | |
{ | |
result = new[] { this }; | |
return true; | |
} | |
result = null; | |
return false; | |
} | |
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) | |
{ | |
switch (binder.Name) | |
{ | |
case "GetEnumerator": // IEnumerable へのキャストと同様の理由。 | |
result = new[] { this }.GetEnumerator(); | |
return true; | |
case "All": // All() 呼び出しで、子要素を全部取得できるようにする。 | |
result = this.element.Elements().Select(x => new DynamicXml(x)).ToList(); | |
return true; | |
case "Name": // Name() で要素名を取得。 | |
result = this.element.Name.ToString(); | |
return true; | |
} | |
return base.TryInvokeMember(binder, args, out result); | |
} | |
public override string ToString() | |
{ | |
return this.element.Value; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment