Command not working with variable in Powershell [duplicate] - powershell

This question already has answers here:
Using a Variable (PowerShell) inside of a command
(2 answers)
Closed 1 year ago.
I have looked at similar questions and not finding answers that apply here. I have also been reading and digging around on learn.microsoft.com. Apologies if this is answered before and I could not locate it.
A geolocation API with a CLI is not working when I feed it a variable in Powershell.
The command: (site, API key and IP are changed for this post)
curl.exe 'https://api.xyz.com/ipgeo?apiKey=XXXX&ip=4.3.2.1'
The script as I have it:
[string]$lookup = $Args[0]
echo $lookup
echo "$lookup"
curl.exe 'https://api.xyz.com/ipgeo?apiKey=XXXX&ip="$lookup"'
I run it from powershell with geo 4.3.2.1
At first I did not use the [string] variable type notation but after it was not working and I did some reading on learn.microsoft.com
I realized I wanted this treated as a string so I added that.
The echo statements are just me checking how the variable is being handled and will be removed from final script. Both of them display the IPv4 address properly.
I have tried the script originally with
curl.exe 'https://api.xyz.com/ipgeo?apiKey=XXXX&ip=$lookup'
then added the double quotes around variable. Neither work.
If I edit the line in the script, and put an IPv4 address in there and run it, it outputs properly, so I know it is not the API or the command for it, it is how the variable is being passed from powershell.
When the variable is used I get an error from the API.
I have tried this in older powershell, and today installed powershell 7.2 and get same result.

'https://api.xyz.com/ipgeo?apiKey=XXXX&ip=$lookup'
'https://api.xyz.com/ipgeo?apiKey=XXXX&ip="$lookup"'
Looks like you are passing it literally. Try double-quotes outside, single inside.
"https://api.xyz.com/ipgeo?apiKey=XXXX&ip='$lookup'"
Edit: Variable expansion in strings and here-strings
https://devblogs.microsoft.com/powershell/variable-expansion-in-strings-and-here-strings/

Related

How can I use dot sourcing to run code from a variable in the same instance? [duplicate]

This question already has answers here:
Are these alternatives to Invoke-Expression really any safer? And why?
(1 answer)
Powershell reevaluate string to array
(1 answer)
Closed 4 months ago.
I have a variable that stores a command that I would like to execute.
ex:
$C = "echo 'test'"
I have one way to execute this by using the following:
powershell .($C)
however this opens a new instance of powershell. How can I go about executing that code in the same instance? I can't seem to find a way to use dot sourcing without opening that second instance.
EDIT: I can not use IEX

Strange powershell behaviour with script blocks and regex replace

I'm trying to use [regex]::Replace with a match evaluator to selectively replace parts of a string. I'm writing and debugging the function in PowerShell ISE. What is strange is that running the replacement code causes one machine to output a string that is the content of the match evaluator script block while the other replaces the text correctly. I had no clue this was even possible nor why it is happening.
Given this code (borrowed from another stackoverflow answer):
$global_counter = 0
$callback = {
$global_counter += 1
"string-$($args[0])-" + $global_counter
}
$re = [regex]"match"
$re.Replace('zzz match match xxx', $callback)
Executing it on one machine causes the output (PowerShell Version 5.1.18362.145):
zzz string-match-1 string-match-1 xxx
But on another it outputs (PowerShell Version 5.1.17134.858):
zzz
$global_counter += 1
"string-$($args[0])-" + $global_counter
$global_counter += 1
"string-$($args[0])-" + $global_counter
xxx
Both are running in an x64 PowerShell ISE clean instance directly from reboot. Does anyone know why this is happening?
With debugging help from Jeroen I've managed to figure out why this is happening.
PowerShell has a security feature called Constrained Language Mode that prevents the use of any, but a core set of whitelisted types. What appears to be happening is that I'm defining a scriptblock that in turn is converted to a System.Text.RegularExpressions.MatchEvaluator before being passed to the Replace function. The match evaluator however is outside of this core set of types which means when the PowerShell engine tries to coerce the type onto an overload of Replace the only other valid one is Replace(string, string, string) (thanks Jeroen for pointing this out in the comments). The Replace function does its job, but with a regular string as a replacement thus resulting in the odd behaviour.
I'm not able to alter the language mode of my PowerShell session on the machine I'm currently working with as it is applied through Group Policies, but a workaround for me at least was to use an elevated PowerShell session and ISE to test my script.

Manage inputs from external command in a powershell script

First, I would like to apologize in case that the title is not descriptive enough, I'm having a hard time dealing with this problem. I'm trying to build an automation for a svn merge using a powershell script that will be executed for another process. The function that I'm using looks like this:
function($target){
svn merge $target
}
Now, my problem occurs when there are conflicts in the merge. The default behavior of the command is request an input from the user and proceed accordingly. I would like to automatize this process using predefined values (show the differences and then postpone the merge), but I haven't found a way to do it. In summary, the workflow that I am looking to accomplish is the following:
Detect whether the command execution requires any input to proceed
Provide a default inputs (in my particular case "df" and then "p")
Is there any way to do this in powershell? Thank you so much in advance for any help/clue that you can provide me.
Edit:
To clarify my question: I would like to automatically provide a value when a command executed within a powershell script require it, like in the following example:
Requesting user input
Edit 2:
Here is a test using the snippet provided by #mklement0. Unfortunately, It didn't work as expected, but I thought it was wort to add this edition to clarify the question per complete
Expected behavior:
Actual result:
Note:
This answer does not solve the OP's problem, because the specific target utility, svn, apparently suppresses prompts when the process' stdin input isn't coming from a terminal (console).
For utilities that do still prompt, however, the solution below should work, within the constraints stated.
Generally, before attempting to simulate user input, it's worth investigating whether the target utility offers programmatic control over the behavior, via its command-line options, which is both simpler and more robust.
While it would be far from trivial to detect whether a given external command is prompting for user input:
you can blindly send the presumptive responses,
which assumes that no situational variations are needed (except if a particular calls happens not to prompt at all, in which case the input is ignored).
Let's assume the following batch file, foo.cmd, which puts up 2 prompts and echoes the input:
#echo off
echo begin
set /p "input1=prompt 1: "
echo [%input1%]
set /p "input2=prompt 2: "
echo [%input2%]
echo end
Now let's send responses one and two to that batch file:
C: PS> Set-Content tmp.txt -Value 'one', 'two'; ./foo.cmd '<' tmp.txt; Remove-Item tmp.txt
begin
prompt 1: one
[one]
prompt 2: two
[two]
end
Note:
For reasons unknown to me, the use of an intermediate file is necessary for this approach to work on Windows - 'one', 'two' | ./foo.cmd does not work.
Note how the < must be represented as '<' to ensure that it is passed through to cmd.exe and not interpreted by PowerShell up front (where < isn't supported).
By contrast, 'one', 'two' | ./foo does work on Unix platforms (PowerShell Core).
You can store the SVN command line output into a variable and parse through that and branch as you desire. Each line of output is stored into a new enumerator (cli output stored in PS variables is in array format)
$var = & svn merge $target
$var

calls to cmd from powershell not parsing correctly?

I am trying to run cURL.exe from powershell as part of a larger script to create various user accounts as new individuals are onboarded.
(I cannot use invoke-method or invoke-webrequest because the header parameter wont accept a string)
The issue is that I can run it from a cmd window perfectly but I cannot seem to make the same thing run from powershell:
curl.exe -H "Authorization: {\"apiKey\":\"ResetAPIKey,\"username\":\"admin\"}" -d "username=someUserName&email=somebody#domain.com&firstName=Joe&lastName=Friday" "http://URL:8080/v1/users/create"
This runs just fine from cmd but when attempting to run from powershell, I get errors like 'url not found' or 'That path/method is not supported'
Additional format attempts:
encasing the whole thing in single quotes
replacing each /" (forward slash + double quote) with `" (backtick + double quote)
adding all the arguments to a here-string variable
variations of above
I would assume I can write it to a .bat file and then run that from powershell but I'd rather not be forced to do that if possible
The stop parsing parameter is a good choice for this type of thing.
The stop-parsing symbol (--%), introduced in Windows PowerShell 3.0,
directs Windows PowerShell to refrain from interpreting input as
Windows PowerShell commands or expressions.
In your case though you need something a little different as you want variables in the mix that need to be resolved.
I figured there would be a dupe for this. Most of those answer are about converting curl.exe to something like Invoke-WebRequest which is something you should look into. In this case, if you have dynamic content use the call operator like this.
$arguments = "-H ""Authorization: {\""apiKey\"":\""ResetAPIKey,\""username\"":\""admin\""}"" -d ""username=someUserName&email=somebody#domain.com&firstName=Joe&lastName=Friday"" ""http://URL:8080/v1/users/create"""
&"curl.exe" $arguments
Noticed I doubled up the inner quotes on the string. If you look at the variable after it would display properly. Now you should be able to make changes.
Passing complex command line to native application from PowerShell can be tricky. PowerShell can add extra quotes in some cases. Although, rules for this are not that complex, but them are not well (if at all) documented, and also there is some substantial changes in that rules in v2-v4 vs v5. IMHO, using stop parsing operator --%, as #Matt offered, is the best approach, in case you targeting on v3+.
Stop parsing operator does not limit you to use literal strings only. You still can use variables with it. That operator expand environment variables in CMD syntax: %VariableName%. So you can assign required values to some environment variables and use them in command line:
$Env:Env_UserName='someUserName'
$Env:Env_Email='somebody#domain.com'
$Env:Env_FirstName='Joe'
$Env:Env_LastName='Friday'
curl.exe --% -H "Authorization: {\"apiKey\":\"ResetAPIKey,\"username\":\"admin\"}" -d "username=%Env_UserName%&email=%Env_Email%&firstName=%Env_FirstName%&lastName=%Env_LastName%" "http://URL:8080/v1/users/create"
Other variant will be to generate full arguments line, you want to pass to native application, and than pass it in single environment variable:
$Arguments=...
$Env:Env_Arguments=$Arguments
curl.exe --% %Env_Arguments%
Matt's answer with the call operator looks like it should work, but if it's not there's a similar alternative I've had good luck with before. Instead of passing your arguments as a string, you can pass them as an array and PowerShell will handle them correctly. In your case, it'd look something like this:
$arguments = #("-H", 'Authorization: {\"apiKey\":\"ResetAPIKey,\"username\":\"admin\"}', "-d", '"username=someUserName&email=somebody#domain.com&firstName=Joe&lastName=Friday"', 'http://URL:8080/v1/users/create')
& "curl.exe" $arguments

Powershell remove quotes when start process

Let's look at the code below
$SBK="0x1682CCD8 0x8A1A43EA 0xA532EEB6 0xECFE1D98"
./windows/nvflash/nvflash.exe --sbk 0x1682CCD8 0x8A1A43EA 0xA532EEB6 0xECFE1D98
./windows/nvflash/nvflash.exe --sbk "0x1682CCD8 0x8A1A43EA 0xA532EEB6 0xECFE1D98"
./windows/nvflash/nvflash.exe --sbk $SBK
I have define a string var $SBK and then I'm going to pass it for some app. The first process call is working properly. The second one fails and therefore application doesn't accepts quotes. But the third call is failed too with the same error. It seems that powershell passes quotes, those are causing errors. But how to eliminate them? Thanks beforehand.
Try doing
iex "./windows/nvflash/nvflash.exe --sbk $SBK"
Also, get echoargs.exe from PowerShell Community Extensions to see how args are passed from Powershell to commands etc.
You should probably not use Invoke-Expression (see This Post from the PowerShell Team)
Instead, you can create an array of arguments, and then pass them using the call operator. See this post of mine on the subject for more details.
In your case, it would look something like this:
$SBKArgs="--sbk", "0x1682CCD8", "0x8A1A43EA", "0xA532EEB6", "0xECFE1D98"
$cmd = Get-Command ./windows/nvflash/nvflash.exe
& $cmd $sbkargs
Hope this Helps