{"id":220,"date":"2025-05-14T22:14:40","date_gmt":"2025-05-15T02:14:40","guid":{"rendered":"https:\/\/ziviz.us\/WP\/?p=220"},"modified":"2025-05-14T22:14:40","modified_gmt":"2025-05-15T02:14:40","slug":"powershell-and-sqlite","status":"publish","type":"post","link":"https:\/\/www.ziviz.net\/WP\/2025\/05\/14\/powershell-and-sqlite\/","title":{"rendered":"PowerShell and SQLite"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">I wanted to use SQLite with PowerShell, but without needing to rely on another module. Just SQLite&#8230; and PowerShell. So here is how to do that&#8230;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Download and Prepare SQLite<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">SQLite is available for the .Net framework, which PowerShell rides on. Great! But you need to make sure that the SQLite binaries you download match the .Net version available to you. To check, open PowerShell and run <code>$PSVersionTable<\/code> and check the CLRVersion, it should look like below:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"506\" height=\"280\" src=\"https:\/\/ziviz.us\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-205124.png\" alt=\"PowerShell Prompt Showing:\n\nPS C:\\&gt; $PSVersionTable\n\nName                           Value\n----                           -----\nPSVersion                      5.1.26100.4061\nPSEdition                      Desktop\nPSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}\nBuildVersion                   10.0.26100.4061\nCLRVersion                     4.0.30319.42000\nWSManStackVersion              3.0\nPSRemotingProtocolVersion      2.3\nSerializationVersion           1.1.0.1\" class=\"wp-image-222\" srcset=\"https:\/\/www.ziviz.net\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-205124.png 506w, https:\/\/www.ziviz.net\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-205124-300x166.png 300w\" sizes=\"auto, (max-width: 506px) 85vw, 506px\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">Per above, I need the SQLite download for .Net 4.0.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you download the wrong architecture, you will likely run into this error:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"173\" src=\"https:\/\/ziviz.us\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-210514-1024x173.png\" alt=\"PowerShell prompt showing:\n\nPS C:\\&gt; Add-Type -Path &quot;C:\\sqlite-netFx20-binary-bundle-Win32-2005-1.0.119.0\\System.Data.SQLite.dll&quot;\nAdd-Type : Could not load file or assembly\n'file:\/\/\/C:\\sqlite-netFx20-binary-bundle-Win32-2005-1.0.119.0\\System.Data.SQLite.dll' or one of its dependencies. An\nattempt was made to load a program with an incorrect format.\nAt line:1 char:1\n+ Add-Type -Path &quot;C:\\sqlite-netFx20-binary-bundle-Win32-2005-1.0.119.0\\ ...\n+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    + CategoryInfo          : NotSpecified: (:) [Add-Type], BadImageFormatException\n    + FullyQualifiedErrorId : System.BadImageFormatException,Microsoft.PowerShell.Commands.AddTypeCommand\" class=\"wp-image-227\" srcset=\"https:\/\/www.ziviz.net\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-210514-1024x173.png 1024w, https:\/\/www.ziviz.net\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-210514-300x51.png 300w, https:\/\/www.ziviz.net\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-210514-768x130.png 768w, https:\/\/www.ziviz.net\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-210514.png 1070w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><figcaption class=\"wp-element-caption\">An attempt was made to load a program with an incorrect format.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">If you download SQLite for a version of .Net you don&#8217;t have and can&#8217;t run, you will likely get this one:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"98\" src=\"https:\/\/ziviz.us\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-210901-1024x98.png\" alt=\"PowerShell prompt showing:\nPS C:\\&gt; Add-Type -Path &quot;C:\\sqlite-netFx20-static-binary-bundle-x64-2005-1.0.119.0\\System.Data.SQLite.dll&quot;\nAdd-Type : Could not load file or assembly 'file:\/\/\/C:\\sqlite-netFx20-static-binary-bundle-x64-2005-1.0.119.0\\System.Data.SQLite.dll' or one of its dependencies. Operation is not supported.\n(Exception from HRESULT: 0x80131515)\nAt line:1 char:1\n+ Add-Type -Path &quot;C:\\sqlite-netFx20-static-binary-bundle-x64-2005-1.0.1 ...\n+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    + CategoryInfo          : NotSpecified: (:) [Add-Type], FileLoadException\n    + FullyQualifiedErrorId : System.IO.FileLoadException,Microsoft.PowerShell.Commands.AddTypeCommand\" class=\"wp-image-228\" srcset=\"https:\/\/www.ziviz.net\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-210901-1024x98.png 1024w, https:\/\/www.ziviz.net\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-210901-300x29.png 300w, https:\/\/www.ziviz.net\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-210901-768x73.png 768w, https:\/\/www.ziviz.net\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-210901-1536x146.png 1536w, https:\/\/www.ziviz.net\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-210901-1200x114.png 1200w, https:\/\/www.ziviz.net\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-210901.png 1710w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><figcaption class=\"wp-element-caption\">Operation is not supported. (Exception from HRESULT: 0x80131515)<\/figcaption><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">Once you have your version figured out, download the matching SQLite binaries from <a href=\"https:\/\/system.data.sqlite.org\/home\/doc\/trunk\/www\/downloads.wiki\">https:\/\/system.data.sqlite.org\/<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As of today, for me, that is the <code>sqlite-netFx40-binary-bundle-x64-2010-1.0.119.0.zip<\/code><\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"449\" height=\"110\" src=\"https:\/\/ziviz.us\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-205626.png\" alt=\"Image from the SQLite download page for .Net 4.0 Binaries for 64-bit Windows\" class=\"wp-image-224\" srcset=\"https:\/\/www.ziviz.net\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-205626.png 449w, https:\/\/www.ziviz.net\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-205626-300x73.png 300w\" sizes=\"auto, (max-width: 449px) 85vw, 449px\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">Next, and very important, you must unblock the zip file. You can do this by right-clicking the zip file, and selecting &#8220;Unblock&#8221; and then clicking &#8220;Apply&#8221;.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"396\" height=\"502\" src=\"https:\/\/ziviz.us\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-205740.png\" alt=\"Showing the File Explorer's properties view of a zip file. At the bottom is a checkbox that is unchecked and it says &quot;Unblock&quot;\" class=\"wp-image-225\" srcset=\"https:\/\/www.ziviz.net\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-205740.png 396w, https:\/\/www.ziviz.net\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-205740-237x300.png 237w\" sizes=\"auto, (max-width: 396px) 85vw, 396px\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">If you do not do this, when you unzip the files, all the decompressed files will also be blocked. If you try and then hook into the SQLite dll from PowerShell you will get the following error:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"101\" src=\"https:\/\/ziviz.us\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-210100-1024x101.png\" alt=\"PowerShell prompt showing the following error:\n\nPS C:\\&gt; Add-Type -Path &quot;C:\\sqlite-netFx40-binary-bundle-x64-2010-1.0.119.0\\System.Data.SQLite.dll&quot;\nAdd-Type : Could not load file or assembly 'file:\/\/\/C:\\sqlite-netFx40-binary-bundle-x64-2010-1.0.119.0\\System.Data.SQLite.dll' or one of its dependencies. Operation is not supported.\n(Exception from HRESULT: 0x80131515)\nAt line:1 char:1\n+ Add-Type -Path &quot;C:\\sqlite-netFx40-binary-bundle-x64-2010-1.0.119.0\\Sy ...\n+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    + CategoryInfo          : NotSpecified: (:) [Add-Type], FileLoadException\n    + FullyQualifiedErrorId : System.IO.FileLoadException,Microsoft.PowerShell.Commands.AddTypeCommand\" class=\"wp-image-226\" srcset=\"https:\/\/www.ziviz.net\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-210100-1024x101.png 1024w, https:\/\/www.ziviz.net\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-210100-300x30.png 300w, https:\/\/www.ziviz.net\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-210100-768x76.png 768w, https:\/\/www.ziviz.net\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-210100-1536x152.png 1536w, https:\/\/www.ziviz.net\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-210100-1200x119.png 1200w, https:\/\/www.ziviz.net\/WP\/wp-content\/uploads\/2025\/05\/Screenshot-2025-05-14-210100.png 1648w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><figcaption class=\"wp-element-caption\">Operation is not supported. (Exception from HRESULT: 0x80131515)<\/figcaption><\/figure>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\">Step 2: Adding and Using SQLite<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Once you have the version figured out, files unblocked. Actually using SQLite is really easy.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">First you must import the dll with the <code>Add-Type<\/code> command. You can just point it at the path to the DLL file. This is the line that will fail if you chose the wrong DLL or forgot to unblock the files.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Add-Type -Path \"C:\\sqlite-netFx40-binary-bundle-x64-2010-1.0.119.0\\System.Data.SQLite.dll\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then you can create a connection string defining your database&#8217;s file path and connect to it.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$connectionString = \"Data Source=C:\\sqlite-netFx40-binary-bundle-x64-2010-1.0.119.0\\MyTest.db;Version=3;\"\n\n$connection = New-Object System.Data.SQLite.SQLiteConnection($connectionString)\n$connection.Open() | Out-Null<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you get this error<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Exception calling &#8220;Open&#8221; with &#8220;0&#8221; argument(s): &#8220;unable to open database file&#8221;<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">Then you likely do not have permissions to the file. SQLite will attempt to create a new db file if one does not exist. You may want to check if the DB has been initiated before using in further code.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">From here, you should be good to go, but here are some rapid-fire scenarios to get you started.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Create a table<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$Query = \"CREATE TABLE IF NOT EXISTS mytable (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, creationtime DATETIME DEFAULT CURRENT_TIMESTAMP);\"\n\n$command = New-Object System.Data.SQLite.SQLiteCommand($Query, $connection)\n$command.ExecuteNonQuery() | Out-Null\n$command.Dispose() | Out-Null<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Remember to dispose when you are done.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Also, lets make an index<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$Query = \"CREATE INDEX name_idx ON mytable (name);\"\n$command = New-Object System.Data.SQLite.SQLiteCommand($Query, $connection)\n$command.ExecuteNonQuery() | Out-Null\n$command.Dispose() | Out-Null<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Insert into a table<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$Query = \"INSERT INTO mytable (name) VALUES (@name);\"\n$Name = \"John.Doe\"\n\n$command = New-Object System.Data.SQLite.SQLiteCommand($Query, $connection)\n$command.Parameters.AddWithValue(\"@name\", $Name) | Out-Null\n$command.ExecuteNonQuery() | Out-Null\n$command.Dispose() | Out-Null<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Note the use of Parameters. This helps protect against SQL injection attacks. You should use them whenever you are adding variable data into your query.  <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Query the table<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$Query = \"SELECT * FROM mytable WHERE name = @name;\"\n$Name = \"John.Doe\"\n\n$command = New-Object System.Data.SQLite.SQLiteCommand($Query, $connection)\n$command.Parameters.AddWithValue(\"@name\", $Name) | Out-Null\n$reader = $command.ExecuteReader()\n\nwhile ($reader.Read()) {\n    Write-Host \"\"\n    for ($i = 0; $i -lt $reader.FieldCount; $i++) {\n        Write-Host \"$($reader.GetName($I)) = $($reader.GetValue($I))\"\n    }\n}\n$reader.Close() | Out-Null\n$reader.Dispose() | Out-Null\n$command.Dispose() | Out-Null<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">These commands have been silent so far, but this time we are getting data out of the database. This code should return:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">id = 1<br>name = John.Doe<br>creationtime = &lt;somedate><\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">Note that we are disposing the reader as well as the command this time. Both are disposable, so it&#8217;s good practice to dispose them when done using them.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We are also using parameters again, since the name we are putting into our query is variable.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Finally, at the end of your script<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Surprise, you should dispose your connection to the database file itself<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$connection.Close()\n$connection.Dispose()<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Hopefully this is useful to someone. If you are looking for a more complete example, I made a simple generic caching module using this info. Check it out on <a href=\"https:\/\/github.com\/zincarla\/SimpleSQLiteCache\/tree\/main\">Github<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I wanted to use SQLite with PowerShell, but without needing to rely on another module. Just SQLite&#8230; and PowerShell. So here is how to do that&#8230; Step 1: Download and Prepare SQLite SQLite is available for the .Net framework, which PowerShell rides on. Great! But you need to make sure that the SQLite binaries you &hellip; <a href=\"https:\/\/www.ziviz.net\/WP\/2025\/05\/14\/powershell-and-sqlite\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;PowerShell and SQLite&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-220","post","type-post","status-publish","format-standard","hentry","category-powershell"],"_links":{"self":[{"href":"https:\/\/www.ziviz.net\/WP\/wp-json\/wp\/v2\/posts\/220","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ziviz.net\/WP\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ziviz.net\/WP\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ziviz.net\/WP\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ziviz.net\/WP\/wp-json\/wp\/v2\/comments?post=220"}],"version-history":[{"count":3,"href":"https:\/\/www.ziviz.net\/WP\/wp-json\/wp\/v2\/posts\/220\/revisions"}],"predecessor-version":[{"id":230,"href":"https:\/\/www.ziviz.net\/WP\/wp-json\/wp\/v2\/posts\/220\/revisions\/230"}],"wp:attachment":[{"href":"https:\/\/www.ziviz.net\/WP\/wp-json\/wp\/v2\/media?parent=220"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ziviz.net\/WP\/wp-json\/wp\/v2\/categories?post=220"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ziviz.net\/WP\/wp-json\/wp\/v2\/tags?post=220"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}