topbanner_forum
  *

avatar image

Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
  • Friday March 29, 2024, 6:35 am
  • Proudly celebrating 15+ years online.
  • Donate now to become a lifetime supporting member of the site and get a non-expiring license key for all of our programs.
  • donate

Author Topic: Help with Windows batch script  (Read 4630 times)

AzureToad

  • Charter Member
  • Joined in 2006
  • ***
  • Posts: 95
    • View Profile
    • Read more about this member.
    • Donate to Member
Help with Windows batch script
« on: May 05, 2015, 11:11 AM »
Ok, 1st off, I'm guessing this probably isn't the best place for this post. If not, someone can move it to the best area - as long as it's not the trash bin!

I am having problems with a Windows batch script. Maybe someone out there can point out my error.

What I'm trying to do is to retrieve a list of remote desktop sessions on a server, then log each one off unless the login name matches a list of names to be ignored.
The list of sessions and logging off is not a problem. It's when I need to check against the list of names that I have a problem.

Here's my code:

Code: Text [Select]
  1. SET serverlist=APPLE BANANA CHERRY
  2. FOR %%s in (%serverlist%) DO (
  3.         FOR /f "tokens=1,2,3" %%a IN ('QUERY USER /server:%%s^"') DO (
  4.                 ::      Don't log off this list of users:
  5.                 ::      administrator, Zebra, Yankee
  6.                 IF /I [%%a] EQU [administrator] (
  7.                         ECHO Ignored user %%a
  8.                 ) ELSE (
  9.                         IF /I [%%a] EQU [Zebra] (
  10.                                 ECHO Ignored user %%a
  11.                         ) ELSE (
  12.                                 IF /I [%%a] EQU [Yankee] (
  13.                                         ECHO Ignored user %%a
  14.                                 ) ELSE (
  15.                                         IF %%c LSS 65536 (
  16.                                                 ECHO Logging off ACTIVE user %%a on session %%c
  17.                                                 LOGOFF /server:%%s %%c
  18.                                         ) ELSE (
  19.                                                 IF %%b LSS 65536 (
  20.                                                         ECHO Logging off DISCONNECTED user %%a on session %%b
  21.                                                         LOGOFF /server:%%s %%b
  22.                                                 )
  23.                                         )
  24.                                 )
  25.                         )
  26.                 )
  27.         )
  28. )

When I DON'T check for individual login names, all users are logged off. That part works great - has been working for years.
Checking for the individuals doesn't work - all users are logged off anyway with the message indicating whether they were active or disconnected.

PLUS, with username checking, the script stops after the 2nd server loop. Server APPLE and BANANA are checked and all users are logged off, but the loop stops without checking server CHERRY.
  (Turns out the script only had APPLE and BANANA defined - no CHERRY on top!)

I figured I must have an unbalanced parenthesis, but I've gone over this until my head hurts and can't find it.  So I turn to this group for help.
« Last Edit: May 05, 2015, 11:17 AM by AzureToad »

4wd

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 5,641
    • View Profile
    • Donate to Member
Re: Help with Windows batch script
« Reply #1 on: May 05, 2015, 08:27 PM »
Bearing in mind I haven't got a Domain setup to test this on:

I get the following return from QUERY USER /server:8x8x64  (8x8x64 is localhost):

Code: Text [Select]
  1. USERNAME      SESSIONNAME       ID   STATE   IDLE TIME      LOGON TIME
  2.  4wd          console            1   Active      none       6/05/2015 10:31

A multi-line return, you seem to be interested in only the first three tokens returned, which would be: USERNAME, SESSIONNAME, ID

If it's a different for a Domain server, can you post an example?

Otherwise, here's a short version that might work, (no output regarding who's logged on/off - but you should be able to add it under the IF statement by parsing the text file for the info):

Code: Text [Select]
  1. SET serverlist=APPLE BANANA CHERRY
  2. SET userlist=administrator zebra yankee
  3. SET tempfile=%TEMP%\quser.txt
  4. FOR %%s in (%serverlist%) DO (
  5.   QUERY USER /server:%%s >%tempfile%
  6.   FOR %%u in (%userlist%) DO (
  7.     FIND /C /I %%u %tempfile%
  8.     IF %ERRORLEVEL% NEQ 0 LOGOFF /server:%%s
  9.     )
  10.   )


Regarding your command file:
'QUERY USER /server:%%s^"'  - seems to escaping a single quotation mark, there's no matching quote, although quotes shouldn't be needed anyway since there's no spaces in any of the arguments.

While it runs, it could be written as:

FOR /f "tokens=1,2,3 usebackq" %%a IN (`QUERY USER /server:%%s`) DO (

AzureToad

  • Charter Member
  • Joined in 2006
  • ***
  • Posts: 95
    • View Profile
    • Read more about this member.
    • Donate to Member
Re: Help with Windows batch script
« Reply #2 on: May 06, 2015, 12:13 AM »
Wow, I like how compact your example is!  :up:
I managed to modify my script, using an array of users and a FOR loop, somewhat similar to yours.

Output from the QUERY USER /SERVER: looks the same as query on localhost.  Here's a sample (names changed, of course):
Code: Text [Select]
  1. USERNAME              SESSIONNAME        ID  STATE   IDLE TIME  LOGON TIME
  2.  ablebz                                    2  Disc         4:25  5/5/2015 5:33 AM
  3.  wertala                                   4  Disc         2:57  5/5/2015 10:21 AM
  4.  trowe801              rdp-tcp#40          7  Active       5:18  5/5/2015 10:49 AM
  5.  aspensma                                  8  Disc         4:17  5/5/2015 3:18 PM

After looking at your code a bit more, i think it would have to be modified a bit. I think you'd need to create a file of the users that should NOT be logged off, then have a FOR loop for each server, and have a FOR loop extracting each user currently logged on that server. Then you could use the FIND command to see if the current login ID is in the file to be ignored, and if it's not, then you'd issue the LOGOFF command.  Unless I totally missed your example?

Bottom line, I finally did get my script to work.
Thanks for your reply!

4wd

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 5,641
    • View Profile
    • Donate to Member
Re: Help with Windows batch script
« Reply #3 on: May 06, 2015, 12:52 AM »
Thanks for the example output, forgot about having more than one user logged in since I only have single user machines on a LAN to play with - so yeah, my example only dealt with that scenario so not having a session specified in the LOGOFF command is kind of limiting :)

I might have a play with your output to see what I can come up with.

4wd

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 5,641
    • View Profile
    • Donate to Member
Re: Help with Windows batch script
« Reply #4 on: May 06, 2015, 02:36 AM »
Seemed to work OK with the example output you gave above, (edited to test various cases), but I couldn't test it listing output from servers, etc.

Create a file in the same directory as the command file called validusers.txt and enter each user, one per line.

Remove the echo. in front of the LOGOFF command if the output looks OK.

Code: Text [Select]
  1. @echo off
  2. SET serverlist=APPLE BANANA CHERRY
  3. SET userlist=.\validusers.txt
  4. SET tempfile=.\quser.txt
  5. for %%s in (%serverlist%) do (
  6.   QUERY USER /server:%%s >%tempfile%
  7.   for /f "skip=1 tokens=1,2,3,4,5,6,7,8" %%a in (%tempfile%) do (
  8. rem If it's a remote session then %%h will not be empty
  9.     if "%%~h" NEQ "" call :Logoff %%a %%b %%c %%d %%s
  10.   )
  11. )
  12. goto :End
  13.  
  14. :Logoff
  15. findstr /I ^%1$ %userlist% >NUL
  16.   if %ERRORLEVEL% NEQ 0 (
  17.     echo.Logging off User: %1, Session: %2, Status: %4
  18.     echo.LOGOFF %2 /server:%5
  19.   ) else (
  20.     echo.Ignored user %1
  21.   )
  22. goto :EOF
  23.  
  24. :End

Example output, (as is, using a modified QUSER output):
Code: Text [Select]
  1. Logging off User: wertala, Session: rdp-tcp#2, Status: Disc
  2. LOGOFF rdp-tcp#2 /server:8x8x64
  3. Ignored user trowe801
  4. Ignored user administrator

So if nothing else, the :Logoff subroutine will maybe give you some ideas.

QUSER test output used
Code: Text [Select]
  1. USERNAME              SESSIONNAME        ID  STATE   IDLE TIME  LOGON TIME
  2.  ablebz                                    2  Disc         4:25  5/5/2015 5:33 AM
  3.  wertala               rdp-tcp#2           4  Disc         2:57  5/5/2015 10:21 AM
  4.  trowe801              rdp-tcp#40          7  Active       5:18  5/5/2015 10:49 AM
  5.  administrator         rdp-tcp#1           8  Active       4:17  5/5/2015 3:18 PM


validuser.txt used
administrator
yankee
zebra
trowe801


Ath

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 3,612
    • View Profile
    • Donate to Member
Re: Help with Windows batch script
« Reply #5 on: May 06, 2015, 03:18 AM »
You might want to create a %server%-validusers.txt file, by making these subtle changes:

Code: Text [Select]
  1. ...
  2. SET userlist=validusers.txt
  3. ...
and
Code: Text [Select]
  1. ...
  2. :Logoff
  3. findstr /I ^%1$ .\%5-%userlist% >NUL
  4. ...

and having 3 files APPLE-validusers.txt, BANANA-validusers.txt and CHERRY-validusers.txt in the current directory.

You could make it even more fancy by adding a check for common users in validusers.txt, but that seems like a little overkill to me.

4wd

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 5,641
    • View Profile
    • Donate to Member
Re: Help with Windows batch script
« Reply #6 on: May 06, 2015, 04:37 AM »
@Ath: I was hoping you'd show us a one line Powershell script.

 :P

Good idea the per server user list.  :Thmbsup: