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`