VisualStudio拡張機能を開発してのTipsまとめ
はじめに
開発の補助ツールとしてVisualStudio拡張機能を開発することがあったので、得られた知見をまとめ。
なお、利用したのはVisualStudio2019で、Vspackage で独自のコンテキストメニューを追加する拡張機能を開発した。
基本的な知識は、公式ドキュメント(Visual Studio SDK - Visual Studio | Microsoft Docs)を参照。
Tips
「○○へのアクセスはメイン スレッドでのみ行う必要があります。まず Microsoft.VisualStudio.ProjectSystem.IProjectThreadingService.VerifyOnUIThread() を呼び出します。」の警告対策
作ってる側としては問題ない気でもこの警告がガンガンでてくる。
この警告が出てくる箇所の前で
ThreadHelper.ThrowIfNotOnUIThread();
を呼び出す。
メソッド単位で出てくるので大変。この対応で合っているのかは不明・・。
コンテキストメニューを追加する
エディタ部分で右クリックしたときのメニュー項目の足し方。
コマンドを追加した後、vsctファイルにて下記のようにParentのidとして"IDM_VS_CTXT_CODEWIN"を指定する。
表示位置を変えたい場合、priorityの値を調整する。
<Groups> <Group guid="guidMyExtensionPackageCmdSet" id="MyMenuGroup" priority="0x0001"> <Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_CODEWIN"/> </Group> </Groups>
特定の条件の場合のみメニューを表示する
vsctファイルにて、デフォルト非表示、表示を動的に設定する。
具体的にはCommandFlagとしてDefaultInvisible、DynamicVisibilityを指定する。
<Button guid="guidMyExtensionPackageCmdSet" id="ConfigJumpCommandId" priority="0x0100" type="Button"> <Parent guid="guidMyExtensionPackageCmdSet" id="MyMenuGroup" /> <Icon guid="guidImages" id="bmpPic1" /> <CommandFlag>DefaultInvisible</CommandFlag> <CommandFlag>DynamicVisibility</CommandFlag> <Strings> <ButtonText>Invoke Command</ButtonText> </Strings> </Button> </Buttons>
そして、CommandクラスのOnBeforeQueryStatusにてVisible属性をON/OFFする。
private void OnBeforeQueryStatus(object sender, EventArgs e) { var cmd = sender as OleMenuCommand; if(表示条件) { cmd.Visible = true; } else { cmd.Visible = false; } }
DTEを利用する
VisualStudioで開いているソリューションやプロジェクト、開いているファイル等にアクセスするには、DTEオブジェクトを利用する。
DTEオブジェクトはCommandクラスのInitializeAsyncにて以下のように取得する。
※CommandクラスにはDTE型のインスタンス変数_dteを用意してある前提
public static async Task InitializeAsync(AsyncPackage package) { // Switch to the main thread - the call to AddCommand in ConfigJumpCommand's constructor requires // the UI thread. await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken); OleMenuCommandService commandService = await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService; Instance = new MyCommand(package, commandService); Instance._dte = package.GetServiceAsync(typeof(EnvDTE.DTE)) as EnvDTE.DTE; }
DTEでカーソルのある行のテキストを取得する
選択行を取得、選択範囲を変更することでカーソル行テキストを取得できる。
ただしカーソルの移動を伴うため、利用時には横スクロール位置が移動するなど弊害も出ることがあるので注意。
_dteという変数でDTEオブジェクトを持っているものとする。
public string GetCurrentLineString() { ThreadHelper.ThrowIfNotOnUIThread(); var textDocument = (TextDocument)_dte.ActiveDocument.Object("TextDocument"); var selection = textDocument.Selection; // 元の選択範囲を保持する var begin = selection.TextRanges.Item(1).StartPoint; var end = selection.TextRanges.Item(selection.TextRanges.Count).EndPoint; selection.StartOfLine(); selection.EndOfLine(true); var line = selection.Text; // 元の選択範囲を復元する selection.MoveToLineAndOffset(begin.Line, begin.LineCharOffset); selection.MoveToLineAndOffset(end.Line, end.LineCharOffset, true); return line; }
DTEからソリューション、プロジェクトにアクセスする
ソリューションから取得するProjectはソリューション直下のもので、ソリューションフォルダも含まれるため注意。
また、ProjectItemもプロジェクト直下のものであるため、プロジェクト内から特定のファイルを探す場合には再帰的に探す必要があるため注意。
// ソリューションを取得 var solution = _dte.Solution; // ソリューション名 var solutionFullName = solution.FullName; var solutionFileName = solution.FileName; // プロジェクトを取得 var projects = solution.Projects foreach(Project project in projects) { // プロジェクト内のアイテムを取得 foreach(ProjectItem item in project.ProjectItems) { // 何か処理をする } }
ProjectItemを開き特定の行へ移動、選択状態にする
ProjectItem projectItem = 何らか取得する; int lineNo = 行数; // 開いてなかったら開く if (!projectItem.IsOpen[Constants.vsViewKindAny]) { projectItem.Open(); } // アクティブにする projectItem.Document.Activate(); // 指定の行に移動する TextDocument textDocument = (TextDocument)projectItem.Document.Object("TextDocument"); TextSelection selection = textDocument.Selection; selection.GotoLine(lineNo, true); // 行を選択状態にする selection.StartOfLine(); selection.EndOfLine(true);
特定のファイルを開き、特定の行へ移動、選択状態にする
_dteという変数でDTEオブジェクトを持っているとする。
string filePath = 開きたいファイルパス; // ファイルを開く var window = _dte.ItemOperations.OpenFile(filePath); // アクティブにする window.Document.Activate(); // 指定の行に移動する TextDocument textDocument = (TextDocument)window.Document.Object("TextDocument"); TextSelection selection = textDocument.Selection; selection.GotoLine(lineNo, true); // 行を選択状態にする selection.StartOfLine(); selection.EndOfLine(true);
おわりに
ググってもあまり情報は多くなかったので、同じ境遇の方に参考になれば幸いです。
AzureFunctionsをVisualStudioでデバッグ実行するとCould not load file or assembly Microsoft.AspNetCore.Mvc.Abstractions, Version=2.0.2.0 エラーになる
細かいトラブルシュートネタ。
環境
- VisualStudio 2017 15.6.7
現象
VisualStudioからAzureFunctions v2(.NET Core)プロジェクトを新規作成する。
この時点では下記の警告が出ているものの、デバッグ実行は問題なく実行可能。
警告 NU1701 パッケージ 'Microsoft.AspNet.WebApi.Client 5.2.2' はプロジェクトのターゲット フレームワーク '.NETStandard,Version=v2.0' ではなく '.NETFramework,Version=v4.6.1' を使用して復元されました。このパッケージは、使用しているプロジェクトとの完全な互換性がない可能性があります。
この警告を解消しようと、とりあえずNuGetパッケージを更新することに。
[ツール]→[NuGetパッケージマネージャー]→[ソリューションのNuGetパッケージの管理]からMicrosoft.NET.Sdk.Functionsを更新。
警告が消えて満足したものの、デバッグ実行をしてみると、下記エラーが発生するようになってしまった。
[2018/08/27 13:24:30] Reading host configuration file 'C:\Users\endok\source\repos\FunctionApp1\FunctionApp1\bin\Debug\netstandard2.0\host.json' [2018/08/27 13:24:30] Host configuration file read: [2018/08/27 13:24:30] { [2018/08/27 13:24:30] } [2018/08/27 13:24:31] ScriptHost initialization failed [2018/08/27 13:24:31] System.Private.CoreLib: Could not load file or assembly 'Microsoft.AspNetCore.Mvc.Abstractions, Version=2.0.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. Could not find or load a specific file. (Exception from HRESULT: 0x80131621). System.Private.CoreLib: Could not load file or assembly 'Microsoft.AspNetCore.Mvc.Abstractions, Version=2.0.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. Listening on http://localhost:7071/ Hit CTRL-C to exit... Object reference not set to an instance of an object.
LogicoolのSetPointでたまに設定が初期化される件
LogicoolのワイヤレスマウスM560が気に入っていて、自宅用と会社用にそれぞれ購入して使っているほどである。Logicool製デバイスの制御のためにSetPointというソフトウェアが提供されていて、これを使うとマウス速度の変更や、アプリケーション毎にボタン割り当ての変更ができる。
SetPointの機能自体は非常に便利で満足しているのだが、スタイバイ復帰やディスプレイ切り替えの拍子に設定が効かなくなることがあったりして若干の不安定さを抱えている。その中でも以前から悩ましかったのが設定が初期化されてしまう件について。
ググった対処法だけでは対応できなかったので対応をメモ。
環境
- Windows10 Enterprise
- SetPoint コントロールセンター6.67.83/ドライバ5.90.41
事象
何らかのタイミング(スタンバイ復帰時や再起動時?)でSetPointのマウス設定が初期化される。
普段はマウスをOFF/ONしてつなぎ直すか、タスクトレイのSetPointをダブルクリックして開くと解決することが多いのだけど、それでは解決しないことが2,3ヶ月に1回程度ある。
SetPointの「マイマウス」タブが一時的に表示されないという事象も発生していた(と思う)。
→こちらは再起動など色々やっていたらいつの間にか直っていた。
同様の事例情報
「SetPoint 初期化」でググると、同様の事象は出てくる。
setpointさんがまじでsetpointさんなので強制的にアプリ設定がリセットされないようにした(autohotkey2) - のら(NORA)のブログ
オレメモ: SetPointが初期化されるアレ
SetPointのアプリケーション固有の設定がデフォルトに戻るのを防ぐ - Logicool
■月筆■ SetPointの設定がPCの再起動で初期化された
対処法
上記記事にも記載があるが、設定ファイルの位置は下記となる。
・機種別デフォルト設定
C:\ProgramData\LogiShrd\SetPointP\Devices\PointingDevice\[マウスのモデルID(16進数表記)]\[マウスのモデルID(16進数表記)].xml
・ユーザー設定
C:\Users\[ユーザー名]\AppData\Roaming\Logitech\SetPoint
モデルIDはuser.xmlにModel="XXX"という形で記載してある。(ReceiverのModelと間違えないように注意)
M560の場合は下記のように記載があり、16781313(10進数)=100010001(16進数)がモデルIDである。
16進数への変換はWindows標準の電卓のプログラマモードなどで可能。
<Device DisplayName="Wireless Mouse M560" Class="PointingDevice" Model="16781313" NumberOfButtons="7" ConnectionID="">
まずは機種別デフォルト設定でOverride設定が無いか確認したが、こちらは特に問題なし。
次に正常だった時のuser.xmlのバックアップから設定ファイルを戻してみるも、SetPointの再起動、OS再起動をしても設定が戻らない。
なんでだろーと思い、設定ファイルの比較をしていると原因が判明。
user.xml内にM560用の設定が複数記載されており、Modelが16781313のものから16781316まで4種類もあった。
機種別の設定フォルダを見てみると、user.xmlのModelと対応するように100010001~100010004までフォルダができていた。
(最初は100010001だけだったと思うんだけど・・・)
理由はよくわからないが何らかのタイミングでModelのIDが変わっていっているようで、そのタイミングで初期化されたように見えていたようだ。
SetPointから設定保存をしてみると、現在は100010004として認識されている模様。
100010001の設定バックアップから戻していたため反映されていなかったと思われる。
最終的には、設定バックアップから復元後、Modelの値を書き換えることでSetPointに設定が認識された。
まとめ
根本的な原因は不明なものの、対処法はわかったのでとりあえずは満足。しかし他の方の記事を見る限り数年前から発生しているようなので、そもそもSetPoint側でしっかり対応して欲しいところ。公式に明言されていない設定ファイルを直接どうこうするというのは、バッドノウハウ感がすごい。
ディープラーニングG検定(JDLA Deep Learning for GENERAL 2018 #1)を受験した
JDLAのディープラーニングG検定を2018/06/16に受験したので、勉強方法や出題傾向、感想などを書いてみる。
公式サイトはこちら。
協会活動 | 一般社団法人 日本ディープラーニング協会 Japan Deep Learning Association
きっかけ、事前知識
インフラ勉強会(https://wiki.infra-workshop.tech/)のディープラーニング回にて、発表者の方がこの検定取得を目指していることを知る。
申し込み受付中かつ試験まで丸々3週間というところだったので、これは間に合うのでは?ということで申し込み。
大学時代に機械学習/統計解析の研究室にいたので、ある程度の下地はあり。
研究にはニューラルネットワーク&強化学習を利用していたので、その辺りはそこそこわかるつもり。
ただその頃はディープラーニングが流行る直前くらい(2006年~2010年あたりかな)の時期だったので、最近の手法は知らない状態。
どんな試験か
- オンライン受験(自宅受験)
- 制限時間120分
- 小問228問
- 出題範囲はシラバス参照(http://www.jdla.org/business/certificate/#G)
- 推薦図書が3冊あり
推薦図書は下記の3冊。
- 人工知能は人間を超えるか ディープラーニングの先にあるもの 角川EPUB選書 (著)松尾 豊 KADOKAWA
- AI白書 2017 (編)独立行政法人情報処理推進機構 AI白書編集委員会 角川アスキー総合研究所
- 深層学習 機械学習プロフェッショナルシリーズ (著)岡谷 貴之 講談社
小問が228問と聞くとかなり多く感じるが、文章の穴埋め1つで1問という数え方なので、実際に解くとそこまで時間はツラくない。
勉強方法
試験まで3週間とそこそこ期間があったので、推薦図書は一通りなめる形で勉強を進めた。
- 推薦図書を一通り読む。順番は「人工知能は人間を超えるか」→「AI白書」→「深層学習」
- シラバスに沿って各推薦図書から要点を抜き出した資料作成(Word)
- ネット上の受験記を探して情報収集+公式の例題をもとに資料を肉付け
- 作成した資料を覚える
推薦図書ごとのおすすめの読み方、出題傾向は下記の通り。
・人工知能は人間を超えるか
内容的にディープラーニング学習の導入にぴったり、ボリュームも手頃で読みやすいため、最初に読むことをおすすめ。
シラバスとの対応としては、「人工知能(AI)とは(人工知能の定義)」「人工知能をめぐる動向」「人工知能分野の問題」あたりに相当する。
範囲的にはAI白書と被る部分もあるが、用語の説明はこちらの方がわかりやすい。
将来的な話も後半多いが、その辺りは置いておいて人工知能の歴史とキーワード、ディープラーニングの概要、何がすごいのか、をこの本でおさえるとよい。
直接的に問題として聞かれる内容はそんなに多くはないという印象であった。
・AI白書
白書という名前だけあって網羅的な内容になっており、すべてを覚えるというのは難しい。
最初から最後まで一応目を通したが、途中から文字列を脳に流し込むだけの状態になっていたので、通し読みする価値があるかは疑問。
試験対策としてはシラバスと対応する箇所を探し、用語や重要そうな事例に絞って覚えるという使い方がよいだろう。
シラバスとの対応としては、ディープラーニングの具体的な手法を除いたほぼ全範囲に関連している。
ディープラーニングの研究や応用、法律、倫理や現行の議論といった話はこの本にしか無いので、そこは重点的に読み込むとよい。
扱う範囲が広いこともあり、ここからの出題比率は高い印象であった。(問題文にこの本を出典としている旨が書いてあるものもあった)
・深層学習
ディープラーニングの具体的な手法や計算方法、テクニックについての本。
数式が結構出てくるが、試験にはほぼ出てこないので、文章や図から読み取れる考え方だけ理解しておけばよい。
シラバスとの対応としては、「ディープラーニングの概要」「ディープラーニングの手法」あたりに相当する。
計算問題(順伝播の計算と偏微分とCNNのパディング、ストライド後画像サイズ)やディープラーニングにおけるテクニックについてはこの本から出ているという印象であった。
試験を終えて
問題量が多いとの評判だったため、わからない問題は悩まずにチェックして次に進むという方法で解いたところ、70分程度で1週目の回答が終わった。その後チェックを付けた問題の2週目を解いて回って時間いっぱいという感じであった。
参考図書には無かったと思われる問題もそこそこあり、機械学習や統計解析の手法のあたりで特に多く感じた。(参考図書はあくまで"参考"ということなんでしょう・・)
全然わからんなーとなった問題で覚えているのは下記の通り。
- アーサー・サミュエルによる人工知能の定義(参考図書にあったかも?)
- SVMとスラック変数、カーネル法、カーネルトリック
- ロジスティック回帰
- 交差検証の方法
- 汎化誤差のバリアンス、バイアス、ノイズ
- カプセルネットワーク
- 後半の法律、倫理、現行の議論の問題全般
機械学習/統計解析手法のところは、1つの話題で数問聞かれるので、全然知らない話題だと結構ショックを受ける。
法律、倫理、現行の議論のところは、「上記はいずれもあてはまらない」のような選択肢が大体最後に付いていて、正確に覚えていないと回答は困難であった。しかしこのあたりの話題を自信持って答えられるほど勉強はしていないので、適当に回答。
自宅での受験という受験形式は初だったが、選択問題ということもあり環境的には特に問題なし。
前回と問題がどのくらい変わっているかわからないが、この受験方式だと過去問出回った途端に合格率が跳ね上がりそうなものだが、大丈夫なんだろうかと心配になる。
受験後の感触は、大問の中の小問が全部合ってて正解方式だと厳しいかもしれないが、小問単独で得点がもらえるなら十分合格していそうというところ。
結果は1週間とわりとすぐに出るようなので、期待して待ちましょう。
まとめ
急に受けることにした試験だったが、ここ数年のAI技術の概要は掴めたと思うし、ジェネラリストという名前の通り、これに受かる知識があればビジネスでAIの話をするレベルになれる良試験だと感じた。
受験料が高いという話もあるが、G検定ならまだ個人でも手が出る程度だし、E検定もベンダー系の資格と思えばそんなに高くはない・・・かも(私は受けない)。
ディープラーニング検定といいつつ実態は人工知能検定なので、名前を変えたほうが受験者増えるんじゃないのという気はする。
開始して間もない試験で、持ってると少なくとも話のネタにはなると思うので、人工知能気になるけどなかなかきっかけが無いという方におすすめの試験です。
Windows10でnslookupするとQuery refusedになる
簡単なトラブルシュートメモ。
環境はWindows10 Pro。
DNSの勉強でもしようとwww.yahoo.co.jpにnslookupしようとしたところ、下記のように名前解決に失敗した。
PS C:\Users\endok> nslookup www.yahoo.co.jp サーバー: UnKnown Address: 2404:1a8:7f01:b::3 *** UnKnown が www.yahoo.co.jp を見つけられません: Query refused
インターネットには繋がっており、ブラウザからであれば表示できるため、nslookup時にうまくいかないだけの様子。
また、digは成功する。
PS C:\Users\endok> dig www.yahoo.co.jp ; <<>> DiG 9.11.2 <<>> www.yahoo.co.jp ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 17486 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;www.yahoo.co.jp. IN A ;; ANSWER SECTION: www.yahoo.co.jp. 311 IN CNAME edge.g.yimg.jp. edge.g.yimg.jp. 14 IN A 182.22.24.124 ;; Query time: 7 msec ;; SERVER: 192.168.11.1#53(192.168.11.1) ;; WHEN: Sat Jan 20 23:57:10 ???? (?W???) 2018 ;; MSG SIZE rcvd: 86
ググってみると、下記の質問に状況が近い。
answers.microsoft.com
ということで、現在特にIPv6は必要ないため、IPv6を無効にしたところ無事解決。
具体的には、
コントロール パネル > ネットワークとインターネット > ネットワークと共有センター
を開き、対象の接続を選択してプロパティを開く。
そしてインターネットプロトコルバージョン6(TCP/IPv6)のチェックを外してOKすればよい。
PS C:\Users\endok> nslookup www.yahoo.co.jp サーバー: ap-endo Address: 192.168.11.1 権限のない回答: 名前: edge.g.yimg.jp Address: 182.22.25.124 Aliases: www.yahoo.co.jp
しかし今はIPv6関連で何かあったらとりあえず無効にして回避してるけど、本格的に使わないといけなくなってきたらちゃんと対応しなきゃいけないんだろうなぁ・・・。