Via PowerShell I'm trying to get the last ticker data from all currency pairs via the public API of a cryptocurrency exchange.
For this I first get all markets and then I want to loop through these, but for some reason only the first currency pair is being returned.
Anyone knows what I'm missing?
$bt_baseapi_url = "https://bittrex.com/api/v1.1/"
$getmarkets = $bt_baseapi_url + "public/getmarkets"
$getticker = $bt_baseapi_url + "public/getticker"
$markets = Invoke-RestMethod -Uri $getmarkets
$marketnames = $markets.result
foreach ($marketname in $marketnames.marketname) {
$tickerurl = $getticker + "?market=" + $marketname
$ticker = Invoke-RestMethod -Uri $tickerurl
return $ticker.result.last
}
As Ansgar Wiechers suggests in a comment on the question, do not use return inside a foreach statement's body in an attempt to return (output) a value while continuing the loop; return would return from any enclosing function or script.
Instead, rely on PowerShell's implicit output behavior, as demonstrated in this simple example:
> foreach ($el in 1, 2, 3) { $el }
1
2
3
Simply referencing $el without assigning to a variable or piping / redirecting it elsewhere cause its value to be output.
If needed at all, use continue to prevent execution of subsequent statements in the loop body while continuing the loop overall; use break to exit the loop.
By contrast - and that may be the source of the confusion - inside the body of a ForEach-Object cmdlet call - as part of a pipeline - rather than the foreach statement, the rules change, and return indeed would only exit the iteration at hand and proceed with the next input object:
> 1, 2, 3 | ForEach-Object { return $_ }
1
2
3
Note that even in this case return $_ is just syntactic sugar for $_; return - i.e., an output generating statement followed by a control-flow statement, and simply using $_ may be enough.
Do NOT use break / continue with the ForEach-Object cmdlet, as these statements would look for an enclosing loop statement (such as foreach, do, while`) and - in the absence of one - exit the entire script.
Unfortunately, there is no direct way to exit a pipeline prematurely, - see https://github.com/PowerShell/PowerShell/issues/3821; make your voice heard there if you think this should change.
Related
OK, First I consider myself a newbie and have much to learn about PowerShell and this is my first post ever.
I am trying to loop through some data and put it into a custom object and put them into separate arrays for later use. The issue is that I want to create a variable representing $week_data1 by using a counter $i so I can reduce the amount of code required. I do have a concatenated variable being written out: write-host '$week++ ='$week$i But I think it is being represented as a string?
How can I get $week_data$i to represent the array to insert the data?
Input data. Each week ends on Saturday.
$week1=#('2021-05-01')
$week2=#('2021-05-02', '2021-05-03', '2021-05-04', '2021-05-05', '2021-05-06', '2021-05-07', '2021-05-08')
$week3=#('2021-05-09', '2021-05-10', '2021-05-11', '2021-05-12', '2021-05-13', '2021-05-14', '2021-05-15')
$week4=#('2021-05-16', '2021-05-17', '2021-05-18', '2021-05-19', '2021-05-20', '2021-05-21', '2021-05-22')
$week5=#('2021-05-23', '2021-05-24', '2021-05-25', '2021-05-26', '2021-05-27', '2021-05-28', '2021-05-29')
$week6=#('2021-05-30', '2021-05-31')
$month =#($week1, $week2, $week3, $week4, $week5, $week6)
Create the output structures to be populated.
$week_data1=#()
$week_data2=#()
$week_data3=#()
$week_data4=#()
$week_data5=#()
$week_data6=#()
$month_data =#($week_data1, $week_data2, $week_data3, $week_data4, $week_data5, $week_data6)
Loop through the array and count the week number that is being processed.
$i = 0
foreach($week in $month)
{ $i++
$n=0
Here I can write out a Variable and it concatenates properly.
**write-host '$week++ ='$week$i**
foreach($day in $week)
{$n++
write-host '$day ='$day
Pull in data from a .csv file to populate the custom object.
foreach($line in $csv)
{
if($line -match $day)
Match the line in the CSV file that has the correct Date in it. One line in the file per date in the month.
{ #write-host '$line.Day = ' $line.Day
# custom object to be used later
$date_data = [PSCustomObject] #{
week_numb = $i
date = $line.Day
attempts = $line.Attempts
connects = $line.Connects
}
I have tried different syntax versions but it does not work here? I want to put the custom object data into the new array for the week being processed.
#write-host '$week_data[$i]='$week_data[$i]
$week_data$i += $date_data # Add data from csv file into a
#$week_data[$i] += $date_data
}
}
}
}
Issue using $week_data$i as a variable I get an error:
At line:38 char:17
$week_data$i += $date_data # Add data from csv file into a
~~
Unexpected token '$i' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken
You're looking for variable indirection, i.e. the ability to refer to a variable indirectly, by a name stored in another variable or returned from an expression.
Note, however, that there are usually superior alternatives, such as using arrays or hashtables as multi-value containers - see this answer for an example.
If you do need to use variable indirection, use Get-Variable and Set-Variable:
$week_data1 = 'foo', 'bar'
$i = 1
# Same as: $week_data1
# Note that "$" must NOT be specified as part of the name.
Get-Variable "week_data$i" -ValueOnly
# Same as: $week_data1 = 'baz', 'quux'
Set-Variable "week_data$i" baz, quux
# Updating an existing value requires nesting the two calls:
# Same as: $week_data1 += 'quuz'
Set-Variable "week_data$i" ((Get-Variable "week_data$i" -ValueOnly) + 'quuz')
As an aside: "extending" an array with += is convenient, but inefficient: a new array must be created behind the scenes every time - see this answer.
Similarly, calling cmdlets to set and get variables performs poorly compared to direct assignments and variable references.
See this answer for applying the indirection technique analogously to environment variables, using Get-Content / Set-Content and the Env: drive.
As for what you tried:
$week_data$i = ... is an assignment expression, which is interpreted as directly juxtaposing two variables, $week_data and $i, which causes the syntax error you saw.
By contrast, something like Write-Output $week_data$i is a command, and while $week_data$i is also interpreted as two variable references, as a command argument it is syntactically valid, and would simply pass the (stringified) concatenation of the two variable values; in other words: $week_data$i acts as if it were double-quoted, i.e. an expandable string, and the command is therefore equivalent to Write-Output "$week_data$i"
Unrelated to the answer, but likely helpful for you, I have a function that will determine what week in a month a given date is.
Function Get-Week{
[cmdletbinding()]
param([parameter(ValueFromPipeline)][string[]]$Date)
process{
ForEach($Day in $Date){
$DTDay=[datetime]$Day
$Buffer = ([datetime]("{0}-01-{1}" -f $DTDay.Month,$DTDay.Year)).dayofweek.value__ -1
[math]::Truncate(($DTDay.Day+$Buffer)/7)+1
}
}
}
So you feed that a string that can be converted to a date like:
'5-13-2021' | Get-Week
or
Get-Week '5-13-2021'
and you get back a number indicating what week (ending on Saturday) of the month that day falls in.
I have 2 arrays here one contains the servername and other contains the IP.
I need to loop through them and create a key value pair like below for each server
server1:ip1
server2:ip2
I have written below code, but the problem is if i debug the code using F11, it is working fine, but i don't it gives some error which is different every time.
so feeling like it is not that reliable piece to continue.
$NewDNSEntryName = $DNSEntryName.Split(",")
$DNSIPs = $DNSIP.Split(",")
if($DNSEntryName -match "," -or $DNSIP -match ",")
{
0..($NewDNSEntryName.Count - 1) | ForEach-Object {
$fullName=""
$fullName += #("$($NewDNSEntryName[$_]):$($DNSIPs[$_])")
This is the line where i am facing trouble
0..($NewDNSEntryName.Count - 1) | ForEach-Object
Please let me know why this code is behaving like this else any alternate idea is appreciated
Assuming each item in each list corresponds with each other exactly, you can use a for loop and loop through the array indexes.
$NewDNSEntryName = $DNSEntryName.Split(",")
$DNSIPs = $DNSIP.Split(",")
for ($i = 0; $i -lt $DNSIPs.count; $i++) {
"{0}:{1}" -f $NewDNSEntryName[$i],$DNSIPs[$i]
}
For the code above to work, $DNSEntryName and $DNSIP must be single strings with commas between names and IPs. If $DNSEntryName and $DNSIP are already lists or arrays, something else will need to be done.
In your attempt, technically, your logic should work given everything written above is true. However, $fullName is emptied at every single iteration, which may produce undesirable results.
Ok, I have coded for quite a while in different, but I am not getting Powershells concept of a function return?....
I am very new to Powershell, so I am sure I am missing something very basic.
I have the function below:
function plGetKeyValue ([string] $FileName, [string] $SectionName, [string] $Key)
{
if ($PSBoundParameters.Count -lt 2 -or $PSBoundParameters.Count -gt 3 )
{
"Invalid call to {0} in {1}" -f $MyInvocation.MyCommand.Name,
$MyInvocation.MyCommand.ModuleName
return
}
# Declaration
$lFileContents = ""
$lSections = ""
$lDataStart = ""
$lStart = -1
$lEnd = -1
$lFoundSection = ""
$lNextSection = ""
$lResults = ""
$lRetValue = ""
# Handle the optional parameter.
if ( $PSBoundParameters.Count -eq 2 ) {
$PSBoundParameters.Add('Key', $SectionName)
$PSBoundParameters.Remove('SectionName')
$Key = $SectionName
$SectionName = $null
}
# Read the file in
$lFileContents = Get-Content $FileName | Select-String -Pattern .*
# Get the sections.
$lSections = $lFileContents -match '\['
$lSections = $lSections -notmatch '#'
# Start of the data.
$lDataStart = $lFileContents | Select-String -Pattern "^#", "^$" -NotMatch `
| select-object -First 1
# We have a section.
if ( $PSBoundParameters.ContainsKey( 'SectionName' ) ) {
# Find the section.
$lFoundSection = $lSections | Select-String -Pattern "$lSectionName\b"
# If none found we are out.
if ( -Not $lFoundSection) { return $lRetValue }
# Starting point for the key search is the line following
# the found section.
$lStart = $lFoundSection[0].LineNumber
# Loop through the sections and find the one after the found one.
$lNextSection = $lSections | ForEach-Object {
# If we hit it, break.
if ($_.LineNumber -gt $lStart) {
break;
}
}
# Set the ending line for the search to the end of the section
# or end of file. Which ever we have.
if ($lNextSection) {
$lEnd = $lNextSection[0].LineNumber
} else {
$lEnd = $lFileContents[-1]
}
} else {
# No section.
$lStart = $lDataStart.LineNumber
# Set the ending line for the search to the end of the section
# or end of file. Which ever we have.
if ($lSections) {
$lEnd = $lSections[0].LineNumber
} else {
$lEnd = $lFileContents[-1]
}
}
# Extract the lines starting with the key.
$lResults = $lFileContents[$lStart..$lEnd] -match "$Key\b"
# We got results.
# Split the value off.
return $lRetValue = $lResults[0] | Select -ExpandProperty "Line"
}
The process of creating this function has sparked several questions that I have researched and become confused with
1) The documentation indicates that $args should be used to determine arguments. It never seems to populate for me? I am using version 4? As a alternative I used $PSBoundParameters. Is this advisable?
2) Based on a lot of reading and head scratching, I have found that return values from functions rturn all uncaptured output to the pipeline. Can someone, please clarify uncaptured?
As an example, I would like the function below to return a string in the variable $lRetValue. Currently, it is returning True. Based on that I believe I have something uncaptured? But everything I am executing is captured in a variable. What am I missing?
The calling routine is calling the code in the following form:
$FileName = "S:\PS\Home\GlobalConfig\jobs.cfg"
$key = "Help"
$section = "Section"
$r = plGetKeyValue $FileName $Key
write-host "r is: $r"
The output shows as follows:
PS C:> S:\PS\Home\Job\Test.ps1
r is: True
Any assistance would be very much appreciated.
Terminology note: somewhat arbitrarily, I'll distinguish between parameters and arguments below:
- parameters as the placeholders that are defined as part of a function declaration,
- as distinct from arguments as the values that are bound to the placeholders in a given invocation.
Conceptual information:
1) The documentation indicates that $args should be used to determine arguments.
$args is a fallback mechanism for examining unbound arguments in non-advanced (non-cmdlet) functions.
$args is populated:
ONLY if your function is not an advanced function (a function is marked as an advanced function by the presence of a param(...) parameter-declaration statement - as opposed to declaring the parameters inside function someFunc(...)) - if decorated with a [CmdletBinding()] attribute).
even then it only contains the unbound arguments (those not mapped to declared parameters).
In other words: only if you declare your function without any parameters at all does $args contain all arguments passed.
Conversely, in an advanced function there mustn't be unbound arguments, and invoking an advanced function with arguments that cannot be bound to parameters simply fails (generates an error).
Since defining advanced functions is advisable in general, because they are best integrated with the PowerShell infrastructure as a whole, it's best to make do without $args altogether.
Instead, use a combination of multiple parameter sets and/or array parameters to cover all possible valid input argument scenarios.
$PSBoundArguments contains the arguments bound to declared parameters, and is normally not needed, because the variable names corresponding to the parameters names (e.g., $SectionName) can be used directly. (It has specialized uses, such as passing all bound parameters on to another cmdlet/function via splat #PSBoundArguments).
2) Based on a lot of reading and head scratching, I have found that return values from functions return all uncaptured output to the pipeline. Can someone, please clarify "uncaptured"?
Generally, any PowerShell statement or expression that generates output is sent to the success stream (loosely comparable to stdout in Unix shells) by default, UNLESS output is captured (e.g., by assigning to a variable) or redirected (e.g., by sending output to a file).
Thus, in a reversal of how most programming languages behave, you must take action if you do NOT want a statement to produce output.
If you're not interested in a statement's output (as opposed to capturing / redirecting it for later use), you can redirect to $null (the equivalent of /dev/null), pipe to cmdlet Out-Null, or assign to dummy variable $null ($null = ...).
Therefore, in a manner of speaking, you can call output that is sent to the success stream uncaptured.
That, however is unrelated to the return statement:
The return statement does not work the same way as in other languages; its primary purpose in PowerShell is as a control-flow mechanism - to exit a function or script block - rather than a mechanism to output data (even though it can also be used for that: with an argument, is another way to send output to the success stream).
Diagnosing your specific problem:
There are many ways in which your function could be made a better PowerShell citizen[1]
, but your immediate problem is this:
$PSBoundParameters.Remove('SectionName')
returns a Boolean value that is sent to the output stream, because you neither suppress, capture nor redirect it. In your case, since the $SectionName parameter is bound, it does have an entry in $PSBoundParameters, so $PSBoundParameters.Remove('SectionName') returns $true.
To suppress this unwanted output, use something like this:
$null = $PSBoundParameters.Remove('SectionName')
Generally speaking, unless you know that a statement does not generate output, it's better to be safe and prepend $null = (or use an equivalent mechanism to suppress output).
Especially with direct method calls on objects, it's often not clear whether a value - which turns into output (is sent to the success stream) - will be returned.
[1] The following help topics provide further information:
- USE of parameters, including how to inspect them with help -Full / -Detailed ...:
help about_Parameters
- DEFINING simple functions and their parameters:
help about_functions,
from which you can progress to advanced functions:
help about_functions_advanced
and their parameter definitions:
help about_Functions_Advanced_Parameters
I've learned from this Stack Overflow question, that PowerShell return semantics are different, let's say, from C#'s return semantics. Quote from the aforementioned question:
PowerShell has really wacky return semantics - at least when viewed from a more traditional programming perspective. There are two main ideas to wrap your head around: All output is captured, and returned.
The return keyword really just indicates a logical exit point.
Let's look at this example:
function Calculate
{
echo "Calculate"
return 11
}
$result = Calculate
If you echo $result you will realise that something is not right. You'd expect this:
11
But the reality, what you actually see, is different:
Calculate
11
So instead of getting back only the intended return value, you actually get back an array.
You could get rid of the echo statements and not polluting the return value, but if you call another function from your function, which echoes something, then you're in trouble again.
How can I write a PowerShell function that only returns one thing? If the built-in PowerShell functions do return only one value, why can't I do that?
The workaround that I'm using now and I'd love to get rid of:
function Calculate
{
# Every function that returns has to echo something
echo ""
return 11
}
# The return values is the last value from the returning array
$result = (Calculate)[-1]
You can also just assign everything to null, and then return just the variable you want:
Function TestReturn {
$Null = #(
Write-Output "Hi there!"
1 + 1
$host
$ReturnVar = 5
)
return $ReturnVar
}
Several answers already given do not fully answer your question because they do not account for other cmdlets you might call--as you point out--that might "pollute" your output. The answer from #Laezylion is essentially correct but I believe bears further elaboration.
It is clear that you appreciate that your current workaround--forcing every function to return an array then taking the last element--is not a very robust solution. (In fact, I think it is safe to call that a kludge. :-) The correct approach--and a direct answer to your question--is clear... though at first glance it sounds like a tautology:
Question: How do you ensure a function returns only one thing?
Answer: By ensuring that it returns only one thing.
Let me elucidate. There are really two kinds of functions/cmdlets in PowerShell: (A) those that return data and (B) those that do not return data but may instead report progress or diagnostic messages. Problems arise, as you have seen, when you try to mix the two. And this may easily happen inadvertently. Thus, it is your responsibility, as the function author, to understand each function/cmdlet call within your function: specifically, does it return anything, be it a true return value or just diagnostic output? You are expecting output from type A functions, but you need to be wary of any type B functions. For any one that does return something you must either assign it to a variable, feed it into a pipeline, or... make it go away. (There are several ways to make it go away: pipe it to Out-Null, cast it to void, redirect it to $null, or assign it to $null. See Jason Archer’s Stack Overflow post that evaluates the performance of each of these flavors, suggesting you shy away from Out-Null.)
Yes, this approach takes more effort, but you get a more robust solution by doing so. For a bit more discussion on this very issue, these A/B functions, etc. see Question 1 on A Plethora of PowerShell Pitfalls recently published on Simple-Talk.com.
Don't use echo to write information, use Write-Host, Write-Verbose or Write-Debug depending on the message.
Echo is an alias for Write-Output which will send it as an Object through the pipeline. Write-Host/Verbose/Debug however is only console-messages.
PS P:\> alias echo
CommandType Name ModuleName
----------- ---- ----------
Alias echo -> Write-Output
Sample:
function test {
Write-Host calc
return 11
}
$t = test
"Objects returned: $($t.count)"
$t
#Output
calc
Objects returned: 1
11
Also, if you return the value on the last line in your function, then you don't need to use return. Writing the Object/value by itself is enough.
function test {
Write-Host calc
11
}
The difference is that return 11 would skip the lines after it you use it in the middle of a function.
function test {
return 11
12
}
test
#Output
11
Worth mentioning:
Any unmanaged command output inside your function will end up as a return value.
I use to get this trouble with a function managing XML content:
Function Add-Node(NodeName){
$NewXmlNode = $Xml.createElement("Item")
$Xml.Items.appendChild($NewXmlNode) | out-null
}
If you remove the Out-Null, the return of your function will be the Node basic properties... (You can also manage the exit code of the appendChild command ... it depends on the motivation) :)
#Michael Sorens's answer is useful, but it suggests a design strategy that seems rather onerous. I don't want to have to separate out data processing functions from functions that report progress or diagnostic messages. Reading his blogpost, I found a less hacky work-around to the OP's question. Here's the key sentence from the blog post:
A PowerShell function returns all uncaptured output.
So what if we capture our output?
function Calculate
{
$junkOutput = echo "Calculate"
return 11
}
$result = Calculate
Now $result just contains 11, as intended.
You could replace echo (alias of Write-Output) with Write-Host:
PS> function test{ Write-Host "foo";"bar"}
PS> $a = test
test
PS >$a
bar
echo is an alias for Write-Output which sends the object to the next command.
Using Write-Host should help:
PS:> function Calculate
>> {
>> # Every function that returns has to echo something
>> Write-Host "test"
>> return 11
>> }
>>
PS:> $A = Calculate
test
PS:> $A
11
The use of parenthesis seems critical when calling a function that accepts parameters.
This example fills a DataTable from SQL Server, and returns an [int] from the first row, fourth column.
Note the parenthesis around the actual function call assigned to the variable [int]$tt1
function InvokeSQL-GetOneCount { param( [string]$cn, [string]$prj )
$sql = "SELECT * FROM [dbo].[dummytable] WHERE ProjectNumber = '$prj' ORDER BY FormID, PartID;"
$handler = [System.Data.SqlClient.SqlInfoMessageEventHandler] { param($sender, $event) Handle-Message -message $event.Message -fcolor "yellow" -bcolor "black"; };
$conn = new-Object System.Data.SqlClient.SqlConnection($cn)
$conn.add_InfoMessage($handler);
$conn.FireInfoMessageEventOnUserErrors = $true;
$cmd = New-Object System.Data.SqlClient.SqlCommand;
$cmd.Connection = $conn;
$cmd.CommandType = [System.Data.CommandType]::Text;
$cmd.CommandText = $sql;
$cmd.CommandTimeout = 0;
$sa = New-Object System.Data.SqlClient.SqlDataAdapter($cmd);
$dt = New-Object System.Data.DataTable("AllCounts");
$sa.Fill($dt) | Out-Null;
[int]$rval = $dt.Rows[0][3];
$conn.Close();
return $rval;
}
clear-host;
[int]$tt1 = (InvokeSQL-GetOneCount -cn "Server=[your server];DataBase=[your catalog];Integrated Security=SSPI" -prj "MS1904");
write-host $tt1;
I ended up using the following to make sure only one value is returned:
write-host 'some console message'
invoke-some-utility arg1 arg2 | write-host
functionCall arg1 arg2 | out-null # suppress any output
return theDesiredValue
PowerShell does pipes awkwardkly. To work around the return value problem and save the pipeline for real data, pass the function a value by reference, that is, an array. The array can be loaded with the value you wish to return. Here's a simple example:
# tp.ps1
# test passed parameters
# show that arrays are passed by reference, and can be used to provide
# return values outside the pipeline
function doprint
{
process { write-output "value now: $psitem" }
}
function recurse($thing, $rtx)
{
$thing++
if($thing -lt 20) {
if($thing -eq 15) { $rtx[0] = $thing }
write-output $thing | doprint
recurse $thing $rtx
}
}
j=0
$rtv=#(4)
recurse $j $rtv
write-output $rtv[0]
I was surprised how powershell return works. Because I never had to write a function which returns a value. It returns not the variable itself, but all output stream of the function. To not pass output, you would have to use Out-Null. So your example would be:
function Calculate
{
. {
echo "Calculate"
$result = 11
return
} | Out-Null
return $result
}
$result = Calculate
And result is:
11
Credits to https://riptutorial.com/powershell/example/27037/how-to-work-with-functions-returns
My script is populating a datarow from a stored procedure in SQL Server. I then reference specific columns in this datarow throughout the script. What I'm trying to do is add functionality that takes action X if the row count = 0, action Y if the row count = 1, and action Z if the row count > 1.
-- PowerShell script snippet
# $MyResult is populated earlier;
# GetType() returns Name=DataRow, BaseType=System.Object
# this works
ForEach ($MyRow In $MyResult) {
$MyFile = Get-Content $MyRow.FileName
# do other cool stuff
}
# this is what I'm trying to do, but doesn't work
If ($MyResult.Count -eq 0) {
# do something
}
ElseIf ($MyResult.Count -eq 1) {
# do something else
}
Else {
# do this instead
}
I can get $MyResult.Count to work if I'm using an array, but then I can't reference $MyRow.FileName directly.
This is probably pretty simple, but I'm new to PowerShell and object-oriented languages. I've tried searching this site, The Scripting Guy's blog, and Google, but I haven't been able to find anything that shows me how to do this.
Any help is much appreciated.
It has everything to do with how you populate $MyResult. If you query the database like
$MyResult = #( << code that returns results from database >> )
that is, enclosing the code that returns your dataset/datatable from the database within #( ... ), then number of rows returned will be easily checked using $MyResult.count.
Your original code should work as-is if you populate $MyResult this way.
I know this thread is old, but if someone else finds it on Google, this should work also on PS V5:
Replace $MyResult.Count with: ($MyResult | Measure-Object | select -ExpandProperty Count)
For Example:
If (($MyResult | Measure-Object | select -ExpandProperty Count) -eq 0)
I don't have experience with PS and SQL, but I'll try to provide an answer for you. If you're object $myresult is a datarow-object, it means you only got the one row. If the results are empty, then $myresult will usually be null.
If you get one or more rows, you can put them in an array and count it. However, if your $myresult are null, and you put it in an array it will still count as one, so we need to watch out for that. Try this:
If ($MyResult -eq $null) {
# do something if no rows
}
Else If (#($MyResult).Count -eq 1) {
# do something else if there are 1 rows.
# The cast to array was only in the if-test,
# so you can reach the object with $myresult.
}
Else {
# do this if there are multiple rows.
}
Looks like this question gets a lot of views, so I wanted to post how I handled this. :)
Basically, the fix for me was to change the method I was using to execute a query on SQL Server. I switched to Chad Miller's Invoke-SqlCmd2 script: TechNet: Invoke-SqlCmd2, i.e.
# ---------------
# this code works
# ---------------
# Register the function
. .\Invoke-Sqlcmd2.ps1
# make SQL Server call & store results to an array, $MyResults
[array]$MyResults = Invoke-Sqlcmd2 -Serve
rInstance "(local)" -Query "SELECT TOP 1 * FROM sys.databases;"
If ($MyResult -eq $null) {
# do something
}
ElseIf ($MyResult.Count -eq 1) {
# do something else
}
Else {
# do this instead
}