PowerShell Array to Table like output -- Possible ForEach problem - powershell

I'm trying to run a sql query via PowerShell and return the results in a table-like format.
It's putting multiple results in one field. I suspect there's something wrong with the 'foreach' loops. What am I missing, please?
To use the code below, just change the server names from 'server1'/'server2' for your sql server instances.
$query = "
SELECT ##SERVERNAME AS ServerName
, (SELECT DB_NAME ()) AS DBName
, s.name AS SchemaName
, st.name AS TableName
, RIGHT(st.name, 8) AS Rgt8
, TRY_CONVERT(DATE, RIGHT(st.name, 8), 103) AS Rgt8Date
FROM sys.tables AS st
INNER JOIN sys.objects AS so ON so.object_id = st.object_id
INNER JOIN sys.schemas AS s ON s.schema_id = st.schema_id
"
$instanceNameList = #('server1', 'server2')
$report = #()
foreach ($instanceName in $instanceNameList) {
write-host "Executing query against SERVER/INSTANCE: " $instanceName
$dbNames = Invoke-DbaQuery -SqlInstance $InstanceName -Database "master" -Query "select name from sys.databases where database_id > 4 and name <> 'TEST'"
foreach ($database in $dbNames.Name ) {
Write-host -Activity "Current DATABASE $database" -Status "Querying: $database"
$results = Invoke-DbaQuery -SqlInstance $InstanceName -Database $database -Query $query
# <#
if ($results -is [array]) {
$CustomObject = [pscustomobject] #{
ServerName = $results.ServerName
DBName = $results.DBName
SchemaName = $results.SchemaName
TableName = $results.TableName
Rgt8 = $results.Rgt8
Rgt8Date = $results.Rgt8Date
OverOneYearOld = $results.OverOneYearOld
Drop_Table = $results.Drop_Table
}
## ADDING EACH ROW/JOB OBJECT THAT HAS BEEN REPORTED, TO THE REPORT ARRAY
$report += $CustomObject
}
}
}
$report | Select-Object ServerName, DbName, TableName | Out-GridView

Basically, you're doing the opposite of what you wanted to do, if $results -is [array] you want to iterate over it instead of add it as is to to your $report array.
On the other hand, adding elements to a fixed collection (+=) is a terrible idea.
$dbquery = #'
select name from
sys.databases
where database_id > 4 and name <> 'TEST'"
'#
$result = foreach ($instanceName in $instanceNameList) {
$params = #{
SqlInstance = $InstanceName
Database = "master"
Query = $dbquery
}
$dbNames = Invoke-DbaQuery #params
foreach ($database in $dbNames.Name) {
$params.Database = $database
$params.Query = $query
Invoke-DbaQuery #params | Select-Object #(
'ServerName'
'DBName'
'SchemaName'
'TableName'
'Rgt8'
'Rgt8Date'
'OverOneYearOld'
'Drop_Table'
)
}
}
$result | Format-Table

Related

Powershell Invoke-Sqlcmd Use result in another query

I'm attempting to use a result returned from Invoke-Sqlcmd $ORDUNIQ as a variable in a second query. However the second $query2 returns 0 records. Substituting the variable for the actual string value '35973189' works fine.
I'm assuming that $ORDUNIQ.ORDUNIQ is the wrong way to use this?, although running $ORDUNIQ.ORDUNIQ on the command line does return '35973189' correctly
Here is my code
$RAWFiles = Get-ChildItem D:\Imports\Test\*.csv
$content = Import-Csv $RAWFiles | Where-Object 'Order Type' -eq 'B2B'
ForEach ($row in $content) {
$ORDNUMBER = $row.'OrderRef'
$SQLServer = "XXXXX-XXX"
$db1 = "XXXXXX"
$query1 = "SELECT ORDUNIQ FROM OEORDH WHERE ORDNUMBER = '$ORDNUMBER'"
$query2 = "SELECT OEORDD.ITEM FROM OEORDD WHERE ORDUNIQ = '$ORDUNIQ.ORDUNIQ'"
$ORDUNIQ = Invoke-Sqlcmd -ServerInstance $SQLServer -Database $db1 -Query $query1
$ORDDATA = Invoke-SQLcmd -ServerInstance $SQLServer -Database $db1 -Query $query2
}

How to process multiple columns from sql in powershell

I have this PowerShell script:
$QUERY = "SELECT name FROM sys.databases";
$Databases = invoke-sqlcmd -serverinstance "SQLInstanceName" -database "master" -Query $QUERY
foreach ($dbname in $Databases)
{
$dbname
}
Let's say I want the recovery model for the databases as below, how do I get them into PowerShell variables?
$QUERY = "SELECT name, recovery_model_desc FROM sys.databases";
May be you are looking for
$QUERY = "SELECT * from sys.databases";
$Databases = invoke-sqlcmd -serverinstance "SQLInstanceName" -database "master" -Query $QUERY
# This is just to print the individual value of column (name and recovery_model)
$Databases | ForEach {
Write-Host '----------------------------------------'
Write-Host 'Database :' $_.name
Write-Host 'Recovery model :' $_.recovery_model
Write-Host '----------------------------------------'
Write-Host
}
# This will give you name and recovery_model of database
$Databases | Select name, recovery_model

ForEach Directory Lookup and InputObject Powershell

Can someone help me and point out why my script isn't looping through my server list and not inserting all the data to my sql table?
$SQLserverDB = #()
$SQLserverDB = get-content "D:\Temp\servers.txt"
foreach ($SQLserver in $SQLserverDB) {
$server = New-Object Microsoft.sqlserver.management.smo.server($SQLserver)
Write-Host "--Server List:"$server"---" -ForegroundColor Yellow
foreach ($db in $Server.Databases) {
$dbobj = New-Object PSObject -Property ([ordered]#{
Instance_Name = $db.Parent
Database_Name = $db.Name
Database_ID = $db.id
Active = $db.Status
DateStamp = $db.CreateDate
Owner = $db.Owner
Compatibility_Level = $db.compatibilitylevel
Recovery_Model = $db.recoverymodel
DB_Size_MB = [Math]::round($db.size, 2)
}
)
}
}
$dt = Out-DbaDataTable -InputObject $dbobj
Write-SqlTableData -ServerInstance localhost -DatabaseName DBA_Central -SchemaName dbo -TableName database_masters2 -InputData $dt

How do I get around this error in PowerShell? Exception setting "Rtf": "Error creating window handle."

This has no issue with SQL. it's when creating the rtf object.
I am connecting to a sql database and pulling information. Some of the information is html,rtf, and plain text. After about 10 mins of running I get this:
Exception setting "Rtf": "Error creating window handle."
At line:24 char:76
+ ... Name System.Windows.Forms.RichTextBox; $rtf.Rtf = $convo.Body; $body ...
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], SetValueInvocationException
+ FullyQualifiedErrorId : ExceptionWhenSetting
Has anyone else ran into this issue?
Here is the script itself.
#Who are you searching for?
#Example User ID: user#domain.com
$Subject = "changeme#domain.com"
#Set the date to search from
#Example date format: 2016-08-16.
#Leave it blank if you don't want to search for just dates.
$Date = ""
#Blank array to store the conversation history
$arr = #()
#Lync Archive Server
$SQLSvr = "ServerName Goes Here"
#Lync Archive Database
$Database = "LcsLog"
#Get the UserId's
$UserUri = Invoke-Sqlcmd -Query "Select UserUri,UserId From dbo.Users u;" -ServerInstance $SQLSvr -Database $Database
#Build the Select Statement
$select = "Select * from dbo.Users d left join dbo.Messages m on FromId = d.UserId or ToId = d.UserId Where d.UserUri = '$Subject' "
if($Date)
{
$select = $select +"and m.MessageIdTime >= '$Date 00:00:01.550' order by m.MessageIdTime asc;"
}
else
{
$select = $select + "order by m.MessageIdTime asc;"
}
#Get the conversation history
$ConvoData = Invoke-Sqlcmd -Query ($select) -ServerInstance $SQLSvr -Database $Database;
#Loop through each conversation
foreach($convo in $ConvoData)
{
#Loop through each user.
foreach($user in $UserUri)
{
#Verify the FromId
if($convo.FromId -eq $user.UserId)
{
$FromID = $user.UserUri
}
#Verify the ToId
if($convo.ToId -eq $user.UserId)
{
$ToId = $user.UserUri
}
}
#Parse the body for legible reading
switch ($convo.ContentTypeId)
{
'1' {$html = New-Object -ComObject "HTMLFile"; $html.IHTMLDocument2_write($convo.Body);$body = $html.IHTMLDocument2_body.innerText; $html.close();}
'2' {$rtf = New-Object -TypeName System.Windows.Forms.RichTextBox; $rtf.Rtf = $convo.Body; $body = $rtf.Text; $rtf.Clear();}
'3' {$body = $convo.Body}
}
#Build the Message Output
$obj = New-Object -TypeName psobject -Property #{User = $Subject; "Message Time" = $convo.MessageIdTime; From = $FromID; To = $ToId; Body = $body}
#Add data to the array
$arr += $obj
}
$arr | Select User,"Message Time",From,To,Body | Export-csv "$env:userprofile\desktop\$Subject - conversation report.csv"
Not really an answer, but a recommendation that you should turn your parameters into a Param block. It would be more useful if you wanted to call the script from the command line or turn it into a function.
Param (
# Parameter Subject
[Parameter(Mandatory = $true,
HelpMessage = 'Who are you searching for? e.g. User ID: user#domain.com')]
$Subject = 'changeme#domain.com',
# Parameter Date
[Parameter(HelpMessage = 'Set the date to search from. e.g. "2016-08-16"')]
[String]
$Date,
# Parameter SQLSvr
[Parameter(Mandatory = $true,
HelpMessage = 'ServerName Goes Here')]
$SQLSvr,
# Parameter Database
[Parameter(Mandatory = $true,
HelpMessage = 'Lync Archive Database')]
$Database = 'LcsLog'
)
I figured it out. By creating one instance of my RTF object at the beginning it corrected my error.
#Who are you searching for?
#Example User ID: user#domain.com
$Subject = "changeme#domain.com"
#Set the date to search from
#Example date format: 2016-08-16.
#Leave it blank if you don't want to search for just dates.
$Date = ""
#Blank array to store the conversation history
$arr = #()
#Create RTF and HTML Objects
$html = New-Object -ComObject "HTMLFile";
$rtf = New-Object -TypeName System.Windows.Forms.RichTextBox;
#Lync Archive Server
$SQLSvr = "Server Name goes here"
#Lync Archive Database
$Database = "LcsLog"
#Get the UserId's
$UserUri = Invoke-Sqlcmd -Query "Select UserUri,UserId From dbo.Users u;" -ServerInstance $SQLSvr -Database $Database
#Build the Select Statement
$select = "Select * from dbo.Users d left join dbo.Messages m on FromId = d.UserId or ToId = d.UserId Where d.UserUri = '$Subject' "
if($Date)
{
$select = $select +"and m.MessageIdTime >= '$Date 00:00:01.550' order by m.MessageIdTime asc;"
}
else
{
$select = $select + "order by m.MessageIdTime asc;"
}
#Get the conversation history
$ConvoData = Invoke-Sqlcmd -Query ($select) -ServerInstance $SQLSvr -Database $Database;
#Loop through each conversation
foreach($convo in $ConvoData)
{
#Loop through each user.
foreach($user in $UserUri)
{
#Verify the FromId
if($convo.FromId -eq $user.UserId)
{
$FromID = $user.UserUri
}
#Verify the ToId
if($convo.ToId -eq $user.UserId)
{
$ToId = $user.UserUri
}
}
#Parse the body for legible reading
switch ($convo.ContentTypeId)
{
'1' {$html.IHTMLDocument2_write($convo.Body);$body = $html.IHTMLDocument2_body.innerText; $html.close();}
'2' {$rtf.Rtf = $convo.Body; $body = $rtf.Text; $rtf.Clear();}
'3' {$body = $convo.Body}
}
#Build the Message Output
$obj = New-Object -TypeName psobject -Property #{User = $Subject; "Message Time" = $convo.MessageIdTime; From = $FromID; To = $ToId; Body = $body}
#Add data to the array
$arr += $obj
}
$arr | Select User,"Message Time",From,To,Body | Export-csv "$env:userprofile\desktop\$Subject - conversation report.csv"

How to isert or update an database using powershell

I need some help with a piece of script.
The situation is as followed:
I have an database in oracle and i would like to insert bios data using powershell. The problem is that i cant update the database with an if else statment because he keeps saying the if is true.
$bios = Get-WmiObject -Namespace root/hp/instrumentedBIOS -Class hp_biosSetting
($bios | Where-Object {$_.Name -eq 'boot order'})
$bios4 =echo $bios3.PSComputerName
$id ="select id FROM TESTAAD"
$CUR="SELECT id FROM TESTAAD WHERE WAARDE1 = $bios4"
if ($CUR -ne $id){
$qu= "INSERT INTO TESTAAD VALUES('$bios4','$waarde6','$waarde5','$waarde4','$waarde3','$waarde2','$waarde1','$id')"
$cmd = $con.CreateCommand()
$cmd.CommandText = $qu
$cmd.ExecuteNonQuery() |out-null
}
else
{
echo $bios4
$qu= "UPDATE TESTAAD SET waarde2 = '$waarde2' , waarde3 = '$waarde3' , waarde4 = '$waarde5' , waarde5 = 'bla' , waarde6 = '$waarde6' WHERE WAARDE1 = '$bios4'"
$cmd = $con.CreateCommand()
$cmd.CommandText = $qu
$cmd.ExecuteNonQuery() |out-null
echo $bios4
}
$con.CLose()
What I would like to acomplise today is to first insert data with an id and pc name en then update the data
The problem lies within non-updated variable. The $CUR is being assigned once, but never updated.
You are comparing if strings select id FROM TESTAAD and SELECT id FROM TESTAAD WHERE WAARDE1 = $bios4 are not equal. I'd assume you'd want to compare if the SQL select statement results are the same.
It seems like you are missing the actual execution for the SQL statements that $id and $CUR contain. The SQL queries sure don't do that:
$id ="select id FROM TESTAAD" # This is not performing an actual SQL query, only text
$CUR="SELECT id FROM TESTAAD WHERE WAARDE1 = $bios4" # Ditto
if ($CUR -ne $id){ # This is always true, as $id is not equal to $CUR
$qu= "INSERT INTO TESTAAD VALUES ('$bios4','$waarde6','$waarde5', `
'$waarde4','$waarde3','$waarde2','$waarde1','$id')"
$cmd = $con.CreateCommand()
$cmd.CommandText = $qu
$cmd.ExecuteNonQuery() |out-null
} else {
echo $bios4
$qu= "UPDATE TESTAAD SET waarde2 = '$waarde2' , waarde3 = '$waarde3', `
waarde4 = '$waarde5' , waarde5 = 'bla' , waarde6 = '$waarde6' WHERE WAARDE1 = '$bios4'"
$cmd = $con.CreateCommand()
$cmd.CommandText = $qu
$cmd.ExecuteNonQuery() |out-null
echo $bios4
}