Windows: Obtaining and Storing a Machine Name in a Variable - windows

I have a script that is run over a network, with VPN being the same as a LAN environment.
The script previously worked fine, as we had variables that stored the username and password for the administrator. However, due to a recent change, when we map a drive over the network and whatnot, the machine name is now needed in front of the administator username, E.g. machinename2343\administrator.
What I would like to do is take an existing command - perhaps such as nbtstat - and after entering the ip address, have the program pull the machine name and insert it into a variable.
I have found that Nbtstat can give me the machine name, but provides large amounts of unnecessary information for my task. Is there a way to filter out just the machine name in a reliable and consistent manner, or is there perhaps another network related command that perform in the same capacity?
`#echo off
FOR /f "tokens=1* delims= skip=23 " %%a IN ('nbtstat -a IPADDRESS) DO (
SET VARIABLE=%%a
GOTO Done
)
:Done
echo Computer name: %VARIABLE%`

You could do ping /a. The computer name is resolved. And this computer name is the second token. I haven't taken care of Error checking. I believe you could implement that yourself.
Try this:
#ECHO OFF
FOR /f "tokens=2* delims= " %%a IN ('PING -a -n 1 IPADDRESS') DO (
SET Variable=%%a
GOTO Done
)
:Done
echo Computer name: %Variable%
Put this in your batch file where it would fit.

You could just use the %computername% environment variable.
When I first read your post I thought you were running the batch file remotely on each machine. If that were the case having %computername% in the batch file would work, because when the batch file is executed remotely %computername% would be expanded based on the remote machine's environment variable not the local machine.
Looking back on it, it's still not very clear, but based on your comment I assume the batch file is running locally and then connecting to a set of machines to perform some operation(s).
You could use tool the WMI command-line tool to get the computer name. The solution would look similar to #Thrustmaster's, but I think it's a little cleaner since the output of wmic, in this case, does "filter out just the machine name in a reliable consistent manner." Of course you'd replace the 127.0.0.1 with the ip you want to query.
#ECHO OFF
FOR /F "tokens=*" %%A IN ('wmic /node:127.0.0.1 ComputerSystem Get Name /Value ^| FIND "="') DO (
SET COMP.%%A
)
ECHO %COMP.NAME%

Related

Check and obtain Server access using Windows Batch File

First of all I'm a complete noob to Batch scripting and networking, with that being said, Here is what I'm trying to accomplish.
I want to check if the server has provided this batch file executing pc to access it, if not create access to it. (many different pc's run this batch file)
This what I came up with for now in my batch file.
net use * \\ip\My_WebApp /Persistent:yes /user:Username Password
Exit
This batch file command create access to the server just fine but It creates a new access connection every time this file get executed. Which is not needed and might crash the server load.
How can I check if the Server already has provided the access, Only if not, execute the above command in a batch file. my logic like like....
boolean status = check_server_accessibility()
if(!status){
net use * \\ip\My_WebApp /Persistent:yes /user:Username Password
}
Exit
Appreciate any help, Thank you so much for your time.
You should only ever need to perform the task once, which suggests that a scripted solution isn't needed, (persistent means that!). I would assume that the following may be sufficient:
#Set "MyMap=\\ip\My_WebApp"
#%__AppDir__%wbem\WMIC.exe LogicalDisk Where "DriveType='4'" Get ProviderPath 2>NUL | %__AppDir__%findstr.exe /R /I "%MyMap:\=\\%\>" 1>NUL && GoTo :EOF
#%__AppDir__%net.exe Use * "%MyMap%" /Persistent:Yes /User:Username Password
Alternatively, if you needed to know which drive letter is currently assigned to it, then use a for-loop to retrieve the data:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Call :MapChk "\\ip\My_WebApp"
GoTo :EOF
:MapChk
Set "MyMap=%~1"
Set "MyDrv="
For /F "Skip=1 Delims=:" %%G In (
'%__AppDir__%wbem\WMIC.exe LogicalDisk Where "DriveType='4' And ProviderPath='%MyMap:\=\\%'" Get DeviceID 2^>NUL'
) Do For %%H In (%%G) Do Set "MyDrv=%%G:"
If Defined MyDrv (
Echo %MyMap% is already mapped to drive %MyDrv%.
%__AppDir__%timeout.exe /T 5 /NoBreak >NUL
GoTo :EOF
)
%__AppDir__%net.exe Use * "%MyMap%" /Persistent:Yes /User:Username Password
I've made this one into a callable label, so that you can more easily extend it for other mappings too, e.g. before the GoTo :EOF, (line 6), Call :MapChk "\\Server\My Share".
Note: These solutions are untested, I do not use a PC and have no mapped network locations to test them against. Please let me know if I have made a mistake somewhere.

How windows(7) gets executable location (from task manager)?

I have a Portable VirtualBox set up on one of my hard drives (Portable Virtual Box). And I have another VirtualBox installed in my system (this one is NOT portable, but classic installation in C:\Program Files)
I'm trying to use a BATCH Script to retrieve the location of the running VirtualBox:
#echo off
cls
setlocal enabledelayedexpansion
ECHO Please make sure you have VirtualBox running, so the script
ECHO will be able to detect VirtualBox.exe process running
rem because of a bug in wmic, I have to get the Input Locale first.
rem I could have had it hardcoded, but I think this is better (more flexible)
for /f "tokens=2 delims=:,;" %%s in ('systeminfo ^| find /i "Input Locale:"') DO (
SET locale=%%~ns
set locale=!locale: =!
)
rem this is the actual search for the executable location
FOR /f "tokens=2 delims=," %%I IN ('wmic process where "name='virtualbox.exe'" get ExecutablePath^,Handle /Format:"%WINDIR%/System32/wbem/!locale!/csv" ^| FIND /i "virtualbox.exe"') DO SET "exepath=%%~I"
ECHO Detected Path: !exepath!
endlocal
But I always get
"C:\Program Files\Oracle\VirtualBox\VirtualBox.exe".
I tried from Task Manager (right click > Open File Location) and it happens the same, no matter which of the VirtualBox instances is running.
Uninstalling the version in my "C:\Program Files" enabled proper detection of the portable one.
Is it any way (using BATCH) to correctly detect running process executable location (VirtualBox.exe, in my case), when the situation is similar with the one described above (running a portable version of an already installed program)?

Parsing second DNS from IPCONFIG /all, Windows batch

I'm quite new to batch files and I'm trying to do something decently advanced and am trying to figure out how to identify and parse the second line under DNS SERVERS in IPCONFIG /all. If the answer is quite advanced, I would appreciate it greatly if you could explain it thoroughly. Here is my code:
#echo off
setlocal enabledelayedexpansion
set adapter=Ethernet adapter Local Area Connection
set adapterfound=false
for /f "usebackq tokens=1-4 delims=:" %%f in (`ipconfig /all`) do (
set item=%%f
if /i "!item!"=="!adapter!" (
set adapterfound=true
) else if not "!item!"=="!item:DNS Servers=!" if "!adapterfound!"=="true" (
rem echo DNS: %%g
set Globaldns=%%g
set adapterfound=false
)
)
for /f "tokens=1-2 delims= " %%m in ("%Globaldns%") do set Globaldns=%%m
echo DNS: %Globaldns%
If someone has two DNS servers set, I need a way to pull the second DNS address and store it in a second variable, the code above is able to pull the first DNS but I have not figured out a way to pull the second. Thank you for your help!!
EDIT:
Another piece of information. This needs to be able to be run on anything from Windows Vista to Windows 10 and it needs to be able to target a specific connection (we are only reconfiguring Ethernet devices, no wireless) So we need to be able to use the adapter's connection name to parse (i.e. Local Area Connection,Ethernet).
LotPings is right, ipconfig output is difficult to parse. Parsing wmic output could be easier.
Take a look at Win32_NetworkAdapter class and Win32_NetworkAdapterConfiguration class and their wmic aliases NIC and NICCONFIG, respectively.
For the first identification, use wmic NIC get /VALUE. Note the /VALUE switch and notice the NetConnectionID property: name of the network connection as it appears in the Network Connections Control Panel program. Then, parse output from
wmic NIC where "NetConnectionID = 'Local Area Connection'" get Index, MACAddress
to get Index property (index number of the Windows network adapter configuration. The index number is used when there is more than one configuration available) value to a varible, e.g. _index and use it as follows:
wmic NICCONFIG where "Index = %_index%" get /Value
For easier parsing, you can narrow output to only desired properties and change format to csv, for instance
set "_properties=DefaultIPGateway,DHCPServer,DNSServerSearchOrder,IPAddress,IPSubnet"
wmic NICCONFIG where "Index = %_index%" get %_properties% /format:CSV
Please notice and apply Dave Benham's WMIC and FOR /F: A fix for the trailing <CR> problem.
Edit: fixed a mistake with path keyword:
NIC       is a wmic alias for path Win32_NetworkAdapter
NICCONFIG is a wmic alias for path Win32_NetworkAdapterConfiguration
so e.g. next commands represent the same ˙WQL˙ query:
wmic NICCONFIG where "Index = %_index%" get /Value
wmic path Win32_NetworkAdapterConfiguration where "Index = %_index%" get /Value
Not a direct answer to the question but this powershell script might help, albeit I don't know if it will work back to vista.
gwmi Win32_NetworkAdapter -filter "netconnectionid is not null"|
%{ gwmi Win32_NetworkAdapterConfiguration `
-filter "interfaceindex=$([int]$_.interfaceindex)"|
select -expandproperty DNSServerSearchOrder}
As I have only one dns server configured my result is proper but meaningless.

How to check if current drive is on a local disk (cmd)?

To get the drive the current batch resides in is easy using
set batchdrive=%~d0
But how is it possible to check if %batchdrive% is on a local drive and not on a (mapped) network share?
Checking for %SYSTEMDRIVE% or a fixed list "C:" "D:" ... is not reliable.
To check whether a drive (%~d0) is a local one, you could use a wmic query:
wmic LogicalDisk where(DeviceID="%~d0" AND DriveType=3) get Description,DeviceID,DriveType
Given that %~d0 expands to the local drive C:, the output looks like:
Description DeviceID DriveType
Local Fixed Disk C: 3
In case %~d0 is a network drive Z:, the error output is:
No Instance(s) Available.
Unfortunately, wmic does not set the ErrorLevel in case of no matches, but the above message is returned at the STDERR stream rather than the STDOUT stream, so we can apply redirection to discard STDOUT (in case the drive matches; so the get query is omitted as it is not used anyway) and redirect STDERR to STDOUT instead (so the error message is returned at STDOUT in case):
2>&1 > nul wmic LogicalDisk where (DeviceID="%~d0" AND DriveType=3)
Hence the command line returns nothing in case %~d0 is a local drive, but something otherwise. Now let us capture the (redirected) STDOUT by a for /F loop:
for /F "delims=" %%L in ('
2^>^&1 ^> nul wmic LogicalDisk where ^(DeviceID^="%~d0" AND DriveType^=3^)
') do echo Drive "%~d0" is not local!
So if %~d0 points to a local drive, the body of for /F is not executed, but otherwise it is.
According to this resource, WMI and therefore the wmic command line tool is available since Windows XP (Prof.) onward; it was not available on Windows XP Home though. wmic does not require administrative privileges. The Win32_LogicalDisk class is available since availability of WMI. Reference the following resources for more information about WMI/wmic: Windows Management Instrumentation: Frequently Asked Questions and WMIC - Take Command-line Control over WMI.
The first thing to check is if batchdrive is an unmapped network share (this happens if you start the batch file outside of cmd.exe, for example via double click or via a system call):
if "%batchdrive%" == "\\" set nshare=1
The second thing is to check if batchdrive is in the list of network shares. These are shown with net use, which output is similar to
status local remote network
-------------------------------------------------------------------
OK D: \\computer1\share1 Microsoft Windows Network
OK E: \\computer1\share2 Microsoft Windows Network
disconnected F: \\computer2\share Microsoft Windows Network
Command executed successfully.
Therefore we filter the output for all lines that looks like a disk drive with findstr /r /c:" [A-Z]: " and took the second part of the output via for /f "tokens=2".
Complete snipped (working on WinXP and above):
if "%~d0" == "\\" (
set nshare=1
) else (
set nshare=0
for /f "tokens=2" %%a in ('net use ^| findstr /r /c:" [A-Z]: "') do (
if "%%a" == "%~d0" set nshare=1
)
)
Comments for possible issues requested :-)

dot net command: net use - How to only get Alphabet and pathname?

When I do a "net use" on my command prompt, it will display the following:
New connections will be remembered.
Status Local Remote Network
-------------------------------------------------------------------------------
OK W: \\hfs2\ATS\Novell Profile Backup\wk\one\two\three\four\five\six\seven\eight\nine\ten\eleven\twelve\thirteen
Microsoft Windows Network
OK X: \\hfs2\ATS\Novell Profile Backup\wk\one\two\three\four\five\six\seven\eight\nine\ten
Microsoft Windows Network
OK Y: \\hfs2\ATS\Novell Profile Backup
Microsoft Windows Network
Unavailable Z: \\hfs2\ATS Microsoft Windows Network
The command completed successfully.
How do I extract ONLY get the drive alphabet and pathname?
W:
\\hfs2\ATS\Novell Profile Backup\wk\one\two\three\four\five\six\seven\eight\nine\ten\eleven\twelve\thirteen
X:
\\hfs2\ATS\Novell Profile Backup\wk\one\two\three\four\five\six\seven\eight\nine\ten
Y:
\\hfs2\ATS\Novell Profile Backup
Z:
\\hfs2\ATS
EDIT
WMIC does not require administrator rights
It does require rights for what you are trying to do. You can't use it to do admin things if not an admin.
It also requires an administrator to run it once on a system to set it up.
From Help
User Account Control
Under UAC, accounts in the local Administrators group have two access tokens, one with standard user privileges and one with administrator privileges. Because of UAC access token filtering, a script is normally run under the standard user token, unless it is run "as an Administrator" in elevated privilege mode. Not all scripts required administrative privileges.
Scripts cannot determine programmatically whether they are running under a standard user security token or an Administrator token. The script may fail with an access denied error. If the script requires administrator privileges, then it must be run in the elevated mode. Access to WMI namespaces differs depending on whether the script is run in elevated mode. Some WMI operations, such as getting data or executing most methods, do not require that the account run as an administrator. For more information about default access permissions, see Access to WMI Namespaces and Executing Privileged Operations.
Wmic
The first time you run Wmic after system installation, it must be run from an elevated command prompt. The elevated mode may not be required for subsequent executions of Wmic unless the WMI operations require administrator privilege.
Use WMIC
wmic netuse get /format:list
gives you what's available.
Use something like
wmic netuse get remotepath, localname /format:list
To put the output in a file or on the clipboard.
WMIC specific switch
/output or /append
eg
wmic /node:"#%userprofile%\desktop\ComputerName.txt" /output:"%userprofile%\desktop\EventLog.html" /failfast:on PATH Win32_NTLogEvent where (EventIDentifier=42 or eventidentifier=1003) get /format:hform
(/node is a list of IP addresses and/or computer names of computers to run the command against, one IP address or computer name per line)
General Command Prompt File Redirection
Appending >filename.ext (or >>filename.ext to append to a file)to a command writes the output to the file rather than the screen.
wmic baseboard get product,Manufacturer,model,partnumber>MotherboardPartNum.txt
General Command Prompt Piping
Appending |command sends the output to a command rather than the screen. The usefull commands that output is sent to are
find or findstr (finds and filters text)
sort (sorts the output)
more (displays output to screen one page at a time)
clip (puts output onto the clipboard)
null (makes the data disappear for good - used for unwanted error messages)
wmic baseboard get product,Manufacturer,model,partnumber|clip
Combining Piping and Redirection
So we can combine them. To send the list to a file on the desktop in reversed sort order (z to a) with blank lines removed.
wmic service get name,displayname /format:list|findstr .|sort /r>"%userprofile%\desktop\services_reversed.txt"
WMIC Output Options
The output options are
/Format:list (a list - use notepad to view)
/format:table (a table - use notepad to view)
/format:hform (an html list - name the file's extension .html so IE will show)
/format:htable (an html table - name the file's extension .html so IE will show)
/format:csv (comma seperated variable - used for importing data into other programs such as excel)
also value, mof, rawxml, and xml.
So,
sort /?
find /?
findstr /?
more /?
clip /?
There are some problems in the output of net use
The Status field can hold information or be empty.
The Network field can have multiple values depending of network mapping. In my case i have "Microsoft Windows Network" and "Netware Services". So, there is no direct substitution.
The Network field can be in the same line that the Remote field or can be on the next line, and as the Remote field may include spaces, checking the character at the column limit position is not reliable. It is necessary to delay the check until the next line is readed to determine if it contains remote data.
So, not a one liner to handle it
#echo off
setlocal enableextensions disabledelayedexpansion
set "drive="
for /f "skip=6 tokens=1,* delims=\" %%a in ('net use') do (
if defined drive (
setlocal enabledelayedexpansion
if "%%b"=="" (
echo !drive! !networkPath!
) else (
echo !drive! !networkPath:~0,26!
)
endlocal
set "drive="
)
if not "%%b"=="" for /f "tokens=2" %%c in ("x%%a") do (
set "drive=%%c"
set "networkPath=\\%%b"
)
)
%%a loop will read the lines from net use and split them using a backslash as delimiter. This will allow us to determine if the line contains or not a network path (if there is no second token, the line did not contain a backslash).
As we are delaying the output of the information in one line until the next is readed (to determine if the remote path continues in the Network column), the first operation inside the for loop is to determine if we have data pending from previous loop. If there is data, depending on the content of the current line we select what to output.
Once the data is echoed, if the current line contains network information, it is saved for later output.
This is the faster solution, but there are two alternatives that require less code:
multiple net use commands
#echo off
setlocal enableextensions disabledelayedexpansion
rem For each line in the output of the net use that includes a drive letter
for /f "delims=" %%a in ('net use^|find ":"') do (
rem Retrieve the drive letter from the line
for /f "tokens=2" %%b in ("x%%a") do (
rem Run a net use with the drive letter and output the drive and the path
for /f "tokens=1,* delims=\" %%c in ('net use %%b') do if not "%%d"=="" echo(%%b \\%%d
)
)
Less code, but as multiple net use commands are executed, it is slower
Use WMIC
#echo off
setlocal enableextensions disabledelayedexpansion
for /f "tokens=2,3 delims=," %%a in (
'wmic netuse get LocalName^, RemoteName^, Status /format:csv ^| find ":"'
) do echo(%%a %%b
Less code, but in this case, adminitrator righs are required to run the command
I might be a little late but this helped me
WMIC NETUSE GET LocalName, RemotePath /FORMAT:TABLE | FIND /i ":"

Resources