Powershell Multiple variables in foreach loop getting AWS-EC2 instance info - powershell

I need to get instanceId and PrivateIpAddress from all my EC2 instances in my environment and insert into table. I have this but doesn't seem to work. I seem to get everything not just the IP and ID.
$instancestate = (get-ec2instance).RunningInstance
foreach ($instances in $instancestate)
{
$query = "INSERT INTO prodinstances (Idinstance, IPAddress)
VALUES ('$instances.InstanceId','$instances.PrivateIpAddress')"
$Rows = Execute-MySQLNonQuery $conn $query
}
If I change the code
$instancestate = (get-ec2instance).RunningInstance.InstanceId
I get the ID and can insert it in the database. I can also change it to
$instancestate = (get-ec2instance).RunningInstance.PrivateIpAddress
and get the IPAddress and insert that into the database, but when i combine them I get all the info for the EC2 instances which does have .instanceId and .PrivateIpAddress in the list when I hover over the variable $instances. Any Idea how to get both those parameters. My code seems correct but alas it is not...

"VALUES ('$instances.InstanceId'"
is the same as
"VALUES ('" + $instances + ".InstanceId'"
Now it doesn't seem correct. You need $() around it, inside the string:
"VALUES ('$($instances.InstanceId)'"

Fixed works like a charm...
$instancestate = (get-ec2instance).RunningInstance
foreach ($instances in $instancestate)
{
$query = "insert into prodinstances (idinstance,IPAddress) VALUES ('$($instances.InstanceId)', '$($instances.PrivateIpAddress)')
ON duplicate key update idinstance='$($instances.InstanceId)',IPAddress='$($instances.PrivateIpAddr ess)'"
$Rows = Execute-MySQLNonQuery $conn $query
}

Related

ODBC Data Reader HasRows=True but No Data

I'm connecting to an Access database through ODBC using Powershell, reading data from Access to convert it to another database. I have one query that is causing me problems because although HasRows returns True, when I attempt to loop through the reader, it acts as if it is at the end of the reader. Here is the code I'm using
$FMconn = new-object System.Data.Odbc.OdbcConnection
$FMconn.ConnectionString = "DSN=AccessFileMaker"
$FMconn.Open()
$FMCmd = $FMconn.CreateCommand()
$FMCmd.CommandTimeout = 0
$sql = "
SELECT
fd__folder.id as folderid
,fd__folder.folderletter
,wl__wallet.id as walletid
,wl__wallet.walletnumber
FROM
fd__folder
INNER JOIN wl__wallet
ON fd__folder.id_wallet = wl__wallet.id
WHERE
fd__folder.folderLetter > ''
"
$FMCmd.CommandText = $sql
$Reader = $FMCmd.ExecuteReader()
if ($Reader.HasRows) {
while ($Reader.Read())
{
$folderID = $Reader["folderid"].ToString()
$folderletter = $Reader["folderletter"].ToString().TrimEnd()
$walletID = $Reader["walletid"].ToString()
$walletNum = "Wallet " + $Reader["walletnumber"].ToString().TrimEnd()
(other code here to insert data into the other DB but irrelevant to the problem)
}
$Reader.Close()
}
As I step through the code I get to the while($Reader.Read()) and it immediately steps to $Reader.Close()
The query runs find in Access as is and returns 56115 records. I've used this same process to extract other records from Access (although none of the queries involved a join). So why can't I loop through the records of this query if the Reader has rows? Any help debugging this would be greatly appreciated.

Powershell - passing variable into loop for string with quotes

I'm trying to understand how to setup my script so that single quotes will wrap around my variable. I have a list of 1500 customers I need to repeat my script for, so my thought as to do a foreach loop.
$customerlist = Invoke-Sqlcmd -Query "SELECT [CustomerNo] FROM [TABLE]" -ServerInstance "SERVER\INSTANCE"
#Loop through
foreach ($customer in $customerlist)
{
$inputParams = #{
"CustomerNo" = "'"+$customer+"'";
}
....Do rest of script
}
I need the $customer variable in my $inputparams to show with the string value in single quotes, e.g. '01233456' instead of just 0123456. I've tried several different iterations of "'"+$customer+"'" but cannot seem to get the correct syntax. Could someone help me out?
Invoke-Sqlcmd returns [System.Data.DataRow] type objects with the field name(s) and value(s) of your query result as its properties (basically a table). To select the value in the CustomerNo, you must specify the value by name:
# Expand the CustomerNo property to strings
foreach ($customer in $customerlist.CustomerNo) { }
# Or, later in the script:
$inputParams = #{
CustomerNo = "'$($customer.CustomerNo)'"
}

Powershell - ODBC MSAccess Commit transaction refresh data for Select Query after Insert

I'm connecting with ODBC in powershell to an .accdb Access Database. After inserting new data into a table (insert into via ExecuteNonQuery), I'm unable to pull the data with a select command for futher processing (create a PDF table). The resulting object of the query is empty (0 rows), though "Select ##IDENTITY" returns the most recent index identifier. The Workflow is something like this:
Data entered into a forms window -> new record is created -> data is pulled off and processed into a report -> report is sent by mail -> record is flagged as sent
I tried to use the SQL transaction mechanism, but even after the commit is done, the data is not immediately retrievable with a select-query. After inserting another record, the previously inserted one can be pulled with a select query, but not the new most recent one.
I have not found any working solution to this behavior. I've heard about this, when using Access forms, where the data will be available when the form has been moved to the next record. Any ideas how I can solve this?
Below are my getter and setter functions. In general they work as intended but using Set-Data with an insert first and firing Get-Data with a select afterwards does not provide any records.
Function Get-Data($SQLCommand){
try{
$Connection = New-Object System.Data.Odbc.OdbcConnection($DSN)
$Connection.Open()
$AccdbCommand = New-Object System.Data.Odbc.OdbcCommand($SQLCommand, $Connection)
$AccdbAdapter = New-Object System.Data.Odbc.OdbcDataAdapter($AccdbCommand)
$AccdbDataSet = New-Object System.Data.DataSet
$AccdbAdapter.Fill($AccdbDataSet)
$Connection.Close()
return $AccdbDataSet
}
catch
{
[System.Windows.Forms.MessageBox]::Show($_.Exception.Message + "`r`n" + $_.Exception.InnerException, "Fehler",'OK','Error')
}
}
Function Set-Data($SQLCommand){
try
{
$Connection = New-Object System.Data.Odbc.OdbcConnection($DSN)
$Connection.Open()
$Transaction = $Connection.BeginTransaction()
$AccdbCommand = New-Object System.Data.Odbc.OdbcCommand($SQLCommand, $Connection, $Transaction)
$AccdbCommand.ExecuteNonQuery()
$transaction.Commit()
$AccdbCommand = New-Object System.Data.Odbc.OdbcCommand("Select ##IDENTITY", $Connection)
$result = $AccdbCommand.ExecuteScalar()
$Connection.Close()
}
catch
{
[System.Windows.Forms.MessageBox]::Show($_.Exception.Message + "`r`n" + $_.Exception.InnerException, "Fehler", 'OK', 'Error')
}
}
I've resolved this Problem. The commit itself is working as intended. The missing data record in the output process was a result of an error in looping the rows in the dataset with a for Statement.

Mysqli AES_DECRYPT

I wonder if any of you can help me with this. I have no trouble encrypting a field and writing it to a database. For example:
$query= mysqli_query($mysqli,"INSERT INTO users (surname) VALUES (AES_ENCRYPT('Blenkinsop','mypassword'))");
The problem comes when trying to get it out again:
$query = mysqli_query($mysqli,"SELECT AES_DECRYPT(surname,'mypassword') FROM users WHERE userID = 1");
while($row = $query->fetch_assoc()){
[$row['surname']]; }
echo $row[0];
I have tried a number of variants, including echo $row['surname']
The error give is: "Undefined index: surname in line...", and the line refers to the line: [$row['surname']].
However, at the bottom of the error screen it says:
$row = array (size=1)
'AES_DECRYPT(surname,'mypassword')' => string 'Blenkinsop' (length=10)
Se the decryption is working; I just cannot find the right syntax to get it out.
If I just run the query without decryption it runs fine with no errors, and echos the still encrypted name:
$query = mysqli_query($mysqli,"SELECT surname FROM users WHERE userID = 1");
Any help would be much appreciated.
Many thanks
Steve Moss
column type surname = varbinary (50)
$query = mysqli_query($mysqli, "SELECT *, CAST(AES_DECRYPT(surname,'mypassword') AS CHAR(50)) surname FROM users WHERE userID = 1");

Can I tell if an ado.net DbCommand is a query or not (before executing it)

I am trying to write a Powershell script to run a general SQL command against a database. The idea is that Run-SQL "select ..." will run the SQL text against the currently open database. If the SQL statement is a query, it should return a DataTable. If it is a non-query (DDL or DML) it should return nothing ($null).
In order to do this, I need to know which method (ExecuteReader or ExecuteNonQuery) to execute against the command. Is there a way to determine this? (I'm happy to prepare the command if that helps).
As an alternative, I can add a -query argument to be supplied by the user, which distinguishes the two cases, but as a potential user, I'd find this annoying (as, in my view, I have already said whether it's a query by the SQL I used, why say again?)
My key use is for Oracle databases, so an Oracle-specific answer is OK with me, although I'd prefer something generic.
I think you could just use ExecuteReader whether it's a query or not. It may be overkill but in some quick experiments with doing an UPDATE ($reader returns nothing) and a COUNT ($reader[0] outputs scalar result) - it just seems to work.
$connstr = "server=.\SQLEXPRESS;Database=AdventureWorks;" +
"Integrated Security=true;Persist Security Info=False"
$conn = new-object System.Data.SqlClient.SqlConnection $connstr
#$query = "UPDATE Production.Product SET Name = 'ACME' WHERE Name = 'Blade'"
$query = "SELECT Count(*) FROM Production.Product"
$cmd = new-object System.Data.SqlClient.SqlCommand $query,$conn
$conn.Open()
try
{
$reader = $cmd.ExecuteReader()
while ($reader.Read())
{
$reader[0]
}
}
finally
{
$conn.Dispose()
}
As an alternative to what Keith said you could try
$sql = 'Select count(1) From SomeTable;'
$sql = $sql.TrimStart(' ')
if ($sql -match "^select") { Write-Host 'ExecuteReader' }
else { Write-Host 'ExecuteNonQuery'}
The trim is there in case the SQL command has a leading space since $sql = ' select ' won't match "^select"