Print Result in Variable Obtained by for

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
deniscalanca
Posts: 11
Joined: 26 Oct 2017 11:30

Print Result in Variable Obtained by for

#1 Post by deniscalanca » 28 Aug 2018 14:32

how do I manage to demand the result obtained in the for?

@echo off

setlocal
setlocal EnableExtensions
setlocal EnableDelayedExpansion

set "usr1_name=user1"

for /F "skip=1 delims= " %%a in ('wmic useraccount where name^="%usr1_name%" get passwordexpires') do (
set usr1_passwdexpiretmp=%%a
)

for /F "skip=1 delims= " %%b in ('wmic useraccount where name^="%usr1_name%" get passwordchangeable') do (
set usr1_passwordchangeabletmp=%%b
)

echo %usr1_passwdexpiretmp%
echo %usr1_passwordchangeabletmp%

pause

Result:

ECHO It's deactivated
ECHO It's deactivated

ShadowThief
Expert
Posts: 881
Joined: 06 Sep 2013 21:28
Location: Virginia, United States

Re: Print Result in Variable Obtained by for

#2 Post by ShadowThief » 28 Aug 2018 14:54

You've enabled delayed expansion, but you aren't using it. Change the echo statements to

Code: Select all

echo !usr1_passwdexpiretmp!
echo !usr1_passwordchangeabletmp!

deniscalanca
Posts: 11
Joined: 26 Oct 2017 11:30

Re: Print Result in Variable Obtained by for

#3 Post by deniscalanca » 28 Aug 2018 17:00

ShadowThief wrote:
28 Aug 2018 14:54
You've enabled delayed expansion, but you aren't using it. Change the echo statements to

Code: Select all

echo !usr1_passwdexpiretmp!
echo !usr1_passwordchangeabletmp!
I made the exchange and yet the return is:

ECHO It's deactivated
ECHO It's deactivated

I disable delayed expansion and still the return is:

ECHO It's deactivated
ECHO It's deactivated

dbenham
Expert
Posts: 2197
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Print Result in Variable Obtained by for

#4 Post by dbenham » 29 Aug 2018 06:47

The ECHO statements are not within the FOR loop, so delayed expansion is not required.

Assuming your code really matches your post, the most likely explanation is that user "user1" does not exist, so there are no iterations and the variables are never set.

It is easy to check - simply add echo %%a within the first FOR loop. If you don't see a value printed when you run the script, then you know the user does not exist.


Dave Benham

deniscalanca
Posts: 11
Joined: 26 Oct 2017 11:30

Re: Print Result in Variable Obtained by for

#5 Post by deniscalanca » 29 Aug 2018 13:35

dbenham wrote:
29 Aug 2018 06:47
The ECHO statements are not within the FOR loop, so delayed expansion is not required.

Assuming your code really matches your post, the most likely explanation is that user "user1" does not exist, so there are no iterations and the variables are never set.

It is easy to check - simply add echo %%a within the first FOR loop. If you don't see a value printed when you run the script, then you know the user does not exist.


Dave Benham
I'm considering that the user exists, and I test the script on a Windows with that created user, follows the piece of script that I want to make work, when trying to execute it the return is:

ECHO It's deactivated
ECHO It's deactivated

if I run "echo %%a" and "echo %%B" I get the result I want, but I need to save the result in a variable that will be used later

@echo off

set "usr1_name=user1"
set "usr1_status=yes"
set "net=%windir%\System32\net.exe"

:start
if /i "%usr1_status%" == "yes" (
%net% user "%usr1_name%" 1>nul 2>nul
if not errorlevel 1 (
for /f "skip=1 delims= " %%b in ('wmic useraccount where name^="%usr1_name%" get passwordchangeable') do (
if /i "%%b" == "true" (
set "usr1_passwordchangeabletmp=yes"
) else if /i "%%b" == "false" (
set "usr1_passwordchangeabletmp=no"
)
)
for /f "skip=1 delims= " %%a in ('wmic useraccount where name^="%usr1_name%" get passwordexpires') do (
if /i "%%a" == "true" (
set "usr1_passwdexpiretmp=yes"
) else if /i "%%a" == "false" (
set "usr1_passwdexpiretmp=no"
)
)
echo %usr1_passwordchangeabletmp%
echo %usr1_passwdexpiretmp%
goto exit
) else (
goto exit
)
) else if /i "%usr1_status%" == "no" (
goto exit
)

:exit
pause

sst
Posts: 71
Joined: 12 Apr 2018 23:45

Re: Print Result in Variable Obtained by for

#6 Post by sst » 29 Aug 2018 14:14

That's because WMIC outputs in Unicode, FOR /F converts it to ANSI encoding but before that, it will strip the LineFeeds and splits the output to individual lines then converts the text, the result is that you end up with orphaned carriage return characters.

So the last line that FOR /F passes to the body is a single carriage return character which will be stripped again by batch parser when using normal expansion, so essentially echo %usr1_passwdexpiretmp% will become just echo with no parameters and you will get ECHO in on/off message, and even if you use delayed expansion, echo prints the CR character which will just moves cursor to the start of the line.

There are multiple ways to overcome this, some are slightly simpler than the others, but will just work if certain conditions are met and output is in some particular format, but i'll prefer more general approach which should not depend on the format and value of the properties you query.

A Simple method which will only work if the value you query does not contain any of these characters: <SPACE>;, which will work for your particular query anyway

Code: Select all

for /f "skip=1 delims=" %%A in ('wmic useraccount where name^="%usr1_name%" get passwordexpires') do for %%B in (%%A) do set "usr1_passwdexpiretmp=%%B"
And a more general approach which will work for most cases

Code: Select all

@echo off
setlocal EnableExtensions

set "usr1_name=user1"

for /f "tokens=1* delims==" %%A in ('wmic useraccount where name^="%usr1_name%" get passwordexpires /value') do (
    if "%%B" NEQ "" set "usr1_passwdexpiretmp=%%B"
)
:: usr1_passwdexpiretmp still contains carriage return, strip it by reassigning with normal expansion
set "usr1_passwdexpiretmp=%usr1_passwdexpiretmp%"

echo %usr1_passwdexpiretmp%
It still is not bullet proof and will fail if the value you query contains double quotes and any batch poison character exist inside the double quotes like "this & that" then when using the last set to strip the CR character this fails: set "value="this & that""

This can happen for example when querying Processes CommandLine values.

deniscalanca
Posts: 11
Joined: 26 Oct 2017 11:30

Re: Print Result in Variable Obtained by for

#7 Post by deniscalanca » 31 Aug 2018 07:12

sst wrote:
29 Aug 2018 14:14
That's because WMIC outputs in Unicode, FOR /F converts it to ANSI encoding but before that, it will strip the LineFeeds and splits the output to individual lines then converts the text, the result is that you end up with orphaned carriage return characters.

So the last line that FOR /F passes to the body is a single carriage return character which will be stripped again by batch parser when using normal expansion, so essentially echo %usr1_passwdexpiretmp% will become just echo with no parameters and you will get ECHO in on/off message, and even if you use delayed expansion, echo prints the CR character which will just moves cursor to the start of the line.

There are multiple ways to overcome this, some are slightly simpler than the others, but will just work if certain conditions are met and output is in some particular format, but i'll prefer more general approach which should not depend on the format and value of the properties you query.

A Simple method which will only work if the value you query does not contain any of these characters: <SPACE>;, which will work for your particular query anyway

Code: Select all

for /f "skip=1 delims=" %%A in ('wmic useraccount where name^="%usr1_name%" get passwordexpires') do for %%B in (%%A) do set "usr1_passwdexpiretmp=%%B"
And a more general approach which will work for most cases

Code: Select all

@echo off
setlocal EnableExtensions

set "usr1_name=user1"

for /f "tokens=1* delims==" %%A in ('wmic useraccount where name^="%usr1_name%" get passwordexpires /value') do (
    if "%%B" NEQ "" set "usr1_passwdexpiretmp=%%B"
)
:: usr1_passwdexpiretmp still contains carriage return, strip it by reassigning with normal expansion
set "usr1_passwdexpiretmp=%usr1_passwdexpiretmp%"

echo %usr1_passwdexpiretmp%
It still is not bullet proof and will fail if the value you query contains double quotes and any batch poison character exist inside the double quotes like "this & that" then when using the last set to strip the CR character this fails: set "value="this & that""

This can happen for example when querying Processes CommandLine values.
Funny that testing only the code I get the result, but when inserting a for inside the if I get echo off

Post Reply