Executing the returned from an echo command in Windows. (if it is a executable file) - echo

I am trying to run a program as administrator using the Command prompt in Windows.
C:\Users\i309\Desktop>set new=whoami.exe
C:\Users\i309\Desktop>%new%
global\i309
C:\Users\i309\Desktop>echo %new%
whoami.exe
C:\Users\i309\Desktop>
Why doesn't the "new" variable have the value global\i309?
My next step will be using the command
/runas /user:%new% /noprofile "application.exe"
When I run the above command, the "new" variable gets replaced to whoami.exe instead of my username. So it asks for the password of "whoami.exe", which is obviously not pertinent.
what could be the solution? Can this be solved using any piping method?

The set command is quite literal.
To set a value to the result of a command, use
for /f "delims=" %%a in ('whoami.exe') do set "new=%%a"
See
for /?
Note : use %%a if this is being executed within a batch file. Use %a instead if this is being executed directly from the prompt.
from the prompt for documentation

Related

How to Randomize the browsers from opening a webpage

I have this PowerShell command line which usually opens a webpage via Google Chrome, but I would like that to open randomly with Chrome and Firefox.
start-process -FilePath chrome.exe "www.quora.com"
One PowerShell solution for usage in a PowerShell script or in PowerShell console window is as posted by Santiago Squarzon:
start-process -FilePath ('chrome.exe','firefox.exe'|get-random) "https://www.quora.com"
For understanding the two used PowerShell cmdlets and how they work, open a PowerShell console window, execute there the following commands, and read entirely the two help pages displayed for the two cmdlets very carefully.
help start-process
help get-random
One batch file solution is:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set /A "Browser=%RANDOM% & 1"
if %Browser% == 0 (set "Browser=chrome") else set "Browser=firefox"
start "" %Browser%.exe "https://www.quora.com"
endlocal
The first two command lines just define the required execution environment completely and creates a new environment variables list as copy of the current environment variables list and the last line just results in restoring the initial execution environment and environment variables list. The second and the last command line could be omitted if it is no problem to depend on Windows defaults or what the process calling this batch file defines as execution environment.
The third line uses an arithmetic expression to apply on a random number a bitwise AND with 1 to get assigned to the environment variable Browser randomly either 0 or 1.
The third line could be also:
set /A Browser=%RANDOM% %% 2
This arithmetic expression divides a random number by two and gets the remainder 0 or 1 assigned to the environment variable Browser.
The fourth line uses an IF condition to redefine the environment variable Browser on having currently the value 0 with the string chrome and otherwise with the string firefox.
The fifth line uses command start to start either chrome.exe or firefox.exe as separate process on which cmd.exe does not wait for self-termination before continuation of processing of the batch file with passing the URL to started executable. "" defines an empty string as optional title for the console window not opened at all as the two browsers are Windows applications with a graphic user interface.
For understanding the used Windows Commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
help echo or echo /?
help endlocal or endlocal /?
help if or if /?
help set or set /?
help setlocal or setlocal /?
help start or start /?
See also:
An A-Z Index of Windows CMD commands
An A-Z Index of Windows PowerShell commands
Windows CMD Shell How-to guides and examples
Windows PowerShell How-to guides and examples
Where is "START" searching for executables?
powershell.exe does the same. PowerShell and CMD use the Windows kernel library function CreateProcess to start the Chrome or Firefox process.

How to set %ERRORLEVEL% in cmd /c?

I want to be able to set the %ERRORLEVEL% environment variable (also referred to as a "system variable") to an arbitrary value in the beginning of a command prompt script (i.e. cmd /c) running in PowerShell. Whenever people want to set %ERRORLEVEL% (1), they do the following:
cmd /c "exit /b 3"
cmd /c "echo %ERRORLEVEL%"
However, although %ERRORLEVEL% is set to 3 when the above is run in the normal Command Prompt, if these exact lines are executed in PowerShell, the exit code environment variable is not set to 3 and remains 0. In addition, you cannot do the following:
cmd /v:on /c "exit /b 3 & echo !ERRORLEVEL!"
The exit command breaks completely out of the command execution (i.e. cmd /c) and no other command after the & is run.
Therefore, I tried executing the following command in PowerShell:
cmd /v:on /c "SET %ERRORLEVEL% = 4 & echo !ERRORLEVEL!"
The expected output is 4, but this always outputs 0. I cannot figure out why I am unable to SET the %ERRORLEVEL% environment variable. I have used delayed command execution (example here), but no amount of fiddling seems to work here.
Does anyone have any idea of why the command SET %ERRORLEVEL% = 4 does not work?
If you are not able SET environment variables, then how can set %ERRORLEVEL% to an arbitrary value in a string of commands separated by an ampersand (&) like above?
If you want to store the eventual exit code in a cmd.exe variable for later use with exit, do not try to set ERRORLEVEL; instead, use a custom variable name; e.g., ec (for exit code):
# Execute in PowerShell
PS> cmd /v /c 'set "ec=3" & echo ... & exit /b !ec!'; $LASTEXITCODE
...
3
On the cmd.exe side:
set "ec=3" sets variable ec to value 3
Enclosing the name-value pair in "..." isn't strictly necessary, but clearly delineates the end of the value, and allows use of values with embedded special characters such as &.
The variable's value can later be referenced as %ec% (up-front expansion) or !ec! (delayed expansion, if enabled via setlocal enabledelayedexpansion or via command-line switch /v - see help setlocal)
echo ... is a sample command representing further commands
exit /b !ec! exits with the value of variable ec as the exit code; note how the variable is of necessity referenced as !ec! rather than %ec%, via delayed expansion, because the variable was set as part of the same statement.
Whether you use /b (exit the current batch file only) or not doesn't make a difference here; either way, the exit statement in this case determines the process exit code of the cmd instance.
The commands are sequenced (unconditionally executed one after the other), with the & operator, as part of a single statement.
On the PowerShell side:
PowerShell's analog to cmd.exe's & is ;, the statement separator - it allows you to place multiple statements on a single line.
$LASTEXITCODE is the automatic PowerShell variable that contains the process exit code of the most recently executed external program, which in this case is cmd.exe's, with value 3.
Does anyone have any idea why the command SET %ERRORLEVEL% = 4 does not work?
To summarize the helpful information from the comments on the question:
Fundamentally, do no try to set the dynamic (pseudo) environment variable %ERRORLEVEL% - it is automatically maintained by cmd.exe to reflect the most recent command's exit code - see the bottom section.
Do not put spaces around = in a cmd.exe variable assignment:
The space(s) before the = become part of the variable name.
The space(s) after become part of the value.
Do not enclose the target variable name in %...% (unless you want to indirectly set a variable, via another variable whose value contains the name of the variable to assign to).
set %ERRORLEVEL% = 4
With %ERRORLEVEL% reflecting 0 at the start of your command sequence, the above assignment creates a variable literally named 0  (that is, the value of %ERRORLEVEL% followed by a single space), whose value is  4 (that is, a single space followed by 4).
Variables in cmd.exe:
Fundamentally, with the exceptions discussed below, variables in cmd.exe are all environment variables.
Unlike in shells such as Bash and PowerShell, there is no separate namespace for shell-local variables that are not seen by child processes.
This has the following implications:
Predefined persistent environment variables such as %Path% share the same namespace as custom variables you define with the SET command, so you have to be mindful of name collisions.
Similarly, child processes you run from your cmd.exe session / batch file inherit custom variables you've created in the session.
Note that the use of setlocal does not change that; setlocal is a cmd-internal scoping mechanism that allows you to control the lifetime of custom environment variables, by localizing them to the scope (batch file) in which setlocal was called, and removing them via a subsequent endlocal call or, implicitly, at the end of the enclosing batch file.
Custom variables are process-only environment variables that go out of scope with the cmd.exe process; persistent environment variable definitions must be created and modified via the registry, such as with the setx.exe utility.
In addition to the predefined (persistent) environment variables and custom (session-only) environment variables, cmd.exe maintains dynamic pseudo environment variables such as %ERRORLEVEL% and %RANDOM% (see list below):
These pseudo environment variables have dynamic values maintained by cmd.exe itself...
... and they are not visible to child processes.
Note: Strictly speaking, these dynamic variables are only enabled with the so-called command extensions turned on, but that is true by default (you can disable them with /E:OFF, but that is ill-advised).
Because these dynamic variables are not strictly part of the process environment that child processes inherit a copy of, they are not environment variables, even though help SET somewhat confusingly calls them dynamic environment variables.
You shouldn't (and cannot) modify these variables.
If you try, what really happens is that you shadow (override) these pseudo variables with real, custom environment variables, which by definition have static values.
Later code that relies on the variables by that name to have their usual, dynamic behavior can therefore malfunction.
The list of dynamic variables, as retrieved on Windows 10 via help SET (emphasis added):
If Command Extensions are enabled, then there are several dynamic
environment variables that can be expanded but which don't show up in
the list of variables displayed by SET. These variable values are
computed dynamically each time the value of the variable is expanded.
If the user explicitly defines a variable with one of these names, then
that definition will override the dynamic one described below:
%CD% - expands to the current directory string.
%DATE% - expands to current date using same format as DATE command.
%TIME% - expands to current time using same format as TIME command.
%RANDOM% - expands to a random decimal number between 0 and 32767.
%ERRORLEVEL% - expands to the current ERRORLEVEL value
%CMDEXTVERSION% - expands to the current Command Processor Extensions
version number.
%CMDCMDLINE% - expands to the original command line that invoked the
Command Processor.
%HIGHESTNUMANODENUMBER% - expands to the highest NUMA node number
on this machine.

Powershell environment variable

In a Powershell script (.ps1)
Launched from the command line of a console (cmd.exe)
How can set and environment variable in the console,
so that when the Powershell script ends processing,
and exits to the console where was invoked...
the environment variable exists,
and can be read by a batch file,
or viewed with the SET command ?
do not want to set a 'Machine' or a 'User' variable...
only a console process variable...
the same variable you get if you use SET in the console
To run a PowerShell script from cmd.exe invariably requires a (powershell.exe / pwsh.exe) child process, and child processes fundamentally cannot set environment variables for their parent process[1].
Your best bet is to have your *.ps1 file output the name and value of the desired environment variable and then have the calling cmd.exe process create it, based on that output.
Security note: Blindly defining environment variables based on the name-value pairs output by another command (a *.ps1 script, in your case) should only be done if you trust that command not to output malicious definitions.
Here's a simple example (run directly from an interactive cmd.exe session):
for /f "delims== tokens=1,*" %v in ('powershell.exe -c "'FOO=bar'"') do #set "%v=%w"
The above defines environment variable %FOO% with value bar, based on the PowerShell command outputting the literal name-value pair FOO=bar.
Verify with echo %FOO%.
To extend this approach to defining multiple environment variables, make the command output each definition on its own line (which in PowerShell you can achieve by outputting an array of strings):
for /f "delims== tokens=1,*" %v in ('powershell.exe -c "'FOO=bar', 'BAZ=bam'"') do #set "%v=%w"
The above additionally defines %BAZ% with value bam.
To make this more convenient, I suggest creating a wrapper batch file (*.cmd) that performs the above:
Note that you'll have to use %%v and %%w instead of %v and %w there.
Instead of -c (for -Command) with the demo command, use -File with the path to your *.ps1 file to invoke it.
Also consider use of -NoProfile as well, to bypass loading of your PowerShell environment's $PROFILE file, which not only slows things down, but may pollute your command's output.
[1] As LotPings points out, child processes inherit copies of the parent process' environment variables. Modifications of these copies are never seen by the parent. A child process is fundamentally unable to modify its parent's environment, which is a restriction at the OS level - for good reasons: Modifying a running process' environment by an arbitrary (child) process would be a serious security concern.

Call multiple .bat from another .bat without waiting for one to finish

So, I want to make a script that will execute 2 .bat files and start some .exe files.
However, the .bat files are supposed to keep running.
I have something like this :
pushd tools\wamp64
start wampmanager.exe
pushd ..\..\server\login
call startLoginServer.bat
pushd ..\test
call startTestServer.bat
start "C:\DEV\P2\Test\client" P2.bin
The problem is that call startLoginServer.bat will not exit and therefore, I'm stucked here.
How can I run my 2 .bat files and let them keep running.
(Ideally, I want them to run in 2 different command prompt windows)
Also, there is probably a better way to handle relative path than using pushd if you can correct me on this.
Thanks
You could use:
start "Wamp Manager" /B /D "%~dp0tools\wamp64" wampmanager.exe
start "Login Server" /B /D "%~dp0server\login" startLoginServer.bat
start "Test Server" /B /D "%~dp0server\test" startTestServer.bat
start "Text Client" /B /D "%~dp0" "C:\DEV\P2\Test\client.exe" P2.bin
Run in a command prompt window start /? for help on this command explaining the options.
"..." ... title for new console window which is optional, but must be often specified on program to start is or must be enclosed in double quotes. The START command in last command line in batch file code in question interprets C:\DEV\P2\Test\client as window title. It is also possible to use an empty window title, i.e. "" which is best if the started application is a Windows GUI application on which no console window is opened at all.
/B ... run without opening a new window, i.e. in "background". This option can be omitted to see what the started applications and batch files output to console if the executables are not Windows GUI applications.
/D "..." or also /D"..." defines the directory to set first as current directory before running the command specified next. %~dp0 references the directory of the batch file containing these commands. This path always ends with a backslash. Therefore no backslash must be added on concatenating the directory of the batch file with a file or folder name or path.
Run in a command prompt window call /? for help on %~dp0 explaining how arguments of a batch file can be referenced from within a batch file.
See also the answer on How to call a batch file that is one level up from the current directory? explaining in total four different methods to call or run a batch file from within a batch file.
Finally read also the Microsoft documentations about the Windows kernel library function CreateProcess and the structure STARTUPINFO used by cmd.exe on every execution of an executable without or with usage of its internal command start. The options of start become more clear on having full knowledge about the kernel function and the structure used on Windows to run a program.

How to start powershell with a window title?

I have a batch file that allows me to go to particular folder based on my input.
d:
cd d:\test\bits
#ECHO off
cls
:start
ECHO.
ECHO 1. Perl
ECHO 2. Python
set choice=
set /p choice=type in number to go to appropriate code folder:
if not '%choice%'=='' set choice=%choice:~0,1%
if '%choice%'=='1' goto pl
if '%choice%'=='2' goto py
ECHO "%choice%" is not valid, try again
ECHO.
goto start
:pl
cd code\pl
goto end
:py
cd code\py
goto end
:end
start "bits"
At the end of execution, a command prompt window with the title "bits" opens up and is in the specified directory corresponding to the input choice. This is all good. But I want to have the same thing done with Powershell.
If, instead of start "bits", I put, start powershell, in the last line, I can get Powershell console to open. By doing this, I have two issues.
Powershell console is still in d:\test\bits folder and not in the one I intended it to go.
I cannot get the title to be bits
How do I get the functionality I want with Powershell?
From what I expected and what I was able to reproduce with your script, the current directory is set to the intended one (d:\test\bits\code\pl if I enter 1)
For the title part, you can do the following:
start powershell -NoExit -command "$Host.UI.RawUI.WindowTitle = 'bits'"
If you add this to your powershell profile.ps1 you can get the window title to show the current running script and if you are just opening a window with no script then 'pwsh' will be displayed.
Will be systematic with no need to add a line on top of each script. The other answers
combined with $MyInvocation.MyCommand seem to give the name of the profile.ps1 instead when running a script from the context menu.
This can also be tweaked to change the result.
[console]::title = Split-Path -Leaf ([Environment]::GetCommandLineArgs()[-1]).Replace('pwsh.dll','pwsh')
Works on both PS 5 and 7 . For ver. 5 replace pwsh.dll by powershell.exe