npocmaka
Which would be the easiest way within batch file?
At the moment I'm using PsList -t and parsing the result knowing that what I'm looking for will be under cmd.exe.
Any other ideas? External tools?
----------------------------
#2 05 Jul 2012 22:28
RG
See
START /?
and
TASKLIST /?
Just execute TASKLIST to see an example of its output.
Last edited by RG (05 Jul 2012 22:28)
Windows Shell Scripting and InstallShield
----------------------------
#3 05 Jul 2012 22:39
npocmaka
I'm familiar with START and TASKLIST.But they won't help me if I want the PID that I've just started.
But what if i want to start example.exe with already running instances of example.exe.And later I want to kill only mine instance.Or watch memory usage of my instance and so on.
Even powershell/vbscript does not help much here
----------------------------
#4 05 Jul 2012 23:07
npocmaka
wmic process call create "notepad.exe" | find "ProcessId"
Now If I find out how to use other properties of process query it will be great.
----------------------------
#5 06 Jul 2012 00:20
npocmaka
and a small script :
When I find more about wmic process will try to improve this.
Last edited by npocmaka (08 Jul 2012 19:52)
----------------------------
#6 09 Jul 2012 20:18
npocmaka
here's a little bit improved script (I've called mine startpid ,but the name does not really matter):
Code: Select all
@echo off
setlocal
set commandline=%1
set workdir=%~dpf2
call :DeQuote commandline
call :DeQuote workdir
if [%1] EQU [] (
call :EchoHelp
goto :eof
)
if [%1] EQU [-help] (
call :EchoHelp
goto :eof
)
if [%2] NEQ [] (
if not exist "%workdir%\" (
echo "directory %workdir% does not exist"
exit
)
) else (
set workdir=%~dp0
)
::this does not work good enough. If there are brackets in the parameters for loop has problems.
::for /f "usebackq tokens=2 delims=;= " %%G IN (`wmic process call create '"%commandline%","%workdir%",null' ^|find "ProcessId"`) do set /A PID=%%G
pushd %workdir%
for /f "tokens=2 delims=;= " %%G IN ('wmic process call create "%commandline%" ^|find "ProcessId"') do set /A PID=%%G
popd
if [%PID%] EQU [] (
echo process didn't start
goto :eof
) else (
echo %PID%
exit /b %pid%
)
::BEGIN FUNCTION::::::::::::::::::::::::::::::::::::::::
@ECHO OFF
:DeQuote
SET DeQuote.Variable=%1
CALL Set DeQuote.Contents=%%%DeQuote.Variable%%%
Echo.%DeQuote.Contents%|FindStr/brv ""^">NUL:&&Goto :EOF
Echo.%DeQuote.Contents%|FindStr/erv ""^">NUL:&&Goto :EOF
Set DeQuote.Contents=####%DeQuote.Contents%####
Set DeQuote.Contents=%DeQuote.Contents:####"=%
Set DeQuote.Contents=%DeQuote.Contents:"####=%
Set %DeQuote.Variable%=%DeQuote.Contents%
Set DeQuote.Variable=
Set DeQuote.Contents=
Goto :EOF
:: Written by Frank P. Westlake, 2001.09.22, 2001.09.24
:: Modified by Simon Sheppard 2002.06.09
:::::::::::::::::::::::::::::::::::::::::::::::::::::::
:EchoHelp
echo starts a process and return PID
echo %~n0 command_line [work_directory]
echo %~n0 -help -will print this message
echo PID of the process will be echoed and set to the errorlevel
goto :EOF
endlocal
https://ss64.com/nt/syntax-dequote.html
The main difference is the added workdir where the process will be started (I'm not sure how big improvement is this )
the PID will be returned as a errorlevel (is it possible to overflow errorlevel's max number allowed?(no - pid is int errorlevel is long))
As this calling of creating a process with wmic wmic process call create "calc.exe" is more popular , but
with this wmic process call create "notepad.exe","c:\",null or this wmic process call create "notepad.exe","c:\"
you can create a process in a certain directory.
The third parameter is a Win32_ProcessStartup -> https://docs.microsoft.com/en-gb/window ... 32-process
but I don't know if it can be created in a WMIC query and how can be used.
It can add more useful options -> https://docs.microsoft.com/en-gb/window ... essstartup
Any idea how this can be used (may be in powershell script it will be possible)?
Creating a process on a remote host is also possible but the processing the parameters will became a mess smile
Last edited by npocmaka (11 Jul 2012 20:59)
----------------------------
#7 12 Jul 2012 21:20
npocmaka
There are a lot of improvements now
Code: Select all
@echo off
setlocal
if [%1] EQU [] (
call :echoHelp
goto :eof
)
if [%1] EQU [-help] (
call :echoHelp
goto :eof
)
set /A shifter=1
set workdir=.
:argParser
if [%1] EQU [-exec] (
set exec=%2
)
if [%1] EQU [-commandline] (
set commandline=%2
)
if [%1] EQU [-workdir] (
set workdir=%2
)
if [%1] EQU [-host] (
set host=%2
)
if [%1] EQU [-user] (
set user=%2
)
if [%1] EQU [-pass] (
set pass=%2
)
if [%1] EQU [-record] (
set record=%2
)
shift
shift
set /A shifter=%shifter% + 1
if %shifter% EQU 7 (
goto :endArgParser
)
goto :argParser
:endArgParser
call :DeQuote exec
call :DeQuote commandline
call :DeQuote workdir
call :DeQuote host
call :DeQuote user
rem call :DeQuote pass
rem echo exec - %exec%
rem echo commandline - %commandline%
rem echo workdir - %workdir%
rem echo host - %host%
rem echo user - %user%
rem echo pass - %pass%
rem echo record - %record%
if [%exec%] EQU [] (
echo executable not defined
goto :eof
)
if [%host%] NEQ [] (
set host_param=/NODE:%host%
if [%user%] NEQ [] (
set user_param=/USER:%user%
if [%pass%] NEQ [] (
set pass_param=/PASSWORD:%pass%
)
)
)
if [%record%] NEQ [] (
set record_param=/RECORD:%record%
)
set global_params=%record_param% %host_param% %user_param% %pass_param%
for /f "usebackq tokens=*" %%G IN (`wmic %global_params% process call create "%exec% %commandline%"^,"%workdir%"`) do (
rem echo %%G
echo %%G | find "ProcessId" >nul
IF %ERRORLEVEL% EQU 0 (
for /f "tokens=2 delims=;= " %%H in ('echo %%G ^| find "ProcessId"') do (
call set /A PID=%%H
rem echo %%H
goto :endLoop1
)
)
echo %%G | find "ReturnValue" >nul
IF %ERRORLEVEL% EQU 0 (
for /f "tokens=2 delims=;= " %%I in ('echo %%G ^| find "ReturnValue"') do (
call set /A RETCOD=%%I
rem echo %%I
goto :endLoop2
)
)
call :concat "%%G"
)
goto :endloop3
::successful execution
:endLoop1
if %PID% NEQ 0 (
echo %PID%
exit /B %PID%
)
::unsuccessful with code
::check the return code and give hints
:endLoop2
echo return code : %RETCOD%
if %RETCOD% EQU 2 (
echo -Access Denied
)
if %RETCOD% EQU 3 (
echo -Insufficient Privilege
)
if %RETCOD% EQU 8 (
echo -Unknown failure
echo Hint: Check if the executable and workdit exists or if command line parameters are correct.
)
if %RETCOD% EQU 9 (
echo -Path Not Found
echo Hint: check if the work exists on the remote machine.
)
if %RETCOD% EQU 21 (
echo -Invalid Parameter
echo Hint: Check executable path.Check if host and user are correct.
)
exit /b 0
goto :eof
::unsuccessful with no code
:endloop3
echo %output%
echo HINT :brackets,quotes or commas in the password may could break the script
goto :eof
endlocal
goto :eof
:echoHelp
echo %~n0 -exec executubale [-commandline command_line] [ -workdir working_directory] [-host remote_host [-user user [-pass password]]] [-record path_to_xml_output]
echo\
echo localhost cant' be used as in -host variable
echo Examples:
echo %~n0 -exec "notepad" -workdir "c:/" -record "test.xml" -commandline "/A startpid.txt"
echo %~n0 -exec "cmd" -workdir "c:/" -record "test.xml" -host remoteHost -user User
goto :eof
:concat
call set output=%output% %1
goto :eof
:DeQuote
SET DeQuote.Variable=%1
CALL Set DeQuote.Contents=%%%DeQuote.Variable%%%
Echo.%DeQuote.Contents%|FindStr/brv ""^">NUL:&&Goto :EOF
Echo.%DeQuote.Contents%|FindStr/erv ""^">NUL:&&Goto :EOF
Set DeQuote.Contents=####%DeQuote.Contents%####
Set DeQuote.Contents=%DeQuote.Contents:####"=%
Set DeQuote.Contents=%DeQuote.Contents:"####=%
Set %DeQuote.Variable%=%DeQuote.Contents%
Set DeQuote.Variable=
Set DeQuote.Contents=
Goto :EOF
::DeQuote ->
:: Written by Frank P. Westlake, 2001.09.22, 2001.09.24
:: and modified by Simon Sheppard 2002.06.09
I've added an options for execution on remote machine.Now I'm parsing also error codes and trying to give some hints.In some cases there's no error code - just a error message and it's also printed. The target executable and its parameters are now separated in two arguments.
I've added an option for recording the wmic command to xml file using wmic /RECORD swith (this was useful durring the testing).
here are the params:
-exec executable : path to executable or the executable if it's in the %PATH%
[-commandline command_line] : command line parameters
[ -workdir working_directory] : working directory.Now I'm not checking the existence of the directory because of the remote host execution.
[-host remote_host [-user user [-pass password]]] : not hard to guess
wmi has a limitation and localost can't be used with user and password.May be I should add check if the host is localhost.
[-record path_to_xml_output] : path for xml used in /RECORD switch - there you'll see the wmi command and full output
In the previous version working directory didn't worked in the wmic query because the FOR /F had eating the "," - now works fine with "^,"
(why the "," is problem for the for /f ? )
Still have a problems with brackets and double quotes in password parameter - it uses wmic /PASSWORD switch and is not parsed well.
Return codes are taken form here : https://docs.microsoft.com/en-gb/window ... 32-process
I still hadn't produced 2 and 3 . 9 is thrown only where the path does not exist on remote machine.
the PID is still stored in errorlevel
I'm still not sure if other global switches could be useful.
examples :
startpid -exec "notepad" -workdir "c:/" -record "test.xml" -commandline "/A startpid.txt"
startpid -exec "cmd" -workdir "c:/" -record "test.xml" -host remoteHost -user User (<-- without pass it will be prompted)
Last edited by npocmaka (12 Jul 2012 21:30)
----------------------------
#8 16 Jul 2012 15:29
smerch
Slightly beautified version (for procedural approach, more like programming style)
Code: Select all
@echo off
setlocal enabledelayedexpansion
if {%~1} NEQ {} (
if {%~1} NEQ {-help} (
call :proc %*
exit /b %ERRORLEVEL%
)
)
call :echoHelp
exit /b
:proc
call :argParser %*
if {%exec%} EQU {} (
call :err 1000
exit /b %ERRORLEVEL%
)
if {%host%} NEQ {} (
set host=/NODE:%host%
if {%user%} NEQ {} (
set user=/USER:%user%
if {%pass%} NEQ {} (
set pass=/PASSWORD:%pass%
)
)
)
if {%record%} NEQ {} (
set record=/RECORD:%record%
)
set global_params=%record% %host% %user% %pass%
for /f "usebackq tokens=*" %%G IN (`wmic %global_params% process call create "%exec% %commandline%"^,"%workdir%"`) do (
rem echo %%G
echo %%G | find "ProcessId" > nul && (
for /f "tokens=2 delims=;= " %%H in ('echo %%G') do (
call set /A PID=%%H
)
)
echo %%G | find "ReturnValue" > nul && (
for /f "tokens=2 delims=;= " %%I in ('echo %%G') do (
call set /A RETCOD=%%I
)
)
call :concat "%%G"
)
rem successful execution
if %PID% NEQ 0 (
echo %PID%
exit /b
rem exit /B %PID%
) else (
call :err %RETCOD%
)
exit /b %ERRORLEVEL%
:argParser
set comstr=-exec-commandline-workdir-host-user-pass-record
for /L %%i in (1,1,7) do (
echo %comstr% | find "%~1" > nul && (
set _tmp=%~1
set !_tmp:-=!=%~2
)
shift
shift
)
set _tmp=
exit /b
:echoHelp
echo %~n0 -exec executubale {-commandline command_line} { -workdir working_directory}
echo {-host remote_host {-user user {-pass password}}} {-record path_to_xml_output}
echo\
echo localhost cant' be used as in -host variable
echo Examples:
echo %~n0 -exec "notepad" -workdir "c:/" -record "test.xml" -commandline "/A startpid.txt"
echo %~n0 -exec "cmd" -workdir "c:/" -record "test.xml" -host remoteHost -user User
exit /b
:concat
call set output=%output% ^& echo %~1
exit /b
:err
if %1 EQU 2 (set errmsg=Access Denied)
if %1 EQU 3 (set errmsg=Insufficient Privilege)
if %1 EQU 8 (set errmsg=Unknown failure ^& echo Hint: Check if the executable and workdit exists or if command line parameters are correct.)
if %1 EQU 9 (set errmsg=Path Not Found ^& echo Hint: check if the work exists on the remote machine.)
if %1 EQU 21 (set errmsg=Invalid Parameter ^& echo Hint: Check executable path.Check if host and user are corect.)
if %1 EQU 1000 (set errmsg=Executable not defined.)
if {%errmsg%} EQU {} (set errmsg=%output% ^& echo Hint: brackets,quotes or commas in the password may could breack the script.)
echo %errmsg%
exit /b %1
#9 16 Jul 2012 17:12
npocmaka
Yeaaaah.
I like the "&&" in the loop and argparser enhancements.
I've tested this but strangely the workdir parameter is never set (it's seems it should work).
And when script fails to create process it prints : "0 was unexpected at this time."
Also a mysterious empty Create() file is created.
I need some testing to see what's going on (for test reasons wmic /record:c:\test.xm %global_params% process call create "%exec% %commandline%"^,"%workdir% can be used")
Last edited by npocmaka (16 Jul 2012 17:12)
----------------------------
#10 17 Jul 2012 08:54
smerch
Ok. Here more working version:
Code: Select all
@echo off
setlocal enabledelayedexpansion
if {%~1} NEQ {} (
if {%~1} NEQ {-help} (
call :proc %*
exit /b %ERRORLEVEL%
)
)
call :echoHelp
exit /b
:proc
call :argParser %*
if {%exec%} EQU {} (
call :err 1000
exit /b %ERRORLEVEL%
)
if {%host%} NEQ {} (
set host=/NODE:%host%
if {%user%} NEQ {} (
set user=/USER:%user%
if {%pass%} NEQ {} (
set pass=/PASSWORD:%pass%
)
)
)
if {%record%} NEQ {} (
set record=/RECORD:%record%
)
set global_params=%record% %host% %user% %pass%
for /f "usebackq tokens=*" %%G IN (`wmic %global_params% process call create "%exec% %commandline%"^,"%workdir%"`) do (
rem echo %%G
set _tmp=%%G
set _tmp=!_tmp:^>=^^^>!
echo !_tmp! | find "ProcessId" > nul && (
for /f "tokens=2 delims=;= " %%H in ('echo !_tmp!') do (
call set /A PID=%%H
)
)
echo !_tmp! | find "ReturnValue" > nul && (
for /f "tokens=2 delims=;= " %%I in ('echo !_tmp!') do (
call set /A RETCOD=%%I
)
)
call :concat
)
set _tmp=
rem successful execution
if {%PID%} NEQ {} (
echo %PID%
exit /b
rem exit /B %PID%
) else (
call :err %RETCOD%
)
exit /b %ERRORLEVEL%
:concat
call set output=%output% ^& echo !_tmp:^>=^^^>!
exit /b
:argParser
set comstr=-exec-commandline-workdir-host-user-pass-record
:nextShift
set /A shifter=shifter+1
echo %comstr% | find "%~1" > nul && (
set _tmp=%~1
set !_tmp:-=!=%~2
)
shift & shift
if %shifter% LSS 7 goto :nextShift
set _tmp=
set shifter=
exit /b
:echoHelp
echo %~n0 -exec executubale {-commandline command_line} { -workdir working_directory}
echo {-host remote_host {-user user {-pass password}}} {-record path_to_xml_output}
echo\
echo localhost cant' be used as in -host variable
echo Examples:
echo %~n0 -exec "notepad" -workdir "c:/" -record "test.xml" -commandline "/A startpid.txt"
echo %~n0 -exec "cmd" -workdir "c:/" -record "test.xml" -host remoteHost -user User
exit /b
:err
if %1 EQU 2 (set errmsg=Access Denied)
if %1 EQU 3 (set errmsg=Insufficient Privilege)
if %1 EQU 8 (set errmsg=Unknown failure ^& echo Hint: Check if the executable and workdir exists or if command line parameters are correct.)
if %1 EQU 9 (set errmsg=Path Not Found ^& echo Hint: check if the workdir exists on the remote machine.)
if %1 EQU 21 (set errmsg=Invalid Parameter ^& echo Hint: Check executable path.Check if host and user are correct.)
if %1 EQU 1000 (set errmsg=Executable not defined.)
if {%errmsg:~0,1%} EQU {} (set errmsg=%output% ^& echo Hint: brackets,quotes or commas in the password may could break the script.)
echo %errmsg%
exit /b %1
Second. Create() file was created due to appearance of "Blah blah -> Create()" to echo command which was interpreted as attempt to write to Create() file — so I made some "circum masking" to prevent that.
Third. "0 was unexpected at this time." was caused by syntax error in if operator due to empty %PID% — curly braces solve this issue.
P.S. Have to use %errmsg:~0,1% construction in :err to prevent appearance of interpreted commands after if operator and syntax errors.
Last edited by smerch (17 Jul 2012 10:13)
----------------------------
#11 17 Jul 2012 13:25
npocmaka
Fast initial testing:
1.When I try to set an executable with spaces in it's path it can't be found - still need dequote.At least it's easy for fix
2.Setting arguments is outside of setlocal enabledelayedexpansion scope and wmic global parameters are not cleaned ( EDIT: Aaahh with your last edit this is fixed)
Last edited by npocmaka (17 Jul 2012 13:25)
----------------------------
#12 17 Jul 2012 20:50
smerch
New even more working version.
Code: Select all
@echo off
setlocal enabledelayedexpansion
if "%~1" NEQ "" (
if "%~1" NEQ "-help" (
call :proc %*
exit /b %ERRORLEVEL%
)
)
call :echoHelp
exit /b
:proc
call :argParser %*
if "%exec%" EQU "" (
call :err 1000
exit /b %ERRORLEVEL%
)
if "%host%" NEQ "" (
set host=/NODE:%host%
if "%user%" NEQ "" (
set user=/USER:%user%
if "%pass%" NEQ "" (
set pass=/PASSWORD:%pass%
)
)
)
if "%record%" NEQ "" (
set record=/RECORD:%record%
)
set global_params=%record% %host% %user% %pass%
for /f "usebackq tokens=*" %%G IN (`wmic %global_params% process call create "%exec% %commandline%"^,"%workdir%"`) do (
rem echo %%G
set _tmp=%%G
set _tmp=!_tmp:^>=^^^>!
echo !_tmp! | find "ProcessId" > nul && (
for /f "tokens=2 delims=;= " %%H in ('echo !_tmp!') do (
call set /A PID=%%H
)
)
echo !_tmp! | find "ReturnValue" > nul && (
for /f "tokens=2 delims=;= " %%I in ('echo !_tmp!') do (
call set /A RETCOD=%%I
)
)
call :concat
)
set _tmp=
rem successful execution
if "%PID%" NEQ "" (
echo %PID%
exit /b
rem exit /B %PID%
) else (
call :err %RETCOD%
)
exit /b %ERRORLEVEL%
:concat
call set output=%output% ^& echo !_tmp:^>=^^^>!
exit /b
:argParser
set comstr=-exec-commandline-workdir-host-user-pass-record
:nextShift
set /A shifter=shifter+1
echo %comstr% | find "%~1" > nul && (
set _tmp=%~1
set !_tmp:-=!=%~2
)
shift & shift
if %shifter% LSS 7 goto :nextShift
set _tmp=
set shifter=
exit /b
:echoHelp
echo %~n0 -exec executubale {-commandline command_line} { -workdir working_directory}
echo {-host remote_host {-user user {-pass password}}} {-record path_to_xml_output}
echo\
echo localhost cant' be used as in -host variable
echo Examples:
echo %~n0 -exec "notepad" -workdir "c:/" -record "test.xml" -commandline "/A startpid.txt"
echo %~n0 -exec "cmd" -workdir "c:/" -record "test.xml" -host remoteHost -user User
exit /b
:err
if %1 EQU 2 (set errmsg=Access Denied)
if %1 EQU 3 (set errmsg=Insufficient Privilege)
if %1 EQU 8 (set errmsg=Unknown failure ^& echo Hint: Check if the executable and workdit exists or if command line parameters are correct.)
if %1 EQU 9 (set errmsg=Path Not Found ^& echo Hint: check if the workdir exists on the remote machine.)
if %1 EQU 21 (set errmsg=Invalid Parameter ^& echo Hint: Check executable path. Check if host and user are corect.)
if %1 EQU 1000 (set errmsg=Executable not defined.)
if "%errmsg:~0,1%" EQU "" (set errmsg=%output% ^& echo Hint: brackets, quotes or commas in the password may could breack the script.)
echo %errmsg%
exit /b %1
Second. setlocal statement defines a local "scope of visibility" for variables, bounded by endlocal, exit or end of file; so any called subroutine will share same variables within same scope. Scopes can be nested, so new scope in subroutine (declared by setlocal) will have all variables of parent scope but any changes to variables will not be visible to parent scope. Conclusion: all shared variables must be defined within same scope.
Last edited by smerch (18 Jul 2012 09:36)
----------------------------
#13 18 Jul 2012 11:43
smerch
Btw, npocmaka, if you can give me a list of not permitted characters for password I can make changes to :argParser so it can deal with them wink
Last edited by smerch (18 Jul 2012 11:44)