Releases: SecretNest/ImageStore
Release list
v2026.08.18.1
Downloads
- ImageStore-v2026.08.18.1.zip — the module and its dependencies. This is the one you want.
- ImageStore-Migrator-v2026.08.18.1.zip — only for upgrading an existing Sql Server library. Not needed
for a new one.
Usage
Unpack the module archive into a folder as a whole, then:
pwsh
Import-Module .\ImageStore.dll
New-ImageStoreDatabase .\library.db
There is no database server to install: a library is a single file, and
New-ImageStoreDatabase creates it and opens it in one step.
Requires Windows, PowerShell 7.6 or later, and the .NET 10 Desktop Runtime.
Built from commit 6d2834f.
Full Changelog: v3.0.4...v2026.08.18.1
v2026.08.15.4
Downloads
- ImageStore-v2026.08.15.4.zip — the module and its dependencies. This is the one you want.
- ImageStore-Migrator-v2026.08.15.4.zip — only for upgrading an existing Sql Server library. Not needed
for a new one.
Usage
Unpack the module archive into a folder as a whole, then:
pwsh
Import-Module .\ImageStore.dll
New-ImageStoreDatabase .\library.db
There is no database server to install: a library is a single file, and
New-ImageStoreDatabase creates it and opens it in one step.
Requires Windows, PowerShell 7.6 or later, and the .NET 10 Desktop Runtime.
Built from commit edff6d3.
What's Changed
Full Changelog: v2.0...v2026.08.15.4
v2026.08.15.3
Downloads
- ImageStore-v2026.08.15.3.zip — the module and its dependencies. This is the one you want.
- ImageStore-Database-v2026.08.15.3.zip — an empty database (DataStore.mdf, DataStore_log.ldf) and the
schema script (CreateDatabase.txt). Only needed once, when setting up a new project;
the contents are the same in every release.
Usage
Unpack the module archive into a folder and load it:
Import-Module .\ImageStore.dll
Requires Windows, .NET Framework 4.8.1 and SQL Server 2017 (LocalDB or Express is enough).
Built from commit 7b51a61.
What's Changed
New Contributors
Full Changelog: v2026.08.15.2...v2026.08.15.3
v2026.08.15.2
Downloads
- ImageStore-v2026.08.15.2.zip — the module and its dependencies. This is the one you want.
- ImageStore-Database-v2026.08.15.2.zip — an empty database (DataStore.mdf, DataStore_log.ldf) and the
schema script (CreateDatabase.txt). Only needed once, when setting up a new project;
the contents are the same in every release.
Usage
Unpack the module archive into a folder and load it:
Import-Module .\ImageStore.dll
Requires Windows, .NET Framework 4.8.1 and SQL Server 2017 (LocalDB or Express is enough).
Built from commit 6d01c6a.
Full Changelog: v2026.08.15.1...v2026.08.15.2
v2026.08.15.1
Downloads
- ImageStore-v2026.08.15.1.zip — the module and its dependencies. This is the one you want.
- ImageStore-Database-v2026.08.15.1.zip — an empty database (DataStore.mdf, DataStore_log.ldf) and the
schema script (CreateDatabase.txt). Only needed once, when setting up a new project;
the contents are the same in every release.
Usage
Unpack the module archive into a folder and load it:
Import-Module .\ImageStore.dll
Requires Windows, .NET Framework 4.8.1 and SQL Server 2017 (LocalDB or Express is enough).
Built from commit 407eb4e.
Full Changelog: https://github.com/SecretNest/ImageStore/commits/v2026.08.15.1
v3.0.4
Fixes Resolve-ImageStoreSimilarFiles failing with:
Unable to cast object of type 'System.Double' to type 'System.Single'.
What was wrong
ExecuteScalar returns a boxed double for a REAL column, and unboxing that directly to float throws. Unlike a data reader, ExecuteScalar has no typed accessor that would hide the difference, so the conversion pass for the SQLite move — which covered every reader[N] — missed this one call site.
Swept the rest
Rather than fixing the single line, every place a database value is read was rechecked:
- All typed getters (
GetGuid,GetBoolean,GetInt32,GetFloat,GetString) feed matching types. - The remaining
reader[N]uses are all BLOB columns —byte[]is the one type that unboxes cleanly. - Nullable columns go through
DBNullableReader. - The only other
ExecuteScalaralready usedConvert.ToInt64.
The migration tool was verified too, using its exact parameter handling — including the awkward case of one reused parameter bound to NULL on one row and a blob on the next. Guids, bools, floats, ints, unicode text and 40/20-byte blobs all round-trip exactly, and COLLATE NOCASE still applies to migrated text. Data produced by the migrator is sound; if you already migrated, there is nothing to redo.
v3.0.3
Warning
Resolve-ImageStoreSimilarFiles in this release fails with "Unable to cast object of type 'System.Double' to type 'System.Single'."
Use v3.0.4.
Fixes the module failing to load. If you hit this in v3.0.2, upgrade:
Open-ImageStoreDatabase: The type initializer for 'Microsoft.Data.Sqlite.SqliteConnection' threw an exception.
What was wrong
Import-Module loads a module assembly directly rather than starting an application, so the RID-specific probing that finds runtimes\<rid>\native never runs — that step is driven by deps.json when a host starts an app, and there is no such step here. The P/Invoke inside SQLitePCLRaw searched only the ordinary OS paths, did not find e_sqlite3.dll, and the failure surfaced as a type-initializer error that says nothing about a missing file.
The engine is now loaded explicitly when the module is imported, choosing the directory by process architecture, so x64, x86 and arm64 hosts all work.
Also fixed
Set-ImageStoreThumbprintCacheFolder resolved its path against AppContext.BaseDirectory, which for a module is the host's directory — the cache would have been created next to pwsh.exe instead of beside the module. Introduced in v2.0 during the .NET 10 upgrade, when Assembly.CodeBase was replaced. Both call sites now resolve from the module's own location.
Workaround for v3.0.2
Copying the engine beside the module also works, if you would rather not upgrade:
Copy-Item .\runtimes\win-x64\native\e_sqlite3.dll .v3.0.2
Warning
The module in this release fails to load with "The type initializer for 'Microsoft.Data.Sqlite.SqliteConnection' threw an exception."
Use v3.0.3.
Fixes a performance problem that would show up on any sizeable library.
What was wrong
SQLite does not maintain query statistics on its own. Until ANALYZE has run there is no sqlite_stat1, and the planner does not merely pick a worse index — it stops using indexes at all.
Measured on a 500,000-file library (5 million similar pairs, 974 MB):
| Query | Without statistics | With statistics |
|---|---|---|
| Single-file lookup | 55 ms, full table scan | under 1 ms, index seek |
| Path prefix search | 126 ms, full scan | under 1 ms, index |
| Exact path match | 83 ms, full scan | under 1 ms, index |
| Load all files | 468 ms | 271 ms |
| Similar pairs by degree | 655 ms | 461 ms |
Sync-ImageStoreFolder performs one single-file lookup per file. At 55 ms each, a 500,000-file sync would take hours instead of minutes.
Sql Server maintained these statistics automatically, so nothing in the move to SQLite made the gap visible.
The fix
Statistics are now maintained in three places:
- The migration tool analyses after loading the data.
- Opening a database analyses if statistics are absent entirely — about 1.5 seconds, once, on a library of that size. Subsequent opens cost nothing.
Compress-ImageStoreDatabaserefreshes them, since compacting normally follows a large deletion.
PRAGMA optimize on close already handled incremental drift.
If you already migrated with v3.0.1
Nothing is wrong with your database — it simply has no statistics yet. Opening it with this release fixes that automatically on the first open. Running ANALYZE by hand would have had the same effect.
v3.0.1
Fixes the migration tool, which could not run at all in v3.0.
What was wrong
ImageStore.Migrator was built with globalization invariant mode enabled. Microsoft.Data.SqlClient refuses to load under that mode and failed immediately with:
Migration failed: Globalization Invariant Mode is not supported.
It never reached the connection string, so no migration was possible. If you are migrating from Sql Server, use this release rather than v3.0.
The module itself never had that setting and is unaffected — ImageStore-v3.0.zip and ImageStore-v3.0.1.zip are equivalent.
Also
A push to master no longer publishes a second, date-named release for a commit that is already being released under a version tag. Previously both went out and the date-named one, landing a minute later, took the "Latest" marker.
Everything else
See the v3.0 release notes — this is that release with the migrator repaired.
v3.0
Warning
The ImageStore-Migrator asset in this release cannot run — it fails with "Globalization Invariant Mode is not supported."
Use v3.0.1 to migrate. The module itself is unaffected.
A library is now a single file. No database server, no instance, no connection string.
pwsh
Import-Module .\ImageStore.dll
New-ImageStoreDatabase D:\Library\library.dbThat creates the file, builds the schema and opens it. Later sessions just open it:
Open-ImageStoreDatabase D:\Library\library.dbRequirements
- Windows
- PowerShell 7.6 or later
- .NET 10 Desktop Runtime
Sql Server is no longer needed or supported.
Upgrading an existing library
Download ImageStore-Migrator below and run it once. It reads the old database without modifying it, so your Sql Server library stays intact as a fallback:
ImageStore.Migrator --source "server=(LocalDB)\MSSQLLocalDB;AttachDbFilename=D:\DataStore.mdf;Integrated Security=True" --target D:\Library\library.db
If you would rather not migrate, v2.0 is the last Sql-Server-only release and remains available.
Keep the database file on a local disk
SQLite coordinates access through file locking, which is unreliable over SMB and other network shares, and write-ahead logging cannot be used there at all. A database on a network share risks corruption.
This does not restrict where your images live. ImageStore stores paths, not image content, so images on a NAS with the database on a local disk is a normal and safe arrangement.
Also in this release
- The database is now closed automatically when the module is removed and when PowerShell exits, so
-waland-shmfiles are not left beside it. Compress-ImageStoreDatabaserunsVACUUM.- Fixed: searching for a file name containing an apostrophe (
Don't.jpg) never matched. This was broken in every previous release, including under Sql Server. - Path, file name and extension comparison stays case-insensitive, as before. One limitation worth knowing: SQLite folds ASCII only, so accented characters now compare exactly —
CAFÉandcaféare treated as different.
A note on this release
This changes where your data lives, which is a bigger step than the usual release. The migration tool does not touch the source database, and v2.0 stays available, so there is a way back if something does not work in your library.