Graphics Memory info with CMD - graphics

Starting from the beginning, I've created an installer (game installer) with command prompt.. I want to set a variable for the available graphics memory on the PC which it is currently running ... Something like this ---
set gfxmem=[code here]
if %gfxmem% leq 1000[mb or value] ( echo Low Graphics memory ) else echo Supported
What might be in place of code here?

I searched the world wide web, found quickly How To Identify Your Computer Video Card (The Manual Way) and downloaded the batch file containing the lines:
#echo off
wmic PATH Win32_videocontroller GET description
wmic PATH Win32_videocontroller GET adapterram
wmic PATH Win32_videocontroller GET driverversion
wmic PATH Win32_videocontroller GET pnpdeviceid
pause
I executed the batch file to see what the line with adapterram outputs and could see a line with AdapterRAM and two lines with a byte value because there are two video adapters installed in my computer.
Next I developed following batch code with using coding techniques described in detail in answer on How to get the % of memory utilization using WMIC in batch script? and in the comments of the batch code itself.
#echo off
goto :GetVideoMemorySize
rem Note: MB = MiB and GB = GiB in this batch file, see
rem https://en.wikipedia.org/wiki/Byte for details on GiB.
rem The command WMIC with the parameters PATH Win32_videocontroller GET
rem AdapterRAM outputs one line per video adapter. The output of WMIC is
rem in UTF-16 LE with BOM. The output is redirected to a temporary file
rem which is printed by command TYPE to STDOUT which makes a better job
rem on UNICODE to ASCII conversion as command FOR.
rem Memory of a video adapter is in bytes which can be greater 2^31 (= 2 GB).
rem Windows command processor performs arithmetic operations always with
rem 32-bit signed integer. Therefore 2 GB or more installed video memory
rem exceeds the bit width of a 32-bit signed integer and arithmetic
rem calculations are wrong on 2 GB or more installed video memory. To
rem avoid the integer overflow, a subroutine is called which makes the
rem calculation depending on string value length, i.e. number of bits.
rem Create a copy of current environment variables. Enabling additionally
rem delayed environment variable expansion is not required for this task.
rem Command extensions are enabled by default, but nevertheless enable it.
:GetVideoMemorySize
setlocal EnableExtensions
set "VideoTotalMemory=0"
set "VideoAdapterCount=0"
%SystemRoot%\System32\wbem\wmic.exe PATH Win32_videocontroller GET AdapterRAM >"%TEMP%\AdapterRam.tmp"
for /F "skip=1" %%M in ('type "%TEMP%\AdapterRam.tmp"') do (
set /A VideoAdapterCount+=1
set "VideoAdapterMemory=%%M"
call :AddVideoMemory
)
del "%TEMP%\AdapterRam.tmp"
if "%VideoAdapterCount%" == "1" (
set "AdapterInfo="
) else (
set "AdapterInfo= of %VideoAdapterCount% video adapters"
)
echo Total video memory is: %VideoTotalMemory% MB%AdapterInfo%
echo.
if %VideoTotalMemory% LEQ 1024 (
echo Low Graphics memory
) else (
echo Supported
)
endlocal
goto :EOF
rem This subroutine calculates the total video adapter memory correct
rem only for video adapter memory sizes being either less than 1 GB or
rem an exact multiple of 1 GB. The calculation is wrong for values like
rem 1.5 GB, 2.5 GB and similar values.
rem For a value with not more than 9 characters the memory size in MB
rem can be directly calculated with a division by 1024 * 1024 = 1048576.
rem To avoid an integer overflow on video memory sizes of 1 GB and more,
rem the last 6 characters are removed from bytes value and the remaining
rem characters are divided by 1073 to get the number of GB which is next
rem multiplied with 1024 to get the value in MB.
rem 1 GB = 1.073.741.824 bytes = 2^30
rem 2 GB = 2.147.483.648 bytes = 2^31
rem 4 GB = 4.294.967.296 bytes = 2^32
rem 8 GB = 8.589.934.592 bytes = 2^33
rem 16 GB = 17.179.869.184 bytes = 2^34
rem 32 GB = 34.359.738.368 bytes = 2^35
:AddVideoMemory
if not "%VideoAdapterMemory:~9,1%" == "" goto AtLeast1GB
set /A VideoTotalMemory+=VideoAdapterMemory/1048576
goto :EOF
:AtLeast1GB
set "VideoAdapterMemory=%VideoAdapterMemory:~0,-6%"
set /A VideoTotalMemory+=(VideoAdapterMemory/1073)*1024
goto :EOF
I tested the batch file on Windows XP SP3 x86 and Windows 7 SP1 x64 with administrator privileges and it worked fine on both computers.
See also User Account Control and WMI and Win32_VideoController class. Interesting to read for me was uint32 AdapterRAM on second web page. This would mean that more than 4 GB are not possible for video adapter RAM.
For understanding the used 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.
call /?
del /?
echo /?
endlocal /?
for /?
goto /?
rem /?
setlocal /?
set /?
type /?
wmic /?
wmic PATH /?
wmic PATH Win32_videocontroller GET /?
And read also the Microsoft article Using command redirection operators for an explanation of redirection operator >.

Related

How to modify lines that hold a given string with new information and save it as a text file

I am working on modifying our batch files where we call #make functions inside. We want to add a script inside the batch file that checks an external header file, finds the line with date information(APP_VERSION_DATE) and updates the information there with new date information(I figured out how to fetch windows date information with batch, this is not an issue)
I know what steps to follow but batch syntax feels completely counter intuitive to me and I am stuck.
These are the steps I would like to follow:
1- Go through the app_version.h file line by line(for /f)
2- Find the lines with string APP_VERSION_DATE(if findstr...)
3- delete everything except APP_VERSION_DATE
4- CONCAT date information to APP_VERSION_DATE like APP_VERSION_DATE "23-05-2022"
5- Keep echoing every other line
6- Pipeline the information a new header file.
7- Delete header file
8- Rename the new header line as the old one.
set strToFind="app_version_date"
set result="Not Found"
for /f "tokens=2 delims=[]" %%A in ('findstr %strToFind% %filename%') do (
set result=%%A
if defined result (
if %result%==this is something
echo hurra this is it
) ELSE echo
)
this is where I am at right now and I am obviously still too far off to do something I want to do.
I am able to make a program that can find a given string in a file and change it but in this case I want to find the line that has the string I am searching for, delete the rest and modify it. I want to find the line where the string is and modify it, not the string itself. This is simply because date information as shown below;
#define APP_VERSION_DATE [2022-05-16 12:13]
won't be static and ever changing with each compile attempt.
I have something like this but this is too far from what I want to do.
Any help would be great! Thanks in advance
Replace date/time in header file app_version.h
There could be used the following commented batch file for this task:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "HeaderFile=app_version.h"
if not exist "%HeaderFile%" exit /B 20
rem Get current local date/time in format [yyyy-MM-dd HH:mm].
for /F "tokens=1-5 delims=/: " %%G in ('%SystemRoot%\System32\robocopy.exe "%SystemDrive%\|" . /NJH') do set "AppVersionDate=[%%G-%%H-%%I %%J:%%K]" & goto UpdateHeaderFile
rem Let FINDSTR output all lines of the header file with a line number and
rem a colon at the beginning for processing really all lines including the
rem empty lines in the header file and output all lines without the line
rem number and the colon with exception of the line containing the string
rem #define APP_VERSION_DATE which is ignored and instead is output a line
rem defined here with the local date/time determined before. All lines output
rem by the loop are written into a newly created temporary header file.
:UpdateHeaderFile
(for /F delims^=^ eol^= %%I in ('%SystemRoot%\System32\findstr.exe /N "^" "%HeaderFile%" 2^>nul') do (
set "Line=%%I"
setlocal EnableDelayedExpansion
if "!Line:#define APP_VERSION_DATE=!" == "!Line!" (
echo(!Line:*:=!
) else (
echo #define APP_VERSION_DATE %AppVersionDate%
)
endlocal
))>"%HeaderFile%.tmp"
rem Replace the original header file with the temporary header file.
if exist "%HeaderFile%.tmp" move /Y "%HeaderFile%.tmp" "%HeaderFile%" >nul
rem Delete the temporary header file if the command line above failed
rem because of the original header file is read-only or write-protected
rem or currently opened by an application with shared access denied.
if exist "%HeaderFile%.tmp" del "%HeaderFile%.tmp"
endlocal
The environment variable HeaderFile can be defined with an absolute path or a relative path.
Please read the chapter Usage of ROBOCOPY to get current date/time in my answer on Time is set incorrectly after midnight for an explanation of the first for /F command line.
Please read next my answer on How to read and print contents of text file line by line? It describes in full details the second for /F loop with the small modification of an additional IF condition to replace the line containing the string #define APP_VERSION_DATE with an current date/time.
For understanding the used 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.
del /?
echo /?
endlocal /?
exit /?
findstr /?
goto /?
if /?
move /?
rem /?
set /?
setlocal /?
See also single line with multiple commands using Windows batch file for an explanation of the unconditional command operator &.
Create header file current_date_time.h with date/time
The task could be done much easier if the file app_version.h contains anywhere the line:
#include "current_date_time.h"
The batch file could be in this case just:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "tokens=1-5 delims=/: " %%G in ('%SystemRoot%\System32\robocopy.exe "%SystemDrive%\|" . /NJH') do echo #define APP_VERSION_DATE [%%G-%%H-%%I %%J:%%K]>"current_date_time.h"& goto EndBatch
:EndBatch
endlocal
This batch file always creates new the file current_date_time.h with just the single line:
#define APP_VERSION_DATE [2022-05-23 18:48]
And this single preprocessor macro definition line is included on compilation into app_version.h.
Define preprocessor macro APP_VERSION_DATE with current date/time
Every C/C++ compiler has an option to define a preprocessor macro on the command line and the option can be used multiple times on the command line to define multiple preprocessor macros.
For example see:
GNU gcc/g++: Options Controlling the Preprocessor explaining case-sensitive option -D
Microsoft C/C++: /D (Preprocessor Definitions)
So it is possible to define an environment variable with the current date/time in the wanted format with the single command line below and reference this environment variable value on running the C/C++ compiler with the appropriate option.
#set "AppVersionDate=" & for /F "tokens=1-5 delims=/: " %%G in ('%SystemRoot%\System32\robocopy.exe "%SystemDrive%\|" . /NJH') do #if not defined AppVersionDate set "AppVersionDate=[%%G-%%H-%%I %%J:%%K]"
GNU gcc/g++ would be run later with -D "APP_VERSION_DATE=%AppVersionDate%" and Microsoft C/C++ compiler with /D "APP_VERSION_DATE=%AppVersionDate%" as one of the options on compilation of the C/C++ source code files.
There are also the predefined macros __DATE__ and __TIME__:
GNU gcc/g++: Predefined Macros
Microsoft C/C++: Predefined macros
Search also for information about the environment variable SOURCE_DATE_EPOCH which gives control over the timestamp added by the C/C++ compiler itself to the produced binaries.

How can I get drive letter by searching USB name using Windows command or Node.js/Electron?

I want to download the content to USB disk named distinguishingly in the background. So I need to find its position. Is there have any function to realize it by using a Windows command?
Or is there any function to find a USB drive by using Node.js/Electron?
And if it possible, how can I distinguish between two USB drives that have the same name?
It is possible to use %~d0 to reference the drive of the batch file if the batch file is stored on the storage media connected via USB to the computer.
But if the batch file is stored on a different storage media like the local hard disk inside the PC, the following small batch files demonstrates how to get the drive letter of the USB storage media via its volume name.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "DriveUSB="
set "VolumeName=NameOfVolume"
:GetDriveLetter
for /F "tokens=2 delims==" %%I in ('%SystemRoot%\System32\wbem\wmic.exe LOGICALDISK where VolumeName^="%VolumeName%" GET DeviceID /VALUE 2^>nul') do set "DriveUSB=%%I"
if not defined DriveUSB (
echo Device with name %VolumeName% not found.
echo/
%SystemRoot%\System32\choice.exe /C YN /N /M "Retry (Y/N):"
if errorlevel 2 goto :EOF
goto GetDriveLetter
)
echo Drive letter of %VolumeName% is: %DriveUSB%
rem More commands using environment variable DriveUSB.
echo/
pause
endlocal
NameOfVolume must be adapted to real volume name. This string is interpreted case-insensitive by WMIC.
Please read the Microsoft documentation for Win32_LogicalDisk class and its properties for more information about the used class.
The device identification could be done also by using VolumeSerialNumber instead of VolumeName which is more difficult to change than the volume name without formatting the volume. Run in a command prompt window the following command to get displayed the volume serial number:
wmic LOGICALDISK where VolumeName="NameOfVolume" GET VolumeSerialNumber
For understanding the used 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.
choice /?
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
rem /?
setlocal /?
wmic /?
wmic logicaldisk /?
wmic logicaldisk get /?
Read the Microsoft documentation about Using command redirection operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded wmic command line with using a separate command process started in background with %ComSpec% /c and the command line within ' appended as additional arguments. This is also the reason why = must be escaped with ^ to be interpreted as literal character and not as argument separator which would be replaced otherwise by a space character by command processor instance processing the batch file making the where clause invalid for wmic executed by the background command process.
It is recommended to read also DosTips forum topic: ECHO. FAILS to give text or blank line - Instead use ECHO/

Start Excel file from Windows batch script in safemode, use default file association

Question Summary:
Can I start Excel file Installer.xlsm from Windows batch script in safemode, without providing EXCEL.EXE installation path?
Details
I have a windows batch script which downloads the latest versions of a family of Excel Add-ins from a remote server, places them in a directory (C:\appname\AddIns) and calls the Excel file Installer.xlsm.
Upon loading, Installer.xlsm executes a VBA macro, which uninstalls older versions of the add-ins and installs their newer version.
Currently I start Installer.xlsm using the command:
start "Launching installer file" /wait "<Path to file>\Installer.xlsm"
What's great about it is that it uses Windows' file association to open Excel, and I don't have to provide the EXCEL.EXE installation path (multiple users with different machine images and MS Office versions).
Now I'd like to load Installer.xlsm in safemode, to make sure that no add-ins are loaded and no other code is run while Installer.xlsm tries to work with the add-ins.
I know I can use "<PathToExcel>excel" /safemode "<PathToXls>Installer.xlsm" as described in this answer, but this method doesn't use Windows' file association and requires that I provide a path.
We have users with various machine images, using different versions of MS Office, so I do not want to get into hardcoding all possible Excel installation locations.
Can I do something of the following form:
start "Launching installer file" /wait "<Path to file>\Installer.xlsm /safemode"
I tried different possible combinations without success. How would you do it?
First I suggest to read the Microsoft documentation page Application Registration. It explains how the installer of an application or an application suite like Microsoft Office should register the installed application(s) so that the executable(s) of the application(s) can be found by other applications.
Recommended is creating under registry key
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths
a subkey with name of the executable file like excel.exe with default string value being name of the executable with full path and optionally adding one more string value with name Path containing just the path to the executable. The Path string can but most not exist and it can but must not end with a backslash.
The command START uses also this key to find an application as explained in answer on Where is “START” searching for executables?
The installers of the various versions of Microsoft Office register excel.exe key under this key too.
So the easiest method on Windows Vista and later Windows versions to get installation location of Microsoft Excel is:
#echo off
for /F "skip=1 tokens=2*" %%A in ('%SystemRoot%\System32\reg.exe QUERY "HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths\excel.exe" /ve 2^>nul') do set "ExcelApp=%%~B"
echo ExcelApp=%ExcelApp%
pause
But on Windows XP the output of reg.exe is different and requires for that reason this batch code:
#echo off
for /F "skip=3 tokens=3*" %%A in ('%SystemRoot%\System32\reg.exe QUERY "HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths\excel.exe" /ve 2^>nul') do set "ExcelApp=%%~B"
echo ExcelApp=%ExcelApp%
pause
The different outputs are explained in answer on Read words separated by space & string value also contains space in a batch script in batch code written to get string value of a default string of a registry key containing spaces.
And it is good coding practice to add extra code which handles an error case like registry key does not exist at all because Microsoft Excel is not installed at all.
But is it possible with batch code to do what command START respectively the Windows shell function ShellExecuteEx does on using in a command prompt window the command line?
start "Launching installer file" "C:\Path to file\Installer.xlsm"
Yes, it is possible as the commented batch code below demonstrates.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem First query default string value of HKEY_CLASSES_ROOT\.xlsm from registry.
call :GetDefaultRegValue "HKCR\.xlsm"
rem Is there no key HKEY_CLASSES_ROOT\.xlsm or was the default string empty?
if not defined RegValue goto GetFromAppPaths
SET RegValue
rem Get the shell command line used for opening a *.xlsm file.
call :GetDefaultRegValue "HKCR\%RegValue%\shell\open\command"
rem Could the command line not read successfully from Windows registry?
if not defined RegValue goto GetFromAppPaths
SET RegValue
rem The command line contains as first string usually enclosed in double
rem quotes EXCEL.EXE with full path enclosed in double quotes. And there
rem can be even more arguments on the command line which are not needed
rem here. The command line below is used to get just first string of
rem the command line which should be EXCEL.EXE with full path.
for %%I in (%RegValue%) do set "RegValue=%%~I" & goto CheckExcelExistence
rem It is not good when both registry queries above fail. This means
rem either Microsoft Excel is not installed at all or a version of
rem Excel is installed which does not support *.xlsm files like Excel
rem of MS Office 2003, MS Office 2000 or MS Office 97.
rem However, perhaps just *.xlsm is not correct registered and therefore
rem get full path to excel.exe from application registration key.
:GetFromAppPaths
call :GetDefaultRegValue "HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths\excel.exe"
if defined RegValue goto CheckExcelExistence
echo Failed to determine installation location of Microsoft Excel.
echo/
endlocal
pause
goto :EOF
:CheckExcelExistence
SET RegValue
rem Remove surrounding double quotes if the Excel executable file name
rem read from Windows registry is still enclosed in double quotes.
set "RegValue=%RegValue:"=%"
if exist "%RegValue%" goto :RunInstall
echo Registered "%RegValue%" does not exist.
echo/
endlocal
pause
goto :EOF
:RunInstall
SET RegValue
ECHO start "Launching installer file" /wait "%RegValue%" "%~dp0Installer.xlsm" /safemode
endlocal
goto :EOF
rem This subroutine queries from Windows registry the default string value of
rem the key passed to the subroutine as first and only parameter and assigns
rem this value to environment variable RegValue. Environment variable RegValue
rem is deleted and therefore is not defined after subroutine exits on failure
rem to get the registry value or when the default value is an empty string.
rem This subroutine works for Windows XP and all later versions of Windows.
:GetDefaultRegValue
set "TypeToken=2"
:Reg3Run
for /F "skip=1 tokens=%TypeToken%*" %%A in ('%SystemRoot%\System32\reg.exe QUERY "%~1" /ve 2^>nul') do (
if "%%A" == "REG_SZ" (
if not "%%~B" == "" (
set "RegValue=%%B"
goto :EOF
)
) else if "%%A" == "NAME>" (
set "TypeToken=3"
goto Reg3Run
)
)
set "RegValue="
goto :EOF
This batch code is just a demonstration. It does not start Excel when really found. Instead it just outputs the command line which would start Excel because of ECHO left of start ... in block below label RunInstall.
Further this batch code contains 4 lines with just SET RegValue. Those 4 lines output just the string value queried successfully from Windows registry and stored in environment variable RegValue. Those 4 commands help to understand what happens on execution of the batch file. Those four command lines should be deleted finally from batch file and also the single ECHO written in upper case.
Note: It is quite easy to test what happens if an expected registry key does not exist or its default value is an empty string. Just insert a single character like # before last double quote on a line starting with call :GetDefaultRegValue and the modified registry key is not found anymore.
For understanding the used 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.
call /?
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
reg /?
reg query /?
rem /?
setlocal /?
start /?
Read also the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded reg.exe command line with using a separate command process started in background.

Setting a variable from a string inside a TXT file with a batch file

I'm attempting to create a batch file for my company's users to use to migrate files from their older 'personal folder' network share to our new OneDrive implementation.
The problem is, some of our users have change the default sync folder for OneDrive to whatever drive and path they wanted, instead of keeping the default (*c:\users\username*)...for example, the one I'm using to test my BAT file against is using:
D:\OneDrive - Business
However, it does still have to work when it contains more or less delimiters, like C:\OneDrive or C:\This Is Where I Foolishly Store Stuff.
At this point, I've tried using REG QUERY to output to a text file from the UserFolder key in the registry to get the path, and now I'm trying to extract this path FROM the text file in question and set it to a variable. The text file that is created looks like the following:
HKEY_CURRENT_USER\SOFTWARE\Microsoft\OneDrive\Accounts\Business1
UserFolder REG_SZ D:\OneDrive - Business
What I want to do is set the "D:\OneDrive - Business" to a variable to use in a scripted MOVE command.
My code is so awful, that I will refrain from posting it unless someone decides its necessary to answer my question.
I'm sure that for at least a DOZEN of you, this is child's play, so I would really appreciate any help that is provided me!!!
Thanks!!
Here is one batch solution for this task:
#echo off
for /F "skip=1 tokens=1,2*" %%A in ('%SystemRoot%\System32\reg.exe QUERY HKCU\SOFTWARE\Microsoft\OneDrive\Accounts\Business1 /v UserFolder 2^>nul') do if /I "%%A" == "UserFolder" if not "%%C" == "" set "UserFolder=%%C" & goto UserFolderSet
echo No user folder for OneDrive found in Windows registry.
goto :EOF
:UserFolderSet
echo Found user folder: "%UserFolder%"
Better readable is this version doing exactly the same:
#echo off
for /F "skip=1 tokens=1,2*" %%A in ('%SystemRoot%\System32\reg.exe QUERY HKCU\SOFTWARE\Microsoft\OneDrive\Accounts\Business1 /v UserFolder 2^>nul') do (
if /I "%%A" == "UserFolder" (
if not "%%C" == "" (
set "UserFolder=%%C"
goto UserFolderSet
)
)
)
echo No user folder for OneDrive found in Windows registry.
goto :EOF
:UserFolderSet
echo Found user folder: "%UserFolder%"
The command FOR executes the command REG in a background command process with capturing its output written to handle STDOUT.
An error message output by REG to handle STDERR is suppressed by redirecting it to device NUL because of 2^>nul. The redirection operator > is escaped with caret character ^ which is necessary to interpret > first as literal character by Windows command interpreter on parsing the FOR command line. But later on execution of REG command line with 2>nul by FOR > is interpreted as redirection operator. An error message could occur if the registry value does not exist at all in Windows registry.
FOR processes each non empty line of captured output of REG command by splitting the line up into substrings (tokens) using space and tab as delimiter (default).
The option skip=1 instructs FOR to skip the first line of captured output.
The option tokens=1,2* instructs FOR that first space/tab delimited string being here value name UserFolder should be assigned to first loop variable A.
The second space/tab delimited string being here type REG_SZ should be assigned to loop variable B being the next character in ASCII table. Now it should be clear why loop variables are case-sensitive while environment variables are not case-sensitive. This loop variable is not further processed here although it might be good in case of type is REG_EXPAND_SZ instead of REG_SZ as in this case the directory path contains most likely also 1 or more environment variable references which must be expanded before having real directory path.
The string after the spaces/tabs after second space/tab delimited string being in your example D:\OneDrive - Business should be assigned without further splitting up on spaces/tabs to loop variable C because of * after 2 in options string tokens=1,2*.
The first IF condition makes sure the right line is processed as on Windows XP the output of REG starts with a header where only the first line would be skipped.
The second IF condition makes sure the user folder value has a non empty value.
The string of interest is finally assigned to environment variable UserFolder and the FOR loop is exited with a jump to the commands below label UserFolderSet.
The commands below the FOR loop are executed if the registry value was not found in Windows registry.
For understanding the used 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.
echo /?
for /?
goto /?
if /?
set /?
Read also the Microsoft article about Using Command Redirection Operators.
Perhaps:
For /F "EOL=H Tokens=2*" %%A In ('Reg Query "HKCU\SOFTWARE\Microsoft\OneDrive\Accounts\Business1" /V "UserFolder"') Do Set "var=%%B"
Echo(%%var%% = %var%
Pause
I won't use a text file but directly Reg.exe to read the registry value
#Echo off
Set "Key=HKCU\SOFTWARE\Microsoft\OneDrive\Accounts\Business1"
Set "Val=UserFolder"
For /f "Tokens=2* delims= " %%A in (
'Reg query "%Key%" /V %Val% ^|find /i "%Val%" '
) Do Set "%Val%=%%B"
Set %Val%
You can combine the output of the [MSDN]: reg with [MSDN]: findstr (to filter out some useless data), and iterate over what's left using [SS64]: for.
Here's the code (it must be run from a batch file):
#echo off
set _KEY_NAME=HKEY_CURRENT_USER\SOFTWARE\Microsoft\OneDrive\Accounts\Business1
set _VALUE_NAME=UserFolder
set _VALUE_DATA=
for /f "tokens=1,2,*" %%f in ('reg query %_KEY_NAME% /v %_VALUE_NAME% /t REG_SZ 2^>NUL ^| findstr %_VALUE_NAME%') do (
set _VALUE_DATA="%%h"
)
echo Data: %_VALUE_DATA%
This is based on the fact that on my machine (Win10), reg query %_KEY_NAME% /v %_VALUE_NAME% /t REG_SZ (with different values for the _KEY_NAME and _VALUE_NAME), output:
HKEY_CURRENT_USER\SOFTWARE\_DummyKey
_DummyValue REG_SZ D:\OneDrive - Business
End of search: 1 match(es) found.
#EDIT0: After looking at #Mofi's solution, I realized that I had no error handling. Added some.

How to run batch script without using *.bat extension

Is there any method in Windows through which we can execute a batch script without *.bat extension?
This is an interesting topic to me! I want to do some observations about it.
The important point first: A Batch file is a file with .BAT or .CMD extension. Period. Batch files can achieve, besides the execution of usual DOS commands, certain specific Batch-file facilities, in particular:
Access to Batch file parameters via %1 %2 ... and execution of SHIFT command.
Execution of GOTO command.
Execution of CALL :NAME command (internal subroutine).
Execution of SETLOCAL/ENDLOCAL commands.
Now the funny part: Any file can be redirected as input for CMD.exe so the DOS commands contained in it are executed in a similar way of a Batch file, with some differences. The most important one is that previous Batch-file facilities will NOT work. Another differences are illustrated in the NOT-Batch file below (I called it BATCH.TXT):
#echo off
rem Echo off just suppress echoing of the prompt and each loop of FOR command
rem but it does NOT suppress the listing of these commands!
rem Pause command does NOT pause, because it takes the character that follows it
pause
X
rem This behavior allows to put data for a SET /P command after it
set /P var=Enter data:
This is the data for previous command!
echo Data read: "%var%"
rem Complex FOR/IF commands may be assembled and they execute in the usual way:
for /L %i in (1,1,5) do (
set /P line=
if "!line:~0,6!" equ "SHOW: " echo Line read: !line:~6!
)
NOSHOW: First line read
SHOW: Second line
NOSHOW: This is third line
SHOW: The line number 4
NOSHOW: Final line, number five
rem You may suppress the tracing of the execution redirecting CMD output to NUL
rem In this case, redirect output to STDERR to display messages in the screen
echo This is a message redirected to STDERR >&2
rem GOTO command doesn't work:
goto label
goto :EOF
rem but both EXIT and EXIT /B commands works:
exit /B
:label
echo Never reach this point...
To execute previous file, type: CMD /V:ON < BATCH.TXT
The /V switch is needed to enable delayed expansion.
More specialized differences are related to the fact that commands in the NOT-Batch file are executed in the command-line context, NOT the Batch-file context. Perhaps Dave or jeb could elaborate on this point.
EDIT: Additional observations (batch2.txt):
#echo off
rem You may force SET /P command to read the line from keyboard instead of
rem from following lines by redirecting its input to CON device.
rem You may also use CON device to force commands output to console (screen),
rem this is easier to write and read than >&2
echo Standard input/output operations> CON
echo/> CON
< CON set /P var=Enter value: > CON
echo/> CON
echo The value read is: "%var%"> CON
Execute previous file this way: CMD < BATCH2.TXT > NUL
EDIT: More additional observations (batch3.txt)
#echo off
rem Dynamic access to variables that usually requires DelayedExpansion via "call" trick
rem Read the next four lines; "next" means placed after the FOR command
rem (this may be used to simulate a Unix "here doc")
for /L %i in (1,1,4) do (
set /P line[%i]=
)
Line one of immediate data
This is second line
The third one
And the fourth and last one...
(
echo Show the elements of the array read:
echo/
for /L %i in (1,1,4) do call echo Line %i- %line[%i]%
) > CON
Execute this file in the usual way: CMD < BATCH3.TXT > NUL
Interesting! Isn't it?
EDIT: Now, GOTO and CALL commands may be simulated in the NotBatch.txt file!!! See this post.
Antonio
Just use:
type mybat.txt | cmd
Breaking it down...
type mybat.txt reads mybat.txt as a text file and prints the contents. The | says capture anything getting printed by the command on its left and pass it as an input to the command on its right. Then cmd (as you can probably guess) interprets any input it receives as commands and executes them.
In case you were wondering... you can replace cmd with bash to run on Linux.
in my case, to make windows run files without extension (only for *.cmd, *.exe) observed, i have missed pathext variable (in system varailbles) to include .cmd. Once added i have no more to run file.cmd than simply file.
environment variables --> add/edit system variable to include .cmd;.exe (ofcourse your file should be in path)
It could be possible yes, but probably nor in an easy way =) cause first of all.. security.
I try to do the same thing some year ago, and some month ago, but i found no solution about it.. you could try to do
execu.cmd
type toLaunch.txt >> bin.cmd
call bin.cmd
pause > nul
exit
then in toLaunch.txt put
#echo off
echo Hello!
pause > nul
exit
just as example, it will "compile" the code, then it will execute the "output" file, that is just "parse"
instead of parsed you could also just rename use and maybe put an auto rename inside the script using inside toLaunch.txt
ren %0 %0.txt
hope it helped!
It is possible at some degree. You'll need an admin permissions to run assoc and ftype commands. Also a 'caller' script that will use your code:
Lets say the extension you want is called .scr.
Then execute this script as admin:
#echo off
:: requires Admin permissions
:: allows a files with .scr (in this case ) extension to act like .bat/.cmd files.
:: Will create a 'caller.bat' associated with the extension
:: which will create a temp .bat file on each call (you can consider this as cheating)
:: and will call it.
:: Have on mind that the %0 argument will be lost.
rem :: "installing" a caller.
if not exist "c:\scrCaller.bat" (
echo #echo off
echo copy "%%~nx1" "%%temp%%\%%~nx1.bat" /Y ^>nul
echo "%%temp%%\%%~nx1.bat" %%*
) > c:\scrCaller.bat
rem :: associating file extension
assoc .scr=scrfile
ftype scrfile=c:\scrCaller "%%1" %%*
You even will be able to use GOTO and CALL and the other tricks you know. The only limitation is that the the %0 argument will be lost ,tough it can be hardcoded while creating the temp file.
As a lot of languages compile an .exe file for example I think this a legit approach.
If you want variables to be exported to the calling batch file, you could use
for /F "tokens=*" %%g in (file.txt) do (%%g)
This metod has several limitations (don't use :: for comments), but its perfect for configuration files.
Example:
rem Filename: "foo.conf"
rem
set option1=true
set option2=false
set option3=true
#echo off
for /F "tokens=*" %%g in (foo.conf) do (%%g)
echo %option1%
echo %option2%
echo %option3%
pause

Resources