I'm building a simple GUI where support staff can look up basic user information. The GUI is supposed to pull this data from an SQL DB, but nothing happens when the button is pressed.
function SQLquery {
param (
[Parameter(Mandatory = $true)]
[ValidateSet('NemOrgDB')]
[string]
$System,
[string]
$Query
)
switch ($System) {
NemOrgDB { $ConnectionString = 'Place holder for Stack Overflow' }
}
#New SqlConnection object
$sqlConnection = New-Object System.Data.SqlClient.SqlConnection
$sqlConnection.ConnectionString = $ConnectionString
$sqlConnection.Open()
#New Sqlcommand object
$sqlCommand = New-Object System.Data.SqlClient.SqlCommand
$sqlCommand.Connection = $sqlConnection
$sqlCommand.CommandText = $Query
#Create new sqldataadapter object
$sqlDataAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$sqlDataAdapter.SelectCommand = $sqlCommand
#Create new dataset object
$DataSet = New-Object System.Data.DataSet
#Fill dataset with dataadapter input
try {
$sqlDataAdapter.Fill($DataSet) | Out-Null
$output = $DataSet.Tables
}
catch {
$output = $null
}
#Close sql connection
$sqlConnection.close()
$null = $sqlConnection
$output
}
Here is the Function in use:
#Søgnigns criteria
$EmployeeID = Read-Host -Prompt "What user to find?"
#SQL Query
SQLquery -System NemOrgDB -Query "Select [medarbejder_wnr]
,[navn]
,[stilling]
,[stilling_nr]
,[firmakode_txt]
FROM [PersonData_NemOrg].[dbo].[Personale]
WHERE medarbejder_wnr ='$EmployeeID';"
The 2 pieces of code work as they should in a console environment with no Gui attached, they return the following results:
EmployeeID: EmployeeID
Name: Name
Role: IT support
Role number : Number
fimakode_txt : Company
When the same code is run inside the GUI nothing happens, here is the GUI code:
#ButtonSearch
#
$ButtonSearch.BackColor = [System.Drawing.SystemColors]::ActiveBorder
$ButtonSearch.FlatStyle = [System.Windows.Forms.FlatStyle]::System
$ButtonSearch.Font = (New-Object -TypeName System.Drawing.Font -ArgumentList #([System.String]'Tahoma',[System.Single]9,[System.Drawing.FontStyle]::Bold,[System.Drawing.GraphicsUnit]::Point,([System.Byte][System.Byte]0)))
$ButtonSearch.Location = (New-Object -TypeName System.Drawing.Point -ArgumentList #([System.Int32]12,[System.Int32]118))
$ButtonSearch.Name = [System.String]'ButtonSearch'
$ButtonSearch.Size = (New-Object -TypeName System.Drawing.Size -ArgumentList #([System.Int32]150,[System.Int32]23))
$ButtonSearch.TabIndex = [System.Int32]24
$ButtonSearch.Text = [System.String]'Search'
$ButtonSearch.UseCompatibleTextRendering = $true
$ButtonSearch.UseVisualStyleBackColor = $false
$ButtonSearch.add_Click($ButtonSearch_Click)
#
AND
$ButtonSearch_Click = {
$Wnummer = $TextBoxWnummer1.Text
SQLquery -System NemOrgDB -Query "Select [medarbejder_wnr]
,[navn]
,[stilling]
,[stilling_nr]
,[firmakode_txt]
FROM [PersonData_NemOrg].[dbo].[Personale]
WHERE medarbejder_wnr ='$Wnummer';"
}
It simply returns nothing.
Related
Trying to use SQL results as variables. This will return the results to the host, but I would like to use each value as a variable.
$job = "22940"
$SQLServer = "my-sql" #use Server\Instance for named SQL instances!
$SQLDBName = "MyDatabase"
$SqlQuery = "DECLARE #Job VARCHAR(5);
SET #Job = '$job'
SELECT dbo.Job.Job, dbo.Job.Customer,
dbo.Job.Note_Text,
dbo.User_Values.Date1 AS 'Setup Date',
dbo.User_Values.Date2 AS 'Due Date'
FROM dbo.Job INNER JOIN
dbo.User_Values ON dbo.Job.User_Values = dbo.User_Values.User_Values
WHERE (dbo.Job.Job = #Job) AND (dbo.Job.User_Values = dbo.User_Values.User_Values)"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = $SQLServer; Database = $SQLDBName; Integrated Security = True"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SqlQuery
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$SqlConnection.Close()
clear
$DataSet.Tables[0]
How can I put each column into a variable that I can use for something else?
I work with data tables directly. You should also look into handling parameters correctly. It helps with handling special characters in the variable value. And, it protects from SQL Injection Attacks:
$Sql = 'select top 100 first_name, Last_name from person where last_name=#lastname'
$Database = 'XXX'
$Server = 'XXX'
$LastName = 'Jones'
$Connection = New-Object System.Data.SqlClient.SqlConnection
$Connection.ConnectionString = "Server=$Server;Database=$Database;Integrated Security=True"
$Connection.Open()
$cmd = new-object system.Data.SqlClient.SqlCommand($Sql, $Connection)
$null = $cmd.Parameters.AddWithValue('#lastname', $LastName)
$DataTable = New-Object System.Data.DataTable
$SqlDataReader = $cmd.ExecuteReader()
$DataTable.Load($SqlDataReader)
$Connection.Close()
$Connection = $null
$DataTable.Rows.Count
foreach ($r in $DataTable.Rows)
{
$fn = $r.first_name
$ln = $r.last_name
"$fn $ln"
}
Not sure if this is really the correct way but it does give me the results I am looking for. Looked through some of my notes on working with CSV files and I added the foreach at the end. The above comments from #notjustme and #jcoehoorn got me looking in the right direction. Thanks
$job = "22940"
$SQLServer = "my-sql" #use Server\Instance for named SQL instances!
$SQLDBName = "MyDatabase"
$SqlQuery = "DECLARE #Job VARCHAR(5);
SET #Job = '$job'
SELECT dbo.Job.Job, dbo.Job.Customer,
dbo.Job.Note_Text,
dbo.User_Values.Date1 AS 'Setup Date',
dbo.User_Values.Date2 AS 'Due Date'
FROM dbo.Job INNER JOIN
dbo.User_Values ON dbo.Job.User_Values = dbo.User_Values.User_Values
WHERE (dbo.Job.Job = #Job) AND (dbo.Job.User_Values = dbo.User_Values.User_Values)"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = $SQLServer; Database = $SQLDBName; Integrated Security = True"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SqlQuery
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$SqlConnection.Close()
clear
foreach($Job in $DataSet.Tables[0])
{
$MyJobNumber = $Job.Job
$MyCustomer = $Job.Customer
$MyNotes = $Job.Note_Text
$MySetupDate = $Job.Setup_Date
$MyDueDate = $Job.Due_Date
}
I'm using Powershell 4 and attempting to write data into a SQL Server 2012.
Here is the script I am using
Add-Type -AssemblyName System.Data
$conn = New-Object System.Data.SqlClient.SqlConnection↵
$conn.ConnectionString = "Data Source=<SQLSERVER>;Initial Catalog=SYSINFO;Integrated Security=true;"
$conn.open()
$cmd = New-Object System.Data.SqlClient.SqlCommand
The error I am getting is:
New-Object : Cannot find type [System.Data.SqlClient.SqlConnection] : verify that the assembly containing this type is loaded.
I assuemd the first line (Add-Type) would load all the required assemblies under System.Data
Am I missing somethign obvious?
You can do it this way:
$Server = 'theServer'
$database = 'theDatabase'
$Connection = New-Object System.Data.SQLClient.SQLConnection
$Connection.ConnectionString = "server=$($Server);database=$($Database);trusted_connection=true;"
$Connection.Open()
$Command = New-Object System.Data.SQLClient.SQLCommand
$Command.Connection = $Connection
$Command.CommandText = 'SELECT TOP 5 * FROM yourTable ORDER BY 1 DESC'
$Reader = $Command.ExecuteReader()
$Datatable = New-Object System.Data.DataTable
$Datatable.Load($Reader)
$Datatable | Export-Csv report.csv -NoTypeInformation
$Connection.Close()
I have a script which look like below:
function Invoke-SQL {
param(
[string] $dataSource = ".\MSSQLSERVER",
[string] $database = "master",
[string] $sqlCommand = $(throw "Please specify a query.")
)
$connectionString = "Data Source=$dataSource; Integrated Security=True; Initial Catalog=$database; Connect Timeout=100"
$connection = new-object system.data.SqlClient.SQLConnection($connectionString)
$command = new-object system.data.sqlclient.sqlcommand($sqlCommand,$connection)
Try {
$connection.Open()
} catch {
return, $null
}
$adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
$dataset = New-Object System.Data.DataSet
$adapter.Fill($dataSet) | Out-Null
$connection.Close()
$dataSet.Tables
}
[string]$SQL = "select CmsSrvName from CmsServerList_VM"
$DbInstances = Invoke-SQL "DBSRV" "Test" $SQL
workflow wf1{
Param([System.Data.DataTable]$instance)
ForEach -Parallel -ThrottleLimit 10 ($i in $instance) {
InlineScript{
$t = $using:i
Write-Verbose "$t['CmsSrvName']"
}
}
}
wf1 -Verbose $DbInstances
Output:
VERBOSE: [localhost]:System.Data.DataRow['CmsSrvName']
VERBOSE: [localhost]:System.Data.DataRow['CmsSrvName']
VERBOSE: [localhost]:System.Data.DataRow['CmsSrvName']
The output is not what I expected, it just print out the type name not the value. How can I access the DataRow value in a workflow?(in Powershell 5)
Thanks in advance for the help
I have the following code which returns what I need but I am struggling to output this to a table from which I can further query.
$instances = invoke-sqlcmd –ServerInstance "myserver" –Database "my db" –query "select instanceconnectname from [dbo].[smytable] WHERE InstanceConnectName LIKE '%CLU%' and connect = 1"
Write-Host $instances.instanceconnectname
foreach ($svr in $instances.instanceconnectname){
$dt = new-object "System.Data.DataTable"
$cn = new-object System.Data.SqlClient.SqlConnection "server=$svr;database=master;Integrated Security=sspi"
$cn.Open()
$sql = $cn.CreateCommand()
$sql.CommandText = "SELECT ##SERVERNAME AS ServerName, SERVERPROPERTY('ComputerNamePhysicalNetBIOS') As ActiveNode"
$rdr = $sql.ExecuteReader()
$dt.Load($rdr)
$cn.Close()
$dt | Format-Table -autosize
}
I have been reading about some custom functions out there is that the only way to do this really? I had thought I could just do some kind of SQL Insert but not figured out how to do it.
Instead of outputting to a DataTable, I would output to a DataSet, which you can then further query. e.g.:
$cn = new-object System.Data.SqlClient.SqlConnection "server=$svr;database=master;Integrated Security=sspi"
#Create the SQL Command from a connection string
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = "SELECT ##SERVERNAME AS ServerName, SERVERPROPERTY('ComputerNamePhysicalNetBIOS') As ActiveNode"
$SqlCmd.Connection = $cn
#Create the SQL DataAdapter
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
#Fill the DataSet
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
Now with it in a DataSet, you can query it, like this:
$DataSet.tables[0].select("ServerName like 'Bob%'")
Hopefully that is enough to get you started...
I have an SSIS execute process task where I am calling a PowerShell script. I found that I can get the process task to fail if the PowerShell script fails by trapping the errors like this:
trap {
$err = $_.Exception
while ( $err.InnerException )
{
$err = $err.InnerException
Write-Host $err.Message
};
exit 1
}
I would like to get the error messages to return to SSIS, but I can't seem to get it to work. It just returns the following:
The process exit code was "1" while the expected was "0".
Any help is appreciated.
Full Code:
Param(
[String]$excelPath,
[String]$serverName,
[String]$databaseName,
[String]$tableName
)
$ErrorActionPreference = 'Stop'
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO.SqlDataType') | Out-Null
Trap {
$err = $_.Exception
while ( $err.InnerException )
{
$err = $err.InnerException
Write-Host $err.Message
};
exit 1
}
$excel = New-Object -ComObject excel.application
$excel.visible = $False
$excel.displayalerts=$False
$workbook = $excel.Workbooks.Open($ExcelPath)
$workSheet = $workbook.worksheets.Item(1).name
$workbook.Close()
$excel.quit()
$excel = $null
$query = "select * from [$workSheet`$]";
$connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=`"$excelPath`";Extended Properties=`"Excel 12.0 Xml;HDR=YES`";"
# Instantiate some objects which will be needed
$serverSMO = New-Object Microsoft.SqlServer.Management.Smo.Server($serverName)
$db = $serverSMO.Databases[$databaseName];
$newTable = New-Object Microsoft.SqlServer.Management.Smo.Table ;
$newTable.Parent = $db;
$newTable.Name = $tableName ;
$conn = New-Object System.Data.OleDb.OleDbConnection($connectionString)
$conn.open()
$cmd = New-Object System.Data.OleDb.OleDbCommand($query,$conn)
$dataAdapter = New-Object System.Data.OleDb.OleDbDataAdapter($cmd)
$dataTable = New-Object System.Data.DataTable
$dataAdapter.fill($dataTable)
$conn.close()
# Drop the table if it exists
if($db.Tables.Contains($tableName).Equals($true))
{
($db.Tables[$tableName]).Drop()
}
# Iterate the columns in the DataTable object and add dynamically named columns to the SqlServer Table object.
foreach($col in $dataTable.Columns)
{
$sqlDataType = [Microsoft.SqlServer.Management.Smo.SqlDataType]::Varchar
$dataType = New-Object Microsoft.SqlServer.Management.Smo.DataType($sqlDataType);
$dataType.MaximumLength = 1000;
$newColumn = New-Object Microsoft.SqlServer.Management.Smo.Column($newTable,$col.ColumnName,$dataType);
$newColumn.DataType = $dataType;
$newTable.Columns.Add($newColumn);
}
$newTable.Create();
#bcp data into new table
$connectionString = "Data Source=$serverName;Integrated Security=true;Initial Catalog=$databaseName;"
$bc = New-Object ("Data.SqlClient.SqlBulkCopy") $connectionString
$bc.DestinationTableName = "$tableName"
$bc.WriteToServer($dataTable)