echo The error level is: %ERRORLEVEL%
Produces
>The error level is: 15
What I would like:
>The error level is: F
do I need to do conversions or is there a way to display numbers differently?
Any help in the right direction is appreciated, thanks.
It was a long time ago, I was very bored.
cmdcalc.cmd
#echo off
if not defined trace set trace=rem
%trace% on
SetLocal
if "%1"=="/?" (
call :help %0
goto :eof
)
Set MinInBase=
if /i "%2" EQU "Bin" call :DoBin %1
if /i "%2" EQU "Hex" call :DoHex %1
If not defined BinStr call :DoDec %1
EndLocal & set RET=%RET%
goto :eof
:DoBin
Set MinInBase=2
Set ShiftBy=1
Set StartSyn=0b
call :DoCalc %1
goto :eof
:DoHex
Set MinInBase=16
Set ShiftBy=4
Set StartSyn=0x
call :DoCalc %1
goto :eof
:DoDec
if {%1} EQU {} goto :eof
set /a BinStr=%1
set RET=%BinStr%
echo %RET%
goto :eof
:DoCalc
Set BinStr=
SET /A A=%1
%Trace% %A%
:StartSplit
SET /A B="A>>%ShiftBy%"
%Trace% %B%
SET /A C="B<<%ShiftBy%"
%Trace% %C%
SET /A C=A-C
%Trace% %C%
call :StringIt %C%
If %B% LSS %MinInBase% goto :EndSplit
set A=%B%
goto :StartSplit
:EndSplit
call :StringIt %B%
set RET=%StartSyn%%BinStr%
Echo %RET%
EndLocal & set RET=%RET%
goto :eof
:StringIt
set Bin=0123456789ABCDEF
FOR /F "tokens=*" %%A in ('echo "%%BIN:~%1,1%%"') do set RET=%%A
set ret=%ret:"=%
Set BinStr=%Ret%%BinStr%
goto :eof
:help
echo %1 syntax:
echo.
echo %1 Calculation [Hex^|Bin]
echo.
echo eg %1 12*2 Hex
echo.
echo gives 0x18.
goto :eof
According to the external resource Windows Environment Variables, there is an undocumented built-in read-only variable =ExitCode which returns the current exit code in hexadecimal format. To ensure the ErrorLevel value equals the exit code, use cmd /C exit %ErrorLevel%.
So if you are using this line code...:
cmd /C exit %ErrorLevel%
echo The error level is: %=ExitCode%
...you will receive this (supposing the ErrorLevel is 15):
The error level is: 0000000F
To get rid of the leading zeros, use this...:
cmd /C exit %ErrorLevel%
for /F "tokens=* delims=0" %%Z in ("%=ExitCode%") do set "HEXCODE=%%Z"
if not defined HEXCODE set "HEXCODE=0"
echo The error level is: %HEXCODE%
...to get this:
The error level is: F
Just write it in vbscript instead of batch
put the vbscript statement below into a file.
WScript.Echo Hex( WScript.Arguments(0) )
then to run it, simple type this on the command line ( in a batch script, use a for loop to capture the value if required )
C:\workspace> cscript //nologo hex.vbs 15
F
There is no need to install anything. vbscript comes by default in most windows systems.
perl -e"printf qq{The errorlevel is: %X\n}, $ENV{ERRORLEVEL}"
Requires Perl to be installed, of course, but that's easy to do.
Related
I've tried a few things but I can't seem to get my .bat file to give proper output and read past the first line of the input. Any help would be greatly appreciated. I am trying to create this for mass account creation in Active Directory.
#echo off
echo ---- >C:\NewUserCreation\createdusers.txt
setlocal
FOR /F "eol=; tokens=1-12* delims=~" %%i in (C:\NewUserCreation\newusers.txt) do (
set "_lastname=%%i"
set "_firsname=%%j"
set _QWERTY=%%k
call set _midinit=%%_QWERTY:~0,2%%
set _edipi=%%l
set _ptc=%%m
set _ranktitle=%%n
set _subcomponent=%%o
set _unit=%%p
set _position=%%q
set _email=%%r
set _descr=%%s
call :do_user
)
endlocal
notepad C:\NewUserCreation\createdusers.txt
goto :EOF
:do_user
if "%_midinit%"=="%_edipi%" goto :no_middlename
set _samacctname1=%_firsname%.%_midinit%.%_lastname%
set _userPrincipalName=%_edipi%
call :find_existing_user
call set _samacctname=%_samaccountname%
call set _lastinit=%%_lastname:~0,1%%
C:\NewUserCreation\admod -h mydomaincontroller -add -b "cn=%_lastname%\, %_firsname% %_midinit%,ou=NewUsers,ou=n,ou=n,dc=n,dc=n,dc=n,dc=n" objectclass::user "sn::%_lastname%" "givenname::%_firsname%" "initials::%_midinit%" "personaltitle::%_ranktitle%" "company::%_subcomponent%" "department::%_unit%" "PhysicalDeliveryOfficeName::%_position%" "title::%_position%" "employeetype::%_ptc%" "displayname::%_descr%" "description::%_descr%" "samaccountname::%_samacctname%" "st::Anywhere,US" "streetAddress::%_unit%" "postalCode::36805" "countryCode::111" "c::USA" "co::United States" "l::Corporation" "telephoneNumber::DSN 318-872-XXXX" "userPrincipalName::%_edipi%#domain" "userPassword::password"
if /I %ERRORLEVEL% EQU 0 (
set _resultcode=Success
if /I %_samnametest% EQU 274 (call set _resultcode=%%_resultcode%%-DUP)
) ELSE set _resultcode=-ERROR-
#echo on
sleep 15
net user %_samacctname% /DOMAIN /passwordreq:yes
C:\Windows\System32\dsquery * "ou=n,ou=n,dc=n,dc=n,dc=n,dc=n" -filter "(&(objectclass=user)(samaccountname=%_samacctname%))" -s mydomain |exchmbx -me SMTP:%_email%"
#echo off
echo %_resultcode%. . . %_samacctname% Contact: SMTP:%_email% >>C:\NewUserCreation\createdusers.txt
goto :EOF
:find_existing_userz
set _search4Name=%_samacctnamez%
call set _samNameSearchz=%%_search4Name:~0,20%%
call set _samNameSearchzv=%%_search4Name:~0,16%%274
C:\Windows\System32\dsquery * "ou=n,ou=n,dc=n,dc=n,dc=n,dc=n" -filter "(&(&(samaccountname=%_search4Name%)(ObjectClass=User))(!objectClass=computer))" -attr samaccountname|find /I "%_samNameSearchz%" >"%_samNameSearchz%.tmp"
call :samnamefilesizez %_samNameSearchz%.tmp _samNameSearchsizez
del %_samNameSearchz%.tmp
if /I %_samNameSearchsizez% LEQ 1 (set _samaccountnamez=%_samNameSearchz%) ELSE (
set _samaccountnamez=%_samNameSearchzv%
set _lastnamez=%_lastnamez%274
)
echo resulting_sam_account_name %_samaccountnamez%
call set _samnametestz=%_samaccountnamez:~-3%
goto :EOF
:find_existing_user
set _search4Name=%_samacctname1%
call set _samNameSearch=%%_search4Name:~0,20%%
call set _samNameSearchv=%%_search4Name:~0,16%%274
C:\Windows\System32\dsquery * "ou=n,ou=n,dc=n,dc=n,dc=n,dc=n" -filter "(&(&(samaccountname=%_samNameSearch%)(ObjectClass=User))(!objectClass=computer))" -attr samaccountname|find /I "%_samNameSearch%" >%_samNameSearch%.tmp
call :samnamefilesize %_samNameSearch%.tmp _samNameSearchsize
del %_samNameSearch%.tmp
if /I %_samNameSearchsize% LEQ 1 (set _samaccountname=%_samNameSearch%) ELSE (
set _samaccountname=%_samNameSearchv%
set _lastname=%_lastname%274
)
echo resulting_sam_account_name %_samaccountname%
call set _samnametest=%_samaccountname:~-3%
goto :EOF
:samnamefilesize
set %2=%~z1
goto :EOF
:samnamefilesizez
set %2=%~z1
goto :EOF
pause
I would suggest that you are calling :do_user, and that is going to :no_middlename. I can only guess that there is nothing at :no_middlename returning it to the call within your original for loop.
I have a subroutine like the following:
:RunProc
SETLOCAL
REM Some code here
:PROC_OK
set RetVal=0
goto PROC_END
:PROC_ERR
set RetVal=1
goto PROC_END
:PROC_END
ENDLOCAL & set ProcResult=%RetVal%
goto:eof
when I call it from other point of the cmd
CALL :RunProc %A% %B%
echo "%ProcResult%"
it doesn't return the %ProcResult% that instead is empty.
What is wrong?
Thanks,
Gianluca
The multithreading part was already replied here and works great (thanks a lot to Magoo)
Main code
SET /a instances=%NUMBER_OF_PROCESSORS%
:: make a tempfile
:maketemp
SET "tempfile=%temp%\%random%"
IF EXIST "%tempfile%?" (GOTO maketemp) ELSE (ECHO.>"%tempfile%a")
::
:loop
SET "nextfile=%~1"
IF NOT DEFINED nextfile (
DEL "%tempfile%a*" >NUL 2>NUL
::ECHO all done
exit
)
FOR /L %%a IN (1,1,%instances%) DO (
IF NOT EXIST "%tempfile%a%%a" (
>"%tempfile%a%%a" ECHO.
START /B "Instance %%a" oneconversion.bat "%~1" "%tempfile%a%%a" %%a
SHIFT
GOTO loop
)
)
timeout /t 1 >NUL
GOTO loop
Code example of oneconversion.bat
#ECHO OFF
SETLOCAL
CALL truepng.exe "%1"
CALL pngwolf.exe "%1"
DEL "%~2" >NUL 2>NUL
cls
exit
This works up to now.
But when I reserve first 10 parameters in use of commands.How I reserve commands
FOR /f "TOKENS=1-11*" %%a in ("%*") DO (
SET filelist=%%l
)
SET varresize=%1
SHIFT
SET varincsmall=%1
SET varwidth=%2
SET varheight=%3
SET varjpegqa=%4
SET varjpegpr=%5
SET varjpegex=%6
SET varpngqa=%7
SET varpngcl=%8
SET varpngqt=%9
I don't know how can I use %filelist% inside main code. And sure replacing %~1 with %filelist% doesn't work. Looks like I missed a point and couldn't find a way out.
Thanks for everyone will help or at least try to.
Add your variable initialization code at the start of the main script and shift the command line parameters additionally 9 times:
SET varresize=%1
SHIFT
SET varincsmall=%1
SET varwidth=%2
SET varheight=%3
SET varjpegqa=%4
SET varjpegpr=%5
SET varjpegex=%6
SET varpngqa=%7
SET varpngcl=%8
SET varpngqt=%9
for /L %%a in (1,1,9) do shift
Thus you won't need filelist, I think.
I have a batch file that takes an input file (in this case the file is a flat text file comprised of a file listing from a specified set of Windows XP system directories).
Then through a combination of a for loop to iterate through each file listed in the text file), setting a variable, using several call commands (in this case 9), and the find command to search the text file for files that appear in the output of other flat files.
The problem I am running into is that csrss.exe is using quite a bit of CPU processing. In reading some other articles it seems that csrss has a relationship with command line processing.
What I want to know is if there is a better way to do this that will:
Reduce overall script time.
Reduce CPU load.
Below is a sample of the script:
:: ------------------------------------------------------
:: Running Multiple Commands
:: ------------------------------------------------------
for /f "delims=?" %%A in (dir-selected_tmp.txt) do (
set filepath=%%A
call :filepathparse
call :md5hashchk
call :versionchk
call :densitychk
call :processchk
call :mutexchk
call :networkchk
call :injectedchk
call :persistservicechk
call :servicedllchk
call :persistrunchk
call :persistothchk
call :unsigneddllchk
call :filesysag
)
goto :comparison
:: ####################################################################
:filepathparse
for %%B in ("%filepath%") do (
set filename=%%~nxB
)
goto :eof
:: ####################################################################
:md5hashchk
for /f "delims= " %%b in ('md5deep.exe "%filepath%"') do set hashvalue=%%b
goto :eof
:: ####################################################################
:versionchk
for /f "delims= " %%e in ('sigcheck.exe /accepteula -q -n "%filepath%"') do set versionvalue=%%e
goto :eof
:: ####################################################################
:densitychk
for /f "delims= " %%d in ('densityscout.exe -p 0.1 "%filepath%"') do set densityvalue=%%d
goto :eof
:: ####################################################################
:processchk
find.exe /I "%filepath%" %temp_outpath%\wmic-processes.txt > nul 2>&1 && goto processexist
set isprocess=NoActiveProc
goto :eof
:processexist
set isprocess=ActiveProc
goto :eof
:: ####################################################################
:mutexchk
if "%startup_chk%"=="-b" (
goto :mutexbl
)
find.exe /I "%filepath%" %temp_outpath%\filesystem-handles_compared.txt > nul 2>&1 && goto mutexexist
set ismutex=NoNewActiveMutex
goto :eof
:mutexexist
set ismutex=NewActiveMutex
goto :eof
:mutexbl
find.exe /I "%filepath%" %parsed_outpath%\filesystem-handles.txt > nul 2>&1 && goto mutexexist
set ismutex=NoNewActiveMutex
goto :eof
:mutexexist
set ismutex=NewActiveMutex
goto :eof
:: ####################################################################
:networkchk
find.exe /I "%filename%" %temp_outpath%\tcpvcon_tmp.txt > nul 2>&1 && goto networkexist
set isnetwork=NoActiveNetwork
goto :eof
:networkexist
set isnetwork=ActiveNetwork
goto :eof
:: ####################################################################
:injectedchk
find.exe /I "%filepath%" %temp_outpath%\injecteddll_tmp.txt > nul 2>&1 && goto injectedexist
set isinjected=NoActiveInject
goto :eof
:injectedexist
set isinjected=ActiveInject
goto :eof
:: ####################################################################
:persistservicechk
find.exe /I "%filepath%" %temp_outpath%\autoruns-services_tmp.txt > nul 2>&1 && goto serviceexist
set isservice=NoInstalledService
goto :eof
:serviceexist
set isservice=InstalledService
goto :eof
:: ####################################################################
:servicedllchk
find.exe /I "%filepath%" %temp_outpath%\registry_hklm_installed_service_dlls_final.txt > nul 2>&1 && goto servicedllexist
set isservicedll=NoInstalledServiceDLL
goto :eof
:servicedllexist
set isservicedll=InstalledServiceDLL
goto :eof
:: ####################################################################
:persistrunchk
find.exe /I "%filepath%" %temp_outpath%\autoruns-run_tmp.txt > nul 2>&1 && goto runpersistexist
set isrunpersist=NoRunPersist
goto :eof
:runpersistexist
set isrunpersist=RunPersist
goto :eof
:: ####################################################################
:persistothchk
find.exe /I "%filepath%" %temp_outpath%\autoruns-oth_tmp5.txt > nul 2>&1 && goto persistothexist
set isothpersist=NoOtherPersist
goto :eof
:persistothexist
set ispersist=OtherPersist
goto :eof
:: ####################################################################
:unsigneddllchk
find.exe /I "%filepath%" %temp_outpath%\listdlls_temp2.txt > nul 2>&1 && goto unsigneddllexist
set isunsigneddll=NoUnSignedProcDLL
goto :eof
:unsigneddllexist
set isunsigneddll=UnSignedProcDLL
goto :eof
:: ####################################################################
:filesysag
:: Compiling Into Syslog Format
echo %datestamp%^|%currtime%^|%computername%^|%currip%^|%username%^|%lastlogintime%^|"%filepath%"^|%hashvalue%^|%versionvalue%^|%densityvalue%^|%isprocess%^|%ismutex%^|%isnetwork%^|%isinjected%^|%isservice%^|%isservicedll%^|%isrunpersist%^|%isothpersist%^|%isunsigneddll% >> %syslog_outpath%\%computername%-syslog.txt
:: Compiling Into Parsed Format
echo "%filepath%"^|%hashvalue%^|%versionvalue%^|%densityvalue%^|%isprocess%^|%ismutex%^|%isnetwork%^|%isinjected%^|%isservice%^|%isservicedll%^|%isrunpersist%^|%isothpersist%^|%isunsigneddll% >> %parsed_outpath%\%computername%-filesystem.txt
goto :eof
Sadly, your reluctance to provide further details means we are severely retricted on the amount of help we can offer.
I'd recommend:
First, build a list of the filepaths yu are interested in
(for /f "delims=?" %%A in (dir-selected_tmp.txt) do echo %%A )>paths_of_interest.txt
Then build temporary files containing a subset of the log data
findstr /I /g:paths_of_interest.txt %temp_outpath%\processes.txt >"%temp%\processes.x.txt"
Then re-process according to your original scheme, instead using paths_of_interest.txt and "%temp%\processes.x.txt"
This should reduce the amount of repetition, especially if you have long files.
:: ------------------------------------------------------
:: Running Multiple Commands
:: ------------------------------------------------------
:: Pre-processing
SET /a step=1000
SET /a dirstart=0
SET "dirskip="
:mainloop
SET /a dirsleft=0
SETLOCAL enabledelayedexpansion
(
for /f "%dirskip%delims=?" %%A in (dir-selected_tmp.txt) do (
SET /a dirsleft+=1
IF !dirsleft! leq %step% ECHO %%A
)
)>temp_dirs.txt
endlocal&SET /a dirsleft=%dirsleft%
FINDSTR /i /l /g:temp_dirs.txt "%temp_outpath%\wmic-processes.txt" >temp_filepathparse.txt
if "%startup_chk%"=="-b" (
FINDSTR /i /l /g:temp_dirs.txt "%parsed_outpath%\filesystem-handles.txt" >temp_mutexchk.txt
) ELSE (
FINDSTR /i /l /g:temp_dirs.txt "%temp_outpath%\filesystem-handles_compared.txt" >temp_mutexchk.txt
)
FINDSTR /i /l /g:temp_dirs.txt "%temp_outpath%\tcpvcon_tmp.txt" >temp_networkchk.txt
FINDSTR /i /l /g:temp_dirs.txt "%temp_outpath%\injecteddll_tmp.txt" >temp_injectedchk.txt
FINDSTR /i /l /g:temp_dirs.txt "%temp_outpath%\autoruns-services_tmp.txt" >temp_persistservicechk.txt
FINDSTR /i /l /g:temp_dirs.txt "%temp_outpath%\registry_hklm_installed_service_dlls_final.txt" >temp_servicedllchk.txt
FINDSTR /i /l /g:temp_dirs.txt "%temp_outpath%\autoruns-run_tmp.txt" >temp_persistrunchk.txt
FINDSTR /i /l /g:temp_dirs.txt "%temp_outpath%\autoruns-oth_tmp5.txt" >temp_persistothchk.txt
FINDSTR /i /l /g:temp_dirs.txt "%temp_outpath%\listdlls_temp2.txt" >temp_unsigneddllchk.txt
for /f "delims=" %%A in (temp_dirs.txt) do (
set "filepath=%%A"
call :filepathparse
....
call :filesysag
)
SET /a dirstart=%dirstart%+%step%
SET /a dirsleft=%dirsleft%-%step%
IF dirsleft gtr 0 SET dirskip=SKIP=%dirstart%&GOTO mainloop
goto :comparison
Then simply replace the filename in each of your routines :processchk to :unsigneddllchk with the corresponding temp_whatever.txt file created in the pre-processing. The switch on mutex is already done in the pre-processing.
This should reduce the searching done by the find command and hence the overall run time by selecting only those lines containing the target strings into the temp_* files created.
[Edit in response to further information provided]
Note the preprocessing block before the first findstr has been changed and that there is now a post-processing block between call :filesysag ) and goto :comparison
The object here is to reduce the size of the temp_dirs.txt file. I've arbitrarily chosen 1,000 (the size of step) but have no real idea of how big step should be. The larger it is, the quicker the process will be, but if it's too large, temp_dirs.txt will be too big for findstr to handle.
Note the use of the parsing trick on the line endlocal&SET /a dirsleft=%dirsleft% which uses the parsing system to move the modified value of dirsleft out of the setlocal/endlocal block.
I need to get last argument passed to windows batch script, how can I do that?
This will get the count of arguments:
set count=0
for %%a in (%*) do set /a count+=1
To get the actual last argument, you can do
for %%a in (%*) do set last=%%a
Note that this will fail if the command line has unbalanced quotes - the command line is re-parsed by for rather than directly using the parsing used for %1 etc.
The easiest and perhaps most reliable way would be to just use cmd's own parsing for arguments and shift then until no more are there.
Since this destroys the use of %1, etc. you can do it in a subroutine:
#echo off
call :lastarg %*
echo Last argument: %LAST_ARG%
goto :eof
:lastarg
set "LAST_ARG=%~1"
shift
if not "%~1"=="" goto lastarg
goto :eof
An enhanced version of joey's answer:
#ECHO OFF
SETLOCAL
:test
:: https://stackoverflow.com/a/5807218/7485823
CALL :lastarg xxx %*
ECHO Last argument: [%XXX%]
CALL :skiplastarg yyy %*
ECHO skip Last argument: [%yyy%]
GOTO :EOF
:: Return all but last arg in variable given in %1
:skiplastarg returnvar args ...
SETLOCAL
SET $return=%1
SET SKIP_LAST_ARG=
SHIFT
:skiplastarg_2
IF NOT "%~2"=="" SET "SKIP_LAST_ARG=%SKIP_LAST_ARG% %1"
SHIFT
IF NOT "%~1"=="" GOTO skiplastarg_2
ENDLOCAL&CALL SET "%$return%=%SKIP_LAST_ARG:~1%"
GOTO :EOF
:: Return last arg in variable given in %1
:lastarg returnvar args ...
SETLOCAL
SET $return=%1
SET LAST_ARG=
SHIFT
:LASTARG_2
SET "LAST_ARG=%1"
SHIFT
IF NOT "%~1"=="" GOTO lastarg_2
ENDLOCAL&call SET %$return%=%LAST_ARG%
GOTO :EOF
Run it with the arguments:
abe "ba na na" "cir cle"
and get:
Last argument: ["cir cle"]
skip Last argument: [abe "ba na na"]
set first=""
set last=""
for %%a in (%*) do (
SETLOCAL ENABLEDELAYEDEXPANSION
if !first!=="" (set first=!last!) else (set first=!first! !last!)
set last=%%a
)
ENDLOCAL & set "last=%last%" & set "first=%first%"
echo %last% "and" %first%