Skip to content

Commit

Permalink
make it easier to include 3rd-party dependencies
Browse files Browse the repository at this point in the history
Address #5
Now 3rd-party dependencies can be included in your project without having to
    manually add the dependency DLL's to your plugin folder
    or worry that referencing a 3rd-party dependency will cause a plugin crash.
  • Loading branch information
molsonkiko committed Mar 9, 2024
1 parent c5e3895 commit 574e196
Show file tree
Hide file tree
Showing 16 changed files with 228 additions and 42 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ UpgradeLog*.XML
*.pyc

Visual Studio Project Template C#/$projectname$.sln
NppCSharpPluginPack/.vs
**/.vs
!NppCSharpPluginPack/Dependencies/x64
NppCSharpPluginPack/UpgradeLog.htm
!testfiles/**/*example*.log
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Avoid plugin crash when too-large int values are entered in the selection-remembering form.
- Holding down `Enter` in a multiline textbox does not add multiple new lines; it only adds one newline on keyup.

## [0.0.4] - (UNRELEASED) YYYY-MM-DD

### Added

1. Make it much easier to [include third-party dependencies](/docs/README.md#loading-third-party-dependencies) in your plugin.

## [0.0.3] - 2024-02-26

### Added
Expand Down
31 changes: 31 additions & 0 deletions ExampleDependency/ExampleClass.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
namespace ExampleDependency
{
public class ExampleClass
{
public static int ExampleClassInstancesCreated = 0;
public string Name = "";
public int InstancesCreatedBeforeThis { get; private set; }

public ExampleClass(string name)
{
Name = name;
InstancesCreatedBeforeThis = ExampleClassInstancesCreated;
ExampleClassInstancesCreated = Add(ExampleClassInstancesCreated, 1);
}

public override string ToString()
{
return $"ExampleClass(\"{Name}\") ({InstancesCreatedBeforeThis} instances created before it)";
}

public static int Add(int x, int y)
{
return x + y;
}

public static int Subtract(int x, int y)
{
return x - y;
}
}
}
57 changes: 57 additions & 0 deletions ExampleDependency/ExampleDependency.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<TargetFramework>net4.8</TargetFramework>
<Platforms>AnyCPU;x64;x86</Platforms>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<FileAlignment>512</FileAlignment>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug-x64</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release-x64</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<FileAlignment>512</FileAlignment>
<PlatformTarget>x64</PlatformTarget>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<!-- references -->
<Reference Include="System" />
</ItemGroup>
</Project>
37 changes: 37 additions & 0 deletions ExampleDependency/ExampleDependency.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34330.188
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExampleDependency", "ExampleDependency.csproj", "{76493ED8-B97B-4C27-91EE-CE065270D87F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{76493ED8-B97B-4C27-91EE-CE065270D87F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{76493ED8-B97B-4C27-91EE-CE065270D87F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{76493ED8-B97B-4C27-91EE-CE065270D87F}.Debug|x64.ActiveCfg = Debug|x64
{76493ED8-B97B-4C27-91EE-CE065270D87F}.Debug|x64.Build.0 = Debug|x64
{76493ED8-B97B-4C27-91EE-CE065270D87F}.Debug|x86.ActiveCfg = Debug|x86
{76493ED8-B97B-4C27-91EE-CE065270D87F}.Debug|x86.Build.0 = Debug|x86
{76493ED8-B97B-4C27-91EE-CE065270D87F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{76493ED8-B97B-4C27-91EE-CE065270D87F}.Release|Any CPU.Build.0 = Release|Any CPU
{76493ED8-B97B-4C27-91EE-CE065270D87F}.Release|x64.ActiveCfg = Release|x64
{76493ED8-B97B-4C27-91EE-CE065270D87F}.Release|x64.Build.0 = Release|x64
{76493ED8-B97B-4C27-91EE-CE065270D87F}.Release|x86.ActiveCfg = Release|Any CPU
{76493ED8-B97B-4C27-91EE-CE065270D87F}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5D7E4DE6-C9EA-4A10-A65B-AC464D1711B7}
EndGlobalSection
EndGlobal
Binary file not shown.
Binary file not shown.
5 changes: 4 additions & 1 deletion NppCSharpPluginPack/Forms/PopupDialog.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using NppDemo.Utils;
using Kbg.NppPluginNET;
using System.Windows.Forms;
using ExampleDependency;

namespace NppDemo.Forms
{
Expand All @@ -21,10 +22,12 @@ private void ComboBox1EnabledCheckBox_CheckedChanged(object sender, System.Event

private void button1_Click(object sender, System.EventArgs e)
{

string msg = ComboBox1.Enabled
? $"ComboBox1 selected value = {ComboBox1.Text}"
: "ComboBox1 is disabled";
MessageBox.Show(msg);
var exampleClassMember = new ExampleClass(msg);
MessageBox.Show(exampleClassMember.ToString());
}

/// <summary>
Expand Down
5 changes: 0 additions & 5 deletions NppCSharpPluginPack/Forms/SelectionRememberingForm.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
using NppDemo.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using Kbg.NppPluginNET;
using System.IO;
using System.Runtime.CompilerServices;

namespace NppDemo.Forms
{
Expand Down
18 changes: 17 additions & 1 deletion NppCSharpPluginPack/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using System.Text.RegularExpressions;
using System.Text;
using System.IO;
using System.Reflection;

namespace Kbg.NppPluginNET
{
Expand Down Expand Up @@ -50,6 +51,9 @@ class Main

static internal void CommandMenuInit()
{
// first make it so that all references to any third-party dependencies point to the correct location
// see https://github.com/oleg-shilo/cs-script.npp/issues/66#issuecomment-1086657272 for more info
AppDomain.CurrentDomain.AssemblyResolve += LoadDependency;
// Initialization of your plugin commands

// with function :
Expand Down Expand Up @@ -97,7 +101,19 @@ static internal void CommandMenuInit()

}

static internal void SetToolBarIcons()
private static Assembly LoadDependency(object sender, ResolveEventArgs args)
{
// Path.GetFullPath(".") will return the path to the Notepad++ executable
// I have *very rarely* seen it instead return another path, but in general this should work properly.
// Unfortunately Npp.notepad.GetNppPath() cannot be used here for reasons discussed in this comment by rdipardo:
// https://github.com/molsonkiko/NppCSharpPluginPack/issues/5#issuecomment-1982167513
string assemblyFile = Path.Combine(Path.GetFullPath("."), "plugins", PluginName, new AssemblyName(args.Name).Name) + ".dll";
if (File.Exists(assemblyFile))
return Assembly.LoadFrom(assemblyFile);
return null;
}

static internal void SetToolBarIcons()
{
string iconsToUseChars = settings.toolbar_icons.ToLower();
var iconInfo = new (Bitmap bmp, Icon icon, Icon iconDarkMode, int id, char representingChar)[]
Expand Down
60 changes: 37 additions & 23 deletions NppCSharpPluginPack/NppCSharpPluginPack.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,21 @@
<Compile Include="Utils\SelectionManager.cs" />
<Compile Include="Utils\Settings.cs" />
</ItemGroup>
<Choose>
<!-- where should we look for dependency assemblies? -->
<When Condition=" '$(Platform)' == ''">
<ItemGroup>
<DEPENDENCY_DIR Include="Dependencies\x64" />
<DEPENDENCY_DLLS Include="Dependencies\x64\*.dll" />
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<DEPENDENCY_DIR Include="Dependencies\$(Platform)" />
<DEPENDENCY_DLLS Include="Dependencies\$(Platform)\*.dll" />
</ItemGroup>
</Otherwise>
</Choose>
<ItemGroup>
<!-- references -->
<Reference Include="System" />
Expand All @@ -153,6 +168,10 @@
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="System.Net.Http" />
<!-- third-party dependencies -->
<Reference Include="ExampleDependency">
<HintPath>@(DEPENDENCY_DIR)\ExampleDependency.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<!-- resx files -->
Expand Down Expand Up @@ -191,37 +210,32 @@
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Condition="Exists($(PkgUnmanagedExports_Repack_Upgrade))"
Project="$(PkgUnmanagedExports_Repack_Upgrade)\build\UnmanagedExports.Repack.Upgrade.targets" />
<Import Condition="Exists($(PkgUnmanagedExports_Repack_Upgrade))" Project="$(PkgUnmanagedExports_Repack_Upgrade)\build\UnmanagedExports.Repack.Upgrade.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
-->
<Target Name="CopyBin" DependsOnTargets="Build" AfterTargets="Build" >
<Target Name="CopyBin" DependsOnTargets="Build" AfterTargets="Build">
<!-- copy over the appropriate DLL and test files to the Notepad++ directory.
Otherwise Notepad++ will just load without the plugin. -->
<ItemGroup>
<RELEASE64 Include="bin\Release-x64\*.*" />
<DEBUG64 Include="bin\Debug-x64\*.*" />
<RELEASE32 Include="bin\Release\*.*" />
<DEBUG32 Include="bin\Debug\*.*" />
<NPP64BIT Include="$(NppPath64)\plugins\CSharpPluginPack" />
<NPP32BIT Include="$(NppPath32)\plugins\CSharpPluginPack" />
</ItemGroup>
<MakeDir Directories="@(NPP64BIT)"
Condition=" '$(Platform)' == 'x64' " />
<MakeDir Directories="@(NPP32BIT)"
Condition=" '$(Platform)' == 'x86' " />
<Copy SourceFiles="bin\Release-x64\CSharpPluginPack.dll"
Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' "
DestinationFolder="@(NPP64BIT)"
SkipUnchangedFiles="true" />
<Copy SourceFiles="bin\Release\CSharpPluginPack.dll"
Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' "
DestinationFolder="@(NPP32BIT)"
SkipUnchangedFiles="true" />
<Copy SourceFiles="bin\Debug-x64\CSharpPluginPack.dll"
Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' "
DestinationFolder="@(NPP64BIT)"
SkipUnchangedFiles="true" />
<Copy SourceFiles="bin\Debug\CSharpPluginPack.dll"
Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' "
DestinationFolder="@(NPP32BIT)"
SkipUnchangedFiles="true" />
<MakeDir Directories="@(NPP64BIT)" Condition=" '$(Platform)' == 'x64' " />
<MakeDir Directories="@(NPP32BIT)" Condition=" '$(Platform)' == 'x86' " />
<!-- copy all dependency DLL's to current bin directory -->
<Copy Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' " SourceFiles="@(DEPENDENCY_DLLS)" DestinationFolder="bin\Release-x64" SkipUnchangedFiles="true" />
<Copy Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' " SourceFiles="@(DEPENDENCY_DLLS)" DestinationFolder="bin\Release" SkipUnchangedFiles="true" />
<Copy Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' " SourceFiles="@(DEPENDENCY_DLLS)" DestinationFolder="bin\Debug-x64" SkipUnchangedFiles="true" />
<Copy Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' " SourceFiles="@(DEPENDENCY_DLLS)" DestinationFolder="bin\Debug" SkipUnchangedFiles="true" />
<!-- copy all files in current bin directory to NPP plugin dir -->
<Copy SourceFiles="@(RELEASE64)" Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' " DestinationFolder="@(NPP64BIT)" SkipUnchangedFiles="true" />
<Copy SourceFiles="@(RELEASE32)" Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' " DestinationFolder="@(NPP32BIT)" SkipUnchangedFiles="true" />
<Copy SourceFiles="@(DEBUG64)" Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' " DestinationFolder="@(NPP64BIT)" SkipUnchangedFiles="true" />
<Copy SourceFiles="@(DEBUG32)" Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' " DestinationFolder="@(NPP32BIT)" SkipUnchangedFiles="true" />
</Target>
</Project>
13 changes: 8 additions & 5 deletions NppCSharpPluginPack/PluginInfrastructure/NppPluginNETHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,14 @@ public enum DockMgrMsg : uint
//nmhdr.hwndFrom = hwndNpp;
//nmhdr.IdFrom = ctrlIdNpp;

DMN_DOCK = (DMN_FIRST + 2),
DMN_FLOAT = (DMN_FIRST + 3)
//nmhdr.Code = DWORD(DMN_XXX, int newContainer);
//nmhdr.hwndFrom = hwndNpp;
//nmhdr.IdFrom = ctrlIdNpp;
DMN_DOCK = (DMN_FIRST + 2),
DMN_FLOAT = (DMN_FIRST + 3),
DMN_SWITCHIN = (DMN_FIRST + 4),
DMN_SWITCHOFF = (DMN_FIRST + 5),
DMN_FLOATDROPPED = (DMN_FIRST + 6),
//nmhdr.Code = DWORD(DMN_XXX, int newContainer);
//nmhdr.hwndFrom = hwndNpp;
//nmhdr.IdFrom = ctrlIdNpp;
}

[StructLayout(LayoutKind.Sequential)]
Expand Down
4 changes: 2 additions & 2 deletions NppCSharpPluginPack/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@
// Build Number
// Revision
//
[assembly: AssemblyVersion("0.0.3.0")]
[assembly: AssemblyFileVersion("0.0.3.0")]
[assembly: AssemblyVersion("0.0.3.1")]
[assembly: AssemblyFileVersion("0.0.3.1")]
2 changes: 1 addition & 1 deletion PluginPackArchitecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Many of the files in the [PluginInfrastructure folder](/NppCSharpPluginPack/Plug
The way to regenerate the auto-generated portions of these code is to download the Notepad++ source code from master and run the Python scripts in [ToolsForMaintainersOfTheProjectTemplate](/ToolsForMaintainersOfTheProjectTemplate/) folder. Read the documentation of those scripts if you're still unsure how to proceed.


## Plugins using this pluginpack (or the original)
## Plugins using this pluginpack (or kbilsted's original)

* https://github.com/kbilsted/NppPluginGuidHelper
* https://github.com/zkirkland/FirstUpper
Expand Down
23 changes: 23 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,29 @@ Here are some important ways that the popup dialog differs from other dialogs:

![Popup dialog](/docs/popup%20dialog.PNG)

## Loading third-party dependencies ##

There are two ways that I (Mark J. Olson) know of to incorporate third-party dependencies into the project, using [NuGet](https://www.nuget.org/) and loading locally installed DLL's. Each will be covered below.
Regardless of which type of dependency you use, __make sure that the depenendencies work for both 32-bit and 64-bit Notepad++.__

Note that the first version of this project to directly support 3rd-party DLL's in this way is `0.0.3.1`.

### Including NuGet packages in your project ###

I have tested this (as of version `0.0.3.1`) by installing [ExcelDataReader 3.6.0](https://www.nuget.org/packages/ExcelDataReader/3.6.0), adding some ExcelDataReader method calls to the [PopupDialog](#popup-dialog), and verifying that the method calls run successfully.
1. Install the NuGet package. In Visual Studio, this entails going to `Project->Manage NuGet packages...` from the main menu, then installing a package.
2. Build the project as normal. The NuGet package should be usable as expected.

### Including locally installed DLL's in your project ###

This is demonstrated with the [ExampleDependency](/ExampleDependency) example dependency, which is referenced in the [Popup Dialog](/NppCSharpPluginPack/Forms/PopupDialog.cs).

1. Add a *64-bit* build of the DLL to the [NppCSharpPluginPack\Dependencies\x64](/NppCSharpPluginPack/Dependencies/x64) directory.
2. Add a *32-bit* build of the DLL to the [NppCSharpPluginPackDependencies\x86](/NppCSharpPluginPack/Dependencies/x86) directory.
3. Build the project for 64-bit and 32-bit Notepad++. Verify that any 3rd-party DLL's are usable as normal.

## Running tests ##

I (Mark J. Olson) believe that without a robust automated test suite, it is hard to make major changes to any large project without breaking things unexpectedly. Over the course of developing my JsonTools plugin, I developed a strategy for running automated tests and performance benchmarks inside of Notepad++.
Expand Down
Loading

0 comments on commit 574e196

Please sign in to comment.