.Net versions
-
Hi
I just “upgraded” my visual studio C# plugin to more recent .Net but when I try to run the plugin I get message saying its not valid plugin. i mean this:Cannot load 64-bit plugin. *********.dll is not compatible with the current version of Notepad++. Do you want to remove this plugin from the plugins directory to prevent this message from the next launch?
So I wonder if there is anything that can be done about that to make it load in NP?
or do I just have to stick with .Net 4.8
thx
-
I’m not familiar with C#, but messages like that usually occur either when you’re trying to load a 32-bit plugin in 64-bit Notepad++, or vice versa; or, the plugin fails to correctly implement the required interfaces. In addition to DllMain, these functions (from PluginInterface.h):
// You should implement (or define an empty function body) those functions which are called by Notepad++ plugin manager extern "C" __declspec(dllexport) void setInfo(NppData); extern "C" __declspec(dllexport) const wchar_t * getName(); extern "C" __declspec(dllexport) FuncItem * getFuncsArray(int *); extern "C" __declspec(dllexport) void beNotified(SCNotification *); extern "C" __declspec(dllexport) LRESULT messageProc(UINT Message, WPARAM wParam, LPARAM lParam); // This API return always true now, since Notepad++ isn't compiled in ANSI mode anymore extern "C" __declspec(dllexport) BOOL isUnicode();
must be implemented with the correct signatures, or loading will fail.
-
@General-Coder said in .Net versions:
do I just have to stick with .Net 4.8 [?]
For modern .NET, have a look at https://github.com/npp-dotnet.
Initial project setup is a bit involved; It’ll be easier when there’s a .NET project template on NuGet.
Start with a new class library, e.g.,
dotnet new classlib --name YourPluginProject
Make sure the
<TargetFramework>
and<RuntimeIdentifiers>
property specifies the Windows platform.Also make sure to set the
<PublishAot>
and<AllowUnsafeBlocks>
properties, e.g.,<PropertyGroup> - <TargetFramework>net9.0</TargetFramework> + <TargetFramework>net9.0-windows</TargetFramework> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + <PublishAot>true</PublishAot> + <RuntimeIdentifiers>win-arm64;win-x64</RuntimeIdentifiers> </PropertyGroup>
Install the plugin template package:
cd YourPluginProject dotnet add package Npp.DotNet.Plugin --prerelease
Define your plugin in the main class file, e.g.,
namespace YourPluginProject; using Npp.DotNet.Plugin; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; public class Class1 : IDotNetPlugin { #region "Implement the plugin interface" /// <summary> /// This method runs when Notepad++ calls the 'setInfo' API function. /// You can assume the application window handle is valid here. /// </summary> public void OnSetInfo() { // TODO: provide setup code, i.e., assign plugin commands to shortcut keys, load configuration data, etc. // For example: var shortcut = new ShortcutKey(Win32.TRUE, Win32.FALSE, Win32.TRUE, 123); // Ctrl + Shift + F12 Utils.SetCommand( $"About {PluginName}", () => Win32.MsgBoxDialog( PluginData.NppData.NppHandle, $"Information about {PluginName}\0", $"{PluginName}", (uint)(Win32.MsgBox.ICONASTERISK | Win32.MsgBox.OK)), shortcut); } /// <summary> /// This method runs when Notepad++ calls the 'beNotified' API function. /// </summary> public void OnBeNotified(ScNotification notification) { // TODO: provide callbacks for editor events and notifications. // For example: if (notification.Header.HwndFrom == PluginData.NppData.NppHandle) { uint code = notification.Header.Code; switch ((NppMsg)code) { case NppMsg.NPPN_SHUTDOWN: // clean up resources PluginData.PluginNamePtr = IntPtr.Zero; PluginData.FuncItems.Dispose(); break; } } } /// <summary> /// This method runs when Notepad++ calls the 'oOnMessageProc' API function. /// </summary> public NativeBool OnMessageProc(uint msg, UIntPtr wParam, IntPtr lParam) { // TODO: provide callbacks for Win32 window messages. return Win32.TRUE; } #endregion /// <summary> /// Object reference to the main class -- must be initialized statically! /// </summary> static readonly IDotNetPlugin Instance; /// <summary> /// The unique name of the plugin -- appears in the 'Plugins' drop-down menu /// </summary> static readonly string PluginName = "Your .NET SDK Plugin\0"; /// <summary> /// The main constructor must be static to ensure data is initialized *before* /// the Notepad++ application calls any unmanaged methods. /// At the very least, assign a unique name to 'Npp.DotNet.Plugin.PluginData.PluginNamePtr', /// otherwise the default name -- "Npp.DotNet.Plugin" -- will be used. /// </summary> static Class1() { Instance = new Class1(); PluginData.PluginNamePtr = Marshal.StringToHGlobalUni(PluginName); } #region "==================== COPY & PASTE *ONLY* ========================" [UnmanagedCallersOnly(EntryPoint = "setInfo", CallConvs = [typeof(CallConvCdecl)])] internal unsafe static void SetInfo(NppData* notepadPlusData) { PluginData.NppData = *notepadPlusData; Instance.OnSetInfo(); } [UnmanagedCallersOnly(EntryPoint = "beNotified", CallConvs = [typeof(CallConvCdecl)])] internal unsafe static void BeNotified(ScNotification* notification) { Instance.OnBeNotified(*notification); } [UnmanagedCallersOnly(EntryPoint = "messageProc", CallConvs = [typeof(CallConvCdecl)])] internal static NativeBool MessageProc(uint msg, UIntPtr wParam, IntPtr lParam) { return Instance.OnMessageProc(msg, wParam, lParam); } [UnmanagedCallersOnly(EntryPoint = "getFuncsArray", CallConvs = [typeof(CallConvCdecl)])] internal static IntPtr GetFuncsArray(IntPtr nbF) => IDotNetPlugin.OnGetFuncsArray(nbF); [UnmanagedCallersOnly(EntryPoint = "getName", CallConvs = [typeof(CallConvCdecl)])] internal static IntPtr GetName() => IDotNetPlugin.OnGetName(); [UnmanagedCallersOnly(EntryPoint = "isUnicode", CallConvs = [typeof(CallConvCdecl)])] internal static NativeBool IsUnicode() => IDotNetPlugin.OnIsUnicode(); #endregion }
Build the plugin:
dotnet publish -c Release -r win-x64 -o $(PLUGIN_FOLDER_PATH)
where
$(PLUGIN_FOLDER_PATH)
is the plugin’s installation path, e.g.,%ProgramFiles%\Notepad++\plugins\YourPluginProject
.(Basic) support for
*.Windows.Forms
is implemented, but your mileage may vary. -
@Coises I used the C# plugin template which version is limited to 4.8. it did all the things for me but upgrading from there is the problem
-
@rdipardo Thanks! i didnt know that modern C# plugin support existed
I’m probably going to give that a try, for now i’m just going with 4.8