Skip to content

Commit ad0489b

Browse files
committed
Improve path resolution for unloaded projects
Remove GUID-based detection and use a more robust fallback approach: 1. Try project.FullName first (works for loaded projects) 2. Try project.UniqueName as absolute path 3. Try combining solution directory with UniqueName
1 parent b095439 commit ad0489b

File tree

3 files changed

+61
-13
lines changed

3 files changed

+61
-13
lines changed

.claude/CLAUDE.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
This is a Visual Studio extension that adds a right-click context menu command to open solution files, project files, or individual files in Notepad++. It targets .NET Framework 4.8 and uses the VS SDK.
8+
9+
## Build Commands
10+
11+
Build the extension (requires Visual Studio with VS SDK or .NET Framework 4.8 targeting pack):
12+
```
13+
msbuild src\CodingWithCalvin.OpenInNotepadPlusPlus.sln
14+
```
15+
16+
Debug by pressing F5 in Visual Studio - this launches the VS Experimental Instance (`/rootsuffix Exp`).
17+
18+
## Architecture
19+
20+
The extension has a simple structure:
21+
22+
- **OpenInNotepadPlusPlusPackage.cs** - The VS package entry point, registers the command and settings page
23+
- **Commands/OpenExecutableCommand.cs** - Handles the context menu command, gets the selected path and launches Notepad++
24+
- **Helpers/ProjectHelpers.cs** - Resolves file paths from Solution Explorer selection (handles solutions, projects, project items, and unloaded projects)
25+
- **Dialogs/SettingsDialogPage.cs** - Options page for configuring the Notepad++ executable path
26+
- **VSCommandTable.vsct** - Defines the context menu command placement
27+
28+
## Key Implementation Details
29+
30+
Path resolution in `ProjectHelpers.GetSelectedPath()` handles three selection types:
31+
1. `ProjectItem` - uses `FileNames[1]`
32+
2. `Project` - uses `FullName` with fallback to `UniqueName` for unloaded projects
33+
3. `Solution` - uses `FullName`
34+
35+
The extension auto-detects Notepad++ in the default install location but allows custom paths via Tools > Options.
36+
37+
## Development Requirements
38+
39+
Install the [Extensibility Essentials 2022](https://marketplace.visualstudio.com/items?itemName=MadsKristensen.ExtensibilityEssentials2022) extension for Visual Studio.

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,7 @@ Desktop.ini
151151
$RECYCLE.BIN/
152152

153153
# Mac crap
154-
.DS_Store
154+
.DS_Store
155+
156+
# Claude Code local settings
157+
.claude/settings.local.json

src/CodingWithCalvin.OpenInNotepadPlusPlus/Helpers/ProjectHelpers.cs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ namespace CodingWithCalvin.OpenInNotepadPlusPlus.Helpers
88
{
99
internal static class ProjectHelpers
1010
{
11-
private const string UnloadedProjectGuid = "{67294A52-A4F0-11D2-AA88-00C04F688DDE}";
12-
1311
public static string GetSelectedPath(DTE2 dte)
1412
{
1513
ThreadHelper.ThrowIfNotOnUIThread();
@@ -36,22 +34,30 @@ private static string GetProjectPath(Project project, Solution solution)
3634
{
3735
ThreadHelper.ThrowIfNotOnUIThread();
3836

39-
bool isUnloaded = project.Kind.Equals(UnloadedProjectGuid, StringComparison.OrdinalIgnoreCase);
40-
41-
if (!isUnloaded)
37+
// Try FullName first - works for loaded projects and sometimes unloaded ones
38+
if (!string.IsNullOrEmpty(project.FullName) && File.Exists(project.FullName))
4239
{
4340
return project.FullName;
4441
}
4542

46-
// For unloaded projects, FullName is empty but UniqueName contains
47-
// the relative path from the solution directory
48-
if (!string.IsNullOrEmpty(project.UniqueName) && !string.IsNullOrEmpty(solution?.FullName))
43+
// Fallback: try UniqueName which may contain the relative or absolute path
44+
if (!string.IsNullOrEmpty(project.UniqueName))
4945
{
50-
var solutionDirectory = Path.GetDirectoryName(solution.FullName);
51-
var projectPath = Path.Combine(solutionDirectory, project.UniqueName);
52-
if (File.Exists(projectPath))
46+
// UniqueName might already be an absolute path
47+
if (Path.IsPathRooted(project.UniqueName) && File.Exists(project.UniqueName))
48+
{
49+
return project.UniqueName;
50+
}
51+
52+
// Try combining with solution directory
53+
if (!string.IsNullOrEmpty(solution?.FullName))
5354
{
54-
return projectPath;
55+
var solutionDirectory = Path.GetDirectoryName(solution.FullName);
56+
var projectPath = Path.Combine(solutionDirectory, project.UniqueName);
57+
if (File.Exists(projectPath))
58+
{
59+
return projectPath;
60+
}
5561
}
5662
}
5763

0 commit comments

Comments
 (0)