From ac41997cacbabacf75d29e2010b5b196bcdf5a6d Mon Sep 17 00:00:00 2001
From: Zolnai Zsolt <44463109+zzsolt@users.noreply.github.com>
Date: Fri, 18 Sep 2026 11:08:47 +0200
Subject: [PATCH 01/14] Fix plugin-name cleanup on shutdown
---
src/CsvVisualEditor/Main.cs | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/src/CsvVisualEditor/Main.cs b/src/CsvVisualEditor/Main.cs
index e2e50b84..df919580 100644
--- a/src/CsvVisualEditor/Main.cs
+++ b/src/CsvVisualEditor/Main.cs
@@ -452,11 +452,10 @@ private void PluginCleanUp()
PluginData.FuncItems.Dispose();
- if (PluginData.PluginNamePtr != IntPtr.Zero)
- {
- Marshal.FreeHGlobal(PluginData.PluginNamePtr);
- PluginData.PluginNamePtr = IntPtr.Zero;
- }
+ // PluginNamePtr's setter owns the allocation and frees the previous pointer.
+ // Assigning zero is sufficient; freeing it manually first would double-free
+ // the unmanaged string during Notepad++ shutdown.
+ PluginData.PluginNamePtr = IntPtr.Zero;
}
}
From d63d7fb23741f4e1656205423ecc549fbdc930d0 Mon Sep 17 00:00:00 2001
From: Zolnai Zsolt <44463109+zzsolt@users.noreply.github.com>
Date: Fri, 18 Sep 2026 11:08:50 +0200
Subject: [PATCH 02/14] Bump shutdown-fix candidate to 1.0.1
---
src/CsvVisualEditor/CsvVisualEditor.csproj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/CsvVisualEditor/CsvVisualEditor.csproj b/src/CsvVisualEditor/CsvVisualEditor.csproj
index 97eb943d..3b603ce9 100644
--- a/src/CsvVisualEditor/CsvVisualEditor.csproj
+++ b/src/CsvVisualEditor/CsvVisualEditor.csproj
@@ -8,7 +8,7 @@
false
CsvVisualEditor
CsvVisualEditor
- 1.0.0
+ 1.0.1
Zolnai Zsolt
Copyright © 2026 Zolnai Zsolt
A 64-bit Notepad++ plugin for viewing, editing, filtering and inspecting CSV data in a docked table.
From 08f7b22be42b77ac1fb1d5f0b81e3aa25ae96d91 Mon Sep 17 00:00:00 2001
From: Zolnai Zsolt <44463109+zzsolt@users.noreply.github.com>
Date: Fri, 18 Sep 2026 11:08:52 +0200
Subject: [PATCH 03/14] Build 1.0.1 candidate
---
.github/workflows/ci.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a1dd16fc..06c31538 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -64,7 +64,7 @@ jobs:
runs-on: windows-latest
timeout-minutes: 30
env:
- PACKAGE_VERSION: 1.0.0
+ PACKAGE_VERSION: 1.0.1
steps:
- uses: actions/checkout@v4
with:
From 308f407d5beb131ad7f1b02abbb392b4a5a34dfe Mon Sep 17 00:00:00 2001
From: Zolnai Zsolt <44463109+zzsolt@users.noreply.github.com>
Date: Fri, 18 Sep 2026 11:08:56 +0200
Subject: [PATCH 04/14] Default local candidate version to 1.0.1
---
tools/build-local.ps1 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/build-local.ps1 b/tools/build-local.ps1
index 6fb4b608..95fa70a9 100644
--- a/tools/build-local.ps1
+++ b/tools/build-local.ps1
@@ -1,5 +1,5 @@
param(
- [string] $PackageVersion = ("1.0.0-local." + [DateTime]::UtcNow.ToString('yyyyMMddHHmmss'))
+ [string] $PackageVersion = ("1.0.1-local." + [DateTime]::UtcNow.ToString('yyyyMMddHHmmss'))
)
$ErrorActionPreference = 'Stop'
From 0e9862f99ccfced637715ec124432430de3c3fb1 Mon Sep 17 00:00:00 2001
From: Zolnai Zsolt <44463109+zzsolt@users.noreply.github.com>
Date: Fri, 18 Sep 2026 11:09:08 +0200
Subject: [PATCH 05/14] Guard shutdown ownership and 1.0.1 release metadata
---
tests/release/test_release_package.py | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/tests/release/test_release_package.py b/tests/release/test_release_package.py
index e3045c39..f80f28ac 100644
--- a/tests/release/test_release_package.py
+++ b/tests/release/test_release_package.py
@@ -15,14 +15,14 @@
class ReleasePackageTests(unittest.TestCase):
def test_entry_matches_plugins_admin_contract(self):
- entry = release.plugin_admin_entry("1.0.0", "a" * 64)
+ entry = release.plugin_admin_entry("1.0.1", "a" * 64)
self.assertEqual("CsvVisualEditor", entry["folder-name"])
self.assertEqual("CSV Visual Editor", entry["display-name"])
- self.assertEqual("1.0.0", entry["version"])
+ self.assertEqual("1.0.1", entry["version"])
self.assertEqual("[8.9.8,]", entry["npp-compatible-versions"])
self.assertEqual("a" * 64, entry["id"])
self.assertTrue(entry["repository"].endswith(
- "/releases/download/v1.0.0/CsvVisualEditor-1.0.0-win-x64.zip"
+ "/releases/download/v1.0.1/CsvVisualEditor-1.0.1-win-x64.zip"
))
self.assertEqual("Zolnai Zsolt", entry["author"])
@@ -36,7 +36,7 @@ def test_archive_requires_root_dll_and_notices(self):
archive.writestr("CsvVisualEditor.dll", dll.read_bytes())
archive.writestr("LICENSE.txt", "GPL")
archive.writestr("THIRD_PARTY_NOTICES.txt", "third-party")
- zip_hash, dll_hash = release.verify_archive(package, dll, "1.0.0")
+ zip_hash, dll_hash = release.verify_archive(package, dll, "1.0.1")
self.assertEqual(64, len(zip_hash))
self.assertEqual(release.sha256_bytes(dll.read_bytes()), dll_hash)
@@ -49,14 +49,14 @@ def test_nested_dll_is_rejected(self):
archive.writestr("LICENSE.txt", "GPL")
archive.writestr("THIRD_PARTY_NOTICES.txt", "third-party")
with self.assertRaises(ValueError):
- release.verify_archive(package, None, "1.0.0")
+ release.verify_archive(package, None, "1.0.1")
def test_repository_declares_stable_gpl_release(self):
project = (ROOT / "src/CsvVisualEditor/CsvVisualEditor.csproj").read_text(encoding="utf-8")
- self.assertIn("1.0.0", project)
+ self.assertIn("1.0.1", project)
self.assertIn("GPL-3.0-only", project)
workflow = (ROOT / ".github/workflows/ci.yml").read_text(encoding="utf-8")
- self.assertIn("PACKAGE_VERSION: 1.0.0", workflow)
+ self.assertIn("PACKAGE_VERSION: 1.0.1", workflow)
build = (ROOT / "tools/build-local.ps1").read_text(encoding="utf-8")
self.assertIn("Join-Path $layout 'CsvVisualEditor.dll'", build)
self.assertIn("LICENSE.txt", build)
@@ -68,6 +68,11 @@ def test_repository_declares_stable_gpl_release(self):
self.assertIn("Npp.DotNet.Plugin 1.0.0-alpha.10", notices)
self.assertIn(".NET Runtime / Native AOT 10.0.12", notices)
+ def test_shutdown_does_not_double_free_plugin_name(self):
+ main = (ROOT / "src/CsvVisualEditor/Main.cs").read_text(encoding="utf-8")
+ self.assertIn("PluginData.PluginNamePtr = IntPtr.Zero;", main)
+ self.assertNotIn("Marshal.FreeHGlobal(PluginData.PluginNamePtr)", main)
+
def test_template_has_required_plugins_admin_fields(self):
data = json.loads((ROOT / "packaging/nppPluginList/entry.template.json").read_text(encoding="utf-8"))
for key in ("folder-name", "display-name", "version", "npp-compatible-versions",
From 00a1f265e7534f297fbb645dde64e89b4dc4f813 Mon Sep 17 00:00:00 2001
From: Zolnai Zsolt <44463109+zzsolt@users.noreply.github.com>
Date: Fri, 18 Sep 2026 11:09:27 +0200
Subject: [PATCH 06/14] Test clean Notepad++ shutdown in production host gate
---
tests/host-review/Invoke-HostReview.ps1 | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/tests/host-review/Invoke-HostReview.ps1 b/tests/host-review/Invoke-HostReview.ps1
index 9577288d..23a18af9 100644
--- a/tests/host-review/Invoke-HostReview.ps1
+++ b/tests/host-review/Invoke-HostReview.ps1
@@ -232,8 +232,12 @@ try {
$aboutText=@([CsvHostWindows]::Children($about) | ForEach-Object { [CsvHostWindows]::ControlText($_) }) -join "`n"
if(!$aboutText.Contains('Zolnai Zsolt') -or !$aboutText.Contains('zzsolt@gmail.com') -or !$aboutText.Contains($env:PACKAGE_VERSION)) {throw 'Production About content or package version mismatch'}
Send-Native $about 0x10 ([IntPtr]::Zero) ([IntPtr]::Zero) | Out-Null
- [ordered]@{ NotepadVersion=(Get-Item $exe).VersionInfo.ProductVersion; Windows=[Environment]::OSVersion.VersionString; Dpi=[CsvHostWindows]::GetDpiForWindow($form); DllSha256=(Get-FileHash $library -Algorithm SHA256).Hash; ProductionDllLoaded=$true; SearchCountObserved=$true; SearchClearObserved=$true; AboutObserved=$true; PackageVersion=$env:PACKAGE_VERSION; DockWidths=$resizes; DataFilterPreviewObserved=$true; DataFilterApplied=$true; DataSummaryObserved=$true; DataCancelPreserved=$true; DataResetObserved=$true; SourceBufferUnchanged=$true; Scope='Automated production-host load/search/resize/About and data filter/preview/apply/cancel/reset/summary, exact source buffer preservation. Not manual acceptance or editing Apply/Undo coverage.' } | ConvertTo-Json | Set-Content (Join-Path $output 'host-evidence.json')
- Write-Host 'Real Notepad++ production-DLL load/render/search review completed.'
+ $evidence = [ordered]@{ NotepadVersion=(Get-Item $exe).VersionInfo.ProductVersion; Windows=[Environment]::OSVersion.VersionString; Dpi=[CsvHostWindows]::GetDpiForWindow($form); DllSha256=(Get-FileHash $library -Algorithm SHA256).Hash; ProductionDllLoaded=$true; SearchCountObserved=$true; SearchClearObserved=$true; AboutObserved=$true; PackageVersion=$env:PACKAGE_VERSION; DockWidths=$resizes; DataFilterPreviewObserved=$true; DataFilterApplied=$true; DataSummaryObserved=$true; DataCancelPreserved=$true; DataResetObserved=$true; SourceBufferUnchanged=$true; CleanShutdownObserved=$false; Scope='Automated production-host load/search/resize/About and data filter/preview/apply/cancel/reset/summary, exact source buffer preservation, and normal Notepad++ shutdown with the production plugin loaded. Not manual acceptance or editing Apply/Undo coverage.' }
+ [CsvHostWindows]::PostMessage($window,0x10,[IntPtr]::Zero,[IntPtr]::Zero) | Out-Null
+ if (!$process.WaitForExit(10000)) { throw 'Notepad++ did not exit cleanly with the production plugin loaded' }
+ $evidence.CleanShutdownObserved = $true
+ $evidence | ConvertTo-Json | Set-Content (Join-Path $output 'host-evidence.json')
+ Write-Host 'Real Notepad++ production-DLL load/render/search/shutdown review completed.'
} finally {
if($process -and !$process.HasExited) { $process.Kill(); $process.WaitForExit() }
Remove-Item -LiteralPath $homeDir -Recurse -Force
From d1ca2df1144c156619d29a7fb279e10fd20fe32a Mon Sep 17 00:00:00 2001
From: Zolnai Zsolt <44463109+zzsolt@users.noreply.github.com>
Date: Fri, 18 Sep 2026 11:09:44 +0200
Subject: [PATCH 07/14] Prepare Plugins Admin template for 1.0.1
---
packaging/nppPluginList/entry.template.json | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/packaging/nppPluginList/entry.template.json b/packaging/nppPluginList/entry.template.json
index c0d1650e..3f3ebbfe 100644
--- a/packaging/nppPluginList/entry.template.json
+++ b/packaging/nppPluginList/entry.template.json
@@ -1,10 +1,10 @@
{
"folder-name": "CsvVisualEditor",
"display-name": "CSV Visual Editor",
- "version": "1.0.0",
+ "version": "1.0.1",
"npp-compatible-versions": "[8.9.8,]",
- "id": "",
- "repository": "https://github.com/zzsolt/notepadplusplus-csv-visual-editor/releases/download/v1.0.0/CsvVisualEditor-1.0.0-win-x64.zip",
+ "id": "",
+ "repository": "https://github.com/zzsolt/notepadplusplus-csv-visual-editor/releases/download/v1.0.1/CsvVisualEditor-1.0.0-win-x64.zip",
"description": "View, edit, filter and inspect CSV data in a docked table with conflict-checked Apply and Notepad++ undo.",
"author": "Zolnai Zsolt",
"homepage": "https://github.com/zzsolt/notepadplusplus-csv-visual-editor"
From 8cd965fb475b2e0e529b26e7d694f2c14ce24b77 Mon Sep 17 00:00:00 2001
From: Zolnai Zsolt <44463109+zzsolt@users.noreply.github.com>
Date: Fri, 18 Sep 2026 11:09:47 +0200
Subject: [PATCH 08/14] Document 1.0.1 maintenance build
---
docs/building.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/building.md b/docs/building.md
index 382e495c..11d215c2 100644
--- a/docs/building.md
+++ b/docs/building.md
@@ -25,13 +25,13 @@ All commands above must succeed before publishing a build. The seven maintained
## Stable release and Plugins Admin
-The stable product version is `1.0.0`. Project code is GPL-3.0-only; do not
+The current stable maintenance version is `1.0.1`. Project code is GPL-3.0-only; do not
remove `LICENSE` or `THIRD_PARTY_NOTICES.txt` from a distributed package.
The complete Windows release gate is:
```powershell
-pwsh -NoProfile -File tools/build-local.ps1 -PackageVersion 1.0.0
+pwsh -NoProfile -File tools/build-local.ps1 -PackageVersion 1.0.1
```
It runs release-policy tests in addition to localization, Core, Native AOT and
From 28c4138cb868d8e9e297e827edd61d8b216825b8 Mon Sep 17 00:00:00 2001
From: Zolnai Zsolt <44463109+zzsolt@users.noreply.github.com>
Date: Fri, 18 Sep 2026 11:09:49 +0200
Subject: [PATCH 09/14] Document 1.0.1 shutdown fix
---
CHANGELOG.md | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d26b5950..69d03df9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
# Changelog
+## 1.0.1 - 2026-09-18
+
+- Fix shutdown cleanup so Notepad++ can exit normally with CSV Visual Editor loaded.
+- Add a production-host regression check for clean Notepad++ shutdown.
+
## 1.0.0 - 2026-09-18
- First stable Windows x64 release.
From fe25448e0375da14cd385554573c4042c66ac7ea Mon Sep 17 00:00:00 2001
From: Zolnai Zsolt <44463109+zzsolt@users.noreply.github.com>
Date: Fri, 18 Sep 2026 11:09:52 +0200
Subject: [PATCH 10/14] Update stable maintenance version
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 823d761b..1364f46d 100644
--- a/README.md
+++ b/README.md
@@ -15,8 +15,8 @@ A 64-bit Notepad++ plugin for viewing, editing, filtering and inspecting CSV dat
## Version
-The first stable release is **1.0.0** for 64-bit Notepad++ on Windows. The
-production release gate is tested with Notepad++ 8.9.8 x64.
+The current stable maintenance line is **1.0.1** for 64-bit Notepad++ on Windows.
+The production release gate is tested with Notepad++ 8.9.8 x64.
## Installation
From a5e62720ae7fc463e02dcaddf993b338647869f0 Mon Sep 17 00:00:00 2001
From: Zolnai Zsolt <44463109+zzsolt@users.noreply.github.com>
Date: Fri, 18 Sep 2026 11:10:09 +0200
Subject: [PATCH 11/14] [test-package] Guard shutdown lifecycle release gate
---
tests/release/test_release_package.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tests/release/test_release_package.py b/tests/release/test_release_package.py
index f80f28ac..a2c48149 100644
--- a/tests/release/test_release_package.py
+++ b/tests/release/test_release_package.py
@@ -72,6 +72,9 @@ def test_shutdown_does_not_double_free_plugin_name(self):
main = (ROOT / "src/CsvVisualEditor/Main.cs").read_text(encoding="utf-8")
self.assertIn("PluginData.PluginNamePtr = IntPtr.Zero;", main)
self.assertNotIn("Marshal.FreeHGlobal(PluginData.PluginNamePtr)", main)
+ host_review = (ROOT / "tests/host-review/Invoke-HostReview.ps1").read_text(encoding="utf-8")
+ self.assertIn("WaitForExit(10000)", host_review)
+ self.assertIn("CleanShutdownObserved=$false", host_review)
def test_template_has_required_plugins_admin_fields(self):
data = json.loads((ROOT / "packaging/nppPluginList/entry.template.json").read_text(encoding="utf-8"))
From 783c977e62211f3114ca3ab33427a2cab7e47c6d Mon Sep 17 00:00:00 2001
From: Zolnai Zsolt <44463109+zzsolt@users.noreply.github.com>
Date: Fri, 18 Sep 2026 11:17:46 +0200
Subject: [PATCH 12/14] Record validated 1.0.1 Plugins Admin entry [skip ci]
---
packaging/nppPluginList/entry.x64.json | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/packaging/nppPluginList/entry.x64.json b/packaging/nppPluginList/entry.x64.json
index b3bfe8aa..305a72e4 100644
--- a/packaging/nppPluginList/entry.x64.json
+++ b/packaging/nppPluginList/entry.x64.json
@@ -1,10 +1,10 @@
{
"folder-name": "CsvVisualEditor",
"display-name": "CSV Visual Editor",
- "version": "1.0.0",
+ "version": "1.0.1",
"npp-compatible-versions": "[8.9.8,]",
- "id": "e513b9316806662dd358853c7f0a718ba78c50ca5b2992d3db23c4c0d77bd351",
- "repository": "https://github.com/zzsolt/notepadplusplus-csv-visual-editor/releases/download/v1.0.0/CsvVisualEditor-1.0.0-win-x64.zip",
+ "id": "2405357696cca26f6887701ab6d4e58c7c8671a201796c7a454048b521b29978",
+ "repository": "https://github.com/zzsolt/notepadplusplus-csv-visual-editor/releases/download/v1.0.1/CsvVisualEditor-1.0.1-win-x64.zip",
"description": "View, edit, filter and inspect CSV data in a docked table with conflict-checked Apply and Notepad++ undo.",
"author": "Zolnai Zsolt",
"homepage": "https://github.com/zzsolt/notepadplusplus-csv-visual-editor"
From 340a6aabd320e84a63837d9ce068296e6628dbc0 Mon Sep 17 00:00:00 2001
From: Zolnai Zsolt <44463109+zzsolt@users.noreply.github.com>
Date: Fri, 18 Sep 2026 11:17:48 +0200
Subject: [PATCH 13/14] Record validated 1.0.1 release manifest [skip ci]
---
packaging/release-manifest-1.0.1.json | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
create mode 100644 packaging/release-manifest-1.0.1.json
diff --git a/packaging/release-manifest-1.0.1.json b/packaging/release-manifest-1.0.1.json
new file mode 100644
index 00000000..c29162e6
--- /dev/null
+++ b/packaging/release-manifest-1.0.1.json
@@ -0,0 +1,19 @@
+{
+ "version": "1.0.1",
+ "zip": "CsvVisualEditor-1.0.1-win-x64.zip",
+ "zipSha256": "2405357696cca26f6887701ab6d4e58c7c8671a201796c7a454048b521b29978",
+ "dll": "CsvVisualEditor.dll",
+ "dllSha256": "f1340be31577ea443199de43844b6170bcd72e05d34229a93f546d973fd542b8",
+ "pluginAdminList": "src/pl.x64.json",
+ "pluginAdminEntry": {
+ "folder-name": "CsvVisualEditor",
+ "display-name": "CSV Visual Editor",
+ "version": "1.0.1",
+ "npp-compatible-versions": "[8.9.8,]",
+ "id": "2405357696cca26f6887701ab6d4e58c7c8671a201796c7a454048b521b29978",
+ "repository": "https://github.com/zzsolt/notepadplusplus-csv-visual-editor/releases/download/v1.0.1/CsvVisualEditor-1.0.1-win-x64.zip",
+ "description": "View, edit, filter and inspect CSV data in a docked table with conflict-checked Apply and Notepad++ undo.",
+ "author": "Zolnai Zsolt",
+ "homepage": "https://github.com/zzsolt/notepadplusplus-csv-visual-editor"
+}
+}
From 739d9eaa93024f06e38741437816cd1c42d61af5 Mon Sep 17 00:00:00 2001
From: Zolnai Zsolt <44463109+zzsolt@users.noreply.github.com>
Date: Fri, 18 Sep 2026 11:17:50 +0200
Subject: [PATCH 14/14] Add 1.0.1 release notes [skip ci]
---
packaging/release-notes-1.0.1.md | 13 +++++++++++++
1 file changed, 13 insertions(+)
create mode 100644 packaging/release-notes-1.0.1.md
diff --git a/packaging/release-notes-1.0.1.md b/packaging/release-notes-1.0.1.md
new file mode 100644
index 00000000..834b8633
--- /dev/null
+++ b/packaging/release-notes-1.0.1.md
@@ -0,0 +1,13 @@
+# CSV Visual Editor 1.0.1
+
+Maintenance release fixing clean Notepad++ shutdown with CSV Visual Editor loaded.
+
+- Fix plugin shutdown cleanup so Plugins Admin restart-based operations can proceed.
+- Add production-host regression coverage for normal Notepad++ exit.
+- Preserve the 1.0 feature set, package layout and Notepad++ 8.9.8 compatibility floor.
+
+Validated release package:
+
+- `CsvVisualEditor-1.0.1-win-x64.zip`
+- ZIP SHA-256: `2405357696cca26f6887701ab6d4e58c7c8671a201796c7a454048b521b29978`
+- DLL SHA-256: `f1340be31577ea443199de43844b6170bcd72e05d34229a93f546d973fd542b8`