Powershell API Post Variable to Ducksboard - windows

Trying to use the following Powershell script which I've taken from Github to push data into a Ducksboard dashboard. The function works excellently however I need to feed in a variable as part of the data. Of the two calls to the function included below the function which pushes in the actual value 44 works fine, however if I substitute it for my variable $qtybord the function falls over. I've tried a number of options to overcome the var being within the single quotes but cannot get it to work - can anyone help me?
# Squirt data to Duscksboard
function Execute-DucksboardApi
{
param(
[string] $url = $null,
[string] $data = $null,
[string] $apikey = $null,
[string] $contentType = "application/json",
[string] $codePageName = "UTF-8",
[string] $userAgent = $null
);
if ($url -and $data -and $apikey)
{
[System.Net.WebRequest]$webRequest = [System.Net.WebRequest]::Create($url);
$webRequest.ServicePoint.Expect100Continue = $false;
[System.Net.NetworkCredential]$credentials = New-Object System.Net.NetworkCredential($apikey, 'ignored');
$webRequest.Credentials = $credentials.GetCredential($url, 'Basic');
$webRequest.PreAuthenticate = $true;
$webRequest.ContentType = $contentType;
$webRequest.Method = "POST";
if ( $userAgent )
{
$webRequest.UserAgent = $userAgent;
}
$enc = [System.Text.Encoding]::GetEncoding($codePageName);
[byte[]]$bytes = $enc.GetBytes($data);
$webRequest.ContentLength = $bytes.Length;
[System.IO.Stream]$reqStream = $webRequest.GetRequestStream();
$reqStream.Write($bytes, 0, $bytes.Length);
$reqStream.Flush();
$resp = $webRequest.GetResponse();
$rs = $resp.GetResponseStream();
[System.IO.StreamReader]$sr = New-Object System.IO.StreamReader -argumentList $rs;
$sr.ReadToEnd();
}
}
$qtybord = 44
Execute-DucksboardApi -url 'https://push.ducksboard.com/v/123752/' -data '{"value": $qtybord}' -apikey 'tu2j3d3epqytWZD1haHnjJSJ1NqBrmvPe5SONc0VYge4BbIPi0'
Execute-DucksboardApi -url 'https://push.ducksboard.com/v/123752/' -data '{"value": 44}' -apikey 'tu2j3d3epqytWZD1haHnjJSJ1NqBrmvPe5SONc0VYge4BbIPi0'
*

try this:
-data "{`"value`": $qtybord}"
or
-data "{""value"": $qtybord}"
in single quote variable aren't expanded, in double quote you need to escape the double quote inside the string.

So make the -data parameter take $data instead and make $data = '{"value": ' + $qtyboard + '}' or just wrap that whole thing in parens after -data.
Also, if you're on PowerShell v3 you can play with something like this:
$data = New-Object -Type PSObject -Property #{
value = $qtyboard
} | ConvertTo-JSON

Related

Faster iteration

I have this code, which is part of a function that returns a list of SQL rows based on a time range.
The query itself (1st line of code) is quite fast. But the foreach loop that extract the relevant data takes a while to complete.
I have around 350.000 lines to iterate, and despite it's has to take a while, I was wondering if there is any change I could make in order to make it faster.
$SqlDocmasterTableResuls = $this.SqlConnection.GetSqlData("SELECT DOCNUM, DOCLOC FROM MHGROUP.DOCMASTER WHERE ENTRYWHEN between '" + $this.FromDate + "' and '" + $this.ToDate + "'")
[System.Collections.ArrayList]$ListOfDocuments = [System.Collections.ArrayList]::New()
if ($SqlDocmasterTableResuls.Rows.Count)
{
foreach ($Row in $SqlDocmasterTableResuls.Rows)
{
$DocProperties = #{
"DOCNUM" = $Row.DOCNUM
"SOURCE" = $Row.DOCLOC
"DESTINATION" = $Row.DOCLOC -replace ([regex]::Escape($this.iManSourceFileServerName + ":" + $this.iManSourceFileServerPath.ROOTPATH)),
([regex]::Escape($this.iManDestinationFileServerName + ":" + $this.iManDestinationFileServerPath.ROOTPATH))
}
$DocObj = New-Object -TypeName PSObject -Property $DocProperties
$ListOfDocuments.Add($DocObj)
}
return $ListOfDocuments
Avoid appending to an array in a loop. The best way to capture loop data in a variable is to simply collect the loop output in a variable:
$ListOfDocuments = foreach ($Row in $SqlDocmasterTableResuls.Rows) {
New-Object -Type PSObject -Property #{
"DOCNUM" = $Row.DOCNUM
"SOURCE" = $Row.DOCLOC
"DESTINATION" = $Row.DOCLOC -replace ...
}
}
You don't need the surrounding if conditional, because if the table doesn't have any rows the loop should skip right over it, leaving you with an empty result.
Since you want to return the list anyway, you don't even need to collect the loop output in a variable. Just leave the output as it is and it will get returned anyway.
Also avoid repeating operations in a loop when their result doesn't change. Calculate the escaped source and destination paths once before the loop:
$srcPath = [regex]::Escape($this.iManSourceFileServerName + ':' + $this.iManSourceFileServerPath.ROOTPATH)
$dstPath = [regex]::Escape($this.iManDestinationFileServerName + ':' + $this.iManDestinationFileServerPath.ROOTPATH)
and use the variables $srcPath and $dstPath inside the loop.
Something like this should do:
$SqlDocmasterTableResuls = $this.SqlConnection.GetSqlData("SELECT ...")
$srcPath = [regex]::Escape($this.iManSourceFileServerName + ':' + $this.iManSourceFileServerPath.ROOTPATH)
$dstPath = [regex]::Escape($this.iManDestinationFileServerName + ':' + $this.iManDestinationFileServerPath.ROOTPATH)
foreach ($Row in $SqlDocmasterTableResuls.Rows) {
New-Object -Type PSObject -Property #{
'DOCNUM' = $Row.DOCNUM
'SOURCE' = $Row.DOCLOC
'DESTINATION' = $Row.DOCLOC -replace $srcPath, $dstPath
}
}
return
[edit - per Ansgar Wiechers, the PSCO accelerator is only available with ps3+.]
one other thing that may help is to replace New-Object with [PSCustomObject]. that is usually somewhat faster to use. something like this ...
$DocObj = [PSCustomObject]$DocProperties
another way to use that type accelerator is to do what Ansgar Wiechers did in his code sample, but use the accelerator instead of the cmdlet. like this ...
[PSCustomObject]#{
'DOCNUM' = $Row.DOCNUM
'SOURCE' = $Row.DOCLOC
'DESTINATION' = $Row.DOCLOC -replace $srcPath, $dstPath
}
hope that helps,
lee

Can't export more than 2 lines to the csv

[void][System.Reflection.Assembly]::LoadWithPartialName("Oracle.DataAccess")
$username = "USER"
$password = "PW"
$datasource = "XXX.XXX.XXX.XXX:YYYY/NODE1"
function getConnectionString()
{
#Below is a one line code
$connectionstring = "Data Source=$datasource;User Id=$($username); Password=$($password)"
return $connectionstring
}
$query = get-content "C:\Test.sql";
$connectionstring = getConnectionString
$DataTable = New-Object System.Data.DataTable
$command = New-Object Oracle.DataAccess.Client.OracleCommand($query,$connectionstring)
$dataAdapter = New-Object Oracle.DataAccess.Client.OracleDataAdapter($command)
[void]$dataAdapter.Fill($DataTable)
#To display data on console
$DataTable | format-table -auto
#To export to csv
$DataTable | Export-Csv "C:\Test.csv" -notype
The "Test.sql contains:
SELECT ACCOUNTNUMBER, ACCOUNTID, USERID FROM account
WHERE ACCOUNTNUMBERLIKE '%0011111%'
That quesy brings back 3 rows.
Issue at hand: My powershell script only gives me the first 2 rows (1 being the headers, the other being the first data row)
Any advice?

How to get specific number of rows from Excel in powershell

I need to get first 35 rows (including empty rows) from column A to a variable.
I looked in the internet but I cannot find the answer anywhere. $data = $worksheet.Range("A1:A35").text returns only cell A1. I tried with Cell.item etc. but with no success. Does anyone know how to extract cell range A1:A35 from excel into variable and save it to the text file? Thanks in advance.
$excel = New-Object -ComObject Excel.Application
$workbook = $excel.workbooks.open("*PATH_TO_THE_FILE*.xlsx")
$worksheet = $workbook.sheets.item("MatrixFill")
$data = $worksheet.Range("A1:A35").text
$excel.Quit()
the text property you are trying to access is actually an object, so you have to treat it as such. Also for ranges you will need to use a , instead of :. Below will give you what you need. It worked for me when I tested it.
$excel = New-Object -ComObject Excel.Application
$workbook = $excel.workbooks.open("*PATH_TO_THE_FILE*.xlsx")
$worksheet = $workbook.sheets.item("MatrixFill")
$worksheet.Range("A1","A35") | select -expand text |out-file "textfilename.txt"
$excel.Quit()
or
$excel = New-Object -ComObject Excel.Application
$workbook = $excel.workbooks.open("*PATH_TO_THE_FILE*.xlsx")
$worksheet = $workbook.sheets.item("MatrixFill")
$data = $worksheet.Range("A1","A35") | select -expand text
$data | out-file "textfilename.txt"
$excel.Quit()

How do i split each row using powershell

I'm trying to insert an table from 1 database to another (rows) using powershell. I already know how to get the data out but when i try to insert it into a new table I get an error that the string is too long (I think it means that i am trying to put all the data into an new row). I already searched the web for an answer. The only thing I could find is a command -split but then i need something to split with and the data is only numbers.
below you will find the script.
$query = “SELECT ZAMNIEUW.MACHINENAME FROM ZAMNIEUW WHERE MACHINENAME not in (SELECT PATCHGROEPEN.MACHINENAME FROM PATCHGROEPEN ) "
$command = $con.CreateCommand()
$command.CommandText = $query
$result = $command.ExecuteReader()
$table = new-object “System.Data.DataTable”
$table.Load($result)
$format = #{Expression={$_.WAARDE_PCNAME};Label=”ID”;width=20}
echo $table.MACHINENAME
$table| foreach {
$qu= " INSERT into TESTZEN (MACHINENAME) VALUES('$table')"
$cmd = $con.CreateCommand()
$cmd.CommandText = $qu
$cmd.ExecuteNonQuery() |out-null
}
apperantly oracle does use something to split each row (;)
the code below
$query = “SELECT ZAMNIEUW.MACHINENAME FROM ZAMNIEUW WHERE MACHINENAME not in (SELECT PATCHGROEPEN.MACHINENAME FROM PATCHGROEPEN ) "
$command = $con.CreateCommand()
$command.CommandText = $query
$result = $command.ExecuteReader()
$table = new-object “System.Data.DataTable”
$table.Load($result)
$format = #{Expression={$_.WAARDE_PCNAME};Label=”ID”;width=20}
$tables =echo $table.MACHINENAME
$tables| foreach {
$tables = $_ -split ';'
$qu= " INSERT into TESTZEN (MACHINENAME) VALUES('$tables')"
$cmd = $con.CreateCommand()
$cmd.CommandText = $qu
$cmd.ExecuteNonQuery() |out-null
}

Powershell - GUI and menustrips

I've tried looking on the internet but can't find anything on this.
I've built a powershell GUI app but want to add a menu bar with different menu items to it.
is this possible? has anyone done it (with examples)?
Thanks
Here is a sample using Windows Forms. I design it with Visual studio and then transform it to PowerSell using Convert-Form a free tool written by Laurent Dardenne from the nice french PowerShell site PowerShelll-Scripting.com
# Load external assemblies
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$MS_Main = new-object System.Windows.Forms.MenuStrip
$fileToolStripMenuItem = new-object System.Windows.Forms.ToolStripMenuItem
$openToolStripMenuItem = new-object System.Windows.Forms.ToolStripMenuItem
$editionToolStripMenuItem = new-object System.Windows.Forms.ToolStripMenuItem
#
# MS_Main
#
$MS_Main.Items.AddRange(#(
$fileToolStripMenuItem,
$editionToolStripMenuItem))
$MS_Main.Location = new-object System.Drawing.Point(0, 0)
$MS_Main.Name = "MS_Main"
$MS_Main.Size = new-object System.Drawing.Size(354, 24)
$MS_Main.TabIndex = 0
$MS_Main.Text = "menuStrip1"
#
# fileToolStripMenuItem
#
$fileToolStripMenuItem.DropDownItems.AddRange(#(
$openToolStripMenuItem))
$fileToolStripMenuItem.Name = "fileToolStripMenuItem"
$fileToolStripMenuItem.Size = new-object System.Drawing.Size(35, 20)
$fileToolStripMenuItem.Text = "&File"
#
# openToolStripMenuItem
#
$openToolStripMenuItem.Name = "openToolStripMenuItem"
$openToolStripMenuItem.Size = new-object System.Drawing.Size(152, 22)
$openToolStripMenuItem.Text = "&Open"
function OnClick_openToolStripMenuItem($Sender,$e){
[void][System.Windows.Forms.MessageBox]::Show("Event openToolStripMenuItem.Add_Click is not implemented.")
}
$openToolStripMenuItem.Add_Click( { OnClick_openToolStripMenuItem $openToolStripMenuItem $EventArgs} )
#
# editionToolStripMenuItem
#
$editionToolStripMenuItem.Name = "editionToolStripMenuItem"
$editionToolStripMenuItem.Size = new-object System.Drawing.Size(51, 20)
$editionToolStripMenuItem.Text = "&Edition"
#
$MenuForm = new-object System.Windows.Forms.form
#
$MenuForm.ClientSize = new-object System.Drawing.Size(354, 141)
$MenuForm.Controls.Add($MS_Main)
$MenuForm.MainMenuStrip = $MS_Main
$MenuForm.Name = "MenuForm"
$MenuForm.Text = "I\'ve got a menu"
function OnFormClosing_MenuForm($Sender,$e){
# $this represent sender (object)
# $_ represent e (eventarg)
# Allow closing
($_).Cancel= $False
}
$MenuForm.Add_FormClosing( { OnFormClosing_MenuForm $MenuForm $EventArgs} )
$MenuForm.Add_Shown({$MenuForm.Activate()})
$MenuForm.ShowDialog()
#Free ressources
$MenuForm.Dispose()

Resources