Subscribe

NppPlugin.NET v0.5

  1. 2011-03-09 16:15:23 PST
    Hi, here's another major update: Forget all previous versions of this package - this is a brand new approach! No more C/C++ code (plugin loader) required at all. Huh? How come? Here's the explanation - all credits for this technique to following guys: -Dark Daskin: http://www.codeproject.com/KB/dotnet/DllExporter.aspx -Robert Giesecke: http://sites.google.com/site/robertgiesecke/Home/uploads/csharpprojecttemplateforunmanagedexports This package should contain 2 folders: 1) Visual Studio Project Template C#: A VS template for very fast and even easier building of .NET plugins for Notepad++. Setting up a plugin for N++ has never ever been as easy as with this package. Please See its containing text file for further information. 2) Demo Plugin: An example .NET plugin for Notepad++, build upon the template above. It demonstrates the same functionality as the original demo plugin by Don HO: http://notepad-plus.sourceforge.net/commun/pluginDemoTemplate/NppPluginTemplate.zip I don't know if I've added new bugs, but I've corrected some small mistakes which are in the original demo. I've also added example code for registering icons for the tab of a dockable dialog and for Notepad++'s tool bar (and how to toogle its state). Both template and demo come with solution files for: . Visual Studio 2005 . Visual Studio 2008 . Visual Studio 2010 Download: ======== https://sourceforge.net/projects/sourcecookifier/files/other%20plugins/ Enjoy UFO
  2. 2011-03-09 16:55:10 PST
    Hi UFO, Haven't checked it out yet, but nice one :) I looked at Robert Giesecke's approach a few weeks back for doing this, and one issue I ran into was the inability to step through and debug the plugin (which is possible with your previous loader - thankfully), if i recall this was because the post build script decompiles and recompiles the DLL putting the exports in. Which meant I gave up on the idea :( Have you overcome this at all in the template? Cheers Ben
  3. 2011-03-09 22:35:26 PST
    hi, I tried it all in VS2005/2008/2010 and was able to debug w/o any issues. What comes to mind is that maybe you tried debugging something with VS2010 when it was compiled with the 2.0 toolset. Afaik you can't, but that's an own issue. Then you can code/debug with a high toolset, but still release with 2.0. So far I only noticed positive things. Everything starts up noticeable faster than with the loader approach. But I still wanna compare the performance.. greets
  4. 2011-03-10 15:29:18 PST
    Hi UFO, Just tried it with your demo one, works fine, I must have been doing something wrong. Time to port my new plugin to 0.5 then :D Cheers Ben
  5. 2011-03-11 02:55:04 PST
    @ UFO : I have only 4 words for your nppPlugin.NET v0.5 : EX-CE-LLEN-T ! Now I'm coding the hash functions in C# with only 4-6 lines instead of hundreds of lines. The only problem is SCI_GETSELTEXT message : I have a pdf file loaded in Notepad++, which contains several NULL characters. In order to compute the hash of the whole PDF file or its partial data, the hash plugin get selected data which contains NULL characters via SCI_GETSELTEXT message. I use StringBuilder as the 4th parameter in Win32.SendMessage() call: int start = (int)Win32.SendMessage(hCurrScintilla, SciMsg.SCI_GETSELECTIONSTART, 0, 0); int end = (int)Win32.SendMessage(hCurrScintilla, SciMsg.SCI_GETSELECTIONEND, 0, 0); int textLen = end - start; StringBuilder sb = new StringBuilder(textLen + 1); Win32.SendMessage(hCurrScintilla, SciMsg.SCI_GETSELTEXT, 0, sb); That works fine with ASCII string but not binary data, because StringBuilder object truncks data due to the 1st NULL character. I'm sure that SCI_GETSELTEXT copies the whole data (with NULL characters) since I did it in ASCII/Hex converter plugin (in C++). Have you any idea to get the selected binary data by using nppPlugin.NET? Don
  6. 2011-03-11 06:54:42 PST
    hi, well, I don't know as which type you need the result, but here are some thoughts in C#: IntPtr hCurrScintilla = PluginBase.GetCurrentScintilla(); int textLen = (int)Win32.SendMessage(hCurrScintilla, SciMsg.SCI_GETSELTEXT, 0, 0); IntPtr ptrText = Marshal.AllocHGlobal(textLen); Win32.SendMessage(hCurrScintilla, SciMsg.SCI_GETSELTEXT, 0, ptrText); // get it as string but truncated.. string s = Marshal.PtrToStringAnsi(ptrText); // or everything.. well as byte array byte[] b = new byte[textLen]; Marshal.Copy(ptrText, b, 0, textLen); Marshal.FreeHGlobal(ptrText); greets
  7. 2011-03-11 13:47:52 PST
    Thank you UFO, it works perfectly. I added your NppPlugin.NET download link in: http://notepad-plus-plus.org/plugin-howto If you want to have a intro in your site or elaborate the tutorial/usage of NppPlugin.NET in the same page, please let me know. Don
  8. 2011-03-12 02:01:49 PST
    Thanks, I will see what I can set up.. cheers
  9. 2011-03-15 09:15:20 PDT
    Hi, is meant to work with visual basic as well? I have converted your example, imported the additional step <Import Project="DLLExport\NppPlugin.DllExport.targets" /> into my vbproj file, copied the additional dlls into the dllExport directory but I don't see the ILDasm and ILAsm commands get executed like in csharp. Do you know what I might have done wrong? Thank you Claudia
  10. 2011-03-15 15:07:03 PDT
    Hi, I have some additional informations.I found out how to get more informations on build process. When build is done using vb, I get Target "AfterBuild" in file "D:\Projects\\NppPluginNET\DLLExport\NppPlugin.DllExport.targets": Task "DllExportTask" Done executing task "DllExportTask". Done building target "AfterBuild" in project "NppPluginNET.vbproj". whereas I get a lot more on csharp like (i truncated the line to make readable) Target "AfterBuild" in file ....: Using "DllExportTask" task from assembly .....VS2008\DllExport\NppPlugin.DllExport.MSBuild.dll". Task "DllExportTask" ILDasm: calling ... ILDasm: ildasm ... ILAsm: Found method: NppPluginNET.UnmanagedExports..method private hidebysig static bool 'isUnicode'() cil managed ILAsm: Removing NppPlugin.DllExport.DllExportAttribute from NppPluginNET.UnmanagedExports.isUnicode . . . Resolving local member refs: 0 -> 0 defs, 0 refs, 0 unresolved Writing PE file Operation completed successfully . . . Done executing task "DllExportTask". Done building target "AfterBuild" in project "NppManagedPluginDemo.VS2008.csproj" Any ideas? Thank you Claudia
  11. 2011-03-19 14:38:25 PDT
    hi, I still don't have a VS with installed VB.NET component at hand, but I will try to add VB.NET support in the next package (and I'm sure it will work). Personally even more important for me is getting this package compiled with SharpDevelop again..
  12. 2011-03-20 11:44:54 PDT
    Hi ufo, thank you very much. Looking forward to the next package. Claudia
  13. 2011-03-22 18:50:03 PDT
    Hi, great work on this project, I'm porting one of my Visual Studio extensions ([url=http://tinyurl.com/alignby]http://tinyurl.com/alignby) to Notepad++, when I saw I could still use c#, I was over the moon. However I've been getting a strange error - FatalExceptionEngineError - often when I run the extension twice in a row (not always, but consistent if the document contents is the same). The error occurs before it even touches my code (although, as I said it's on the 2nd call) The calls I use are SCI_GETLINECOUNT, SCI_GETSELECTIONNSTART, SCI_GETSELECTIONNEND, SCI_LINEFROMPOSITION, SCI_GETLINE, SCI_POSITIONFROMLINE, SCI_INSERTTEXT (all on CurrentScintilla). P.S. Also I noted adding a post build event (like coping the addin to the plugin folder) causes it to not build correctly and Notepad++ complains it's an ANSI plugin
  14. 2011-03-23 01:49:13 PDT
    Regarding the post built event: Usually you simply define the plugin folder as the project's output folder. No need for additional actions. And the FatalExceptionEngineError.. will it be open source to have a look at the issue? Maybe somebody else knows more about SCI calls and their traps, but for me it's enough information. greets
  15. 2011-03-23 05:46:46 PDT
    /EDIT lol I meant NOT enough information
  16. 2011-03-23 08:18:16 PDT
    Hi https://www.google.com/accounts ;-) regarding the ANSI complains, I assume that the necessary ILDAsm and ILAsm steps didn't run. You can easily check this by running dependency walker on the generated dll. If you see exported functions like IsUnicode you should have a vaild "c-"dll. To extend the verbosity on the output - goto tools-options-projects and solutions-build and run and set MSBuild... to Diagnostic for example. Hope this help to identify the cause of your problem. Sorry for my bad english - I'm not a native speaker. Claudia
  17. 2011-03-23 19:37:41 PDT
    Thanks, though a bit of testing I figured out it was caused by SciMsg.SCI_GETLINE when you don't provide the StringBuffer with an initial capacity. Strange, but easy fix.
  18. 2011-03-23 19:38:49 PDT
    Sorry StringBuilder, haven't used Java in ages, don't know why I had a relapse
  19. 2011-04-22 14:46:24 PDT
    Hi guys, I am the one who wrote the MSBuild task that allows you to create unmanaged exports. @Ufo Pretty cool thing you have created. This is exactly the reason why I have published this build task. There're a lot of apps out there with just a plain DLL plugin interface, and it's up to guys like you to let C# folks write their stuff as well. :-) Some pointers to some questions in this thread: @Debugging problems: You probably did a release build or something like that. Without a pdb, IlDasm won't be able to get the line numbers. So that after re-assembling, all debug infos are gone. The IlDasm/IlAsm tool chain is pretty stable and shouldn't create this kind of problem on its own for a debug build. I did go through quite some lengths to ensure that I do not mangle your IL or debug infos in any way. I even use those infos to pinpoint error messages to the exact method that has a problem. So, if you have debugging problems, I would be very interested to hear about them. You can reach me via mail using robert dot giesecke at google's mail service. Probably should put up a google group forum kinda thing some time… ;-) @SharpDevelop I am using plain MsBuild, so it should work just fine with #d. However, it could be that #D is not providing all environmental infos to the MsBuild engine like VS is doing. So, if you do run into problems with #d, I'd like to hear about that, too. Chances are, that they are just providing the same infos using a different property name. @VB.Net It is entirely possible to have this working with VB.Net as well. But I would strongly suggest to reference an assembly that contains the DllExportAttribute. The reason is, that VB.Net's creepy way of trying to comfort old VB classic users can result in a lot of problems when you have to have tight control over how your code ends up as IL. The problem here is, that VB.Net will mess up your namespaces. Which makes it hard to have a class with the full name of RGiesecke.DllExport.DllExportAttribute. You can get around this, by telling my task that another Attribute class shall be used as the "export marker". This is done so by creating a property in your project file like this <DllExportAttributeFullName>Your.Name.Space.YourAttributeClass</DllExportAttributeFullName>. I use ducktyping to read the properties that are set on the attribute, so you could just recreate what you are seeing in the DllExportAttribute.cs file. However, it is by far easier to just reference the RGiesecke.DllExport.DllExportAttribute.dll, though. (You can find it here http://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports, it's in the attached archive) In this case, I will remove the reference to this assembly after my task is done (the attributes in you methods will be removed as well), so you do not need to redistribute this assembly along yours. Long story short: - grab RGiesecke.DllExport.DllExportAttribute.dll from the archive at the link above - reference it - Follow the steps on that page, so that you have the DllExport subfolder in your project and added the task to your project file - decorate your methods with DllExport - have fun with it
  20. 2011-04-23 01:51:05 PDT
    Hi Robert, thx for the explanations! I will add your notes about the debugging problems into the package next time. Regarding #D and VB.NET you probably did not see the current version of this package: https://sourceforge.net/projects/notepad-plus/forums/forum/482781/topic/4429157 greets and thx again
  21. 2011-10-06 13:59:15 PDT
    1st off: Love this template. Thanks! Since I'm very new to Windows messages and np++ plugins, I had a bit of trouble finding out how to get notifications. To make it easier, I created a helper with events for notifications. Maybe you'd like to use it in the next version of this template. public static class NppNotification { public static event NppNotificationEvent Ready; public static event NppNotificationEvent TBModification; public static event NppNotificationEvent FileBeforeClose; public static event NppNotificationEvent FileClosed; public static event NppNotificationEvent FileBeforeOpen; public static event NppNotificationEvent FileOpened; public static event NppNotificationEvent FileBeforeSave; public static event NppNotificationEvent FileSaved; public static event NppNotificationEvent Shutdown; public static event NppNotificationEvent BufferActivated; public static event NppNotificationEvent LangChanged; public static event NppNotificationEvent WordStylesUpdated; public static event NppNotificationEvent ShortcutRemapped; public static event NppNotificationEvent FileBeforeLoad; public static event NppNotificationEvent FileLoadFailed; public static event NppNotificationEvent DocOrderChanged; internal static void Process(SCNotification nc) { switch(nc.nmhdr.code) { case (uint)NppMsg.NPPN_DOCORDERCHANGED: if (DocOrderChanged != null) DocOrderChanged(nc); break; case (uint)NppMsg.NPPN_FILEBEFORELOAD: if (FileBeforeLoad != null) FileBeforeLoad(nc); break; case (uint)NppMsg.NPPN_SHORTCUTREMAPPED: if (ShortcutRemapped != null) ShortcutRemapped(nc); break; case (uint)NppMsg.NPPN_WORDSTYLESUPDATED: if (WordStylesUpdated != null) WordStylesUpdated(nc); break; case (uint)NppMsg.NPPN_LANGCHANGED: if (LangChanged != null) LangChanged(nc); break; case (uint)NppMsg.NPPN_BUFFERACTIVATED: if (BufferActivated != null) BufferActivated(nc); break; case (uint)NppMsg.NPPN_FILEBEFORESAVE: if (FileSaved != null) FileSaved(nc); break; case (uint)NppMsg.NPPN_FILEOPENED: if (FileOpened != null) FileOpened(nc); break; case (uint)NppMsg.NPPN_FILEBEFOREOPEN: if (FileBeforeOpen != null) FileBeforeOpen(nc); break; case (uint)NppMsg.NPPN_FILECLOSED: if (FileClosed != null) FileClosed(nc); break; case (uint)NppMsg.NPPN_TBMODIFICATION: if (TBModification != null) TBModification(nc); break; case (uint)NppMsg.NPPN_READY: if (Ready != null) Ready(nc); break; case (uint)NppMsg.NPPN_SHUTDOWN: if (Shutdown != null) Shutdown(nc); break; case (uint)NppMsg.NPPN_FILEBEFORECLOSE: if (FileBeforeClose != null) FileBeforeClose(nc); break; } } } public delegate void NppNotificationEvent(SCNotification nc); and then in UnmanagedExports.cs: [DllExport(CallingConvention = CallingConvention.Cdecl)] static void beNotified(IntPtr notifyCode) { SCNotification nc = (SCNotification)Marshal.PtrToStructure(notifyCode, typeof(SCNotification)); NppNotification.Process(nc); //process the notification to fire off the associated event if (nc.nmhdr.code == (uint)NppMsg.NPPN_TBMODIFICATION) { PluginBase._funcItems.RefreshItems(); Main.SetToolBarIcon(); } else if (nc.nmhdr.code == (uint)NppMsg.NPPN_SHUTDOWN) { Main.PluginCleanUp(); Marshal.FreeHGlobal(_ptrPluginName); } }
  22. 2011-10-10 17:51:49 PDT
    Out of interest is there any reason you haven't made an assembly that contains most of this logic and distributing it through NuGet? This would allow people devs to make sure they have the latest version easily.
  23. 2011-12-28 02:00:42 PST
    Hs anyone found a good way of referencing external managed assemblies that aren't registered in the GAC? Typically, I've followed either of 2 approaches: - Merge assemblies using ILMerge, or - Place additional assemblies in the same folder as the target assembly or program ILMerge isn't working (because there's unmanaged code in the plugin assembly as a result of the additional MSBuild steps I guess) - maybe reordering this process to have the ILMerge process happen first would work. I'll report back when I've looked into that. In terms of placing the addiional assemblies in the same folder as the plugin assembly, there are two problems: - Notepad++ tries to load all dlls in that folder as plugins, and complains if they're not - It looks like the search path for auto-resolving assembly paths is not including the plugins folder anyway. To get the assemblies loaded correctly I need to place them in the main notepad++ program folder (which is impolite :)) So far, I can think of two approaches that I haven't looked into yet: - Placing the assemblies in an arbitrary subfolder of plugins, and loading them via reflection - should work but could be expensive - Attempting to have the assemblies merged before the DllExport MSBuild stuff gets to them - I'm guessing I'd have to create my own custom MSBuild task, which certainly sounds like a headache. Does anyone have any experience with either of these approaches, or other thoughts?
  24. 2011-12-28 09:31:49 PST
    Imho easiest is following approach: Add a method like this one: internal static void SetupDomain() { Assembly pluginAssembly = Assembly.GetExecutingAssembly(); string pluginPath = pluginAssembly.Location; string pluginName = Path.GetFileNameWithoutExtension(pluginPath); string pluginSubFolder = Path.Combine(Path.GetDirectoryName(pluginPath), pluginName); AppDomain.CurrentDomain.AppendPrivatePath(pluginSubFolder); } Now you can place your referenced stuff into a subfolder, which has the same name as your plugin. If your main DLL is called "MyPlugin.dll", then your subfolder should be called "MyPlugin". It's a sensemaking but unwritten (?) convention followed by myself and other plugin authors aswell. Of course there's still the warning CS0618. I personally add following at top of the source file: #pragma warning disable 618 cheers
  25. 2011-12-28 09:35:12 PST
    /EDIT: It's not 'clean' because of the warning, but I guess I should add the code in the template next time anyway. Unless somebody comes up with a cleaner/sexier solution of course?
Jump To:
< Previous | 1 | 2 | Next >

Add a Reply

This forum does not allow anonymous participation.

Log in to add a reply. Not registered? Create an account to participate and receive email updates when replies are posted to this topic.