views:

225

answers:

3

I want to find out which ip can be remote. (remote desktop)

For example, I set a valid IP of my network into an edit box and the program says it can be remote or not.

A: 

Search a Remote Desktop component for Delphi and try to connect.

Marco van de Voort
thanks, but i want to do it by API or the component are installed on Delphi.
behzad
+4  A: 

to determine if an ip address is a remote desktop server you can use WTSEnumerateServers function.

follow these steps

  • enumerate the servers in a network domain using the WTSEnumerateServers function
  • when you get the list of the servers convert the name of each server to an ip address
  • now compare the ip address of each server with the ip to check.

see this sample, wich show how use the WTSEnumerateServers function

uses
  Classes,
  Windows,
  SysUtils;

type
PWTS_SERVER_INFO = ^WTS_SERVER_INFO;
_WTS_SERVER_INFO = packed record
pServerName:LPTSTR;
end;
WTS_SERVER_INFO = _WTS_SERVER_INFO;
WTS_SERVER_INFO_Array  = Array [0..0] of WTS_SERVER_INFO;
PWTS_SERVER_INFO_Array =^WTS_SERVER_INFO_Array;

{$IFDEF UNICODE}
function WTSEnumerateServers( pDomainName: LPTSTR; Reserved: DWORD; Version: DWORD; ppServerInfo: PWTS_SERVER_INFO; pCount: PDWORD):BOOLEAN; stdcall; external 'wtsapi32.dll'  name 'WTSEnumerateServersW';
{$ELSE}
function WTSEnumerateServers( pDomainName: LPTSTR; Reserved: DWORD; Version: DWORD; ppServerInfo: PWTS_SERVER_INFO; pCount: PDWORD):BOOLEAN; stdcall; external 'wtsapi32.dll'  name 'WTSEnumerateServersA';
{$ENDIF}
procedure WTSFreeMemory(pMemory:Pointer);stdcall; external 'wtsapi32.dll' name 'WTSFreeMemory';

procedure GetRemoteDesktopsList(const Domain:PChar;const Servers:TStrings);
var
ppServerInfo : PWTS_SERVER_INFO_Array;//PWTS_SERVER_INFO;
pCount       : DWORD;
i            : integer;
begin
  Servers.Clear;
  ppServerInfo:=nil;
  try
    if WTSEnumerateServers(Domain,0,1,PWTS_SERVER_INFO(@ppServerInfo),@pCount) then
      for i := 0 to pCount - 1 do
        Servers.Add(ppServerInfo^[i].pServerName)
    else
    Raise Exception.Create(SysErrorMessage(GetLastError));
  finally
    if ppServerInfo<>nil then
    WTSFreeMemory(ppServerInfo);
  end;
end;

and then call like this

   Servers:=TStringList.Create;
    try
     GetRemoteDesktops(nil,Servers); //using nil for the current domain.
     //now  process the list and do your stuff

    finally
     Servers.Free;
    end;
RRUZ
thank you, i think it will be useful, but i'm at home and i don't have a real network now. how can i set my IP(127.0.0.1) in to this function and get information about it?
behzad
That sounds like it is very slow. It enumerates all servers and then checks whether the server he is looking for is in the list. Wouldn't trying to connect to it and handling success and failure be much more efficient?
dummzeuch
RRUZ, i ran your code but it didn't work. it has a message : The format of the specified domain name is invalid. here is the calling code : GetRemoteDesktopsList(pchar('192.168.10.1'),ListBox1.Items);
behzad
you must use a domain name not a ip address, please check the documentation about the `WTSEnumerateServers` function http://msdn.microsoft.com/en-us/library/aa383832%28VS.85%29.aspx
RRUZ
PRUZ, I used nill for domain and it showed same message. did you check this code?
behzad
behzad, the code was tested and works ok, check your network comfiguration (domain, tcp/ip settings).
RRUZ
i gave it to my friend and he tested it on his local network and it showed the same message !
behzad
behzad this function only work the if NetBIOS Over TCP/IP (NetBT) is enabled. do you have enabled NetBT in the computer where you run the tests?
RRUZ
Yes! it's enable but doesn't work. how about internet? if i want check an IP on the Internet, what should i do?
behzad
A: 

It depends on what you are trying to accomplish: do you want to see if the server is up and running from within your network? If so try my Terminal Server Ping Tool. Else you can only check if something is listening on port 3389 eg with Indy.

Remko
yes, i think it can be with indy, but i don't know how do it?! if you know, help me pleas.
behzad
remko the `WinStationServerPing` function looks promising, you can provide a sample source code showing how use it? because it's a undocumented Windows api.
RRUZ
Remko about check the 3389 port, is not a very reliable solution because the Terminal server service can be running on another port.
RRUZ
WinStationServerPing is declared in JwaWinsta unit, it's signature is: function WinStationServerPing(hServer: HANDLE): BOOLEAN; stdcall;Just open a handle to the server with WtsOpenServer or WinStationOpenServer and pass the handle (and close the handle afterwards)
Remko
@Port 3389: yes I know but in order to detect different port you would need access to (remote) registry.
Remko
Remko, thanks for the info.
RRUZ