Need help with getting started using C++ Plugin Template
-
Okay, it’s my turn to ask for help, rather than always giving advice. ;-)
I’ve never developed my own plugin before, but I’m starting to play with it again. (I had tried a few times in the past, with just mingw/gcc, but never had much luck; I now have VS2022, so was hoping it would go more smoothly for me; unfortunately, it has not.) Based on my experience, Don’s grandmom must be more experienced in VS/C++ than I am.
I thought adding an “About” box to the template would be a reasonable place to start, but it’s already stymied me, despite the fact that I am trying to copy the way that another C++-based plugin did it: Since Plugins Admin doesn’t tell you the base language of a given plugin, I just searched all of github for
NPP_PLUGIN_NAME
(since that’s a variable in the template, and is likely to be there for other projects using the template, and is unique to the N++ environment and won’t be in billions of unrelated projects), and looked down the list until I saw a plugin name I had noticed in the PluginsAdmin by an author I recognized, so I picked DoxyIt by @dail, and tried to start by making a simplified version of that AboutDialogMy first attempt is in https://github.com/pryrt/NppPlugin-CollectionInterface – unfortunately, when I try to run the About dialog from the plugin’s menu, nothing shows up.
Now that I’ve explained the background, I’ve got two questions:
- How do I use the debugger in VS to single-step through code for a plugin DLL?
- when I’ve build the main N++ app, I can easily set a breakpoint, and run Notepad++ from the VS debugger environment, and it will stop at the appropriate line.
- But I obviously cannot just “run” a DLL from VS without it being loaded by N++
- my guess would be that I’d have to build a debug copy of N++, loaded in and run from the VS debugger, and somehow hook to my build of the DLL so that N++ sees it and VS sees it; and then somehow set a breakpoint … but since it’s in a completely different VS Solution (not even multiple projects in the same solution), I have no idea how to go about doing that…
- if I had that piece of knowledge, I might not need to ask the second question, but i will anyway:
- Can anyone with more experience with plugin debug/development look in my repo and point out what stupid beginner’s mistake I’ve made that causes running the “About” command to do nothing (ie, not show the dialog, but also not crash)?
Anyway, thanks for any advice.
- How do I use the debugger in VS to single-step through code for a plugin DLL?
-
@PeterJones said in Need help with getting started using C++ Plugin Template:
How do I use the debugger in VS to single-step through code for a plugin DLL?
In your plugin’s Properties you need to set an exe to run that will load your plugin DLL, e.g.:
(OK, I have totally no idea why it came out so dark!)
After that, when you “run” your plugin, N++ will run and when a breakpoint you’ve set in your plugin is encountered, the debugger will “break”.
-
@PeterJones said in Need help with getting started using C++ Plugin Template:
Now that I’ve explained the background, I’ve got two questions:
- How do I use the debugger in VS to single-step through code for a plugin DLL?
- when I’ve build the main N++ app, I can easily set a breakpoint, and run Notepad++ from the VS debugger environment, and it will stop at the appropriate line.
- But I obviously cannot just “run” a DLL from VS without it being loaded by N++
(I know I got this from somewhere other than my own ingenuity, but I don’t remember where.) What I do is have the Post-Build Event copy the plugin to my installed copy of Notepad++:
- Right-click the project in the solution explorer and select Properties.
- At the top, make sure Platform is set to Active.
- Under Build Events, select Post-Build Event.
- Click the down-arrow to the right of Command line and select <Edit…>.
- Enter (adjust as needed):
if EXIST "%PROGRAMFILES%\Notepad++\plugins\" ( mkdir "%PROGRAMFILES%\Notepad++\plugins\$(TargetName)" copy "$(TargetPath)" "%PROGRAMFILES%\Notepad++\plugins\$(TargetName)" )
That will automatically copy your plugin to your Notepad++ installation. (I like to keep it in my main installation so that I’m in effect testing my development whenever I use Notepad++. You can, of course, use a portable copy instead.)
Now, still in the Properties dialog, select Debugging under Configuration Properties. Set Command Line there to:
"%Program Files%\Notepad++\notepad++.exe"
(or whatever copy of Notepad++ you used in the Post-Build Event).
Then when you launch the debugger it will launch Notepad++ and you can debug your plugin.
- How do I use the debugger in VS to single-step through code for a plugin DLL?
-
, Don’s grandmom must be more experienced in VS/C++ than I am.
Well, I think his grandma is Grace Hopper. :-D
-
@PeterJones said in Need help with getting started using C++ Plugin Template:
Can anyone with more experience with plugin debug/development look in my repo and point out what stupid beginner’s mistake I’ve made that causes running the “About” command to do nothing (ie, not show the dialog, but also not crash)?
You used CreateDialogParam, which creates a non-modal dialog. When you create a non-modal dialog you typically have to show the dialog window after creation.
Edit: Sorry… I see you do show it. Still looking at why that doesn’t work. But you still probably want a modal dialog for an about box.
Edit 2: That code to center and show the dialog would normally go in the dialog procedure, in the WM_INITDIALOG process. I think it’s not working where you have it because the dialog hasn’t yet been initialized.
For an About box, you probably meant to create a modal dialog. For that, use DialogBoxParam.
-
Where is your IDD_ABOUTDLG defined? Can’t see it.
Sorry I don’t have access to VS at the momentFOUND IT in dialogs
-
Thanks to all for the help with Debugging > Command and Post-Build Event … I was able to easily single-step once that was setup correctly.
CreateDialogParam
was returning NULL, with GetLastError() => 0x716 (ERROR_RESOURCE_NAME_NOT_FOUND). It turned out that the _hModule being NULL was the culprit: when it’s NULL, it looks in the executable for the resource, and couldn’t find it there; looking at DoxyIt again, he’d actual set it as a project global, and set it during pluginInit(). When I try that, I can get it to show my About box.you probably meant to create a modal dialog. For that, use DialogBoxParam.
Actually, I meant to copy whatever was done in DoxyIt: at this point, I didn’t care about modal vs non-modal. But point taken, About boxes often are modal (though I kindof like when they are not, as it makes it possible to show multiple About boxes from multiple plugins at the same time)
As you can probably tell, GUI development is not my thing; my c++ experience is primarily behind-the-scenes and command-line style code, not GUI. I’m using this exercise to try to learn some GUI techniques and improve my skills. It is quite possible that DoxyIt was not the best choice for a template-based plugin (it was probably created on a much earlier version of the template, and may not do things in the “best” way): if you know of a “best practices” C++ plugin I can use as a reference
-
This post is deleted! -
@PeterJones said in Need help with getting started using C++ Plugin Template:
if you know of a “best practices” C++ plugin I can use as a reference
For some reason, I thought that @Coises was one of the C# programmers so I didn’t think of looking at Columns++; but I now see it is, in fact, in C++, so I’ll probably at least use it for reference. :-)
-
I was working on a personal project to create a Visual Studio Template for C++ plugins for Notepad++. I put that on hold while I’m working on improving the regular expression search for Unicode files in Columns++.
If you would like to try it as a starting point, I put a copy here:
https://www.coises.com/extrn/SampleNppPlugin1.zip
I don’t have it packaged as a template yet, so the included instructions for installing it don’t apply. Just unzip, put it somewhere you’ll leave it, and double-click the Waiting for Godot.sln file to open it in Visual Studio.
It is a working (though useless) plugin that includes an About dialog, a Settings dialog, a non-modal dialog, a docking panel and a mechanism for saving settings as a JSON file.
The included help file is somewhat out of date, but it will still give you an idea how the thing is organized. As noted at the start of that file:
This project is not a part of Notepad++ and is not endorsed by the author of Notepad++.
This template includes framework code for making a Notepad++ plugin in C++, along with various utility functions and examples.
I have constructed it to give myself and others a useful starting point when developing a Notepad++ plugin in C++.
It necessarily reflects my own idiosyncrasies as a programmer. I hope it may prove useful to others, and I welcome comments, suggestions and problem reports in the Issues; however, I make no apologies for its incorporation of my personal choices and styles — which might not meet with universal approval — and I do not promise to make changes to accommodate all plausible programming styles and use cases. So be it.
-
@PeterJones said in Need help with getting started using C++ Plugin Template:
For some reason, I thought that @Coises was one of the C# programmers so I didn’t think of looking at Columns++; but I now see it is, in fact, in C++, so I’ll probably at least use it for reference. :-)
See my previous post about a template I have in progress. Even though it is not finished yet, it is probably a better model than Columns++. It does load and open dialogs.
Columns++ was my first plugin, and I made a few design decisions I would do differently now. It also has a lot of complexity because of what it does… untangling that from what parts are needed to work as a plugin could be confusing.
In the template-in-progress, I’m making an effort to separate the code that needs to be there for a plugin to work from the code that does what your plugin does. If you try it, you can tell me to what extent I’ve succeeded. ;-)
-
A Alan Kilborn referenced this topic on
-
@Coises said in Need help with getting started using C++ Plugin Template:
See my previous post about a template I have in progress.
👍 Looks like a promising object-oriented replacement for Don HO’s mostly C-like template (with its global variables, constants declared with
#define
instead ofconstexpr
, raw pointers, etc.).One small tip: if you don’t want the Win API’s
min()
/max()
macros to shadowstd::min
/*::max
, simply put#define NOMINMAX
before you include<windows.h>
(to hide the macros from the current file), or addNOMINMAX
to the project’s compiler definitions (to hide them everywhere). That will slightly clean up the preprocessor kludge at the top of.../src/Framework/PluginFramework.h
, i.e.,// ... #include <windows.h> // ... #undef min #undef max
-
@rdipardo said in Need help with getting started using C++ Plugin Template:
#define NOMINMAX
Thanks! I didn’t know about that.
And thank you for the encouragement. I hope it might be helpful. Every time I think, “Maybe that should just be a plugin of its own,” I shudder at the housekeeping needed to start one. I plan for this to end up as a Visual Studio template that will appear in the “Create a new project” list. (I have that working, but I haven’t updated it with the many changes I’ve already made to the code, so I just made a zip of the trial project that I’ll eventually turn back into a template.)
-
Picking up from where my previous post in this thread ended…
Hmm, I submitted that post, then I edited it to add more info, and…somehow never submitted that. :-( Maybe there were gremlins in the machine (or the user!)…the same ones that caused my screenshot to somehow be dark…
OK, well, I meant to say that what I’ve done to debug/step a plugin code is “what I said earlier” plus I do some “trickery” to get things in the correct folder scheme so that Notepad++ finds the plugin when it starts up. That trickery involves a symbolic link, so that the plugin development folder can be anywhere but yet also maps to being in the plugins folder underneath Notepad++.
Thus:
In the plugins folder under Notepad++, from a cmd prompt, create the folder for the plugin (
md PluginName
), and then executemklink /D PluginName PathToDebugFolderOfPlugin
-
@Coises said:
Under Build Events, select Post-Build Event
Regarding this approach, it surprises me that it works, because that file is going to be a different file from the one the IDE knows about. When the plugin is “run” under the debugger, the IDE runs Notepad++ (due to the other setup step), but I’d think when it loads the DLL file (copy!), it wouldn’t hit any breakpoints because it would be “keying on” the DLL file (and supporting debug data) it built into the plugin’s Debug folder, not some solitary copy of the file elsewhere in the file system.
-
@Coises said:
Every time I think, “Maybe that should just be a plugin of its own,” I shudder at the housekeeping needed to start one. I plan for this to end up as a Visual Studio template that will appear in the “Create a new project” list. (I have that working, but I haven’t updated it with the many changes I’ve already made to the code, so I just made a zip of the trial project that I’ll eventually turn back into a template.)
This sounds like a great idea. Others have had a similar idea but I don’t know that anyone has ever taken it so far as to produce a really solid “this IS the C++ plugin template” to use.
Perhaps a collaborative effort with @ThosRTanner (another with a better-plugin-template idea; see HERE ) would be in order.
-
@Alan-Kilborn said in Need help with getting started using C++ Plugin Template:
@Coises said:
Under Build Events, select Post-Build Event
Regarding this approach, it surprises me that it works, because that file is going to be a different file from the one the IDE knows about. When the plugin is “run” under the debugger, the IDE runs Notepad++ (due to the other setup step), but I’d think when it loads the DLL file (copy!), it wouldn’t hit any breakpoints because it would be “keying on” the DLL file (and supporting debug data) it built into the plugin’s Debug folder, not some solitary copy of the file elsewhere in the file system.
As I understand it, there is a GUID in compiled modules. When you run the debugger within the project, it has the locations of the source and symbol files. Upon loading a module (exe or dll) the debugger looks to see if it has a symbol file (pdb) for that module name and then checks that the GUIDs match. It doesn’t care from where the module was loaded.
I didn’t figure out that this would work, though… I copied it from somewhere else, I just don’t remember where.
I did make a mistake and an omission in what I wrote earlier (to @PeterJones).
%ProgramFiles%
works in the Post-Build Event command, but for some reason you have to spell out the actual path in the Debugging command. And to use the automatic copying into Program Files, you have to change the permissions on the Plugins folder so that privilege elevation isn’t required to modify it — OK on a personal development machine, not so good on a shared machine. -
@Coises ,
I did make a mistake and an omission in what I wrote earlier (to @PeterJones).
%ProgramFiles%
works in the Post-Build Event command, but for some reason you have to spell out the actual path in the Debugging command.I actually figured that out.
$(ProgramFiles)
works for the Debugging Command –for some reason
I think the difference is that Post-Build Event is essentially a cmd.exe script, whereas the Debugging Command goes through VS variable substitution then gets sent to something akin to ShellExecute, probably without a
cmd.exe
wrapper, so it doesn’t know cmd environment variable syntax.And to use the automatic copying into Program Files, you have to change the permissions on the Plugins folder so that privilege elevation isn’t required to modify it —
Yeah, that “permissions” bit me at first, trying it that way.
I switched over to @Alan-Kilborn’s symbolic link-- but if I do both the
mkdir
and themklink
, themklink
complains; doing themklink
from theplugins\
directory without doing themkdir
first works to make the psuedo-directory for the plugin.OK on a personal development machine, not so good on a shared machine.
Interesting to note: the DebuggerCommand seems to be stored in
blah.vcxproj.user
whereas the PostBuildEvent gets stored inblah.vcxproj
(at least in my experiments)… so when multiple people are developing in the same project, but one needs to run$(ProgramFiles)\notepad++\notepad++.exe
but the other needs to runc:\path\to\portable\notepad++.exe
, the DebuggerCommand can be separate for the two developers. OTOH, if the DLL gets copied to a fixed location in DebuggerCommand, that will try to do the same copy for both users, which wouldn’t work. Having each developer just create the symbolic link from the appropriateplugins\
directory pointing to their local<arch>\Debug
directory with the appropriate DLL and meta-information seems to make good logical sense to me -
@Alan-Kilborn said in Need help with getting started using C++ Plugin Template:
, it surprises me that it works, because that file is going to be a different file from the one the IDE knows about.
@Coises is right. There is a PDB (debug symbols file, which binds together the source code and its binary) location info inside the binary PE-header. It’s not a GUID but simply an original path to the PDB-file. A sample of that info from my custom PythonScript plugin:
-
@xomx said in Need help with getting started using C++ Plugin Template:
simply an original path to the PDB-file
Ah, so as long as that file stays where it is, the project can be “debugged” from the IDE no matter where the DLL is located. Ok, well, thanks for filling in that little nugget of seemingly missing info!
…from my custom PythonScript plugin
Oooh. What kind of customizations? :-)