runshell Redirect to file

Started by bmclellan, July 28, 2020, 02:42:30 PM

Previous topic - Next topic

bmclellan

Hello,

I am using Runshell to execute qwinsta.exe to see if a user is logged in. Is there a way to redirect the output to a file to parse afterwards? I can't seem to get that to work here.
Mind you, if there is a better way to do this, feel free to let me know :)

Code:
   qwinstaCommandLine = "C:\Windows\System32\qwinsta.exe"
   ParamsToRun = StrCat("/SERVER:",ServerName," ",UserName," /CONNECT /VM > ",WorkingDir,"Barry.txt")
;Value is: /SERVER:110.92.68.110 bmclella@cx.ciscolabs.com /CONNECT /VM > C:\Users\bmclella\Documents\AdminTools\Barry.txt
   t1 = RunShell(qwinstaCommandLine, ParamsToRun, WorkingDir, @NORMAL,@WAIT)

Thanks!
Barry

td

The simplest solution is to use the command shell:

https://techsupt.winbatch.com/webcgi/webbatch.exe?techsupt/nftechsupt.web+WinBatch/DOS+Slash~C~and~Redirection~Symbol~Not~Working.txt

There are more elaborate ways of redirecting stdout in the Tech Database but the command shell should be sufficient in this case.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

ChuckC

It is completely unnecessary to execute QWINSTA in a child process with output redirected to a file that is then parsed by your WinBatch script.

Instead, take a look at the Windows Terminal Server [WTS] Extender.  The functions that it provides allow you to enumerate all terminal services sessions and to query information about each session, including the account name of the user associated with each session.  In the Consolidated WIL Help, under the "WIL Extenders -> Terminal Service Extender -> Sample Code" topic, there is a sample script named TSEXplorer.wbt that fully demonstrates the usage of the extender's functions and which provides a UI to display session information.

td

I will leave it to the OP to decide whether the command shell executable or the extender is the better fit but the Terminal Server extender example can also be found here:

https://docs.winbatch.com/mergedProjects/TerminalServices/TERMSERVTSExplorerwbt.htm
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

bmclellan

Thanks guys!

Chuck, I tried out the extender, but I could never get it to return anything to me other than RC=106 assuming that meant server not found. I'm running in a virtual workspace and connecting to servers from there. Maybe that has something to do with it?

I tried this example below putting in my server IP with \\ as a prefix. As well, I also tried the full example and changed my domain to the one my server farm is on.

;Load 32-bit or 64-bit extender
AddExtender( "WWWTS44I.DLL" , 0, "WWWTS64I.DLL" )

server = AskLine("Server", "Please enter your server", "", 0)

Title01 = 'Test wtsEnumSessions()'
ErrorMode(@OFF)
Result = wtsEnumSessions(server)
RC = LastError()
ErrorMode(@CANCEL)
TempMsg = StrCat('wtsEnumSessions(%server%) RC = ',RC,@CRLF)
If (RC == 0)
   TempMsg = StrCat(TempMsg,@CRLF,'Total # of Sessions = ',Result[0])
   TempMsg = StrCat(TempMsg,@CRLF,@CRLF,'Session #''s = "',StrReplace(Result[1],@TAB,', '),'"')
   TempMsg = StrCat(TempMsg,@CRLF,@CRLF,'Session Names = "',StrReplace(Result[2],@TAB,', '),'"')
   TempMsg = StrCat(TempMsg,@CRLF,@CRLF,'Connection Statuses = "',StrReplace(Result[3],@TAB,', '),'"')
EndIf
Message(Title01,TempMsg)
Exit

td

    If your server was not found, I would have expected the error 103 - Unable to open a terminal server handle.  It might be the case that you don't have query information permission on the server. According to MSFT documentation:

    • To enumerate a session, you must enable the query information permission. For more information, see Remote Desktop Services Permissions.
    • To change permissions on a session, use the Remote Desktop Services Configuration administrative tool.
    • To enumerate sessions running on a virtual machine hosted on a RD Virtualization Host server, you must be a member of the Administrators group on the RD Virtualization Host server.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

bmclellan

Thanks Tony, I wonder why qwinsta.exe works and the extender does not. Maybe it's trying to pull more information than just what this needs.

Sadly though, I can't even get this to run from the command line and have it redirect to a file. The file is created, but somehow the text output from that command does not go into it! I probably should have tried this  manually before looking for a way to shell out to it!

     qwinsta.exe /SERVER:10.92.68.222 mclellan /CONNECT /VM > a.txt


Have a great day!
Barry


ChuckC

From the "List of Errors" help topic for the Terminal Service Extender:

"106: Unable to enumerate sessions".

Refer to the wwwbatch.ini file and look for a section in it that is named for the extender.  It will contain data relating to the underlying API function that failed and what the native error code was.

In most cases, we're dealing with a security related issue, either an authentication issue due to a lack of credentials, or an authorization issue with not having sufficient permissions.

Are you logged on as a domain user on a domain member computer that is in the same domain as the server for which you are passing to the WtsEnumSessions() function?

Does your user account meet the security requirements of the remote system w/respect to enumerating terminal services sessions?


QWINSTA may possibly be making an API call that is slightly different than what the WTS extender uses to connect to a remote server.  Internally, the extender calls the WTSOpenServer() API function to get a handle to the remote server, which was the only API function available for this at the time the extender was developed, and it is documented as requiring a minimum of Windows Vista / Windows Server 2008.  Additionally, the docs state that it "Opens a handle to the specified Remote Desktop Session Host (RD Session Host) server."  There is a newer API function STSOpenServerEx(), which still takes a single parameter that is the name of the server to connect to, but it is only supported on Windows 7 / 2008 R2 [and newer], and is documented as "Opens a handle to the specified Remote Desktop Session Host (RD Session Host) server or Remote Desktop Virtualization Host (RD Virtualization Host) server.".  Note the reference to a "RD Virtualization Host" in that description.  Seeing that the "/VM" switch is being used with QWINSTA, I expect that QWINSTA is actually calling WTSOpenServerEx() and that this is most likely the cause of the problem.

Tony - It should be trivial to modify the extender so that it calls WTSOpenServerEx() instead of WTSOpenServer() on any Windows system where the WTSOpenServerEx() function is exported from WTSAPI32.DLL.  In the event that WTSOpenServerEx() is not exported, then WTSOpenServer() should be used with the understanding that the Terminal Service Extender is running on a down-level system that won't be able to interoperate with an up-level server that has "RD Virtualization Host" capabilities.


bmclellan

Thanks Chuck,

I'm logged in as a domain user (no special permissions I'm aware of) and am checking the IP of a server that is on a completely different domain. The user ID I am logged in as is not a member of the domain/server I am checking if that helps. I'm on a customer's network so I'm pretty sure my login is limited accept that I have RDP access into other servers and can install software on my own desktop.

If you do decide to make that change, I am more than happy to test it out, matter of fact I just renewed my winbatch support today!

Error in wwwbatch.ini

[WWWNT64I]
LastError=6118 (NetServerEnum() : extender wntServerList())
[Windows Terminal Server Extender]
LastError=6AB "WTSEnumerateSessionsAX() : WWWTS_EnumerateSessions()"



Thanks
Barry


ChuckC

Quote"'I'm logged in as a domain user (no special permissions I'm aware of) and am checking the IP of a server that is on a completely different domain. The user ID I am logged in as is not a member of the domain/server I am checking if that helps. I'm on a customer's network so I'm pretty sure my login is limited accept that I have RDP access into other servers and can install software on my own desktop."


Having RDP access to a remote server does not mean that you have remote admin access to interrogate the server and query it for information about the RDP sessions that exist on it.  All that grants you is the ability to make a connection from a RDP client to establish a session on that remote server.

If there isn't an appropriate trust relationship between the two domains involved, either by being in the same AD forest, or an explicit inter-domain trust that permits authentication, then there should be zero chance of successfully enumerating RDP sessions on the remote server in the other domain.  The only exception to this would be to establish a connection to the IPC$ share on the remote server using credentials that are valid on the remote server.

Just for giggles & grins, try something like the following:

NET USE \\<remote-server-dns-name-or-ip-address>\IPC$ /user:<remote-user-account-name> <password>

If that is successful, follow it with running the TSExplorer script.  Make sure that both are done at the same UAC elevation level so you don't get tripped up by the split-token network drive name space issue in a situation where the registry setting that unifies the name space is missing.

If that results in being able to enumerate sessions, then it was an authentication/authorization type of issue.

If you get the same failure as before, then it's likely to be an issue related to WTSOpenServer() vs. WTSOpenServerEx().

It would be up to Tony to make any changes in the extender w/respect to making selective use of WTSOpenServerEx() when it is available.  I happen to know the internals of the extender since I originally wrote it and donated it to Wilson WindowWare, but on going development work on the extender is purely in Island Lake's court.



bmclellan

Hi Chuck,

The net use command works. I ran the TSExplorer script and it didn't work, I changed the domain name and still no luck.

And you are correct, I thought I was accessing a few servers in a different domain but turns out my IP list wasn't as accurate as I thought. Either way though, with qwinsta I can at least get that to work with the servers in the domain I've logged into.


Thanks!
Barry

td

FWIW, the system error listed in the wwwbatch.ini file is  "The network address is invalid."   It appears to be generated by the call to the "WTSEnumerateSessions" function.  Since "WTSOpenServer" is returning a session handle without erroring, not sure that the error favors one explanation over the other.

Using network credentials can be tricky in the UAC/spit token environment. There have been cases where users have found that a standard user has more rights than an elevated admin because of token stripping done on the server-side. As mentioned one way to prevent this type of problem is to make sure that the failing example is working with exactly the same account and elevation as the working example.

As for the extender modifications, they certainly need to be done whether or not this is the cause of the current issue. WinBatch and its many extenders are already full of alternate API calls based on OS version and API availability so a couple more is not a problem.  Both "WTSOpenServer" and "WTSEnumerateSessions" have "EX" versions but the entire API should be checked against documentation. The time-consuming part will be testing to make sure nothing was broken in the process. It may involve racking up some minutes on an Azure account.

"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

td

Quote from: bmclellan on July 29, 2020, 01:30:26 PM
Hi Chuck,

The net use command works. I ran the TSExplorer script and it didn't work, I changed the domain name and still no luck.

And you are correct, I thought I was accessing a few servers in a different domain but turns out my IP list wasn't as accurate as I thought. Either way though, with qwinsta I can at least get that to work with the servers in the domain I've logged into.


Thanks!
Barry

The 580 error simply means "No browser servers found" which is not all that surprising given your network environment. Since the erroring function is not a part of the TS extender but the NT extended, it is not related to the above discussion concerning APIs.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

td

This is slightly off-topic but the Win32 Network extender's wntRunAsUser function can be used to set credentials for enumerating sessions on a remote terminal server. To do this set the logon type to 6 - "credentials are used only for network connections.  Primarily need for enumeration sessions on remote term servers."  This is similar to using the "net use" command with the "IPC$" share but is done in-script without launching another process.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

bmclellan

Thanks Tony, I'll try that out!

Barry