How to make two running command-prompt windows sen

2019-08-22 05:52发布

I am somewhat new to using the command-prompt for programming related purposes so if this makes no sense or seems unclear please request that I elaborate and I will do my best.

What I am hoping to be able to do is have two command-prompt windows open on my windows machine (running Windows 7) and have them communicate with each other. For instance I want Cmd window A to tell Cmd window B to print the contents of a file and vice versa.

Is this in anyway possible? Also, I know there may be a way to do this by polling a file in one Command-prompt window, but I would like an asynchronous/non-blocking way of doing this if it is possible.

Thanks in advance!

3条回答
倾城 Initia
2楼-- · 2019-08-22 06:05
@ECHO Off
SETLOCAL ENABLEDELAYEDEXPANSION 
:: %1 supplied to routine specifies the instance name
SET "myname=%1"
:: A communications area...
SET "flagdir=U:\comms"
:: Log this instance in - file "name.run"
ECHO.>"%flagdir%\%myname%.run"
:: grab hundredths-of-seconds to modify %random%
FOR /f "tokens=2delims=." %%a IN ("%time%") DO SET /a randmod=1%%a-100
:: record of other-instances-found
SET "othero="

:: Loop runs about every second

:loop
PING -n 2 127.0.0.1 >NUL
:: If the file "quit" exists, terminate
IF EXIST "%flagdir%\quit" GOTO endrun
:: look for others
SET "others="
FOR /f %%a IN ('dir/b "%flagdir%\*.run"') DO IF /i %%~na neq %myname% SET "others=!others! %%~na"
:: Report if changed
IF "%othero%" neq "%others%" CALL :report "I see %others% now"
SET "othero=%others%"
:: 2% chance of doing something...
SET /a selection=(%randmod% + (%RANDOM% %% 100)) %% 100
ECHO %selection%
IF %selection%==37 (CALL :instruct count) ELSE IF %selection%==51 (CALL :instruct repeat)
:: Do I have any instructions?
IF NOT EXIST "%flagdir%\*.%myname%" GOTO loop
:: I've been sent instructions
FOR %%i IN ("%flagdir%\*.%myname%") DO (
 SET /p instruction=<"%%i"
 DEL "%%i"
 CALL :report "%%~ni instructs ===!instruction!==="
 CALL :execute
)
GOTO loop

:endrun
DEL "%flagdir%\%myname%.run"

GOTO :EOF

:report
ECHO %TIME% %~1
GOTO :eof

:instruct
:: instruct another instance - select destination
SET /a found=0
FOR %%a IN (%othero%) DO SET /a found+=1
SET /a selection=(%RANDOM% %% %found%) + 1
FOR /f "tokens=%selection%" %%a IN ('echo %othero%') DO SET sendto=%%a
SET /a selection=4 + (%RANDOM% %% 8)
SET "line=%1 %selection%"
CALL :report "to %sendto%: %line%"
>"%flagdir%\%myname%.%sendto%" ECHO %line%

GOTO :eof

:: Instructions that may be passed
:count
FOR /l %%z IN (1,1,%1) DO ECHO count...%%z
GOTO :eof
:repeat
FOR /l %%z IN (1,1,%1) DO ECHO repeat...%1
GOTO :eof

:execute
CALL :%instruction%
GOTO :eof

Here's a way...

Starting with an empty directory (U:\comm), you can start any number of instances of the batch, each with a unique name as its first parameter.

Establish a file called instancename.run to flag that a routine is running.

The caper with "randmod" is designed to modify the return of %random% by recording the hundredths-of-a-second. Two batch files starting at "the same" time will generate the same sequence of random numbers, but the hundredths-of-a-second will likely be different. To supplement this, I'd invoke the above as

start thisbatch fred&ping -n 3 127.0.0.1&start thisbatch derf&ping -n 3 127.0.0.1&start thisbatch blue&ping -n 3 127.0.0.1&start thisbatch pink

In a loop controlled by the ping timeout, we then see whether the flagfile "quit" exists and if it does, delete the instancename.run file (and quit)

Otherwise, look for other names that are running (*.run files) and set others to a list of those instancenames. If it changes from the previous version, report the change (this is solely for demo purposes, of course.)

Then select a random number 0..99, modifying the returned random to get over synchronisation (it's quick and dirty for a demonstration. Doesn't need to be exact...)

If the chosen number is 37 then send a "count" insruction to another instance, else if it's 51, send a "repeat" instruction (just for demo - 1% chance of each)

The instruct routine chooses a destination from the list of other instances and builds an instruction (count/repeat + a random number) which is recorded in a file called thisinstancename.destinationinstance

Then we check to see whether we've received an instruction and if we have, we execute it.

The two routines count and repeat simply show different things in the destination instance - all for demonstration purposes.

The selection is echoed for security-blanket purposes - showing that the loop's still running and displaying a significant number controlling the destination process.

查看更多
来,给爷笑一个
3楼-- · 2019-08-22 06:13

The only way of interaction of 2 cmd windows is to call one from another from a batch file. You can pass variables from one to another.

E.g. you can set a variable in one batch and then call the second one from the first passing a variable as an input parameter. here is an example when I determine SID value for user user first and then pass it to the script for running it to patch the computer remotely.

@echo off
setlocal
echo.
:entercname
set /p cname=Please enter computer name or IP address: 
if not defined cname goto entercname
echo.
FOR /F %%a IN ('psgetsid \\%cname% %uname% /accepteula') DO set sid=%%a
echo %uname%'s SID is %sid%
echo.

start /wait cmd /c c:\temp\run_lync_fix.bat %sid%

What I have in the second batch that I run from the first one is:

@echo off
set sid=%1
echo SID is %sid%
REG ADD HKU\%sid%\Software\Policies\Microsoft\Communicator /v GalDownloadInitialDelay /t REG_DWORD /d 0 /f
REG ADD HKU\%sid%\Software\Policies\Microsoft\Office\15.0\Lync /v GalDownloadInitialDelay /t REG_DWORD /d 0 /f
REG ADD HKLM\Software\Policies\Microsoft\Communicator /v GalDownloadInitialDelay /t REG_DWORD /d 0 /f
IF %ERRORLEVEL% EQU 0 (echo Registry patched.) ELSE (Echo Error. Registry not patched.)
ping -n 5 localhost > nul

So I pass %sid% from first batch and second one accepts it via set sid=%1.

The second tip is to store some variable to a temp or txt file in one batch and to read from it in another batch.

@echo off
Setlocal EnableDelayedExpansion
reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Render" > c:\temp\reg.txt
for /f %%a in ('find /c /v "" ^< "c:\temp\reg.txt"') do set count=%%a
echo Number of lines: !count!
for /l %%i in (2,1,!count!) do (
echo Current line is: %%i
for /f "tokens=2 delims=]" %%b in ('find /n /v "" ^< "c:\temp\reg.txt" ^| findstr "^\[%%i\]"') do set test=%%b
set regstring=!test!^\Properties
echo !regstring!
for /f "tokens=3*" %%c in ('reg query !regstring! ^/v "{a45c254e-df1c-4efd-8020-67d146a850e0},2"') do set value=%%c %%d
echo !value!
)

This code stores a set of registry subkeys from a specific key to reg.txt. Then we read this file line by line in for /l cycle.

查看更多
来,给爷笑一个
4楼-- · 2019-08-22 06:19

I found it quite simple to make two command windows interact with each other.

Batch file 1:

:keepsending
set /p message=
Echo set run=%message% >command.bat
goto :keepsending

Batch file 2:

:running
%run%
set ran=%run%
:check
if not "%ran%"=="%run%" goto :running
call command.bat
timeout 1 >nul
goto :check

Add in a counter on it and i would guess you could make it work in a longer code that interacts with each other.

If you want it to work over your network then use poshd/popd

查看更多
登录 后发表回答