トップ回答者
拡張機能作成に関する基本的内容

質問
-
VS 2017向けの拡張機能(コマンド)作成の際に気になった、こまごまとした点がいくつかあったので質問させてください。
【Q1】
DTE関連を使う関数内では、先に
ThreadHelper.ThrowIfNotOnUIThread();
を呼んでおく必要があるようなのですが、明らかにUIスレッドからしか呼ばれないコードになっているはず、というケースでも、警告を抑制するためには、DTE関連のものに触れる関数は片っ端から書く必要があるような感じがしてます。
これは面倒でも仕方ない、やっておくべきという事でしょうか?
それとも、クラスに何か属性とかつけたら、そのメンバのメソッドでは省略出来たり・・・とかはないでしょうか?
【Q2】
DTEを使ってソリューション構成を確認するような一連の処理内では、別スレッドに処理を移しUIスレッドにおける現在のコールスタックを一時的に手放してしまう可能性のある、async awaitは、ソリューション構成がその時変化する可能性も考えると、「使う事はできない」と考えるべきでしょうか?
【Q3】
を見ると、Microsoft.VisualStudio.PlatformUI.DialogWindow から派生したものにShowModalすることが推奨されていますが
特にデザインにこだわりのない、ちょっとした設定ダイアログをサクッと作ろうとしたときにWPFは若干面倒に感じたのですが、Windows Formsの Form.ShowDialogではダメなのでしょうか?
【Q4】
通常の.exeなどでは自由なパスに自由に動的な、環境設定向けファイルを作ることができますが
拡張機能の場合、アプリケーションの動的な設定は、プロジェクトのプロパティ(Settings.settings使用 …… user.configに記録される)でやればいいでしょうか?
【Q5】
InitializeAsyncは初回コマンド実行時に呼ばれるようですが、これだけだと、その拡張機能の付属させたイベント発火等は初回コマンド実行時までは有効になりません。
これより前のタイミング・・・
Visual Studioの起動時に任意の処理を走らせれるような方法はないでしょうか?
また、初期化イベントと対になる、終了・解放関連に使えるようなイベントはないでしょうか?
- 編集済み mr.setup 2020年7月2日 22:36
回答
-
>1
- 全体で警告を無効にする場合
ソリューションエクスプローラーでプロジェクトの参照を展開するとアナライザーが存在しているはずです。
そのアナライザーのMicrosoft.VisualStudio.Threading.Analyzersを展開してVSTHRD010を右クリックして、重要度を「なし」などに変更できます。 - 一部分を無効にする場合
#pragma warning disable VSTHRD010
//ここに警告VSTHRD010が出る処理
#pragma warning restore
>2
awaitする場合はCancellationTokeを渡しておいて、SolutionEventsやProjectItemEventsを検知したらキャンセル
>3
VS本体の処理や他の拡張機能と協調sる必要があり自分が全てを管理できないので、リンク先の説明されているように問題が出ます。(async/awaitでズレたタイミングでダイアログ表示すると他のダイアログの上にダイアログが出たりもする)
WPFで作るのが苦手ならWindowsFormsHostでFormのUserControlを表示させればいいです。
自分だけが使うツールなら気にせずFromだけで表示すればいいです。
>4
プロジェクトのプロパティというのが、拡張機能プロジェクトのuser.configという意味ならダメ。
それだとWindowsアカウント別に作られるが、VisualStudioはさらにプロファイルを切り替えられるのにプロファイル別に設定が保存されないことになる。PackageにDialogPageを関連づけて保存すればプロファイルごとの設定が保存でき、設定のインポートとエクスポートや別PC間でプロファイルの同期が可能になる。
>5
QueryCloseかDispose
一つのスレッドに複数質問されると、タイトルと内容が一致せず、あとで同じような疑問を持った人が調べるのが難しくなるし、回答者の手間が何倍にもなる。
なんどかアクセスしてるらしいのに分割されないので、しないと決めたみたいなので仕方ないね。
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答としてマーク mr.setup 2020年7月6日 8:55
- 全体で警告を無効にする場合
すべての返信
-
>1
- 全体で警告を無効にする場合
ソリューションエクスプローラーでプロジェクトの参照を展開するとアナライザーが存在しているはずです。
そのアナライザーのMicrosoft.VisualStudio.Threading.Analyzersを展開してVSTHRD010を右クリックして、重要度を「なし」などに変更できます。 - 一部分を無効にする場合
#pragma warning disable VSTHRD010
//ここに警告VSTHRD010が出る処理
#pragma warning restore
>2
awaitする場合はCancellationTokeを渡しておいて、SolutionEventsやProjectItemEventsを検知したらキャンセル
>3
VS本体の処理や他の拡張機能と協調sる必要があり自分が全てを管理できないので、リンク先の説明されているように問題が出ます。(async/awaitでズレたタイミングでダイアログ表示すると他のダイアログの上にダイアログが出たりもする)
WPFで作るのが苦手ならWindowsFormsHostでFormのUserControlを表示させればいいです。
自分だけが使うツールなら気にせずFromだけで表示すればいいです。
>4
プロジェクトのプロパティというのが、拡張機能プロジェクトのuser.configという意味ならダメ。
それだとWindowsアカウント別に作られるが、VisualStudioはさらにプロファイルを切り替えられるのにプロファイル別に設定が保存されないことになる。PackageにDialogPageを関連づけて保存すればプロファイルごとの設定が保存でき、設定のインポートとエクスポートや別PC間でプロファイルの同期が可能になる。
>5
QueryCloseかDispose
一つのスレッドに複数質問されると、タイトルと内容が一致せず、あとで同じような疑問を持った人が調べるのが難しくなるし、回答者の手間が何倍にもなる。
なんどかアクセスしてるらしいのに分割されないので、しないと決めたみたいなので仕方ないね。
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答としてマーク mr.setup 2020年7月6日 8:55
- 全体で警告を無効にする場合
-
gekkaさんありがとうございます。
一通り動作確認が完了しました。>1
今の所多すぎはしないので、毎回ThreadHelper.ThrowIfNotOnUIThread();を書くコードとして必要機能は揃っているため、後日追加機能の必要が生じた場合などにどうにも気になったら
#pragma warning disable VSTHRD010#pragma warning restore
で囲ったところに固めておくことにします。
>2
つまり、やはり非同期が絡めばソリューション構成の同一性の保証を別途考慮する必要があることは確かということですね。
今回の場合だと極力キャンセルはしたくないので、ひとまず長い処理にならないように注意して通常の同期処理にしておき、どうにも問題だという状況になったらその時考えます。
>3
「WindowsFormsHostでFormのUserControlを表示」は、具体的にはこんな感じですね
.NET TIPS WPF/XAMLでWindowsフォームを利用するには?[3.0、3.5、VS 2008、C#、VB]
出来ることは確認したので、対象の拡張機能の実装を変更するには少し時間がかかるため一旦はそのまま、公開必要性が生じたら、自作ダイアログを使う場合後日これで置き換えか、WPFをがっつり使うかを選ぶことにします。
ただ実際には4のDialogPageを使う方が良さげですね
>4
DialogPageの具体的な導入手順としては
たいちょーの雑記 > VisualStudioの設定ダイアログを作る
あたりでしょうか。
Hello Visual Studio Extensions
のようにPackageの派生クラスで
GetDialogPage(typeof(DialogPageの派生型)) as DialogPageの派生型
で取得するようにしておけば任意タイミングで参照できるっぽいですね。
>5
ProvideAutoloadAttributeの調査だけはまだ手を回していませんが、普段使うときはショートカットキーでコマンド実行でいい、設定は最初の時にどのみち読み込める…という結論になったため、結果的には使わなくてすむかもしれません。
どうにも必要になったらその時再調査させて頂きます。お手数おかけ致しました。
QueryCloseかDisposeはともに確認できました。
Disposeは、調べてみるとbool付きoverride時用の基本パターンがあるようですが、私自身.NET内部で要求されていることへの正確な理解が怪しいので、QueryCloseの方を主眼として対応することにします。
Remarksの内容 (By default this method returns
canClose
astrue
and S_OK. ) から行くと
protected override int QueryClose(out bool canClose) { //ここに任意処理 canClose = true; return 0; }
でよさそうですね。
------------------------以下は質問内容とは無関係です------------------------
Hebikuzure aka Murachi Akiraさんにもご指摘いただきました「1スレッド内で複数の異なる質問」の件ですが
分けすぎると、想定していなかった「背景の説明が求められたとき」にあちこちに散らばるのでわかり辛くなるケースがあります。
MSDNフォーラムでだったかは覚えていませんが、実際に分割しすぎて分かりにくいのでまとめてほしいというようなことを言われたケースは何度かあったと記憶しています。
また、質問している側は分からないから質問しているため、何と何の関係性が深いのか、全体像を把握している可能性は極めて低いです。一般的には、まとめるにしても分割するにしても、質問した時点で適切にそれを行うのは難しいというのが私の見解です。
加えて、今回は一つ一つの質問が非常にコンパクトなうえ、拡張機能の開発初学者が割と普通に必要(疑問)としやすい内容ではないかと思っていたため、わざわざ細かく分けるほどではなく、簡単にサクッと解決しそれほど掘り下げたりする必要もない事を期待・想定していたのですが、それについては若干見立てが間違っていたのかもしれません。(?)
実際は
3は4によりほぼ不要となり、gekkaさんのご回答では3のときにasync/awaitについて言及されていますが、これは2で私がasync awaitについて質問に記述したことによって自然に言及する流れになった可能性が高く思え、そうであるなら私にとっては2は3とセットで書いておいたことはあながち間違っているようには思われません。
そして、質問時点でこれらのことを予想するのは全くの不可能と言っていい状態でした。
とはいえ、1と2は若干関連してそうですが、1・2は3・4とは関連性は低そうなので、分けることもできたかもしれません。
ただし、たくさん質問を作っても、もし回答がつかなかったら無意味です。そこの確実性が全く不明だったのと、今重大な事がありそちらに非常に精神力・集中力を要し、見極めなければならない状況(というかまだ戦いの最中)だったため、判断を保留させて頂いていました。
仮に、 Hebikuzure aka Murachi Akiraさんが「質問を分ければ全部回答します」とおっしゃってくださっていた場合は、ほぼ確実に分けていたでしょう。
後は
>タイトルと内容が一致せず
の件は、タイトルは「拡張機能作成に関する基本的内容」という、具体的な内容を特定をするには何ともしょぼい、汎用的ではあるが特徴に欠ける内容になっているため、今回はその心配はないと思います。
また、特徴的なタイトルの場合であっても、多少の脱線はありつつも関連するものの総集編みたいな感じになってる方が、実は後から見る人にとって予想していなかった思わぬメリットとなる可能性もあり、一概に予測は困難です。複数あっても関連性が高い質問になっている場合は、用語を知らない状態から調べなければならない人の場合、まわりくどく関連性の高い言葉が色々付与されている文章の方が、複数のページに散らばっているよりかえって検索で見つけやすくなる可能性もあります。
>同じような疑問を持った人が調べるのが難しくなる
それは実際の所どうなのでしょうか?
ここに限ったことではないですが、フォーラムや掲示板等でやり取りされている内容は、未解決のままだったり丸投げされていたりということもザラにあります。(MSDNフォーラムは、平均的にはだいぶマシだとは思いますが)
どうしても重要で知る必要があるものを調べている場合、はじめから「これで一発解決しなくても、調査は続行する」という意気込みで調べる可能性が極めて高いです。(私自身はそうです)
重要度の低い調査の場合は、解決の成否によらず、適当に折り合いをつけれるでしょう。
また、「質問のタイトルをつけるのは詳細が分からないから聞いている質問者、答えは回答者の返信メッセージの中にある」および「質問のニーズの一致確率は、質問が必要なマイナーな内容ほど、それほどは期待できない」のが通常とすれば、ピンポイントに的確なタイトルでの質問でない限り、解決のために検索で強く機能するのはタイトルより本文の一部である可能性が高いです。
ただし
>回答者の手間が何倍にもなる。
これは確かにそうなのかもしれません。
ただ気になるのは、逆に、質問を分けたら何分の一とかになるのかどうかです。
私は質問文において、必ず全ての質問に答えてくださいとは言っていません。
ほんの一部であってもご回答いただければとても助かります。
また、別々の返信としてお答えいただきましても構いません
その前提だと、質問を分けるかどうかにはよらないと思います。
ただ、そうはいっても中途半端に回答するより全部まとめて回答出来た方が格好がつくとかはあるのかもしれません。
その視点は私には欠けていた可能性があります。
・相手がほぼ仕様を自分で決めれることに対する、細かい大量の質問一覧を、個人的に聞く
のと
・誰がどの程度知っているかわからない、自分で仕様を決めれないことに対する、多くの質問を、公の場で聞く
では、「答えやすさ」という点において、全く状況が違うといえるかもしれません。
最近は前者が必要になるケースが多かったため、同じような感覚で質問していた部分もあった気がします。
※しかし、結果としては gekkaさんのご協力により、この質問はあっさり決着ということでいいのではないか、と感じています。というより、gekkaさんがご存じないような点(少なくともすぐには答えられないような点)がもしあったとしたなら、それはもう「拡張機能作成に関する基本的内容」ではない、と考えていいんでは?とも考えていたため、その時は英語圏の利用も視野に入れ、ケースバイケースで対応することはあり得るというようなイメージで考えていた気がします。
しかしながら、今後質問する場合は、「内容の関連性の高さ」という点については、もう少し熟慮する価値があるということは言えそうですね。
- 編集済み mr.setup 2020年7月6日 8:57