There is the command net user
to list all User Accounts.
The output of the command is something like this:
Administrator Guest asroot
1psaadm 2satish 3shyam
4sushil 5sysuser_8 6sysuser_b
tcuser test1 test11
...
If I run this command
net user shyam
the output is:
Workstations allowed All
Logon script
User profile
Home directory C:\Inetpub\vhosts\example.com
Last logon 6/5/2021 4:57:17 AM
Logon hours allowed All
I want only the Home Directory
path from all user accounts
. So I want only this path C:\Inetpub\vhosts\example.com
from all user accounts.
I tried to get the wanted data with this command, but there is no output.
for /f "tokens=* skip=1" %a in ('wmic UserAccount get Name') do net user %a | findstr /c:"Home directory"
How can I get the list of all paths of all user accounts?
Note: If there is no Home directory
path in your cmd then you can try to list:
Logon hours allowed ALL
The output of WMIC is always a Unicode output with encoding UTF-16 LE (little endian) with BOM (byte order mark) which is a problem in this case because of the Windows command processor cmd.exe
is designed for processing text data with a character encoding using just one byte per character. CMD interprets the UTF-16 LE encoded line ending with the hexadecimal byte values 0D 00 0A 00
(carriage return + line-feed) wrong as 0D 0D 0A
and for that reason each line processed further from captured output has a carriage return at end after removing the line ending 0D 0A
.
There is one more problem with the command line:
wmic UserAccount get Name
WMIC appends on all lines trailing spaces so that every output line has the same number of characters. That is problematic as a user name can contain also one or more spaces and for that reason the default string delimiters normal space and horizontal tab cannot be used to remove the unwanted trailing spaces. The usage of tokens=*
results in removing just all leading spaces/tabs, but the trailing spaces remain.
What happens on using the following command line?
for /f "tokens=* skip=1" %a in ('wmic UserAccount get Name') do
There is assigned one user account name after the other to the specified loop variable a
with trailing spaces and a carriage return at end and for that reason the next command fails to work as expected.
In a command prompt window can be used:
for /F "skip=2 tokens=1* delims==" %G in ('%SystemRoot%\System32\wbem\wmic.exe USERACCOUNT GET Name /VALUE 2^>nul') do @for /F "eol=| delims=" %I in ("%H") do @for /F "tokens=2*" %J in ('%SystemRoot%\System32\net.exe user "%I" 2^>nul ^| %SystemRoot%\System32\findstr.exe /B /L /C:"Home directory"') do @echo Home directory for "%I" is: "%K"
In a batch file can be used:
for /F "skip=2 tokens=1* delims==" %%G in ('%SystemRoot%\System32\wbem\wmic.exe USERACCOUNT GET Name /VALUE 2^>nul') do for /F "eol=| delims=" %%I in ("%%H") do for /F "tokens=2*" %%J in ('%SystemRoot%\System32\net.exe user "%%I" 2^>nul ^| %SystemRoot%\System32\findstr.exe /B /L /C:"Home directory"') do echo Home directory for "%%I" is: "%%K"
This long command line is used best in a batch file as posted above, but better readable is:
for /F "skip=2 tokens=1* delims==" %%G in ('%SystemRoot%\System32\wbem\wmic.exe USERACCOUNT GET Name /VALUE 2^>nul') do (
for /F "eol=| delims=" %%I in ("%%H") do (
for /F "tokens=2*" %%J in ('%SystemRoot%\System32\net.exe user "%%I" 2^>nul ^| %SystemRoot%\System32\findstr.exe /B /L /C:"Home directory"') do (
echo Home directory for "%%I" is: "%%K"
)
)
)
The first command FOR with option /F
and a string enclosed in '
starts in background one more command process with option /c
to execute WMIC with full qualified file name and its four arguments with redirection 2>nul
to redirect a possible error message from handle STDERR (standard error) to device NUL. So executed is in background with Windows being installed into C:\Windows
the command:
C:\Windows\System32\cmd.exe /c C:\Windows\System32\wbem\wmic.exe USERACCOUNT GET Name /VALUE 2>nul
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.
WMIC uses in this case the Win32_UserAccount class as documented by Microsoft.
The output of WMIC with option /VALUE
at end is different to the output without this option. The output is now for each user account name:
Name=
and user account name appended without trailing spaces which is one reason for using option /VALUE
.There are output two more empty lines in this case at the end by WMIC.
FOR respectively cmd.exe
processing the batch file waits for self-termination of started cmd.exe
and then processes the captured text data which was output to handle STDOUT (standard output) of the background command process.
FOR with option /F
ignores always empty lines. But the Unicode encoded output of WMIC is not correct processed unfortunately by cmd.exe
and for that reason there are lines containing just a carriage return and lines starting with Name=
and a user account name and an erroneous carriage return at the end. So it is not possible to process the captured output directly.
The usage of the options skip=2 tokens=1* delims==
results in
Name
on the lines of interest with the account name,;
which is no problem here as the lines of interest start always with Name
G
the carriage return on the wrong processed empty lines or Name
on a line with a user account name and to next but one loop variable H
according to the ASCII table either no string at all on the empty lines or the user account name with an unwanted carriage return at the end.NOTE: A user account name beginning very unusual with one or more equal signs would not be correct processed by this code as all equal signs at beginning of the user account name would be removed by FOR too.
The second FOR again with option /F
processes now just the string assigned to the loop variable H
. So there is no string to process at all assigned to H
for empty lines interpreted wrong as a line with a single carriage return and so the second FOR loop filters out the empty lines.
For the lines with the user account name the name with the unwanted carriage return at end assigned to loop variable H
is processed by the the second FOR with removing the newline character carriage return and assigned the rest to the specified loop variable I
which is the wanted user account name. The option eol=|
is used here to avoid that an unusual name starting with one or more semicolons is ignored by second FOR. No user account name can contain a vertical bar as this is a character not allowed for file/folder names.
The third FOR loop once again with option /F
runs in background again one more command process to execute NET with output redirected first to FINDSTR to filter out all lines except the line starting case-sensitive with Home directory
. NET outputs the text data with a one byte per character encoding making it possible to filter the output with FINDSTR and processing the captured output by FOR more easily. The command executed in background is:
C:\Windows\System32\cmd.exe /c C:\Windows\System32\net.exe user "%%I" 2>nul | C:\Windows\System32\findstr.exe /B /L /C:"Home directory"
The third FOR has to process always only one line starting with Home directory
, fifteen spaces for alignment and perhaps nothing more or the home directory path as defined for the user account. There is used the option tokens=2*
to split up the line using default space/tab as line delimiters to get assigned the word directory
to the specified loop variable J
and the entire home directory path to next but one loop variable K
which can contain also one or more spaces or being an empty string as on my Windows computer for all accounts.
The third FOR executes finally the command ECHO to output the message with the user account name as determined by the second FOR and the home directory path as determined by third FOR if there is a home directory path at all.
Compo suggested to use WMIC with the Win32_NetworkLoginProfile class by using:
%SystemRoot%\System32\wbem\WMIC.exe NetLogin Get Caption,HomeDirectory
That class has account name and home directory path as members and so the wanted data can be get directly with WMIC.
The list of names is different between the two classes as it can be seen on running both WMIC commands in a command prompt window and reading the description for property Name of both classes carefully whereby the string of property Caption
of Win32_NetworkLoginProfile
class differs also from string of property Name
of this class. The string of Caption
is just the account name for a real user account while the string of Name
is ComputerName\AccountName for a local account or Domain\AccountName for a domain account.
However, it is perhaps possible to use the data of this class with the following code in a batch file:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "skip=2 tokens=1* delims==" %%G in ('%SystemRoot%\System32\wbem\wmic.exe NETLOGIN GET Caption^,HomeDirectory /VALUE 2^>nul') do (
if "%%G" == "Caption" (
set "AccountName="
for /F "eol=| tokens=1,2 delims=\" %%I in ("%%H") do if "%%J" == "" set "AccountName=%%I"
) else if "%%G" == "HomeDirectory" (
set "HomeDirectory="
for /F "eol=| delims=" %%I in ("%%H") do set "HomeDirectory=%%"
if defined AccountName (
setlocal EnableDelayedExpansion
echo Home directory for "!AccountName!" is: "!HomeDirectory!"
endlocal
)
)
)
endlocal
There is again the option /VALUE
as otherwise there would be again trailing spaces after home directory path if there is a home directory path output at all for an account which is not the case on my Windows computer.
The code is written to ignore the accounts containing in Caption
a backslash like NT AUTHORITY\SYSTEM
, NT AUTHORITY\LOCAL SERVICE
and NT AUTHORITY\NETWORK SERVICE
which are most likely not of interest at all. Well, it would be also possible to use if not "%%I" == "NT AUTHORITY"
instead of if "%%J" == ""
to filter out the accounts of no interest as not being real user accounts.
The advantage of this solution is that there is started cmd.exe
only once in background to run wmic.exe
and get all the data of interest. So this solution is faster.
To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.
cmd /?
echo /?
endlocal /?
for /?
if /?
net /?
net user /?
set /?
setlocal /?
wmic /?
wmic netlogin /?
wmic netlogin get /?
wmic useraccount /?
wmic useraccount get /?