トップ回答者
vsixを使った拡張機能の作成(ソリューションエクスプローラで選択しているファイルのパス取得)について

質問
-
Visual Studio 2015 を用いて、vsixを使った機能拡張の作成を行っています。
ソリューションエクスプローラに1つメニューを追加したのですが、C#プロジェクト配下のファイルであれば、フルパスを取得できます。
しかし、ソリューションフォルダ以下(C#プロジェクト等に属さない)のファイルの場合は取得できません。
一般的に公開されている 「copy as path 」(以下パス参照)でもエラーになります。
https://marketplace.visualstudio.com/items?itemName=AlexEyler.CopyasPath
これをモデル化されていないプロジェクトというのかと思いますが、
選択しているファイルのフルパスは取得できないのでしょうか?
コードはサンプルで以下のように記載しています。
-----------------------------------------------------------------------
private void MenuItemCallback(object sender, EventArgs e) { try { Object selectedObject = null; var monitorSelection = Package.GetGlobalService(typeof(SVsShellMonitorSelection)) as IVsMonitorSelection; IntPtr hierarchyPointer; uint projectItemId; IVsMultiItemSelect multiItemSelect; IntPtr selectionContainerPointer; monitorSelection.GetCurrentSelection ( out hierarchyPointer, out projectItemId, out multiItemSelect, out selectionContainerPointer ); IVsHierarchy selectedHierarchy = (IVsHierarchy)Marshal.GetTypedObjectForIUnknown(hierarchyPointer, typeof(IVsHierarchy)); if (selectedHierarchy != null ) { Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure ( selectedHierarchy.GetProperty ( projectItemId, (int)__VSHPROPID.VSHPROPID_ExtObject, out selectedObject ) ); } if (selectedHierarchy != null) { Marshal.ReleaseComObject(selectedHierarchy); } var selectedProjectItem = selectedObject as ProjectItem; // ↓ここでプルジェクト配下のアイテムではなく、ソリューション配下のアイテムの場合はFullPathがとってこない // string fullPath = selectedProjectItem.Properties.Item("FullPath").Value.ToString(); ・・・・・
ご存じの方がいらっしゃいましたら、よろしくお願い致します。- 編集済み coco2014 2019年10月11日 2:54
回答
-
PropertiesではなくFileNamesを使えば取れます
//string fullPath = selectedProjectItem.Properties.Item("FullPath").Value.ToString(); for (short i = 1; i <= selectedProjectItem.FileCount; i++) { string path = selectedProjectItem.FileNames[i]; System.Diagnostics.Debug.WriteLine(path); }
あと、面倒なインターフェースから掘り出すよりもEnvDTEからとったほうが楽です。
var dte = Package.GetGlobalService(typeof(EnvDTE.DTE)) as EnvDTE80.DTE2; if (dte != null) { foreach (object osel in (object[])dte.ToolWindows.SolutionExplorer.SelectedItems) { EnvDTE.UIHierarchyItem node = osel as EnvDTE.UIHierarchyItem; if (node != null) { string type = ""; string name = null; string filePath = null; if (node.Object is EnvDTE.ProjectItem) { var pitem = node.Object as EnvDTE.ProjectItem; for (short i = 1; i <= pitem.FileCount; i++) { type = "プロジェクトアイテム"; name = pitem.Name; filePath = pitem.FileNames[i]; } if (pitem.Kind == Microsoft.VisualStudio.VSConstants.ItemTypeGuid.PhysicalFile_string) { type += "(物理ファイル)"; } else if (pitem.Kind == Microsoft.VisualStudio.VSConstants.ItemTypeGuid.PhysicalFolder_string) { type += "(物理フォルダ)"; } else if (pitem.Kind == Microsoft.VisualStudio.VSConstants.ItemTypeGuid.VirtualFolder_string) { filePath = "<<仮想フォルダ>>";//C言語のフィルタとか } EnvDTE.Properties properties = pitem.Properties; if (properties != null) { for (int i = 1; i < pitem.Properties.Count; i++) { EnvDTE.Property prop = pitem.Properties.Item(i); if (prop != null) { System.Diagnostics.Debug.WriteLine(prop.Name + "=" + prop.Value); } } } } else if (node.Object is EnvDTE.Project) { var proj = (EnvDTE.Project)node.Object; type = "プロジェクト"; name = proj.Name; filePath = proj.FileName; if (proj.Kind == "{66A26720-8FB5-11D2-AA7E-00C04F688DDE}")//フォルダ { filePath = "<<ソリューションフォルダ>>"; } } else if (node.Object is EnvDTE.Solution) { var sol = (EnvDTE.Solution)node.Object; type = "ソリューション"; name = sol.FullName; filePath = sol.FileName; } #if VSLangProjを参照追加している場合 else if (node.Object is VSLangProj.Reference) { VSLangProj.Reference @ref = node.Object as VSLangProj.Reference; type = "参照"; name = @ref.Name; filePath = @ref.Path; } #endif else { type = "<<不明>>"; name = node.Name; filePath = "<<不明>>"; } string msg = "TYPE= " + type + "\r\n" + "NAME= " + name + "\r\n" + "FILE= " + filePath; VsShellUtilities.ShowMessageBox(this.package, msg, "選択しているアイテムの情報", OLEMSGICON.OLEMSGICON_NOICON, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); } } }
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
すべての返信
-
PropertiesではなくFileNamesを使えば取れます
//string fullPath = selectedProjectItem.Properties.Item("FullPath").Value.ToString(); for (short i = 1; i <= selectedProjectItem.FileCount; i++) { string path = selectedProjectItem.FileNames[i]; System.Diagnostics.Debug.WriteLine(path); }
あと、面倒なインターフェースから掘り出すよりもEnvDTEからとったほうが楽です。
var dte = Package.GetGlobalService(typeof(EnvDTE.DTE)) as EnvDTE80.DTE2; if (dte != null) { foreach (object osel in (object[])dte.ToolWindows.SolutionExplorer.SelectedItems) { EnvDTE.UIHierarchyItem node = osel as EnvDTE.UIHierarchyItem; if (node != null) { string type = ""; string name = null; string filePath = null; if (node.Object is EnvDTE.ProjectItem) { var pitem = node.Object as EnvDTE.ProjectItem; for (short i = 1; i <= pitem.FileCount; i++) { type = "プロジェクトアイテム"; name = pitem.Name; filePath = pitem.FileNames[i]; } if (pitem.Kind == Microsoft.VisualStudio.VSConstants.ItemTypeGuid.PhysicalFile_string) { type += "(物理ファイル)"; } else if (pitem.Kind == Microsoft.VisualStudio.VSConstants.ItemTypeGuid.PhysicalFolder_string) { type += "(物理フォルダ)"; } else if (pitem.Kind == Microsoft.VisualStudio.VSConstants.ItemTypeGuid.VirtualFolder_string) { filePath = "<<仮想フォルダ>>";//C言語のフィルタとか } EnvDTE.Properties properties = pitem.Properties; if (properties != null) { for (int i = 1; i < pitem.Properties.Count; i++) { EnvDTE.Property prop = pitem.Properties.Item(i); if (prop != null) { System.Diagnostics.Debug.WriteLine(prop.Name + "=" + prop.Value); } } } } else if (node.Object is EnvDTE.Project) { var proj = (EnvDTE.Project)node.Object; type = "プロジェクト"; name = proj.Name; filePath = proj.FileName; if (proj.Kind == "{66A26720-8FB5-11D2-AA7E-00C04F688DDE}")//フォルダ { filePath = "<<ソリューションフォルダ>>"; } } else if (node.Object is EnvDTE.Solution) { var sol = (EnvDTE.Solution)node.Object; type = "ソリューション"; name = sol.FullName; filePath = sol.FileName; } #if VSLangProjを参照追加している場合 else if (node.Object is VSLangProj.Reference) { VSLangProj.Reference @ref = node.Object as VSLangProj.Reference; type = "参照"; name = @ref.Name; filePath = @ref.Path; } #endif else { type = "<<不明>>"; name = node.Name; filePath = "<<不明>>"; } string msg = "TYPE= " + type + "\r\n" + "NAME= " + name + "\r\n" + "FILE= " + filePath; VsShellUtilities.ShowMessageBox(this.package, msg, "選択しているアイテムの情報", OLEMSGICON.OLEMSGICON_NOICON, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); } } }
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)