1. kob58im

    No comment

    kob58im
Changes in body
Source | HTML | Preview
@@ -1,248 +1,263 @@
-判ったこと:PSObjectのMembersプロパティやMethodsプロパティは、COMオブジェクトの情報は拾えないようである。。
+
+
+![comobjbrowser.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438183/74fe8480-6a6e-700c-51dc-5f7497a1dc04.png)
+
```csharp
using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
using System.Management.Automation;
class MainForm:Form
{
Button btn;
+ Button btnGetMembers;
SplitContainer spl;
+ TextBox txtClassName;
ListView lsvObj;
ListView lsvMemb;
- ListView lsvMethod;
static Collection<PSObject> GetObjNames()
{
string[] source = new string[] {
@"$a = dir REGISTRY::HKEY_CLASSES_ROOT\CLSID -Include PROGID -Recurse",
"$a | foreach {$_.GetValue(\"\")} | sort"
};
using ( var invoker = new RunspaceInvoke() ) {
Collection<PSObject> tmp = invoker.Invoke(source[0]);
Collection<PSObject> result = invoker.Invoke(source[1]);
return result;
}
}
+ static Collection<PSObject> GetMembers(string comObjectName)
+ {
+ Regex r = new Regex(@"^[._0-9A-Za-z]+$");
+
+ if ( r.IsMatch(comObjectName) ) { // 危険なパラメータが混入しないように簡易チェック
+ string[] source = new string[] {
+ "$t = New-Object -ComObject " + comObjectName,
+ "Get-Member -InputObject $t"
+ };
+
+ using ( var invoker = new RunspaceInvoke() ) {
+ try {
+ Collection<PSObject> tmp = invoker.Invoke(source[0]);
+ Collection<PSObject> result = invoker.Invoke(source[1]);
+ return result;
+ }
+ catch (System.Management.Automation.CmdletInvocationException e) {
+ // memo:
+ // VideoRenderCtl.VideoRenderCtl.1 選んだらCreateInstanceに失敗したっぽい例外を吐いたので
+ // とりあえずcatchしておく
+ Console.WriteLine(e);
+ return new Collection<PSObject>();
+ }
+ }
+ }
+ else {
+ return new Collection<PSObject>();// 要素数 0 の Collection を返しておく
+ }
+ }
+
MainForm()
{
- Text = "Object Browser";
+ Text = "COM Object Browser";
btn = new Button();
btn.Size = new System.Drawing.Size(130,25);
btn.Text = "Get Object List";
- btn.Click += (sender,e)=>{ReloadPSObject();};
+ btn.Click += (sender,e)=>{ReloadLsvObj();};
Controls.Add(btn);
+ txtClassName = new TextBox();
+ txtClassName.Location = new Point(160, 0);
+ txtClassName.Width = 250;
+ txtClassName.Text = "InternetExplorer.Application";
+ Controls.Add(txtClassName);
+
+ btnGetMembers = new Button();
+ btnGetMembers.Location = new Point(430, 0);
+ btnGetMembers.Size = new System.Drawing.Size(130,25);
+ btnGetMembers.Text = "Get Members";
+ btnGetMembers.Click += (sender,e)=>{ReloadLsvMemb(txtClassName.Text);};
+ Controls.Add(btnGetMembers);
+
spl = new SplitContainer();
spl.Location = new Point(0, btn.Bottom);
spl.Orientation = Orientation.Vertical;
Controls.Add(spl);
////// 左 Panel ここから
lsvObj = new ListView();
lsvObj.View = View.Details;
lsvObj.FullRowSelect =true;
lsvObj.GridLines = true;
- lsvObj.Columns.Add("Name", 170, HorizontalAlignment.Left);
+ lsvObj.Columns.Add("Name", 210, HorizontalAlignment.Left);
lsvObj.Dock = DockStyle.Fill;
lsvObj.SelectedIndexChanged += LsvObj_SelectedIndexChanged;
spl.Panel1.Controls.Add(lsvObj);
////// 左 Panel ここまで
////// 右 Panel ここから
- var tabc = new TabControl();
- tabc.Dock = DockStyle.Fill;
- spl.Panel2.Controls.Add(tabc);
-
- var tabp1 = new TabPage();
- tabp1.Text = "Members";
- tabp1.Dock = DockStyle.Fill;
- tabc.Controls.Add(tabp1);
-
lsvMemb = new ListView();
lsvMemb.View = View.Details;
lsvMemb.FullRowSelect =true;
lsvMemb.GridLines = true;
- lsvMemb.Columns.Add("Name", 90, HorizontalAlignment.Left);
- lsvMemb.Columns.Add("MemberType", 90, HorizontalAlignment.Left);
- lsvMemb.Columns.Add("TypeNameOfValue", 230, HorizontalAlignment.Left);
+ lsvMemb.Columns.Add("MemberType", 70, HorizontalAlignment.Left);
+ lsvMemb.Columns.Add("ReturnType", 100, HorizontalAlignment.Left);
+ lsvMemb.Columns.Add("Name", 130, HorizontalAlignment.Left);
+ lsvMemb.Columns.Add("Definition", 350, HorizontalAlignment.Left);
lsvMemb.Dock = DockStyle.Fill;
- tabp1.Controls.Add(lsvMemb);
-
- // --
-
- var tabp2 = new TabPage();
- tabp2.Text = "Methods";
- tabp2.Dock = DockStyle.Fill;
- tabc.Controls.Add(tabp2);
-
- lsvMethod = new ListView();
- lsvMethod.View = View.Details;
- lsvMethod.FullRowSelect =true;
- lsvMethod.GridLines = true;
- lsvMethod.Columns.Add("ReturnType", 90, HorizontalAlignment.Left);
- lsvMethod.Columns.Add("Name", 90, HorizontalAlignment.Left);
- lsvMethod.Columns.Add("Arguments", 300, HorizontalAlignment.Left);
- lsvMethod.Dock = DockStyle.Fill;
- tabp2.Controls.Add(lsvMethod);
+ spl.Panel2.Controls.Add(lsvMemb);
////// 右 Panel ここまで
- ClientSize = new System.Drawing.Size(700,530);
-
-
+ ClientSize = new System.Drawing.Size(800,530);
Load += Form_Resize;
Resize += Form_Resize;
ResizeEnd += Form_Resize;
}
void Form_Resize(object sender, EventArgs e)
{
spl.Size = new System.Drawing.Size(ClientSize.Width, ClientSize.Height - spl.Top);
}
- void ReloadPSObject()
+ void ReloadLsvObj()
{
Collection<PSObject> psObjs;
btn.Enabled = false; // 処理に時間がかかるので操作を禁止しておく。※結局押したら意味ないかも
try {
psObjs = GetObjNames();
}
finally {
btn.Enabled = true;
}
lsvObj.Items.Clear();
lsvObj.BeginUpdate();
try {
foreach ( var t in psObjs ) {
lsvObj.Items.Add(MyNewListItem_LsvObj(t));
}
}
finally {
lsvObj.EndUpdate();
}
}
- void ReloadPSMemberInfo(PSMemberInfoCollection<PSMemberInfo> memberInfos)
+ void ReloadLsvMemb(string comName)
{
- lsvMemb.Items.Clear();
- lsvMemb.BeginUpdate();
+ Collection<PSObject> psObjs;
+
+ btnGetMembers.Enabled = false;
try {
- foreach ( var mi in memberInfos ) {
- lsvMemb.Items.Add(MyNewListItem_LsvMemb(mi));
- }
-
+ psObjs = GetMembers(comName);
+
}
finally {
- lsvMemb.EndUpdate();
+ btnGetMembers.Enabled = true;
}
- }
-
- void ReloadPSMethodInfo(PSMemberInfoCollection<PSMethodInfo> methodInfos)
- {
- lsvMethod.Items.Clear();
- lsvMethod.BeginUpdate();
+
+ lsvMemb.Items.Clear();
+ lsvMemb.BeginUpdate();
try {
- foreach ( var mi in methodInfos ) {
- foreach ( string s in mi.OverloadDefinitions ) {
- lsvMethod.Items.Add(MyNewListItem_LsvMethod(s));
- }
-
+ foreach ( var t in psObjs ) {
+ lsvMemb.Items.Add(MyNewListItem_LsvMemb(t));
}
}
finally {
- lsvMethod.EndUpdate();
+ lsvMemb.EndUpdate();
}
}
ListViewItem MyNewListItem_LsvObj(PSObject psObj)
{
var itm = new ListViewItem(new string[]{psObj.ToString()});
itm.Tag = psObj;
return itm;
}
-
- ListViewItem MyNewListItem_LsvMemb(PSMemberInfo mi)
- {
- // https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.psmemberinfocollection-1.item?view=pscore-6.2.0
- var itm = new ListViewItem(new string[]{mi.Name, mi.MemberType.ToString(), mi.TypeNameOfValue});
- return itm;
- }
-
- ListViewItem MyNewListItem_LsvMethod(string s)
+
+ ListViewItem MyNewListItem_LsvMemb(PSObject psObj)
{
ListViewItem itm;
- Regex r = new Regex(@"^([^ ]+) ([^( ]+)\((.*)\)$");
- Match m = r.Match(s);
+ Regex r = new Regex(@"^([^ ]+)\b");
+ // フォーマットが複雑すぎて分解することが困難なため、戻り値の型(っぽい)部分だけを取り出す。
+ // - overloadが1行に入ってたりする (例: System.Random)
+ // - 仮引数名があったりなかったり
+ // - ()がない場合もある
+ // - ()がネストしている場合もある
+ // - 後ろに{get} {set} がつく場合もある
+
+ Match m = r.Match(psObj.Members["Definition"].Value.ToString());
+ //Match m = r.Match(psObj.ToString());
if ( m.Success ) {
+ string memberType = (psObj.Members["MemberType"].Value).ToString(); // PSMemberTypes (Method / Property など)
string returnType = m.Groups[1].Value;
- string methodName = m.Groups[2].Value;
- string arguments = m.Groups[3].Value;
- itm = new ListViewItem(new string[]{returnType , methodName, arguments});
+ string methodName = psObj.Members["Name"].Value.ToString();
+ string definition = psObj.Members["Definition"].Value.ToString();
+ itm = new ListViewItem(new string[]{memberType, returnType , methodName, definition});
}
else {
- // 想定外の形式の場合は、とりあえず全文表示しておく
- itm = new ListViewItem(new string[]{"", "", s});
+ // 想定外の形式の場合は、とりあえずToString()して表示しておく
+ itm = new ListViewItem(new string[]{"", "", "", psObj.ToString()});
}
return itm;
}
-
void LsvObj_SelectedIndexChanged(object sender, EventArgs e)
{
if (lsvObj.SelectedIndices.Count != 1) {return;}
int index = lsvObj.SelectedIndices[0];
PSObject psObj = (PSObject)(lsvObj.Items[index].Tag);
- ReloadPSMemberInfo(psObj.Members);
- ReloadPSMethodInfo(psObj.Methods);
+ txtClassName.Text = psObj.ToString();
}
-
-
[STAThread]
static void Main(){
Application.Run(new MainForm());
}
}
+```
+判ったこと:
+PSObjectのMembersプロパティやMethodsプロパティは、COMオブジェクトの情報は拾えないようである。。
+
機能追加したいこと:
-・検索(filtering)
・テキストコピーできるようにする
-オブジェクトリストの取得に時間かかるのでキャッシュしたい・・
+ListView上の検索(filtering)
-```
# コンパイル方法
```
csc ^
/r:C:\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll ^
xxxx.c
```
# 参考サイト
-- [powershellのよびだし (++C++)](https://ufcpp.net/study/powershell/interop.html)
+- [C# 上で PowerShell スクリプトを実行 (++C++; //未確認飛行 C)](https://ufcpp.net/study/powershell/interop.html)
- [PSObjectクラス (Microsoft) ](https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.psobject?view=pscore-6.2.0)