Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Parsing NET USERS output

517 views
Skip to first unread message

jgq...@gmail.com

unread,
Aug 10, 2015, 9:49:05 AM8/10/15
to
I find I last looked at this area about 12 years ago, but haven't much improved on it since then. I have simplified it somewhat because I know that the user names will never contain a blank.

@echo off
setlocal
:: show what the 'net users' command produces:
:: * headers
:: * three user names per line
:: * one, two or three user names on final line
:: * trailers
net users
:: split the result lines into individual user names
for /f "skip=4 tokens=1-3" %%a in ('net users') do (
call :process1to3 %%a %%b %%c
)
endlocal
PAUSE
exit
::----------
:process1to3
ECHO Parms are "%1" "%2" "%3"
PAUSE
:: check if we've completed all users
if "%1 %2 %3"=="The command completed" goto :eof
:: there must always be a %1 !
call :process_single %1
if not "%2"=="" call :process_single %2
if not "%3"=="" call :process_single %3
goto :eof
::-----
:process_single
echo User is %1
:: additional useful processing for this user goes here
goto :eof

Can anyone enhance the elegance of this routine, please?

foxidrive

unread,
Aug 10, 2015, 10:04:07 AM8/10/15
to
On 10/08/2015 23:49, jgq...@gmail.com wrote:
> I find I last looked at this area about 12 years ago, but haven't much
> improved on it since then. I have simplified it somewhat because I know
> that the user names will never contain a blank.

AIUI User names can contain a space. Are you saying that the users in your
business will never contain a space?

https://msdn.microsoft.com/en-us/library/bb726984.aspx

jgq...@gmail.com

unread,
Aug 10, 2015, 1:05:25 PM8/10/15
to
Yes, that is precisely what I'm saying! Hence no substringing of the NET USERS line in 25-character 'chunks', and removing trailing blanks from each chunk.

foxidrive

unread,
Aug 10, 2015, 6:37:54 PM8/10/15
to
On 11/08/2015 03:05, jgq...@gmail.com wrote:
> On Monday, August 10, 2015 at 3:04:07 PM UTC+1, foxidrive wrote:
>> On 10/08/2015 23:49, jgq...@gmail.com wrote:
>>> I find I last looked at this area about 12 years ago, but haven't
>>> much improved on it since then. I have simplified it somewhat
>>> because I know that the user names will never contain a blank.
>>
>> AIUI User names can contain a space. Are you saying that the users in
>> your business will never contain a space?
>
> Yes, that is precisely what I'm saying! Hence no substringing of the
> NET USERS line in 25-character 'chunks', and removing trailing blanks
> from each chunk.

Does this help to give you a list of only the lines containing usernames?

net users|find " "


On my machine it does but I have a limited scope to test with, and the
Windows version itself may be significant.

JJ

unread,
Aug 11, 2015, 7:48:29 AM8/11/15
to
AFAIK, it's not possible using the FOR command since it always treat space
as delimiter and the user names may contain space(s).

My solution is this.

@echo off
setlocal

:: get list into file
net users>users.tmp
:: call self with file as input
call :input_start<users.tmp
del users.tmp
goto :eof

:input_start
:: skip first 4 input lines
set/p i=
set/p i=
set/p i=
set/p i=

:input_line
:: process each line
set/p i=
echo ==========
echo Line is "%i%"
if "%i%" == "The command completed successfully." goto :eof
call :get_user %i:~0,24%
call :get_user %i:~25,24%
call :get_user %i:~50,24%
goto input_line

:get_user
:: process each user. trim user name
if "%*" == "" goto :eof
echo Got user "%*"

jgq...@gmail.com

unread,
Aug 11, 2015, 2:24:48 PM8/11/15
to
No, sadly - all it does is to remove the line of all hyphens!
you still get:
User accounts for \\Windows7ProComputername
and
The command completed successfully
and
a terminating blank line 0D0A

jgq...@gmail.com

unread,
Aug 11, 2015, 2:37:33 PM8/11/15
to
Yes, your BATch file works for me - but you CAN use a FOR command

for /f "tokens=* skip=4" %%a in ('net users') do call :process "%%a"

and substring the line (having removed the double quotes) like you did.

Remember that I specified that none of my account names contains a space!

foxidrive

unread,
Aug 11, 2015, 7:49:35 PM8/11/15
to
Try it again. Copy and paste this time.


JJ

unread,
Aug 12, 2015, 7:03:07 AM8/12/15
to
On Tue, 11 Aug 2015 11:37:31 -0700 (PDT), jgq...@gmail.com wrote:
>
> Yes, your BATch file works for me - but you CAN use a FOR command
>
> for /f "tokens=* skip=4" %%a in ('net users') do call :process "%%a"
>
> and substring the line (having removed the double quotes) like you did.
>
> Remember that I specified that none of my account names contains a space!

In that case, your code already work as needed and efficiently.
What more do you want?
Using substring method would only make the code more cluttered and performs
slower.

It can still be simplified more, however.

@echo off
setlocal
::net users
for /f "skip=4 tokens=1-3" %%a in ('net users') do (
if "%%a %%b %%c"=="The command completed" goto end
call :process_single %%a
call :process_single %%b
call :process_single %%c
)
:end
pause
exit
:process_single
if "%1"=="" goto :eof
echo User is %1

jgq...@gmail.com

unread,
Aug 12, 2015, 2:43:38 PM8/12/15
to
That has the neatness which I was looking for.

I have made a minor change, and incorporated foxidrive's neat FIND command, to give:
@echo off
setlocal
:: note that there are TWO spaces between the double-quotes!
for /f "tokens=1-3" %%a in ('net users^|find " " ') do (
if not "%%a %%b %%c"=="The command completed" (
call :process %%a
call :process %%b
call :process %%c
)
)
pause
exit
::-----
:process
if "%1"=="" goto :eof
echo User is %1
:: other processing here
goto :eof

Thanks very much to you both!

jgq...@gmail.com

unread,
Aug 12, 2015, 2:47:40 PM8/12/15
to
One final improvement!

@echo off
setlocal
:: note that there are TWO spaces between the double-quotes!
for /f "tokens=1-3" %%a in ('net users^|find " " ') do (
call :process %%a
call :process %%b
call :process %%c
)
pause
exit
::-----
:process
if "%1"=="" goto :eof
echo User is %1
:: other user processing here
goto :eof

Kerr Mudd-John

unread,
Aug 12, 2015, 4:15:17 PM8/12/15
to
On Wed, 12 Aug 2015 19:47:39 +0100, <jgq...@gmail.com> wrote:

> One final improvement!
>
> @echo off
> setlocal
> :: note that there are TWO spaces between the double-quotes!
> for /f "tokens=1-3" %%a in ('net users^|find " " ') do (
> call :process %%a
> call :process %%b
> call :process %%c
> )
> pause
> exit
Instead of "exit" I'd use
goto :eof
here; just for old times sake! (exit terminates the current cmd
environment, "goto :eof" just exits the current batch; handier if you're
nesting them)

> ::-----
> :process
> if "%1"=="" goto :eof
> echo User is %1
> :: other user processing here
> goto :eof


--
Bah, and indeed, Humbug

jgq...@gmail.com

unread,
Aug 13, 2015, 6:21:21 AM8/13/15
to
I always used to use goto :eof throughout, but I've moved to exit [/b n] to indicate where the batch file is terminating, and use goto :eof just to leave 'subroutines'.
It all seems to give the same result!
0 new messages