write command in interactive prompt (powershell or bat) - powershell

I work in program with interactive prompt call XDIAL
I want write *select * from pcastd* in this prompt like this
D:\Aither\Exe\xdial.exe
start-sleep-seconds 1
/C "select * from pcastd"
xdial interactive prompt
there is not "select * from pcastd" writed ...
how to do this ?

As an alternative to interactive input, command-line utilities typically accept input via the pipeline, which sends an input command's output to the target utility's stdin (standard input):
Therefore, you can echo the string of interest and pipe it to xdial.exe:
# From PowerShell
'select * from pcastd' | xdial.exe
REM # From cmd.exe
REM # Note that there's no space before the "|" by design,
REM # because a space would become part of `echo`'s output.
echo select * from pcastd| xdial.exe

Related

Set and execute a command from a function

How can I write a fish function that executes a command in a string and make it appear in the history?
function qh --description 'Use peco to query command history'
if test (count $argv) = 0
set peco_flags --layout=bottom-up
else
set peco_flags --layout=bottom-up --query "$argv"
end
history | peco $peco_flags | read cmd
if test $cmd
commandline $cmd
else
commandline ''
end
end
This does not work...
It is possible to create a key binding which sets the command line and then executes it; that command will then appear in history. Example:
function whatday
commandline "echo Today is $(date +%A)"
commandline -f execute
end
bind \eq whatday
now alt-q will set the commandline to echo Today is Sunday and execute it; it appears in history.
Beyond that there are also abbreviations which allow replacing tokens with text; but the text is just static (e.g. gco -> git checkout).
There is as yet no way for an arbitrary fish function (e.g. run as part of a shell script) to append to history, only delete and read from it.

Avoid Line break at end of cmd output?

when I use this command pwsh -c echo hello in cmd I get the following output:
C:\>pwsh -c echo hello
hello
C:\>
I do not get that line break at the end
when I run it on powershell:
PS C:\> pwsh -c echo hello
hello
PS C:\>
So I think the problem is in cmd. I know this is not such a problem and have an easy fix but I have some programs uses cmd to access powershell and removing that line break is not that fun.
So is there any fix to prevent cmd to add that line ?
Mofi has provided the crucial pointers in comments:
When executing a command interactively, cmd.exe unconditionally appends a a newline (line break) to the command's output, presumably for readability and perhaps also to ensure that the next prompt always starts on a new line.
This applies irrespective of what that command is. In other words: It doesn't matter that your command happens to be a PowerShell command.
However, that trailing newline does not become part of the command's output, therefore programmatic processing of a command's output is not affected, such as when you redirect > to a file or process the output lines one by one with for /f.
In other words: for programmatic processing you need not remove the trailing newline, because it isn't part of the actual command output.
Conversely, if you really need to in effect suppress the trailing newline for display, you'll have to modify the command's output - if that is even an option - so that the output itself doesn't end in a newline, as shown in this SuperUser answer for cmd.exe's own echo command; for PowerShell, you could do pwsh -c Write-Host -NoNewLine hello.
Edge case:
When capturing output from a batch file that is running without #echo off (or with echo on) - in which case the trailing newlines do become part of the output - you can filter out empty lines by piping to findstr /r /v /c:"^$" (as also shown in the linked answer); e.g.
foo.cmd | findstr /r /v /c:"^$"
However, note that all empty lines are filtered out this way - potentially including actual empty lines in the output from commands executed by the batch file.
If preventing that is required, a more sophisticated approach is required, which, however (a) relies on the standard prompt string (e.g., C:\>) being used and (b) can still yield false positives:
foo.cmd | powershell -nop -c "#($Input) -join \"`n\" -replace '\n(?=[a-z]:\\.*?>)'"
Finally note that if you execute the above commands without capturing or redirecting their output, their overall output in the cmd.exe console will again have a trailing newline.

User input as a command line argument

I have a program BIL.exe that prompts for user four inputs (marked with pink below).
I would like to run this program from command line by specifying the inputs as arguments. Something like this:
.\BIL.exe "HOAL" 78 80 1
In a batch script I can do it as shown below. However this doesn't work in command line.
#echo off
set var1="HOAL"
set var2=78
set var3=80
set var4=1
(echo %var1% && echo %var2% && echo %var3% && echo %var4%)|BIL.exe
Does the solution differ between CMD and powershell?
So given your confirmation that stdin from file worked means that the solution should be simple:
batch_name.cmd
#echo off
(echo %1&echo %2&echo %3&echo %4)|bil.exe
it sends the output in list format. so you should be able to run the batch as:
batch_name.cmd "HOAL" 78 80 1
keep in mind, I am not stripping outside quotations, as it seems that those are used by the executable. If not, then change to:
#echo off
(echo %~1&echo %~2&echo %~3&echo %~4)|bil.exe
As you never need to set anything in relation to the variable name, we simply do not use variables as they come as input meta variables from your input.

"SFC" output redirection formatting issue - Powershell / Batch

I'm working on a powershell script in which several commands output are shown in the window and appended to a file or a variable. It worked correctly until I used the sfc command. When piped or redirected, the output is "broken":
> sfc /?
Vérificateur de ressources Microsoft (R) Windows (R) version 6.0[...]
> sfc /? | Tee-Object -Variable content
V Ú r i f i c a t e u r d e r e s s o u r c e s M i c r o s o f t ( R ) W i n d o w s ( R ) v e r s i o á 6 . 0[...]
Are there other commands like sfc that are formatted in the same way, or that will result in a broken output if redirected?
EDIT
Powershell sample code, using the code from the accepted answer:
# Run a command
function RunCommand([ScriptBlock] $command) {
# Run the command and write the output to the window and to a variable ("SFC" formatting)
$stringcommand = $command.ToString()
if (
$stringcommand -match "^SFC$" -or
$stringcommand -match "^SFC.exe$" -or
$stringcommand -match "^SFC .*$" -or
$stringcommand -match "^SFC.exe .*$"
) {
$oldEncoding = [console]::OutputEncoding
[console]::OutputEncoding = [Text.Encoding]::Unicode
$command = [ScriptBlock]::Create("(" + $stringcommand + ")" + " -join ""`r`n"" -replace ""`r`n`r`n"", ""`r`n""")
& ($command) 2>&1 | Tee-Object -Variable out_content
[console]::OutputEncoding = $oldEncoding
# Run the command and write the output to the window and to a variable (normal formatting)
} else {
& ($command) 2>&1 | Tee-Object -Variable out_content
}
# Manipulate output variable, write it to a file...
# ...
return
}
# Run commands
RunCommand {ping 127.0.0.1}
RunCommand {sfc /?}
[void][System.Console]::ReadKey($true)
exit
CMD sample code, using more to format the sfcoutput:
#echo off
setlocal enabledelayedexpansion
set "tmpfile=%TEMP%\temp.txt"
set "outputfile=%TEMP%\output.txt"
REM; Run commands
call :RunCommand "ping 127.0.0.1"
call :RunCommand "sfc"
pause
exit /b
REM; Run a command
:RunCommand
REM; Run the command and write the output to the window and to the temp file
set "command=%~1"
(!command! 2>&1) >!tmpfile!
REM; Write the output to the window and to the output file ("SFC" formatting)
set "isSFC=0"
(echo !command!|findstr /I /R /C:"^SFC$" > NUL) && (set "isSFC=1")
(echo !command!|findstr /I /R /C:"^SFC.exe$" > NUL) && (set "isSFC=1")
(echo !command!|findstr /I /R /C:"^SFC .*$" > NUL) && (set "isSFC=1")
(echo !command!|findstr /I /R /C:"^SFC.exe .*$" > NUL) && (set "isSFC=1")
(if !isSFC! equ 1 (
(set \n=^
%=newline=%
)
set "content="
(for /f "usebackq tokens=* delims=" %%a in (`more /p ^<"!tmpfile!"`) do (
set "line=%%a"
set "content=!content!!line!!\n!"
))
echo.!content!
(echo.!content!) >>!outputfile!
REM; Write the output to the window and to the locked output file (normal formatting)
) else (
type "!tmpfile!"
(type "!tmpfile!") >>!outputfile!
))
goto :EOF
As noted in js2010's answer, the sfc.exe utility - surprisingly - outputs text that is UTF-16LE ("Unicode") encoded.
Since PowerShell doesn't expect that, it misinterprets sfc's output.[1]
The solution is to (temporarily) change [console]::OutputEncoding to UTF-16LE, which tells PowerShell / .NET what character encoding to expect from external programs, i.e., how to decode external-program output to .NET strings (which are stored as UTF-16 code units in memory).
However, there's an additional problem that looks like a bug: bizarrely, sfc.exe uses CRCRLF (`r`r`n) sequences as line breaks rather than the Windows-customary CRLF (`r`n) newlines.
PowerShell, when it captures stdout output from external programs, returns an array of lines rather than a single multi-line string, and it treats the following newline styles interchangeably: CRLF (Windows-style), LF (Unix-style), and CR (obsolete Mac-style - very rare these days).
Therefore, it treats CRCRLF as two newlines, which are reflected in both "teed" and captured-in-a-variable output then containing extra, empty lines.
The solution is therefore to join the array elements with the standard CRLF newline sequences - (sfc /?) -join "`r`n" and then replace 2 consecutive `r`n with just one, to remove the artificially introduced line breaks: -replace "`r`n`r`n", "`r`n".
To put it all together:
# Save the current output encoding and switch to UTF-16LE
$prev = [console]::OutputEncoding
[console]::OutputEncoding = [Text.Encoding]::Unicode
# Invoke sfc.exe, whose output is now correctly interpreted and
# apply the CRCRLF workaround.
# You can also send output to a file, but note that Windows PowerShell's
# > redirection again uses UTF-16LE encoding.
# Best to use ... | Set-Content/Add-Content -Encoding ...
(sfc /?) -join "`r`n" -replace "`r`n`r`n", "`r`n" | Tee-Object -Variable content
# Restore the previous output encoding, which is the system's
# active OEM code page, which should work for other programs such
# as ping.exe
[console]::OutputEncoding = $prev
Note that $content will then contain a single, multi-line string; use $content -split "`r`n" to split into an array of lines.
As for:
Are there other commands like "sfc" that are formatted in the same way, or that will result in a broken output if redirected?
Not that I'm personally aware of; unconditional UTF-16LE output, as in sfc.exe's case, strikes me as unusual (other programs may offer that on an opt-in basis).
Older console programs with a Windows-only heritage use a (possibly fixed) OEM code page, which is a single-byte 8-bit encoding that is a superset of ASCII.
Increasingly, modern, multi-platform console programs use UTF-8 (e.g., the Node.js CLI), which is variable-width encoding capable of encoding all Unicode characters that is backward-compatible with ASCII (that is, in the 7-bit ASCII range UTF-8 encodes all characters as single, ASCII-compatible bytes).
If you want to make your PowerShell sessions and potentially all console windows fully UTF-8 aware, see this answer (However, doing so stil requires the above workaround for sfc).
[1] Direct-to-console output:
When sfc output is neither captured by PowerShell nor routed through a cmdlet such as Tee-Object, sfc writes directly to the console, presumably using the Unicode version of the WriteConsole Windows API function, which expects UTF-16LE strings.
Writing to the console this way allows printing all Unicode characters, irrespective of what code page (reflected in chcp / [console]::OutputEncoding) is currently active.
(While the rendering of certain characters may fall short, due to limited font support and lack of support for (the rare) characters outside the BMP (Basic Multilingual Plane), the console buffer correctly preserves all characters, so copying and pasting elsewhere may render correctly there - see the bottom section of this answer.)
Therefore, direct-to-console output is not affected by the misinterpretation and typically prints as expected.
Looks like sfc outputs unicode no bom. Amazing.
cmd /c 'sfc > out'
get-content out -Encoding Unicode | where { $_ } # singlespace
Output:
Microsoft (R) Windows (R) Resource Checker Version 6.0
Copyright (C) Microsoft Corporation. All rights reserved.
Scans the integrity of all protected system files and replaces incorrect versions with
correct Microsoft versions.
SFC [/SCANNOW] [/VERIFYONLY] [/SCANFILE=<file>] [/VERIFYFILE=<file>]
[/OFFWINDIR=<offline windows directory> /OFFBOOTDIR=<offline boot directory>]
/SCANNOW Scans integrity of all protected system files and repairs files with
problems when possible.
/VERIFYONLY Scans integrity of all protected system files. No repair operation is
performed.
/SCANFILE Scans integrity of the referenced file, repairs file if problems are
identified. Specify full path <file>
/VERIFYFILE Verifies the integrity of the file with full path <file>. No repair
operation is performed.
/OFFBOOTDIR For offline repair specify the location of the offline boot directory
/OFFWINDIR For offline repair specify the location of the offline windows directory
e.g.
sfc /SCANNOW
sfc /VERIFYFILE=c:\windows\system32\kernel32.dll
sfc /SCANFILE=d:\windows\system32\kernel32.dll /OFFBOOTDIR=d:\ /OFFWINDIR=d:\windows
sfc /VERIFYONLY
Or delete the nulls and blank lines (windows prints nulls as spaces):
(sfc) -replace "`0" | where {$_}

How to run a command without opening new shell using the AutoIt command line

I am currently writing a command line application in AutoIt and am having trouble with making it print back to the same command line I opened it in. My goal is to have the entire program work within a single shell. Here is what I tried initially:
;myprogram.au3
$MyCommand = 'dir'
Run(#ComSpec & " /c " & $MyCommand, #SystemDir, #SW_Show)
Run(#ComSpec & " /c #echo off && echo Command completed successfully. && #echo on", #SystemDir, #SW_Show)
Then I compiled it and ran it via the command line (each code box represents a new shell):
C:\Users\Matthew>myprogram.au3
C:\Users\Matthew>
Opens new shell
↓
Volume in drive C has no label.
Volume Serial Number is 0287-990C
Directory of C:\Users\Matthew
<Finishes normal dir command output>
Once finished, listing files in my directory that exits and
Opens new shell
↓
The command completed successfully.
And that window closes immediately.
The output I am looking for is the same thing, but in one window, like this:
C:\Users\Matthew>myprogram
*Output of dir command*
The command completed successfully
C:\Users\Matthew>
You compile your project as a console application for this to work. You can do that by checking the somewhat cryptically named "Create CUI instead of GUI EXE" checkbox when compiling. Then call myprogram.exe from the shell instead of .au3.
#include <Constants.au3>
;myprogram.au3
$MyCommand = 'dir'
Local $foo = Run(#ComSpec & " /c " & $MyCommand & " \& echo Command completed successfully.", #SystemDir, #SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)
Local $output
While 1
$output = StdoutRead($foo)
If #error Then ExitLoop
ConsoleWrite($output)
Wend
Since this question is unanswered:
$MyCommand = 'ping www.google.com && ping www.stackoverflow.com'
Run(#ComSpec & " /c " & $MyCommand, #SystemDir, #SW_Show)
Like this both commands are executed in the same CMD-Box.