11using System ;
22using System . IO ;
3+ using System . Runtime . InteropServices ;
34using EnvDTE ;
45using EnvDTE80 ;
6+ using Microsoft . VisualStudio ;
57using Microsoft . VisualStudio . Shell ;
8+ using Microsoft . VisualStudio . Shell . Interop ;
69
710namespace CodingWithCalvin . OpenInNotepadPlusPlus . Helpers
811{
@@ -25,11 +28,62 @@ UIHierarchyItem selectedItem in (Array)
2528 return GetProjectPath ( project , dte . Solution ) ;
2629 case Solution solution :
2730 return solution . FullName ;
31+ default :
32+ // Handle unloaded projects - they don't expose a Project object
33+ // but we can get the path via IVsMonitorSelection and IVsHierarchy
34+ var path = GetPathFromHierarchy ( ) ;
35+ if ( ! string . IsNullOrEmpty ( path ) )
36+ {
37+ return path ;
38+ }
39+ break ;
2840 }
2941 }
3042 return null ;
3143 }
3244
45+ private static string GetPathFromHierarchy ( )
46+ {
47+ ThreadHelper . ThrowIfNotOnUIThread ( ) ;
48+
49+ // Use IVsMonitorSelection to get the current selection's IVsHierarchy
50+ // This works for unloaded projects where selectedItem.Object is not a Project
51+ var monitorSelection = Package . GetGlobalService ( typeof ( SVsShellMonitorSelection ) ) as IVsMonitorSelection ;
52+ if ( monitorSelection == null )
53+ {
54+ return null ;
55+ }
56+
57+ var hr = monitorSelection . GetCurrentSelection ( out var hierarchyPtr , out var itemId , out _ , out _ ) ;
58+ if ( hr != VSConstants . S_OK || hierarchyPtr == IntPtr . Zero )
59+ {
60+ return null ;
61+ }
62+
63+ try
64+ {
65+ var hierarchy = Marshal . GetObjectForIUnknown ( hierarchyPtr ) as IVsHierarchy ;
66+ if ( hierarchy == null )
67+ {
68+ return null ;
69+ }
70+
71+ // GetCanonicalName returns the full path for project files
72+ if ( hierarchy . GetCanonicalName ( itemId , out var canonicalName ) == VSConstants . S_OK
73+ && ! string . IsNullOrEmpty ( canonicalName )
74+ && File . Exists ( canonicalName ) )
75+ {
76+ return canonicalName ;
77+ }
78+ }
79+ finally
80+ {
81+ Marshal . Release ( hierarchyPtr ) ;
82+ }
83+
84+ return null ;
85+ }
86+
3387 private static string GetProjectPath ( Project project , Solution solution )
3488 {
3589 ThreadHelper . ThrowIfNotOnUIThread ( ) ;
0 commit comments