Issues when getting a list of user profiles using WMIC - windows

I was using the following batch command to retrieve all local user profiles (including domain users too) :
for /f "delims=" %%I in ('dir /a:d-h /b "%SystemDrive%\Users\*" 2^>nul ^| %SystemRoot%\System32\findstr.exe /i /l /x /v /g:"%bin%\exclude_users.txt"') do (
The problem is that this command has its limits: it doesn't really check if the users in question do actually have an account.
The user Compo provided me a methodology for retrieving the profile names, using WMIC.
So I ended up writing the following command:
#For /F "tokens=* skip=1" %%I In ('%__AppDir__%wbem\WMIC.exe UserAccount Get Name ^|%__AppDir__%findstr.exe /i /l /x /v /g:"%bin%\exclude_users.txt"') do (
The problem is: it ignores my exclusion file (which contains one user per line) and it ends up a profile without any name.
Any idea How I can solve these issues ?

#echo off
setlocal
set "bin=%~dp0"
for /f "tokens=* skip=1" %%I in ('
%__AppDir__%wbem\WMIC.exe UserAccount where Disabled^="FALSE" get Name ^|
%__AppDir__%WindowsPowerShell\v1.0\powershell -noprofile -command "$input.trim()" ^|
%__AppDir__%findstr.exe /i /l /x /v /g:"%bin%\exclude_users.txt"
') do echo "%%~I"
The wmic output is piped to powershell to be trimmed and then piped to findstr.
The wmic command will exclude disabled accounts by use of the where clause.
Change the setting of bin as needed.

If you want a solution which still uses WMIC, and your exclusion list, then the following should do as you require.
#For /F Tokens^=4Delims^=^" %%G In ('%__AppDir__%wbem\WMIC.exe UserAccount Where "LocalAccount='TRUE'" Assoc:List /ResultRole:Name 2^>NUL')Do #Echo %%G|%__AppDir__%findstr.exe /VXLIG:"%~dp0exclude_users.txt"
You can split that over multiple lines for easier reading too:
#For /F Tokens^=4Delims^=^" %%G In ('%__AppDir__%wbem\WMIC.exe UserAccount^
Where "LocalAccount='TRUE'" Assoc:List /ResultRole:Name 2^>NUL'
)Do #Echo %%G|%__AppDir__%findstr.exe /VXLIG:"%~dp0exclude_users.txt"

Related

Get from the windows system the user email registered from cmd

do you know how to retrieve from the windows system the email with which the user registered in the operating system? When you create an account, windows asks you for an email to register. Is it possible to retrieve that information via code line, cmd or who knows what else?
I got a customer PC in today which actually had a single account which was created using an email address. The only possibilities I could find were by trying to retrieve the email address via the Windows registry.
This first idea was to see if the user account still had the default OneDrive account attributed to that email. So based upon that as a possibility you could try to isolate it from the User registry branch.
From the Command Prompt:
For /F "EOL=H Tokens=2*" %G In ('%SystemRoot%\System32\reg.exe Query "HKCU\SOFTWARE\Microsoft\OneDrive\Accounts\Personal" /V "UserEmail" 2^>NUL') Do #Echo(%H
From a batch file:
#For /F "EOL=H Tokens=2*" %%G In ('%SystemRoot%\System32\reg.exe Query "HKCU\SOFTWARE\Microsoft\OneDrive\Accounts\Personal" /V "UserEmail" 2^>NUL') Do #Echo(%%H
Alternatively you'd have to use the Machine registry branch, which would list all found. This however would only identify the current user if theirs was the only account on that machine which had been created to log in with an email address created account. If there are more than one, then it would list them all.
From the Command Prompt:
For /F "Delims=" %G In ('%SystemRoot%\System32\reg.exe Query "HKLM\SOFTWARE\Microsoft\IdentityStore\LogonCache" /S /F "Name2Sid" /K 2^>NUL ^| %SystemRoot%\System32\find.exe "HKEY_"') Do #For /F "EOL=H Tokens=2*" %H In ('%SystemRoot%\System32\reg.exe Query "%G" /S /V "IdentityName" 2^>NUL ^| %SystemRoot%\System32\find.exe "#"') Do #Echo(%I
From a batch file:
#For /F "Delims=" %%G In ('%SystemRoot%\System32\reg.exe Query "HKLM\SOFTWARE\Microsoft\IdentityStore\LogonCache" /S /F "Name2Sid" /K 2^>NUL ^| %SystemRoot%\System32\find.exe "HKEY_"') Do #For /F "EOL=H Tokens=2*" %%H In ('%SystemRoot%\System32\reg.exe Query "%%G" /S /V "IdentityName" 2^>NUL ^| %SystemRoot%\System32\find.exe "#"') Do #Echo(%%I
Please note, as per the comment section, the majority of user's computers I've worked on, and that is a very large number, do not have user accounts created using an email address, and the above examples would be unlikely to perform the task you require.

Exclude some outputs from WMIC query

I'm getting the list of Windows users and their local path, through wmic (thanks Compo).
I would like some user names to be excluded from the output in this wmic command :
#For /F "Skip=1Tokens=1,2" %%G In ('%__AppDir__%wbem\WMIC.exe UserAccount Where^
"LocalAccount='True' And Not Name Like '[_]%%'" Get Name^,SID 2^>Nul'
)Do #For /F %%I In ("%%H")Do #For /F "Tokens=2Delims==" %%J In ('
%__AppDir__%wbem\WMIC.exe Path Win32_UserProfile Where^
"SID='%%I' And Special!='True'" Get LocalPath /Value 2^>Nul'
)Do #For /F "Tokens=*" %%K In ("%%J")Do #Echo User name:"%%G",Profile path:"%%K"
I'm not sure how I can add this exclusion file :
%__AppDir__%findstr.exe /V /X / L/ /I G:"usernames.txt"
Can you help me please ?
Thank you
If your intention is to exclude names from the output, the general rule for efficiency, is to filter your commands as soon as possible in your code.
For this reason, the most efficient method would be to make the individual exclusions within the Where clause. I provided an example of how to do that in my comment, e.g. change the current exclusion, of names beginning with an underscore, (And Not Name Like '[_]%%'), to And Name!='Dimitri' And Name!='Kalinda' And Name!='Peter'.
If you have a list of exclusions one per line in a file, and there are too many to transfer into the Where clause, then you should perform that filtering in the Do portion of that initial For loop. You could at that point use findstr.exe with the options you chose, (just fixed).
As the code you chose from my original answer was not the robust one, which caters for user names with spaces/problematic characters, I'd suggest you change to that too.
For that reason, this would be my suggested answer, (excluding names within usernames.txt using findstr.exe):
#For /F Tokens^=4Delims^=^" %%G In ('%SystemRoot%\System32\wbem\WMIC.exe
UserAccount Where "LocalAccount='TRUE'" Assoc:List /ResultRole:SID 2^>NUL'
)Do #Set /P "=%%G"<NUL|%SystemRoot%\System32\findstr.exe /XVLIG:"usernames.txt"^
>NUL&&(For /F "Tokens=1*Delims==" %%H In ('%SystemRoot%\System32\wbem\WMIC.exe
UserAccount Where "Name='%%G'" Get SID /Value 2^>NUL
^|%SystemRoot%\System32\find.exe "="')Do #For %%J In (%%I
)Do #For /F "Tokens=1*Delims==" %%K In ('%SystemRoot%\System32\wbem\WMIC.exe
Path Win32_UserProfile Where (SID^="%%J" And Special!^="TRUE" And LocalPath
Is Not Null^) Get LocalPath /Value 2^>NUL^|%SystemRoot%\System32\find.exe
"="')Do #For /F Tokens^=* %%M In ("%%L"
)Do #Echo UserName:"%%G", UserProfile:"%%M")

Excluding a character in a FOR loop

I would like to display the information regarding the ProfileImagePath value of one windows user who don't have the "_" character in his username :
#echo off
cls
for /f %%I in ('dir /a:d-h /b C:\Users\ ^| %SystemRoot%\System32\findstr.exe /b /l /v "_"') do (
FOR /F "delims=" %%k IN ('reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"^|findstr.exe /R "S-1-5-21-[0-9]*-[0-9]*-[0-9]*-[0-9]*$" 2^>nul') do (
reg query "%%k" /v "ProfileImagePath"|findstr /i /e /c:"%%~I"
)
)
But the findstr command also takes into account users with the "_" character, while in the first FOR command, I have excluded this character :
ProfileImagePath REG_EXPAND_SZ C:\Users\user1
ProfileImagePath REG_EXPAND_SZ C:\Users\_user1
How is it possible ? How to take this into account in the 2nd FOR command ?
findstr /i /e /c:"user1" searches for strings ending with user1. However _user1 also ends with user1 :(
Changing it to findstr /i /e /c:"\%%~I" is one way to solve your problem :)

Batch scripting, mutlple finds and multple do sets

At the moment I am running the following to get some information from 'systeminfo', however it needs to run systeminfo twice which takes some time. How would I be able to do multple 'Find"XXX" do sets'?
For /f "delims=" %%A IN ('systeminfo ^| Find "OS Name"') DO Set "VarA=%%A"
For /f "delims=" %%A IN ('systeminfo ^| Find "BIOS Version"') DO Set "VarB=%%A"
Any help is greatly appreciated.
Next code snippet could work (note set commands are merely ECHOed for debugging purposes; remove capitalized ECHO no sooner than debugged):
For /f "delims=" %%A IN ('systeminfo') DO (
For /F "delims=" %%G IN ('echo %%A ^| Find /I "OS Name"') Do ECHO Set "VarA=%%A"
For /F "delims=" %%G IN ('echo %%A ^| Find /I "BIOS Version"') DO ECHO Set "VarB=%%A"
)
However, follow Stephan's advice and parse wmic output rather (do not forget /value option). To do that correctly, note great Dave Benham's article WMIC and FOR /F: A fix for the trailing <CR> problem
I too would use WMIC, but there is a simple solution if you want to use SYSTEMINFO - use FINDSTR with two /C:"search strings"
for /f "tokens=1,2*" %A in ('systeminfo ^| findstr /c:"OS Name" /c:"BIOS Version"') do set "%A=%C"
The above will define two variables on an English machine: OS and BIOS.
Thanks for the replies guys.
I wanted to set the bit version windows the batch file would run on, I figured it out ages ago but thought I would post it here for those that came across it:
echo %PROCESSOR_ARCHITECTURE% | find "64" > NUL
If %ERRORLEVEL% equ 0 (Set bit=64) else (Set bit=32)
Thanks!

batch: ignore last line of an output

I have a pretty basic script that echos local administrator accounts. My goal is to get rid of all of the header/footer information.
So far I have:
FOR /F "skip=6" %%G IN ('net localgroup administrators') DO echo %%G
Which echos:
Administrator
MyName
The
"The" being the first word in the footer: "The command completed successfully."
So I'd like to get rid of "The" but I understand that I may have to restructure the entire script, which is fine. I have tried saving to a variable %str% but you can't set multi-line variables. Also, using a txt file as a buffer is not an option.
Any input?
I can think of two simple solutions:
FOR /F "skip=6" %%G IN ('net localgroup administrators') DO if %%G neq The echo %%G
or
FOR /F "skip=6" %%G IN ('net localgroup administrators ^| findstr /vb The') DO echo %%G
I suppose one could argue a user name could be "The", in which case you can be more precise with the filter:
FOR /F "skip=6" %%G IN ('net localgroup administrators ^| findstr /vc:"The command completed successfully."') DO echo %%G

Resources