How can I execute this line of code in the run box? - powershell

I have the following line of code that I use to download and combine dns text records from my website and execute them in powershell. I can run this command just fine from the console but can not figure out how to effectively run it from the run box (win+r)
1..3|%{$p+=Resolve-DnsName "$_.website.com." -Ty TXT -EA 0|% S*s};& ([scriptblock]::Create($p))
Below is a simplified version I use to pull down and execute a single dns text record using a single word instead of iterating through through numbers and combining them.
powershell . (nslookup -q=txt example.website.com)[-1]
The above simplified version works fine from the console but in order for it to work in the run box it has to be modified as seen below:
powershell "powershell . (nslookup -q=txt sub.website.com)[-1]"
I can not seem to find a way to modify that first example in a way that allows me to execute it from the run box. Doing something like the example below errors out. I have tried about 20 variations of the code below with no success
powershell .(1..3|%{$p+=Resolve-DnsName "$_.website.com." -Ty TXT -EA 0|% S*s};& ([scriptblock]::Create($p)))

Try the following:
powershell 1..3|%{$p+=Resolve-DnsName \"$_.website.com.\" -Ty TXT -EA 0|% S*s};& ([scriptblock]::Create($p)))
The crucial change is to escape the " chars. as \", so that PowerShell considers them part of the command to execute.
See this answer for more information.
There's no reason to use . (...) for execution - just use ... directly, as shown.
Note that the above command only works from no-shell environments such as the Windows Run dialog (WinKey-R) - to execute it from cmd.exe, you'd need additional quoting or escaping.

Related

code --diff fails when filename contains an ampersand '&'

I am experiencing a rather puzzling error while trying to perform a diff on two files using Visual Studio Code from the command line. I have a text file in the cloud where I save some work related notes. I need to resolve conflicts with other clients editing the file. Usually this only happens during a loss of connection though somehow I find myself having to resolve a lot of them so between this and other uses of diff I will use the usual syntax. It looks something like this:
code --diff "R&D (cloud conflict 2-5-23).txt" "R&D.txt"
My filename happens to have a '&' in it and this command launches the usual 2-way diff in VS Code and reads through the first file name with no problem but doesn't read past the second '&' and the resulting diff tab in VS Code looks something like:
R&D (cloud conflict 2-25-23).txt <-> R
Where the right side "R" doesn't exist. So it would seem '&' needs to be processed literally.
No problem, let's see if backslash \ is an accepted escape parameter...
code --diff "R\&D (cloud conflict 2-5-23).txt" "R\&D.txt"
Nope. Same problem. 🤔 In fact this outputs something even stranger:
Code diff tab:
&D (cloud conflict 2-25-23).txt <-> R
with shell output:
'D.txt' is not recognized as an internal or external command, operable program or batch file.
I also tried the carrot symbol '^' as an escape parameter to a similar effect. I just includes it in the first file and the editor still thinks the second file name is just "R".
The help file for the VS Code command line integration didn't have a lot to say about the --diff parameter other than a short description and I was hoping to get something about processing strings literally or escape characters. Perhaps another parameter that I need or maybe this has more to do with the shell in general.
I find it really strange that it can read the first full file name but breaks at the second '&'. Weirder still that if a supposed escape character is included in the second file name, it will omit that as well. 😵
For now all I can do is rename the file which is a bummer. 🤷‍♂️ I have VS Code version 1.75.0 on Windows 10 Home latest version/build and I'm using PowerShell version 5.1.19041.2364.
Edit: The issue definitely appears to be PowerShell related as it turns out. I was finally able to run this command successfully in a regular command prompt. (Simply typing "cmd" and Enter into the PowerShell window before running the diff command). Unfortunately, I happen to be running this command as part of PowerShell script. I may have to figure out how to run a CMD command from inside my PowerShell script if that is at all possible. I'm not sure. 🤔 If not, I need to figure out what exactly PowerShell is doing to my command when it reaches the '&' character.
tl;dr
You need a workaround:
cmd /c 'code --diff "R&D (cloud conflict 2-5-23).txt" "R&D.txt"'
Alternatively, using --%, the stop-parsing token:
code --diff "R&D (cloud conflict 2-5-23).txt" --% "R&D.txt"
Note: --% comes with fundamental limitations, notably the inability to reference PowerShell variables - see this answer.
Background information:
The root cause is that code is implemented as a batch file (code.cmd) and that cmd.exe, the interpreter that executes batch file inappropriately parses its list of arguments as if they had been submitted from INSIDE a cmd.exe session.
PowerShell, which - of necessity - has to rebuild the process command line behind the scenes on Windows after having performed argument parsing based on its rules, and - justifiably - places "R&D.txt" as verbatim R&D.txt on the process command line, given that the argument value contains no spaces.
The result is that cmd.exe interprets the unquoted R&D.txt argument on its command line as containing metacharacter &, which is its command-sequencing operator, causing the call to break.
Given that cmd.exe, the legacy Windows shell, is unlikely to receive fixes, the actively maintained PowerShell (Core) 7+ edition could as a courtesy compensate for cmd.exe's inappropriate behavior.
Doing so has been proposed in GitHub issue #15143, but, alas, it looks like these accommodations will not be implemented.

powershell running the code instead of create a new line

I think that my question is something too easy that you guys will solve in 1 minute.
I'm trying to run a script that have multiple lines of code. But, when I write the first line and hits SHIFT+ENTER it runs the code. I need to write a new line, instead of running what I've wrote.
Anybody knows what should I do (instead killing myself because I'm too dumb) ?
In powershell console there are a few ways to make a new line
A. Shift + Enter : Use this at any point to make a new line
B. The opening of a string " or ' until the closing of the string " or ' : use this when you have a string that you wish to span many lines
C. A pipe | : Use this if you have output that you would like to pass to another command
D. The Back tick (escape char) ` : use this to separate lines for a new command or splitting a command into other lines
If you are new to powershell, I would suggest using Powershell ISE. If its installed you can go to the powershell console and type ISE or go to start and type Powershell ISE. This will be a good place to run scripts and debug as you can add breakpoints to your scripts.
The easiest and best way to do this would be to create the script inside of the PowerSheell ISE program. You can then reference this script and run it in the console by preceding it with a .\script.ps1.
If needed you can create script on the command line by creating and writing to the file from the console.
Open the PowerShell console
Run the following command to create a file New-Item script.ps1
Run the next command as many times as it takes to populate the file Add-Content script.ps1 "My code line here"
Run the code using the script run command .\script.ps1
Now let it be known that the ISE is a much better tool because it allows for debugging of files and testing them on demand. The only downside is it will cache whatever it uses or creates (such as variables or references). If you aren't getting the expected result trying closing and reopening to clear the cache run it from the console in tandem. One last thing to note is that if you use the ISE and it successfully runs there that doesn't mean it will run in the console. Be sure to test thoroughly.

PowerShell SCript to Execute CMD.exe with Arguments

SO I have surfed this site and the web and I feel as though I am missing something simple.
I find related questions but none that combine a scriptblock and remote calling of a 3rd party app (not a simply windows function or app)
I have the following string that I can copy into a command window and run without issue
"C:\Program Files (x86)\Vizient\Vizient Secure Channel v2.1\VizientSC.exe" UID=me#musc.edu PWD=XXXXXXXXX HCOID=123456 PRODTYPE=PRO-UHCSECURECHANNEL-CDB PACKAGETYPE=OTH FOLDERPATH="\\da\db5\MyFiles\Viz\20180413"
To simplify this, lets just assume I want to run this same String every time BUT with a REMOTE call.
I have written this many different ways but to no avail using
Invoke-Command -ComputerName "edwsql" -ScriptBlock { .........
I simply want to run the designated string using cmd.exe on a remote machine.
The EXE being run in the string is a 3rd party software that I do not want to install all all possible locations. Much simpler to run remote form the box it is already installed and is secure.
Can someone point me in the right direction???? Pls???? I'm new to PowerShell. I am trying to phase out some old PERL as the folks who can support that on the client site are few and far between these days.
You don't need to try so hard. PowerShell can run commands. If the command you want to run contains spaces, enclose in " (as you have done) and invoke it with the & (call or invocation) operator. This is all you need to do:
& "C:\Program Files (x86)\Vizient\Vizient Secure Channel v2.1\VizientSC.exe" UID=me#musc.edu PWD=XXXXXXXXX HCOID=123456 PRODTYPE=PRO-UHCSECURECHANNEL-CDB PACKAGETYPE=OTH FOLDERPATH="\\da\db5\MyFiles\Viz\20180413"
If a parameter on the executable's command line contains any characters that PowerShell interprets in a special way, you will need to quote it.

Executing powershell command directly in jenkins pipeline

Is it possible to call a PowerShell command directly in the pipelines groovy script? While using custom jobs in Jenkins I am able to call the command with the PowerShell Plugin. But there is no snippet to use this in the groovy script.
I also tried sh() but it seems that this command does not allow multiple lines and comments inside the command.
To call a PowerShell script from the Groovy-Script:
you have to use the bat command.
After that, you have to be sure that the Error Code (errorlevel) variable will be correctly returned (EXIT 1 should resulting in a FAILED job).
Last, to be compatible with the PowerShell-Plugin, you have to be sure that $LastExitCode will be considered.
I have notice that the 'powershell' is now available in pipeline, but since it have several issues I prefer this variant. Still waiting it works stabil. I actually have an issue with the 'dontKillMe' behavior.
Since Jenkins 2.207 with Powershell plugin 1.4, I have replace all my calls with the official powershell pipeline command. I do now recommend to use it.
Note that you must predent \$ErrorActionPreference='Stop'; to your Script if you want it to abort on Write-Error because of an Issue with the powershell plugin.
For that porpuse I have written a little groovy method which could be integrate in any pipeline-script:
def PowerShell(psCmd) {
psCmd=psCmd.replaceAll("%", "%%")
bat "powershell.exe -NonInteractive -ExecutionPolicy Bypass -Command \"\$ErrorActionPreference='Stop';[Console]::OutputEncoding=[System.Text.Encoding]::UTF8;$psCmd;EXIT \$global:LastExitCode\""
}
[EDIT] I have added the UTF8 OutputEncoding: works great with Server 2016 and Win10.[/EDIT]
[EDIT] I have added the '%' mask[/EDIT]
In your Pipeline-Script you could then call your Script like this:
stage ('Call Powershell Script')
{
node ('MyWindowsSlave') {
PowerShell(". '.\\disk-usage.ps1'")
}
}
The best thing with that method, is that you may call CmdLet without having to do this in the Script, which is best-praxis.
Call ps1 to define CmdLet, an then call the CmdLet
PowerShell(". '.\\disk-usage.ps1'; du -Verbose")
Do not forget to use withEnv() an then you are better than fully compatible with the Powershell plugin.
postpone your Script with . to be sure your step failed when the script return an error code (should be preferred), use & if you don't care about it.
Calling PowerShell scripts is now supported with powershell step as announced on Jenkins blog.
The documentation mentions it supports multiple lines scripts.
From version 2.28 of Pipeline Nodes and Processes Plugin, we can directly use 'powershell'.
Eg: powershell(". '.Test.ps1'")
You can use the sh command like this:
sh """
echo 'foo'
# bar
echo 'hello'
"""
Comments are supported in here.

PowerShell - Outputting to a variable not working

I am writing a rather lengthy PowerShell script to perform a lot of functions. For the most part, everything is going very well.
However, another function I am running at all levels of the script is a very detailed log. I'll post the command line portion as an example (simplified):
$Batch = $RunMe[1]
$ResultCode = (Invoke-Expression $Batch -ErrorAction Stop)
$ResultCode
My expected result is:
Return Code 0
Then I would log it. Instead I am getting something like:
C:\batchfiles\batchfile.bat argument
Which is the command I am using Invoke-Expression to execute.
Some quick explanation of the variables:
$RunMe is an array that stores the commands (0 is either "Batch" or "Proc" and 1 is the command to run)
$Batch is created in the code as written (this is the first reference to it)
$CurrFileToExec is the current file being processed (the script runs on a folder at a time). I'm using it for a string replace for the command line I got from SQL.
I can't get $ResultCode to pass the correct output of the command. It just passes the command line function ($Batch) again.
As I said, the actual functionality part works great, but I can't get that return code to my logfile.
If I can presume $batch contains external executables, the return code will be in the automatic variable $LASTEXITCODE - invoke-expression's return consists of things written to STDOUT and STDERR by external applications or things written to powershell's output or error streams by script. It will not contain the executable's dos-style return code, if you called one.
The solution was to modify my $Batch variable to add a cmd /c to the beginning. I think there was an issue with just using Invoke-Expression and scoping of the output parameter. I added a line for:
$Batch = "cmd /c " + $Batch
Then ran again, and $ResultCode had the expected output.