Cannot pass asterisk character to external command via powershell - powershell

I cannot pass an asterisk character to external command using powershell
I use following a line like
& .\args.bat #("-arg1", "-arg2", "*.test.com")
where args.bat just dumps passed arguments
#ECHO off
ECHO The %~nx0 script args are...
for %%I IN (%*) DO ECHO %%I
And instead of passing "*.test.com" it lookups up current directory for files matching pattern "*.test.com" and sends list of them to args.bat
That can be seen if you use "*" instead of "*.test.com"
I've also tried back tick character to escape asterisk, but it didn't help
In my case using asterisk is required as I'm passing it to makecert.exe to create wildcard domain certificate
Please help

I'm not seeing that. As a test I created args.bat like so:
'pause' > args.bat
Then executed it:
& .\args.bat #("-arg1", "-arg2", "*.ps1")
When I look in task manager at the command line for that cmd.exe, I see:
It must be something the batch file is doing because PowerShell is doing nothing to your *. BTW I used *.ps1 because the directory I executed from had a ton of ps1 files in it.

If you are PS 3.0 or higher you can use "stop parsing operator" --%. See help about_parsing for details.

Related

Passing a semicolon as a parameter to a .bat file from both cmd and PowerShell

This question seems to be rather simple, but even after searching the web for a couple of hours, I was not able to find a solution...
I have a batch file test.bat
set MY_VARIABLE=%~1
echo %MY_VARIABLE%
The point is that I want to call this programm with a semicolon as input parameter, i.e.,
.\test.bat ";",
from both cmd and Windows PowerShell. While this works fine from cmd, PowerShell does not seem to get anything as an input. Is there any way to make this work for both simultaneously?
This is because of command line syntax. The semicolon is one of multiple delimiters, that split the command line into words: a;b would be interpreted as two separate arguments a (%1) and b (%2).
Therefore, quotes are required. Since Powershell uses quotes for string literals (Powershell does its own re-quoting behind the scenes when passing arguments), you need to include them in the string:
.\test.bat '";"'
# or
.\test.bat "`";`""
Or as #mklement0 pointed out, the stop-parsing symbol --% would also be an option:
.\test.bat --% ";"
Note that this is specific to Powershell syntax.
In CMD, this will suffice:
test.bat ";"

How to write STDOUT/STDIN via RedMon/cmd.exe to file?

I am trying to redirect a PS output to a file and process it further.
For this I am using the Printer Port Redirection RedMon which is sending the output to CMD.exe
C:\Windows\system32\cmd.exe
As arguments I expected that something like the following should work, but it does not. "%1" contains the user input for filename.
/c >"%1"
or
/c 1>"%1"
or
/c |"%1"
or
/c > "%1" 2>&1
What almost works if I send the output to a batch file which writes it then to file.
/c WriteOutput.bat "%1"
However, the batch file is somehow altering the file (skipping empty lines, and ignoring exclamation marks and so on...)
If possible I want to avoid a batch file. Is there a way to get it "directly" to a file?
Select "Print to FILE" in the printer options is not an option for me. I want the same end result but via cmd.exe being able to process it further.
Any ideas?
Edit:
Well, that's the batch file I used. It neglects empty lines and space at the beginning.
#echo off
setlocal
set FileName=%1
echo(>%FileName%.ps
for /F "tokens=*" %%A in ('more') do (
echo %%A>>%FileName%.ps
)
Well, so far I still haven't found a direct way to write STDIN via RedMon via CMD.exe to a file. As #aschipfl wrote, all the versions with for /F will skip lines and ignore certain characters.
However, with the following batch script (via RedMon) I end up with a "correct looking" file on disk.
C:\Windows\system32\cmd.exe /c WritePS.bat "%1"
"%1" contains the user input for filename without extension.
The Batch-File WritePS.bat looks as simple as this:
#echo off & setlocal
set FileName=%1.ps
more > "%FileName%"
However,
the resulting Postscript file is different from a file which I "Print to FILE" via the Postscript-Printer setup. I am pretty sure that all the printer settings which I can set are the same in both cases.
If anybody has an idea why there might be a difference, please let me know.

Start process, wait for it, and throw away all output

I'd like to do this in PowerShell:
myprogram.exe arg1 arg2 >nul 2>nul
How does it work? There are like a million options to start processes in PowerShell, it's impossible to know the right one you need at a time.
nul is a special device (see this answer on SuperUser for instance) that's available in CMD, but not in PowerShell. In PowerShell you can use $null instead. Starting with PowerShell v3 you can use *> to redirect all output streams, but since you want to redirect output from an external program there should only be output on STDOUT and STDERR (Success and Error output stream in PowerShell terms), so >$null 2>$null should be fine.
A notable difference between CMD and PowerShell is that PowerShell doesn't include the current working directory in the PATH (the list of directories that is searched when you call a program/script without a path). If you want to run myprogram.exe from the current directory you need to prepend it with the path to the current directory (./).
You may also want to use the call operator (&). Although it's not required in this particular case I consider using it good practice. If you specify the command as a string (for instance because the path or filename contains spaces, or you want to use a variable instead of a literal) you MUST use the call operator, otherwise the statement would throw an error.
Something like this
& ./myprogram.exe arg1 arg2 >$null 2>$null
or like this
& ./myprogram.exe arg1 arg2 *>$null
should work.

How do I pass an equal sign when calling a batch script in Powershell?

We have a batch file that invokes our MSBuild-based build process. Syntax:
build App Target [ Additional MSBuild Arguments ]
Internally, it does this:
msbuild.exe %1.msbuild /t:%2 %3 %4 %5 %6 %7 %8 %9
Which results in calls to MSBuild that look like this:
msbuild.exe App.msbuild /t:Target
When any argument contains the equal sign, =, Powershell completely removes it. My batch script never sees it. This does not happen with the standard cmd.exe command prompt.
For example, if I call
build App Target "/p:Property=Value"
this is what gets passed to MSBuild:
msbuild.exe App.msmbuild /t:Target /p:Property Value
I expected this:
msbuild.exe App.msbuild /t:Target "/p:Property=Value"
I've tried the Powershell escape character, the standard Command Prompt escape character, and even stuff I made up:
build App Target "/p:Property=Value"
build App Target '/p:Property=Value'
build App Target /p:Property^=Value
build App Target /p:Property`=Value
build App Target /p:Property==Value
None of it works. What do I do to get the equal sign to not be stripped out or removed?
I've seen this before and have found a way to trick it out. I wish I could explain what's going on in particular with the '=' but I cannot. In your situation I'm fairly certain the following will work if you want to pass properties to msbuild:
build App Target '"/p:Property=Value"'
When echoed, this produces the following:
msbuild.exe App.msbuild /t:Target "/p:Property=Value"
With PowerShell 3 you can use --% to stop the normal parsing powershell does.
build --% App Target "/p:Property=Value"
I don't know if there's an easier answer (I think not) but you can solve the problem by using .Net's process class to invoke cmd.exe. Here's an example:
# use .NET Process class to run a batch file, passing it an argument that contains an equals sign.
# This test script assumes the existence of a batch file "c:\temp\test.bat"
# that has this content:
# echo %1
# pause
$cmdLine = $cmdLine = '/c c:\temp\test.bat "x=1"'
$procStartInfo = new-object System.Diagnostics.ProcessStartInfo("cmd", $cmdLine )
$proc = new-object System.Diagnostics.Process
$proc.StartInfo = $procStartInfo
$proc.Start();
Have you tried single quotes to force a literal interpretation?
Or:
cmd /c 'msbuild.exe App.msbuild /t:Target "/p:Property=Value"'
It seems that only single-quote around double-quote might be the best for multiple scenario around windows environment.
Following link from MS shows its support(or limitation) of equal sign
http://support.microsoft.com/kb/35938
It is specific to Batch Files but it likely affect lots of other MS shell products.
The answer is that %2 becomes "/p:property" and %3 becomes "value".
Make this work in your batch file by using BOTH %2 and %3 and insert an = sign between them:
msbuild.exe %1.msbuild /t:%2=%3 %4 %5 %6 %7 %8 %9
and do not use the quote chars on the command line call. Use:
build App Target /p:property=value
For additional args with = signs just keep pairing them up.
I had the same issue with a simple batch file to run youtube-dl where the URL I pass has an = sign in it.
solved as :
#echo off
REM YTDL audio only
echo %1=%2
youtube-dl -f bestaudio --extract-audio --audio-format mp3 --audio-quality 0 %1=%2

Best automation scripting for command line commands in Windows?

I need to make a script that automates the following:
Read comma or tab separated values from the input file
Construct a command from them and run it
Get the command output, looks for substrings in it and update the log file based on the existence of a substring
I do this in Windows Server 2008, so I can do this in CMD or PowerShell but I am not sure they provide such possibilities. I can try Perl or C#, but I want to try a minimalistic approach first.
Minimalistic as far as coding - Perl
Minimalistic as far as installing new software - PowerShell (IIRS W.S.2008 included that?)
So many answers, and none providing a solution that would meet the requirements...
You didn't say what are the conditions to be checked against each CSV row, and what the CSV would be like, and what the log would be like - so I made it all up... Here's an example in BATCH:
#echo off
set csvfile=input.csv
set logfile=output.log
for /F "tokens=1,2,3 delims=," %%a in (%csvfile%) do call :processline "%%a" "%%b" "%%c"
exit /B 0
:processline
set param=%~3
set check=%param:um=%
rem if they are not equal - substring 'um' exists in it.
if not "$%check%" == "$%param%" (
rem this passes all params to output.
rem I'm not calling echo directly here, because there might be symbols, that will confuse CMD at the end of the %*.
call :output %*>> %logfile%
)
exit /B 0
:output
set colA=%~1
set colB=%~2
set colC=%~3
rem output to log
echo [%DATE% %TIME%] (%colB%) %colA% %colC%.
exit /B 0
Here's the example input file that I tested it with:
foo,1,dum
bar,3,dim
baz,15,dirum
And here's the resulting log messages:
[2009-10-14 14:57:35.87] (1) foo dum.
[2009-10-14 14:57:35.89] (15) baz dirum.
I hope this shows clearly, that BATCH is not nasty nor it is hard to use. :P
If you have further question about BATCH - don't be shy, post them all on SO. ;)
I would recommend going with Python (or Perl if you swing that way). These are very minimal tools to have to install on a machine and add all the functionality you need.
The string handling you describe is unpleasant in any shell (Bash included) unless you are using sed or awk... and that just gets esoteric. In the end you'll retain more hair if you go straight to a scripting language first.
Perl was called into existence to quickly solve these kind
of tasks. It should not take more 20 lines for this
particular problem.
It is also really easy to install:
Download ActivePerl (17.7 MB, Perl 5.10.)
Run the installer.