I want to add and remove user from the lokal Administrator group. Problem is that even I elevate rights in first place It still Access Denies me when I try to add them.
In a similar code It works this way... only thing I changed it that I created a GUI for it.
Here is the code:
$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
if (!$myWindowsPrincipal.IsInRole($adminRole)){
start-process "powershell" -Verb "runas" -ArgumentList "-File",$MyInvocation.MyCommand.Definition
}
[VOID] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[Void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$objForm = New-Object System.Windows.Forms.Form
$objForm.BackgroundImageLayout = 0
$objForm.BackgroundImage =[System.Drawing.Image]::FromFile('xx')
$objForm.StartPosition = "CenterScreen"
$objForm.Icon="xx"
$objForm.Size = New-Object System.Drawing.Size(400,200)
$objForm.Text = "Lokal Admin Adder v.01"
$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(75,30)
$objLabel.Size = New-Object System.Drawing.Size(240,20)
$objLabel.Text = "Nutzernamen eingeben(m_mustermann)"
$objForm.Controls.Add($objLabel)
$objLabel2 = New-Object System.Windows.Forms.Label
$objLabel2.Location = New-Object System.Drawing.Size(280,140)
$objLabel2.Size = New-Object System.Drawing.Size(300,20)
$objLabel2.Text = "by Lucas Klarner"
$objForm.Controls.Add($objLabel2)
$objTextBox = New-Object System.Windows.Forms.TextBox
$objTextBox.Location = New-Object System.Drawing.Size(85,50)
$objTextBox.Size = New-Object System.Drawing.Size(200,20)
$objForm.Controls.Add($objTextBox)
$FinishButton = New-Object System.Windows.Forms.Button
$FinishButton.Location = New-Object System.Drawing.Size (20,80)
$FinishButton.Size = New-Object System.Drawing.Size (150,20)
$FinishButton.Text = "Nutzer hinzufügen"
$FinishButton.Name = "Nutzer hinzufügen"
$FinishButton.Add_Click({
$Usr = $objTextBox.Text; Add-LocalGroupMember -Group Administratoren -Member $Usr })
$objForm.Controls.Add($FinishButton)
$DeleteButton = New-Object System.Windows.Forms.Button
$DeleteButton.Location = New-Object System.Drawing.Size (210,80)
$DeleteButton.Size = New-Object System.Drawing.Size (150,20)
$DeleteButton.Text = "Nutzer entfernen"
$DeleteButton.Name = "Nutzer entfernen"
$DeleteButton.DialogResult = "OK"
$DeleteButton.Add_Click({
$Usr = $objTextBox.Text;Remove-LocalGroupMember -Group Administratoren -Member $Usr -Verbose })
$objForm.Controls.Add($DeleteButton)
[void] $objForm.ShowDialog()
Thanks a lot!!
FIXED:
Somehow my elevation code was not running correctly and I made a new one out of some internet posts:
if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
$CommandLine = "-File `"" + $MyInvocation.MyCommand.Path + "`" " + $MyInvocation.UnboundArguments
Start-Process -FilePath PowerShell.exe -Verb Runas -ArgumentList $CommandLine
Exit
}
}
Here's how it works:
The first line checks to see if the script is already running in an elevated environment. This would occur if PowerShell is running as Administrator or UAC is disabled. If it is, the script will continue to run normally in that process.
The second line checks to see if the Windows operating system build number is 6000 (Windows Vista) or greater. Earlier builds did not support Run As elevation.
The third line retrieves the command line used to run the original script, including any arguments.
Finally, the fourth line starts a new elevated PowerShell process where the script runs again. Once the script terminates, the elevated PowerShell window closes.
https://blog.expta.com/2017/03/how-to-self-elevate-powershell-script.html
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 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 script, which connect to db. I need get technical info about execute script. Or when in my sql srcipt exist mistake,I see very scant information. But I need detail of error. How can I get more detail info?
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connectionString
$connection.Open()
$query = "SELECT * FROM Animal"
$command = $connection.CreateCommand()
$command.CommandText = $query
$result = $command.ExecuteReader()
$table = new-object “System.Data.DataTable”
$table.Load($result)
$table
//how get info
$connection.Close()
After your code executes run Error[0] | fl -Force to get the details of (last) error.
Is there a way to execute an arbitrary query on a SQL Server using Powershell on my local machine?
For others who need to do this with just stock .NET and PowerShell (no additional SQL tools installed) here is the function that I use:
function Invoke-SQL {
param(
[string] $dataSource = ".\SQLEXPRESS",
[string] $database = "MasterData",
[string] $sqlCommand = $(throw "Please specify a query.")
)
$connectionString = "Data Source=$dataSource; " +
"Integrated Security=SSPI; " +
"Initial Catalog=$database"
$connection = new-object system.data.SqlClient.SQLConnection($connectionString)
$command = new-object system.data.sqlclient.sqlcommand($sqlCommand,$connection)
$connection.Open()
$adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
$dataset = New-Object System.Data.DataSet
$adapter.Fill($dataSet) | Out-Null
$connection.Close()
$dataSet.Tables
}
I have been using this so long I don't know who wrote which parts. This was distilled from others' examples, but simplified to be clear and just what is needed without extra dependencies or features.
I use and share this often enough that I have turned this into a script module on GitHub so that you can now go to your modules directory and execute git clone https://github.com/ChrisMagnuson/InvokeSQL and from that point forward invoke-sql will automatically be loaded when you go to use it (assuming your using PowerShell v3 or later).
You can use the Invoke-Sqlcmd cmdlet
Invoke-Sqlcmd -Query "SELECT GETDATE() AS TimeOfQuery;" -ServerInstance "MyComputer\MyInstance"
http://technet.microsoft.com/en-us/library/cc281720.aspx
This function will return the results of a query as an array of powershell objects so you can use them in filters and access columns easily:
function sql($sqlText, $database = "master", $server = ".")
{
$connection = new-object System.Data.SqlClient.SQLConnection("Data Source=$server;Integrated Security=SSPI;Initial Catalog=$database");
$cmd = new-object System.Data.SqlClient.SqlCommand($sqlText, $connection);
$connection.Open();
$reader = $cmd.ExecuteReader()
$results = #()
while ($reader.Read())
{
$row = #{}
for ($i = 0; $i -lt $reader.FieldCount; $i++)
{
$row[$reader.GetName($i)] = $reader.GetValue($i)
}
$results += new-object psobject -property $row
}
$connection.Close();
$results
}
Here's an example I found on this blog.
$cn2 = new-object system.data.SqlClient.SQLConnection("Data Source=machine1;Integrated Security=SSPI;Initial Catalog=master");
$cmd = new-object system.data.sqlclient.sqlcommand("dbcc freeproccache", $cn2);
$cn2.Open();
if ($cmd.ExecuteNonQuery() -ne -1)
{
echo "Failed";
}
$cn2.Close();
Presumably you could substitute a different TSQL statement where it says dbcc freeproccache.
If you want to do it on your local machine instead of in the context of SQL server then I would use the following. It is what we use at my company.
$ServerName = "_ServerName_"
$DatabaseName = "_DatabaseName_"
$Query = "SELECT * FROM Table WHERE Column = ''"
#Timeout parameters
$QueryTimeout = 120
$ConnectionTimeout = 30
#Action of connecting to the Database and executing the query and returning results if there were any.
$conn=New-Object System.Data.SqlClient.SQLConnection
$ConnectionString = "Server={0};Database={1};Integrated Security=True;Connect Timeout={2}" -f $ServerName,$DatabaseName,$ConnectionTimeout
$conn.ConnectionString=$ConnectionString
$conn.Open()
$cmd=New-Object system.Data.SqlClient.SqlCommand($Query,$conn)
$cmd.CommandTimeout=$QueryTimeout
$ds=New-Object system.Data.DataSet
$da=New-Object system.Data.SqlClient.SqlDataAdapter($cmd)
[void]$da.fill($ds)
$conn.Close()
$ds.Tables
Just fill in the $ServerName, $DatabaseName and the $Query variables and you should be good to go.
I am not sure how we originally found this out, but there is something very similar here.
There isn't a built-in "PowerShell" way of running a SQL query. If you have the SQL Server tools installed, you'll get an Invoke-SqlCmd cmdlet.
Because PowerShell is built on .NET, you can use the ADO.NET API to run your queries.
Invoke-Sqlcmd -Query "sp_who" -ServerInstance . -QueryTimeout 3
To avoid SQL Injection with varchar parameters you could use
function sqlExecuteRead($connectionString, $sqlCommand, $pars) {
$connection = new-object system.data.SqlClient.SQLConnection($connectionString)
$connection.Open()
$command = new-object system.data.sqlclient.sqlcommand($sqlCommand, $connection)
if ($pars -and $pars.Keys) {
foreach($key in $pars.keys) {
# avoid injection in varchar parameters
$par = $command.Parameters.Add("#$key", [system.data.SqlDbType]::VarChar, 512);
$par.Value = $pars[$key];
}
}
$adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
$dataset = New-Object System.Data.DataSet
$adapter.Fill($dataset) | Out-Null
$connection.Close()
return $dataset.tables[0].rows
}
$connectionString = "connectionstringHere"
$sql = "select top 10 Message, TimeStamp, Level from dbo.log " +
"where Message = #MSG and Level like #LEVEL"
$pars = #{
MSG = 'this is a test from powershell'
LEVEL = 'aaa%'
};
sqlExecuteRead $connectionString $sql $pars
You can even format string and pass parameters as you want.
case "ADDSQLSERVERUSER":
//0 = coprorateName;
//1 = user password
//2 = servername
command = #"$sqlQuery = Use JazzUWS_'{0}'
Create login UWSUser_'{0}' with password='{1}';
Create user UWSUser_'{0}' for login UWSUser_'{0}';
Grant Execute to UWSUser_'{0}';
Use ReportSvrUWS_'{0}'
Create user UWSUser_'{0}' for login UWSUser_'{0}';
Grant Execute to UWSUser_'{0}';
Invoke-Sqlcmd -Query $sqlQuery -ServerInstance '{2}'";
break;
C# Code for remote execution(you can organize your way)
string script = PowershellDictionary.GetPowershellCommand("ADDSQLSERVERUSER");
script = String.Format(script, this.CorporateName, password, this.SQLServerName)
PowerShellExecution.RunScriptRemote(_credentials.Server, _credentials.Username, _credentials.Password, new List<string> { script });
You could use the best SQL Server module around: DBATOOLS. You would also benefit from running a query to multiple sql instances.
Install-Module dbatools -Scope CurrentUser
$sql = 'SQL1','SQL1\INSTANCE1','SQL2'
$query = "SELECT 'This query would run on all SQL instances'"
Invoke-DbaQuery -SqlInstance $sqlinstances -Query $query -AppendServerInstance