Function containing a process is returning a garbled value - function

Spent my whole morning trying to find where my return value was getting garbled. Now that I've finally found where, I still have no idea why. Function looks like this:
function Run-RemoteCommand {
param(...) # params are $Remote (host) $Command $Credentials $Quiet (optional switch)
if($Quiet) {
$Process = New-Object System.Diagnostics.Process
$Process.StartInfo.UseShellExecute=$false
$Process.StartInfo.Domain=$Credentials.GetNetworkCredential().Domain
$Process.StartInfo.UserName=$Credentials.GetNetworkCredential().UserName
$Process.StartInfo.Password=$Credentials.Password
$Process.StartInfo.WindowStyle="Hidden"
$Process.StartInfo.FileName=$PSExec
$Process.StartInfo.Arguments=#("/acceptEULA",$Remote,"-s",$Command)
$Process.Start()
$Process.WaitForExit()
$result = $Process.ExitCode
return $result
} else {
...
}
}
What's odd is that I can step through this in a debugger and watch everything work fine. The command runs, $result is filled with the return code, but the calling function receives True appended to the return code (eg True0 on success). I even tried overriding the return value and just saying
return "false"
The calling function receives "Truefalse." All I can tell is that it's tied to $Process running. If I comment out $Process.Start(), the return code functions normally. Someone please save my sanity.

$Process.Start() returns a boolean value which is True if it succeeds. Remember that functions in PowerShell behave differently than standard programming languages. PowerShell functions "return" or more technically correct "output" any command output that isn't captured by a variable or redirected to a file or Out-Null. In this case change the Start line to:
[void]$Process.Start()
or
$Process.Start() | Out-Null
Check out this blog post for a deeper explanation.

Related

Retrieving A Function From A WebhookScript Global Variable

In WebhookScript, I can store a function in a variable with:
sub = function(a, b) {
return a - b
}
I'd like to store a function in a Global Variable so that I can use it in multiple Custom Actions. But if I've saved the above function as $sub$ then
sub2 = var('$sub$')
subX = sub(1,2)
causes an error:
Trying to invoke a non-function 'string' # line...
And
function subX(a,b){
var('$sub$')
}
when sub only contains return a - b, doesn't work either.
Obviously I need to convert the string to a function but I'm not sure whether that's possible.
I know this is a bit of an obscure language but if anyone knows how this can be done in similar languages like JavaScript and PHP, I'm happy to test out any guesses...
The solution here is to remove the function section and just enter the script, which inherits the execution scope so if my global variable $script$ is:
return 'hello ' + a
Then I can execute the function with:
a = 'world'
value = exec(var('$script$'))
echo(value)
(credit to Webhook.Site's support team for explaining this)

Return variable from one function to another in powershell

I am inside function #1 and triggering function #2. Function #2 has a variable that I want to get back into function #1 and use it.
My output ends up being:
hey there
var is:
What I want is the output to be:
var is: hey there
Why is it that I can feed a function a variable, and it uses it, but when I change that variable in the #2 function, it does not change the variable after it returns?
$var = $null
function one() {
two($var)
write-host "var is:" $var
}
function two($var){
$var = "hey there"
return($var)
}
clear
one
First, change your two function to actually return a value:
function two {
$var = "hey there"
return $var
}
and then update the one function to actually "capture" the output value by assigning it to a variable:
function one {
# PowerShell doesn't use parentheses when calling functions
$var = two
Write-Host "var is:" $var
}
If you really do want to reach up and change a variable in the scope of your caller, you can...
Set-Variable -Name $Name -Value $Value -Scope 1
It's a little meta/quirky but I've run into cases where it seemed proper. For example, I once wrote a function called RestoreState that I called at the beginning of several functions exported from a module to handle some messy reentrant cases; one of the things it did is reach up and set or clear $Verbose in the calling function's scope.

How to implement a basic Lua function in Conky?

I am trying to add a function to my Conky which prints the length of a string for debug purposes. The code, inside a file called test.lua, is pretty trivial:
function test(word)
return string.len(word)
end
...and I load it like this. In my conky.config section I have:
lua_load = '/home/xvlaze/test.lua',
lua_draw_hook_pre = 'test'
...in the conky.text section I have:
${lua test "fooo"}
...where test is the name of the function and fooo the string to test.
The expected result should be a printed 4 in Conky, but instead of that I get:
conky: llua_do_call: function conky_test execution failed: /home/xvlaze/test.lua:2: attempt to index a nil value (local 'string')
conky: llua_getstring: function conky_test didn't return a string, result discarded
I have browsed through the documentation, but I can't find anything. Does anybody know where the failure is?
Several guidances on how to implement functions in Conky:
First of all: YOU MUST USE conky_ BEFORE YOUR FUNCTION'S NAME.
Otherwise, you will get the following error when running your Conky:
attempt to call a nil value
Secondly: YOU MUST ALWAYS RETURN A VALUE.
I don't mind repeating it - it is crucial. Otherwise, you will get:
function foobar didn't return a string, result discarded
function_result
...in your terminal, and your Conky will be left empty of values related to your extra code. Nothing will be printed regarding your function.
Last but not least: YOU MUST ALWAYS CALL YOUR FUNCTION LIKE:
lua_load = '/path/to/function.lua',
-- Whatever content...
${lua function_name function_parameter1 function_parameterN} -- In case you use more than one parameter.
In summary, a dummy function template could be:
MAIN FILE (conky.conf):
conky.config = {
-- Whatever content... Lua styled comments.
lua_load = '/path/to/function.lua',
}
conky.text = [[
# Whatever content... In this section comments are started with '#'!
${lua function_name parameter}
]]
FUNCTION FILE:
function conky_function_name(parameter)
-- Whatever content... Remember this is Lua, not conky.text syntax. Always use '--' comments!
return whatever -- No return, no party. A function MUST always return something!
end

Strange behaviour from MySQL in Powershell

I'm new to PowerShell and have a specific question about working with MySQL in PowerShell.
I got this function:
Function run-mySQLInsertQuery{
param(
$connection,
[string[]]$insertQuery
)
foreach ($command in $insertQuery){
$MySQLCommand = $connection.CreateCommand()
$MySQLCommand.CommandText = $command
$rowsInserted = $MySQLCommand.ExecuteNonQuery()
if ($rowsInserted) {
return $rowsInserted
} else {
return $false
}
}
}
With this version of the function i get the following Error:
Cause:
"The CommandText property has not been properly initialized."
Errorline:
$rowsInserted = $MySQLCommand.ExecuteNonQuery()
I searched for a solution and edited my function a bit to the following (for testing purpose):
Function run-mySQLInsertQuery{
param(
$connection,
[string[]]$insertQuery
)
$abcd = $insertQuery[1]
foreach ($command in $insertQuery){
$MySQLCommand = $connection.CreateCommand()
$MySQLCommand.CommandText = $abcd
$rowsInserted = $MySQLCommand.ExecuteNonQuery()
}
}
With this code, the function executes the query without a problem. My question now is, why? i cant really see a difference, because in $command should be the exact same query like it is in $abcd. Or am I getting something wrong?
EDIT:
As its asked it the comments, here is how i call the function:
[String[]]$statements = ""
foreach($key in $arrayStatus.Keys){
$item = $arrayStatus[$key]
$insertStatus = "INSERT INTO tx_tphbusinessofferings_domain_model_status (status_id, status) VALUES ('$key', '$item')"
$statements += $insertStatus
}
$Rows = run-mySQLInsertQuery -connection $mySQLconnection -insertQuery $statements
The problem is that you are initializing your array (the one you are passing in) with an empty string:
[String[]]$statements = ""
And then adding elements to it... so your first iteration of the passed array is an empty string, which won't work (it'll set the command text as empty, that's the error you are getting). It works on the second code because you are grabbing the second object of the array (which is your insert statement).
Initialize your array to empty and it should work:
[String[]]$statements = #()
Apart from that, your first script always returns on the first iteration, so it'll only work once (not for every insert you pass). Not sure what do you want to return if you are passing in more than one query, but that's up to your design decisions

Powershell json RESTful api - Conditional Statement

Currently, I am attempting to write a conditional statement that states the following
If($JSON.response = false){
'Dont do anything and continue to the next block of code.'
}
Right now the JSON returns like this when there is no data:
response_code response
------------- --------
0 {}
This is what I have so far:
If($json.response = 0){
'Dont do anything here'
}elseif($json.response = 1){
'Do the code'
}
I'd like to add that response_code is always equal to 0 when the response is error free as in status code 200. However, when there are no fields returned response is just an empty hashtable.
Do you really want to be testing json.response rather than json.response_code? The numeric comparison suggests that you should be testing json.response_code.
Also, if json is a structure that is stored in a variable, you should be testing it as $json.response_code - note the $ - and using the -eq comparison operator as #JamesC. noted.
Finally, unless you're likely in the future to change what you do in the event that $json.response_code is zero, just drop that test entirely, and only test for $json.response_code values where you actually do something.
I found the answer since the object is an array it was best to roll out like this.
If($json.object.Count -eq 0){
'dont do the code'
}Else{
'Do the code'}