File opened that is not a database file (but it is) - powershell

I'm trying to pull information from an SQLite database using a Powershell script from a Redgate article.
#I've installed the 64 bit System.Data.SQLite ADO.NET data provider in this directory
Add-Type -Path "C:\Program Files (x86)\SQLite.NET\bin\x64\System.Data.SQLite.dll"
#I just create a connection to my existing database
$con = New-Object -TypeName System.Data.SQLite.SQLiteConnection
# I then give it a simple connection string
$con.ConnectionString = "Data Source=C:\Users\name\Desktop\fax.sqlite"# CHANGE THIS
#and open the connection
$con.Open()
#We'll just start by creating a SQL statement in a command
$sql = $con.CreateCommand()
$sql.CommandText = "select column from table;"
# we now execute the SQL and return the results in a dataset
$adapter = New-Object -TypeName System.Data.SQLite.SQLiteDataAdapter $sql
#we create the dataset
$data = New-Object System.Data.DataSet
#and then fill the dataset
[void]$adapter.Fill($data)
#we can, of course, then display the first one hundred rows in a grid
#(1..100)|foreach{$data.tables[0].Rows[$_]}|out-gridview #-Title 'Authors and books'
I viewed the database using SQLite DB Browser (didn't need a password to open). However, whenever I use this script I get the below error:
Exception calling "Open" with "0" argument(s): "File opened that is
not a database file file is encrypted or is not a database" At
C:\Users\name\Desktop\query sqlite db.ps1:9 char:1
$con.Open()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : SQLiteException

Assuming you have all the libraries in place, to import the assemblies you need to use the Add-Type command:
Add-Type -Path "C:\Program Files\System.Data.SQLite\2010\bin\System.Data.SQLite.dll"
To connect to the database using the ADO.NET protocol, you need to create a SQLiteConnection object with the proper connection string:
$connection_details = New-Object -TypeName System.Data.SQLite.SQLiteConnection
$connection_details.ConnectionString = "Data Source=C:\database\test.db"
Your $con.ConnectionString = "Data Source=C:\Users\name\Desktop\fax.sqlite" is having issue. It is expecting a proper DB connection but instead it is getting a string statement.

I got the same error when running a 32-bit dll on a 64-bit system.
If you are running a 64-bit Windows system then download sqlite-netFx46-static-binary-x64-2015-1.0.116.0.zip from https://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki
and extract the contents to C:\Program Files\System.Data.SQLite\2010\bin\
Then run this command once or place it in your PowerShell script before making your connection object:
Add-Type -Path "C:\Program Files\System.Data.SQLite\2010\bin\System.Data.SQLite.dll"

Related

Powershell and WinSCP - Connect to FTP Server

I am trying to construct a Powershell script that leverages the WinSCP binaries to download files from an FTP server.
The script so far is as follows (minus actual IPs and folder paths):
# Load WinSCP .NET assembly
Add-Type -Path "WinSCPnet.dll"
# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions -Property #{
Protocol = [WinSCP.Protocol]::Ftp
FtpMode = [WinSCP.FtpMode]::Passive
HostName = "ftp server ip address"
UserName = "ftp-username"
Password = "ftp-password"
}
$session = New-Object WinSCP.Session
try
{
# Connect
$session.Open($sessionOptions)
# Download files
$session.GetFiles("/home/ftp-username/uploads/*.txt", "C:\temp\").Check()
}
finally
{
# Disconnect, clean up
$session.Dispose()
}
I keep on getting the following error:
Exception calling "Open" with "1" argument(s): "Connection failed.
Timeout detected. (control connection)
Connection failed."
At C:\winscp-ftp.ps1:18 char:5
+ $session.Open($sessionOptions)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : SessionRemoteException
I did some reading and suggestions say that FTPMode Passive will solve this, but even after including that, the error persists.
Any advice/guidance will be appreciated.
Windows 10 64-bit. Winscp v.5.1
I was getting the same error message. I used WinSCP to generate the script and it started working.
My guess, and it is a weak one at that, is your hostname and/or username and/or password is malformed. If you use WinSCP to generate the script it has a "copy to clipboard" function.
This works on my ftp server. I don't know why. My code is hardly different than yours. Could it be whitespace after hostname, username, password?
Use the full path to winscpnet.dll
I don't think it makes any difference whether you use $sessionOptions.AddRawSettings("ProxyPort", "0")
It worked whether I did passive or not, which is odd because I always have to use passive.
I connected to my ftp server and downloaded files to c:\temp
I installed Posh-SSH 2.2 but the error message continued. I un-installed Posh-SSH 2.2 before getting the script to work.
If you use WinSCP to generate the code it does not tell you to use the full path to winscpnet.dll
It works after logging off and on.
It works after a restart.
It works in a window w/ or w/o admin privileges.
# Load WinSCP .NET assembly. If you are not in the winscp directory use the full path.
Add-Type -Path "C:\Program Files (x86)\WinSCP\WinSCPnet.dll"
# Set up session options
$sessionOptions = New-Object WinSCP.SessionOptions -Property #{
Protocol = [WinSCP.Protocol]::Ftp
FtpMode = [WinSCP.FtpMode]::Passive
HostName = "ftp server ip address"
UserName = "ftp-username"
Password = "ftp-password"
}
$sessionOptions.AddRawSettings("ProxyPort", "0")
$session = New-Object WinSCP.Session
try
{
# Connect
$session.Open($sessionOptions)
# Download files
$session.GetFiles("/home/ftp-username/uploads/*.txt", "C:\temp\").Check())
}
finally
{
# Disconnect, clean up
$session.Dispose()
}

The term 'Microsoft.SqlServer.Dac.BacPackage::Load' is not recognized

I have created a bacpac from an azure sql db, copied it to blob, from blob brought it down locally.
I run this code in powershell
Add-Type -path "C:\Program Files (x86)\Microsoft SQL Server\140\DAC\bin\Microsoft.SqlServer.Dac.dll"
$restoredDatabaseName = 'AuditTest'
$bacpacFile = "H:\backup\audit\audit.bacpac"
$conn = "Data Source=.;Initial Catalog=master;Connection Timeout=0;Integrated Security=True;"
$importBac = New-Object Microsoft.SqlServer.Dac.DacServices $conn
$loadBac = Microsoft.SqlServer.Dac.BacPackage::Load($bacpacFile)
$importBac.ImportBacpac($loadBac, $restoredDatabaseName)
#Clean up
$loadBac.Dispose()
Get this error back:
Microsoft.SqlServer.Dac.BacPackage::Load : The term 'Microsoft.SqlServer.Dac.BacPackage::Load' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the
name, or if a path was included, verify that the path is correct and try again.
I have also tried to use the import data tier wizard and get the following error.
Could not load file or assembly 'Microsoft.SqlServer.Dac, Version=13.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified. (Microsoft.SqlServer.Management.Dac.DacWizard)
It is driving me nuts, I have found a few things about registry hacking and so on for the wizard error, nothing helpful at all for the powershell one.
SQL Azure DB PRS1
Restoring to SQL 2016 in an Azure VM.
When invoking a static method, the full type name goes in square brackets.
So should be:
Add-Type -path "C:\Program Files (x86)\Microsoft SQL Server\140\DAC\bin\Microsoft.SqlServer.Dac.dll"
$restoredDatabaseName = 'AuditTest'
$bacpacFile = "H:\backup\audit\audit.bacpac"
$conn = "Data Source=.;Initial Catalog=master;Connection Timeout=0;Integrated Security=True;"
$importBac = New-Object Microsoft.SqlServer.Dac.DacServices $conn
$loadBac = [Microsoft.SqlServer.Dac.BacPackage]::Load($bacpacFile)
$importBac.ImportBacpac($loadBac, $restoredDatabaseName)
#Clean up
$loadBac.Dispose()

Set-SqlColumnEncryption throws error

I am encrypting several columns in an existing table using the Encrypt Columns feature in SSMS. I have chosen to generate a Powershell script instead of encrypting the columns in the wizard so I can encrypt the columns at a later point in time. The script is below:
# Generated by SQL Server Management Studio at 3:03 PM on 4/05/2018
Import-Module SqlServer
# Set up connection and database SMO objects
$sqlConnectionString = "Data Source=.;Initial Catalog=MyDatabase;Integrated Security=True;MultipleActiveResultSets=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;Packet Size=4096;Application Name=`"Microsoft SQL Server Management Studio`""
$smoDatabase = Get-SqlDatabase -ConnectionString $sqlConnectionString
# If your encryption changes involve keys in Azure Key Vault, uncomment one of the lines below in order to authenticate:
# * Prompt for a username and password:
#Add-SqlAzureAuthenticationContext -Interactive
# * Enter a Client ID, Secret, and Tenant ID:
#Add-SqlAzureAuthenticationContext -ClientID '<Client ID>' -Secret '<Secret>' -Tenant '<Tenant ID>'
# Change encryption schema
$encryptionChanges = #()
# Add changes for table [dbo].[Voucher]
$encryptionChanges += New-SqlColumnEncryptionSettings -ColumnName dbo.Voucher.Code -EncryptionType Randomized -EncryptionKey "cek"
Set-SqlColumnEncryption -ColumnEncryptionSettings $encryptionChanges -InputObject $smoDatabase
However when I run the script, I get the below exception from the Set-SqlColumnEncryption cmdlet:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an
invocation. ---> System.TypeInitializationException: The type initializer for
'Microsoft.SqlServer.Management.AlwaysEncrypted.Management.AlwaysEncryptedManagement' threw an
exception. ---> System.IO.FileNotFoundException: Could not load file or assembly 'Newtonsoft.Json,
Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The
system cannot find the file specified.
I updated the Sqlserver module also. Surely I don't have to manually drop the Newtonsoft.Json.dll file into the SqlServer module directory. Any ideas?
You're using 'Always Encrypted'. I'm assuming your column master key is stored in Windows Certificate Store on the machine where your script is running. And, I'm assuming your keys are setup correctly.
Let's say I have a table with schema:
CREATE TABLE dbo.property_bag (
id int identity(1,1) primary key
, insert_user sysname not null
, insert_date datetime2 not null
, insert_source sysname not null
, [stuff] varchar(max) ENCRYPTED WITH (ENCRYPTION_TYPE = RANDOMIZED
, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256'
, COLUMN_ENCRYPTION_KEY = [dbo-property_bag]) NULL
);
GO
Here is a script to insert data into my table:
$insert_count = 10
$words = #('bobby','mikey','billy','suzie','kenny','narav','navneet','rachel','jose','juan')
$conn = New-Object System.Data.SqlClient.SqlConnection
$conn.ConnectionString = “Server='<db-server>';Database='<db>';Column Encryption Setting=enabled;Integrated Security=True;”
$hostname = $env:computername
try {
$conn.Open()
 
for ($i = 1; $i -le $insert_count; $i++) {
    $val = Get-Random -Maximum 10
    $word_to_insert = $words[$val]
    $sqlcmd = New-Object System.Data.SqlClient.SqlCommand
    $sqlcmd.Connection = $conn
    $sqlcmd.CommandText = “INSERT INTO dbo.property_bag ([insert_user], [insert_date], [insert_source], [stuff]) VALUES (SUSER_SNAME(), GETDATE(), '${hostname}', #value)”
    $sqlcmd.Parameters.Add((New-Object Data.SqlClient.SqlParameter("#value",[Data.SQLDBType]::VarChar, 4000))) | Out-Null
    $sqlcmd.Parameters[0].Value = $word_to_insert
    $sqlcmd.ExecuteNonQuery() | Out-Null
Write-Progress -Activity "Inserting Records..." -Status "Progress $($i / $insert_count * 100)%" -percentComplete ($i / $insert_count)
}
} finally {
$conn.Close()
$conn.Dispose()
}
When I registered the column master key with the database (through Object Explorer) I'd set the path to the "CurrentUser/My/". SQL Server will pass that location back to the driver, which will search that location in the local key store for the certificate matching the thumbprint provided. That key (which in my case is on my app-server where the script is running) will decrypt the column encryption key. None of this is detailed in the script. It's all setup in the database. Here is the data flow for this example:
In your example, the connection string doesn't contain the "Column Encryption Setting=enabled". I don't believe the Get-SqlDatabase commandlet takes a connection string parameter. I believe you'd pass it an instance object. There are just a bunch of things that don't look quiet right.
If your keys aren't setup correctly, I'd start here.
I was having the exact same issue, and I believe this is some kind of component integration issue on your particular mix of OS and Sql Server.
Case in point, I received this error when trying to run that powershell script on my laptop. My laptop happens to use Windows 10 and Sql Server Management Studio 17.2 (which is what ultimately generates the ps1). And furthermore, my laptop does contain Newtonsoft.Json.dll in the correct directory.
However, I hopped on to a server, which was using Windows 2012 R2 and SSMS 17.2 and the script DOES work!
Ultimately, it's as if there is some kind of assembly binding redirect missing in the Windows10/SSMS17.2 installation which Windows2012R2/SSMS17.2 seems to resolve correctly.

Error in download file using powershell

Am trying to download sqlserver express 2012 on my EC2 instance.following sample given here.
this is my script:
$storageDir = "C:\download"
$webclient = New-Object System.Net.WebClient
$url = "https://www.microsoft.com/en-us/download/confirmation.aspx?id=29062"
$file = "$storageDir"
$webclient.DownloadFile($url,$file)
C:\download is where i want the downloaded file to be save.
but i keep getting this error:
Exception calling"DownloadFile" with "2" argument(s):"An exception occurred
during a webClient request."
At line:1 chart:1
+$wc.DownloadFile($url,$output)
+$webclient.DownloadFile($url,"file)
+CategoryInfo :NotSpecified:(:)[], MethodInvocationException
Can anyone please tell me what am i doing wrong.
I have tried to download from my pc and copying to aws vis rdc but takes hours
The second parameter to the DownloadFile method is the path to the filename you want to use for saving the file - not the directory. You would need to change your line to:
$file = "$storageDir\SQLEXPRE_x64_ENU.exe"
Reference: https://msdn.microsoft.com/en-us/library/ez801hhe.aspx

How to run Powershell script on local computer but with credentials of a domain user

I have to implement a solution where I have to deploy a SSIS project (xy.ispac) from one machine to another. So far I've managed to copy-cut-paste the following stuff from all around the internet:
# Variables
$ServerName = "target"
$SSISCatalog = "SSISDB" # sort of constant
$CatalogPwd = "catalog_password"
$ProjectFilePath = "D:\Projects_to_depoly\Project_1.ispac"
$ProjectName = "Project_name"
$FolderName = "Data_collector"
# Load the IntegrationServices Assembly
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Management.IntegrationServices")
# Store the IntegrationServices Assembly namespace to avoid typing it every time
$ISNamespace = "Microsoft.SqlServer.Management.IntegrationServices"
Write-Host "Connecting to server ..."
# Create a connection to the server
$sqlConnectionString = "Data Source=$ServerName;Initial Catalog=master;Integrated Security=SSPI;"
$sqlConnection = New-Object System.Data.SqlClient.SqlConnection $sqlConnectionString
$integrationServices = New-Object "$ISNamespace.IntegrationServices" $sqlConnection
$catalog = $integrationServices.Catalogs[$SSISCatalog]
# Create the Integration Services object if it does not exist
if (!$catalog) {
# Provision a new SSIS Catalog
Write-Host "Creating SSIS Catalog ..."
$catalog = New-Object "$ISNamespace.Catalog" ($integrationServices, $SSISCatalog, $CatalogPwd)
$catalog.Create()
}
$folder = $catalog.Folders[$FolderName]
if (!$folder)
{
#Create a folder in SSISDB
Write-Host "Creating Folder ..."
$folder = New-Object "$ISNamespace.CatalogFolder" ($catalog, $FolderName, $FolderName)
$folder.Create()
}
# Read the project file, and deploy it to the folder
Write-Host "Deploying Project ..."
[byte[]] $projectFile = [System.IO.File]::ReadAllBytes($ProjectFilePath)
$folder.DeployProject($ProjectName, $projectFile)
This seemed to be working surprisingly well on the development machine - test server pair. However, the live environment will be a bit different, the machine doing the deployment job (deployment server, or DS from now on) and the SQL Server (DB for short) the project is to be deployed are in different domains and since SSIS requires windows authentication, I'm going to need to run the above code locally on DS but using credentials of a user on the DB.
And that's the point where I fail. The only thing that worked is to start the Powershell command line interface using runas /netonly /user:thatdomain\anuserthere powershell, enter the password, and paste the script unaltered into it. Alas, this is not an option, since there's no way to pass the password to runas (at least once with /savecred) and user interactivity is not possible anyway (the whole thing has to be automated).
I've tried the following:
Simply unning the script on DS, the line $sqlConnection = New-Object System.Data.SqlClient.SqlConnection $sqlConnectionString would use the credentials from DS which is not recognized by DB, and New-Object does not have a -Credential arg that I could pass to
Putting everything into an Invoke-Command with -Credential requires using -Computername as well. I guess it would be possible to use the local as 'remote' (using . as Computername) but it still complains about access being denied. I'm scanning through about_Remote_Troubleshooting, so far without any success.
Any hints on how to overcome this issue?
A solution might be to use a sql user (with the right access rights) instead of an AD used.
Something like this should work.
(Check also the answer to correct the connection string)