OS Name Variable - variables

I would like to run a script where I can get the windows Name and version of the system of all computers running in the company, put it in a text fil. Then make a system variable out of my windows name . I know what to run but where I am running into an issue is a place holder. so here is my code:
:OS_NAME
Set OS_NAME= systeminfo | find "OS Name"
:OS_Ver
Set OS_Version= systeminfo | findstr /B /C:"OS Version"
systeminfo | findstr /B /C:"OS Name" /C:"OS Version" /c:"BIOS Version" | >> G:\Directory\%Computername%
:OS_Arch
IF exist "%programfiles(x86)% (SET OS_ARCH=X64)
Else (SET OS_ARCH=X86)
:Win_7
systeminfo | find "Microsoft Windows 7" > nul
if %ERRORLEVEL% == 0 (
goto ver_7)
:Ver_7
Set Win7= systeminfo | find "Microsoft Windows 7"
Echo %computername% is running %WIN7% in %OS_ARCH% Environment >> G:\Directory\Win7Comps.txt
So basically I would like a place holder for the results of Systeminfo which i can refer to and parse it my SET command when I am making my system variables.
Thanks, any help would be appreaciated.

Not exactly sure what you're looking for, but the biggest problem I see is that systeminfo takes forever to run and returns much more information than you're looking for. You'd be better off capturing wmi queries using wmic. This is basically a rewrite of your example script, just using wmic rather than systeminfo. It should be much, much faster.
#echo off
setlocal
set prefix=G:\Directory
for /f "usebackq tokens=1,2 delims==|" %%I in (`wmic os get name^,version /format:list`) do 2>NUL set "%%I=%%J"
for /f "tokens=2 delims==" %%I in ('wmic bios get version /format:list') do set "bios=%%I"
for /f "tokens=2 delims==" %%I in ('wmic computersystem get model /format:list') do set "model=%%I"
>>"%prefix%\%COMPUTERNAME%" echo OS Name: %name%
>>"%prefix%\%COMPUTERNAME%" echo OS Version: %version%
>>"%prefix%\%COMPUTERNAME%" echo PC Model: %model%
>>"%prefix%\%COMPUTERNAME%" echo BIOS Version: %bios%
if defined PROGRAMFILES(x86) (set arch=X64) else set arch=X86
if "%name%" neq "%name:Windows 8=%" (
set out=%prefix%\Win8Comps.txt
) else if "%name%" neq "%name:Windows 7=%" (
set out=%prefix%\Win7Comps.txt
) else if "%name%" neq "%name:Windows Vista=%" (
set out=%prefix%\WinVistaComps.txt
) else if "%name%" neq "%name:Windows XP=%" (
set out=%prefix%\WinXPComps.txt
)
>>"%out%" echo %COMPUTERNAME% is running %name% in %arch% environment
Type wmic /? for more info, and try wmic computersystem get /? or similar to see a list of items that can be queried under each class.
wmic is the Swiss Army knife of Windows. Fun fact: you can even use wmic to generate a web page table of installed software on a remote system.

You are giving batch a little too much credit. If you ran echo %OS_NAME% it would literally echo systeminfo | find "OS Name". Variables in batch will always just expand, it won't process any further. This will also more than likely try to run find "OS Name" when you try to set the variable as the | is not escaped nor enclosed in double quotes.
If you want to set the output of a command to a value you have to capture it in a for statement like this:
for /f "tokens=2 delims=:" %%a in ('systeminfo ^| find "OS Name"') do set OS_Name=%%a
Then remove the leading spaces like this: (there is probably a better way to do this)
for /f "tokens=* delims= " %%a in ("%OS_Name%") do set OS_Name=%%a
A few things to note here. 1.) "tokens=2 delims=:" is setting the delimiter to : and it is selecting the second section only, which will pull only the part you want. 2.) the | is escaped with a ^, this needs to be done in for loops or anything after that will attempt to execute as seperate commands. 3.) "tokens=* delims= " The token here is * which is all tokens.
A few other problems I found.
systeminfo | findstr /B /C:"OS Name" /C:"OS Version" /c:"BIOS Version" | >> G:\Directory\%Computername%
This has an extra | character at the end.
IF exist "%programfiles(x86)% (SET OS_ARCH=X64)
Else (SET OS_ARCH=X86)
Two problems here, you didn't finish the double quote around the path, and else has to be on the same line as the ending parentheses of the if statement, like this:
IF exist "%programfiles(x86)% (SET OS_ARCH=X64
) Else (SET OS_ARCH=X86)
Otherwise it tries to process else as it's own command

Related

How to set batch variable to output of another script

I try to set a batch variable to an output of another command. In Linux/Unix you can simply use backticks, e.g. (in csh)
set MY_VAR = `tail /etc/passwd`
Is there something similar available in windows batch?
Actually I found already something but it is not fully working:
d:\>for /F "skip=1" %n in ('wmic OS Get CurrentTimeZone') do set TimeZone=%n
d:\>set TimeZone=120
:\>set TimeZone=
d:\>
The problem is the wmic commands returns several lines, otherwise it would work fine. The first I know to skip, however I did not manage to skip the second empty line. I tried with IF but no success.
yes - the output of wmic is a bit ugly to handle.
Use a trick: search for a number in the ouput (findstr "[0-9] will only return lines, that contain a number):
for /F %n in ('wmic OS Get CurrentTimeZone ^|findstr "[0-9]"') do set TimeZone=%n
echo Timezone is %TimeZone%.
(for use in a batchfile use %%n instead of %n)
Another way is:
for /F %n in ('wmic OS Get CurrentTimeZone') do if not defined TimeZone set TimeZone=%n
EDIT:
I prefer the first version, as findstr (or find) converts the wmic-line-endings, so the second for mentioned by MC ND is not neccessary.
I suggest following batch code:
#echo off
for /F "skip=1" %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS Get CurrentTimeZone') do (
set "TimeZone=%%I"
goto BelowLoop
)
:BelowLoop
echo Time zone difference is: %TimeZone%
The FOR loop is exited with command GOTO after the value of interest is assigned to environment variable TimeZone.
The entire FOR loop can be optimized to a single command line:
#echo off
for /F "skip=1" %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS Get CurrentTimeZone') do set "TimeZone=%%I" & goto BelowLoop
:BelowLoop
echo Time zone difference is: %TimeZone%
Exiting the FOR loop after having the value of interest avoids the problem with wrong parsing of Unicode (UTF-16 Little Endian) encoded output of WMIC by FOR which otherwise would result in deleting the environment variable TimeZone. For details on wrong parsing of Unicode output by FOR see answer on How to correct variable overwriting misbehavior when parsing output?
for /f "tokens=2 delims==" %a in ('wmic OS get CurrentTimeZone /value') do set "timeZone=%a"
(to use in a batch file, remember to double the percent signs)
The added /value in wmic changes its output to key=value format. The delims clause in for command indicates a = as a separator. The tokens clause ask to retrieve only the second token/field in the line. As the only line with two tokens is the line with the required data, only this line is processed.
BUT, wmic output includes an aditional carriage return at the end of its output, that needs to be removed from the variable. An aditional for command can be used. The resulting command will be
for /f "tokens=2 delims==" %a in ('wmic OS get CurrentTimeZone /value') do for /f %b in ("%a") do set "timeZone=%b"
Or, for a batch file
for /f "tokens=2 delims==" %%a in (
'wmic OS get CurrentTimeZone /value'
) do for /f %%b in ("%%a") do set "timeZone=%%b"
echo %timeZone%

How to split an ip address into seperate octets and perform arithmetic in cmd

What I am trying to do is configure some vlan scopes via cmd. What I have accomplished so far is to retrieve the IP Address of the Domain Controller and remove the space in front of the value. I have accomplished this using the following commands:
rem extract ip address via local cmd
for /f "tokens=2 delims=:" %i in ('ipconfig ^| find /i "IPv4 Address"') do set ip_address=%i
example result: set ip_address= 10.0.0.25
rem remove empty space from ip address var
set ip_address=%ip_address: =%
echo %ip_address% now results in 10.0.0.25 without the space in front.
What I would like to do next is split the ip_address variable in separate octet variables so that arithmetic can be performed on the octet of choice.
For example: 10.0.0.25 could then be manipulated to reflect 10.[+100].0.[-24]
the desired result would then be 10.100.0.1
I would prefer to accomplish this strictly using windows command line but if a better method exits I am open to suggestions.
Thanks in advance
Joel
Try this to split up the octets into variables.
#echo off
set "ip=10.0.0.25"
SET "offsets=0.100.0.-24"
#echo off
for /f "tokens=1-4 delims=. " %%a in ("%ip%") do (
set octetA=%%a
set octetB=%%b
set octetC=%%c
set octetD=%%d
)
FOR /f "tokens=1-4 delims=." %%a in ("%offsets%") do (
SET /a octetA+=%%a
SET /a octetB+=%%b
SET /a octetC+=%%c
SET /a octetD+=%%d
)
echo "%octetA%","%octetB%","%octetC%","%octetD%"
pause
This is the same solution of foxidrive, but squashed a little... :)
#echo off
set "ip= 10.0.0.25"
SET "offsets=0.100.0.-24"
for /F "tokens=1-4 delims=. " %%a in ("%ip%") do (
for /F "tokens=1-4 delims=." %%i in ("%offsets%") do (
set /A octetA=%%a+%%i, octetB=%%b+%%j, octetC=%%c+%%k, octetD=%%d+%%l
)
)
echo "%octetA%","%octetB%","%octetC%","%octetD%"
pause
Are you aware of autohotkey?
Also, you could try a powershell script.

How to type in between two bracets-Batch File

Hey well I'm here again and this time I want to know how to type in between bracets from an input variable for the input of an IP Address.
I want the code to look something like this.
set input=
set /p input=IP Address: [ ].[ ].[ ].[ ]
And once I've executed the batch and typed in my IP I want it to look like this.
IP Address: [ 127 ].[ 0 ].[ 0 ].[ 1 ]
Is there anyway of doing this?
I think this would be a very complicated thing to do.
If you would try to do this in Batch you need to rewrite your line with braces on every keyboardhit the user does. The only command I know so far which listens on a single KB-hit is the Choice command.
If you manage it somehow to repeat the users input on every KB-hit you need to bytehack your batch file with backspace characters and have a logic to combine the users input with the braces. This is not only very unconfortable but also very slow.
I would recommend to let your users enter any string and after this checking it by "regex" (windows regex is not very nice)
Here is an example function which I use to check IPs of printers.
%printer% would be the string your user enters. This functions also has an nslookup function. You can ommit this if you like.
This 2nd line does all the magic, but you can also enter some IPs which are not possible like 321.099.000.666
:CheckIP
echo %printer% | findstr /R "[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*">nul || goto :EOF
FOR /F "tokens=* delims=" %%A in ('nslookup %printer% 2^>^&1 ') do (
echo %%A | findstr /R /C:"Name: ">nul && set printer=%%A
echo %%A | findstr /R /C:"\*\*\*">nul && (set printerfqdn=%printer% & goto printerip)
)
rem ***************************************
rem * Name: printername.location.companydomain
rem * printerfqdn begins at position 10
rem ***************************************
set printer=%printer:~9%
goto :EOF

There is no column for User Name in the 'WMIC process' output

The Processes tab of the Windows Task Manager shows several columns with information, one of which being User Name of the user that owns the process.
Using the command WMIC process (from an administrator-started cmd.exe) gives me the same sort of information, but I can not find any column for the user name. How can I find out which user started the process with WMIC?
Owner can be retrieved using GetOwner method on win32_process class instances.
I would suggest using PowerShell for that, where it's pretty simple:
Get-WmiObject -Class Win32_Process |
Select-Object Name, #{
Name = 'Owner'
Expression = {
$_.GetOwner().User
}
}
If you have to use wmic, than you can hack your way through by mixing results of:
wmic process get Name
...with call GetOwner e.g:
#echo off
echo Domain\User,Machine,ProcessName,ProcessID,WorkingSetSize
(for /f "skip=2 tokens=2 delims=, eol= " %%P in ('wmic process get ProcessId /format:csv') do #call :AddOwner %%P) 2> nul
goto :EOF
:AddOwner
SET Process=%1
(for /f "skip=5 tokens=1,2 delims==; " %%O in ('wmic process WHERE ProcessID^=%Process% Call GetOwner') do #call :BuildOwner %%O %%P) > nul
for /f "skip=1 tokens=* eol= " %%L in ('wmic process WHERE ProcessID^=%Process% GET Name^, ProcessID^, WorkingSetSize /format:csv') do #SET INFO=%%L
echo %DOMAIN%\%USER%,%INFO%
goto :EOF
:BuildOwner
SET PARAM=%1
SET VALUE=%~2
IF [%PARAM%]==[Domain] SET DOMAIN=%VALUE%
IF [%PARAM%]==[User] SET USER=%VALUE%
goto :EOF
To get the owners of all of the taskeng.exe processes (Windows Task Scheduler processes for individual tasks), run this from an 'admin' Command Prompt window:
wmic process where "name='taskeng.exe'" call GetOwner

Batch file read from largest registry sub-key?

I am trying to modify my batch script to get the install path for a piece of software, however it needs to be version independent and the install path is stored in a version sub-key, so basically what I am looking to do is detect the greatest version sub-key and get the install path from there.
Here is what the code for getting the registry value looks like now:
FOR /F "skip=2 tokens=2,*" %%A IN ('REG.exe query "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node......\6.30" /v "InstallLocation"') DO set "InstallPath=%%B"
Basically I want to not be dependent on the "6.30" part on the end of the key address, how can I do this?
Since I do not know which exact software you are looking at, I will reference Adobe Reader on Winodws 7 x64.
Answer:
The following example will output all of the sub keys within the parent.
for /f "delims=" %%A in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Adobe\Acrobat Reader"') do if not "%%~A"=="" echo.%%~nxA
Output:
9.5
10.0
11.0
Sample:
From there it would just be a matter of remembering the largest and using it in the next query for the value data.
#echo off
setlocal EnableDelayedExpansion
set "xVersion="
set "xPath="
:: Retrieve Greatest Version
for /f "delims=" %%A in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Adobe\Acrobat Reader"') do (
if not "%%~A"=="" if "%%~nxA" GTR "!xVersion!" set "xVersion=%%~nxA"
)
:: Validate Version
if "%xVersion%"=="" goto :eof
:: Retrieve Install Path
for /f "tokens=1,2,*" %%A in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Adobe\Acrobat Reader\%xVersion%\Installer" /v Path') do (
set "xPath=%%~C"
)
:: Show Results
echo.%xPath%
endlocal
Output:
C:\Program Files (x86)\Adobe\Reader 10.0\
Bonus:
If you want to validate that the %%~nxA is a number, here is a batch routine of mine.
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:IsNumber <xReturn> <xInput> [xDelims]
:: Return true if the input is a base 10 number, else return false.
:::: Does not allow any seperators unless specified by xDelims. ,.[tab][space]
setlocal
if not "%~2"=="" set "xResult=true"
for /f "tokens=1 delims=1234567890%~3" %%n in ("%~2") do set xResult=false
endlocal & if not "%~1"=="" set "%~1=%xResult%"
goto :eof
:: Usage Example.
:: The variable xResult will be set to true if %%~nxA is a decimal number.
call :IsNumber xResult "%%~nxA" "."