Articles   Members Online:
-Article/Tip Search
-News Group Search over 21 Million news group articles.
-Delphi/Pascal
-CBuilder/C++
-C#Builder/C#
-JBuilder/Java
-Kylix
Member Area
-Home
-Account Center
-Top 10 NEW!!
-Submit Article/Tip
-Forums Upgraded!!
-My Articles
-Edit Information
-Login/Logout
-Become a Member
-Why sign up!
-Newsletter
-Chat Online!
-Indexes NEW!!
Employment
-Build your resume
-Find a job
-Post a job
-Resume Search
Contacts
-Contacts
-Feedbacks
-Link to us
-Privacy/Disclaimer
Embarcadero
Visit Embarcadero
Embarcadero Community
JEDI
Links
How to write Delphi apps in a Terminal Server environment. Turn on/off line numbers in source code. Switch to Orginial background IDE or DSP color Comment or reply to this aritlce/tip for discussion. Bookmark this article to my favorite article(s). Print this article
Write Delphi apps in a Terminal Server environment. 03-Oct-04
Category
Win API
Language
Delphi All Versions
Views
796
User Rating
No Votes
# Votes
0
Replies
0
Publisher:
Zanello, Alex
Reference URL:
			How to write Delphi apps in a Terminal Server environment, a primer.
(Infos derived from carefully harvesting the net)

The Terminal Server environment (TS) it's quite common nowadays; it's often used to 
WAN-enable older apps, something like retro-fitting an app. 
It's also useful when no decent speed lines are available.

TS is an extension of the Windows NT 4.0 product line and is a multi user kernel in 
which the 100% processing is done on the central server and only the desktop is 
transferred to the terminal client (also called "Super thin client" by Microsoft).

It's not a technology invented by Microsoft (;-), but they did integrate it in the 
OS.

There are three part of a terminal server system: 
1. A multi user kernel, running on a strong (in terms of resources) central server
2. A protocol for the transfer of mouse and key board event from terminal client to 
the server and desktop from terminal server to the client.
3. A super thin client 

Windows TS provides users access to 16-32 bit Windows based application from any of 
the following types of desktops:
1. Low cost hardware (Windows based terminals)
2. Any existing Windows desktop operating system such as Windows 95 or Microsoft 
Windows NT Workstation (running the 32 bit Terminal server client as a window 
within the local desktop environment).
3. Old 16 bit Windows-based desktops running the Windows 3.11 operating system 
(running the 16 bit Terminal Server client as a window within the local desktop 
environment).
4. X-based terminals, Apple Macintosh, MS-DOS, Networked computers, and UNIX based 
desktops (albeit via third party add-on products).

A thin client is a network-dependent terminal capable of displaying remote 
applications that run entirely on attached server. A thin client can be a PC, NC 
(Network Computer), or terminal.

The key point to thin client computing is that applications run on the server- not 
on the client.
An NC or PC that runs all or part of the application is not a thin client.

When writing for the Terminal Server environment (TS), we must pay more than usual 
attention to some details. 

If you develop a Windows application, it can be run on Terminal Server as long as 
it takes care of data/files/registry informations by design, so that multiple user 
settings or data don't clash with each other.

I.e., if you have an application that on starting creates a file on c:\, then this 
creates a problem in Terminal Server, when multiple users run the application.
You can solve this by placing the common/log files into "c:\Documents and 
Settings\\"

Likewise, if your application is using an .ini file to store user information, 
consider instead using the HKEY_CURRENT_USER registry section, because all the 
users will be using the same directory and will overwrite the same .ini file in the 
same directory. 

When using registry entries you have to do that in HKEY_CURRENT_USER, not in 
HKEY_LOCAL_MACHINE; make sure your application doesn't write to the 
HKEY_LOCAL_MACHINE registry section, since it's often only the Administrator who 
can write to it. 

Remember also that mutexes are system-wide, so if you use one (e.g. for detecting 
if multiple copies of your applications are simultaneously run) it will make 
impossible to run more copies of your app at the same time.

There's more information on Microsoft's website at (warning: beware of word-wrap):
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/termserv/termserv/t
erminal_services_start_page.asp 

I also found the following MS infos useful:

----------------------------------------------------------------
GetCurrentProcessId

The GetCurrentProcessId function retrieves the process identifier of the calling 
process.

DWORD GetCurrentProcessId(void);

Parameters
This function has no parameters.
Return Values
The return value is the process identifier of the calling process.

Remarks
Until the process terminates, the process identifier uniquely identifies 
the process throughout the system.

Requirements
Client: Included in Windows XP, Windows 2000 Professional, Windows NT 
          Workstation, Windows  Me, Windows 98, and Windows 95.
Server: Included in Windows Server 2003, Windows 2000 Server, and Windows NT Server.
Header: Declared in Winbase.h; include Windows.h.
Library: Use Kernel32.lib.

ProcessIdToSessionId

The ProcessIdToSessionId function retrieves the Terminal Services session 
associated with a specified process.

1   BOOL ProcessIdToSessionId(
2      DWORD dwProcessId,
3      DWORD* pSessionId
4   );


Parameters
dwProcessId
[in] Specifies a process identifier. Use the GetCurrentProcessId function 
to retrieve the process identifier for the current process.
pSessionId
[out] Pointer to a variable that receives the identifier of the Terminal 
Services session under which the specified process is running. A value of 
zero identifies the terminal server console session.
Return Values
If the function succeeds, the return value is a nonzero value.

If the function fails, the return value is zero. To get extended error 
information, call GetLastError.

Remarks
If the calling process is not running in a Terminal Services environment, 
the value returned in pSessionId is zero.

Requirements
Client: Included in Windows XP and Windows 2000 Professional.
Server: Included in Windows Server 2003 and Windows 2000 Server.
Redistributable: Requires Terminal Server 4.0 SP4 on Windows NT 4.0 SP4.
Header: Declared in Winbase.h; include Windows.h.
Library: Use Kernel32.lib.

--------------------------------------------------------

The following funcs (also found somewhere on the Net, credit where due), are also 
useful to be able to detect if an application is running alone or in a Terminal 
Server environment:
5   
6   --------------------------------------------------------
7   unit WTSapi;
8   
9   interface
10  { Public Domain, by Thomas Stutz 10 April 02 }
11  
12  uses
13     Windows;
14  
15  const
16     // The WM_WTSSESSION_CHANGE message notifies applications of changes in 
17     // session state.
18     WM_WTSSESSION_CHANGE = $2B1;
19  
20     // wParam values:
21     WTS_CONSOLE_CONNECT = 1;
22     WTS_CONSOLE_DISCONNECT = 2;
23     WTS_REMOTE_CONNECT = 3;
24     WTS_REMOTE_DISCONNECT = 4;
25     WTS_SESSION_LOGON = 5;
26     WTS_SESSION_LOGOFF = 6;
27     WTS_SESSION_LOCK = 7;
28     WTS_SESSION_UNLOCK = 8;
29     WTS_SESSION_REMOTE_CONTROL = 9;
30  
31     // Only session notifications involving the session attached to by the window
32     // identified by the hWnd parameter value are to be received.
33     NOTIFY_FOR_THIS_SESSION = 0;
34     // All session notifications are to be received.
35     NOTIFY_FOR_ALL_SESSIONS = 1;
36  
37  function RegisterSessionNotification(Wnd: HWND; dwFlags: DWORD): Boolean;
38  function UnRegisterSessionNotification(Wnd: HWND): Boolean;
39  function GetCurrentSessionID: Integer;
40  
41  implementation
42  
43  function RegisterSessionNotification(Wnd: HWND; dwFlags: DWORD): Boolean;
44  // The RegisterSessionNotification function registers the specified window
45  // to receive session change notifications.
46  // Parameters:
47  // hWnd: Handle of the window to receive session change notifications.
48  // dwFlags: Specifies which session notifications are to be received:
49  // (NOTIFY_FOR_THIS_SESSION, NOTIFY_FOR_ALL_SESSIONS)
50  type
51     TWTSRegisterSessionNotification = function(Wnd: HWND; dwFlags: DWORD): BOOL; 
52  stdcall;
53  var
54     hWTSapi32dll: THandle;
55     WTSRegisterSessionNotification: TWTSRegisterSessionNotification;
56  begin
57     Result := False;
58     hWTSAPI32DLL := LoadLibrary('Wtsapi32.dll');
59     if (hWTSAPI32DLL > 0) then
60     begin
61       try
62         @WTSRegisterSessionNotification := 
63                 GetProcAddress(hWTSAPI32DLL, 'WTSRegisterSessionNotification');
64         if Assigned(WTSRegisterSessionNotification) then
65           Result:= WTSRegisterSessionNotification(Wnd, dwFlags);
66       finally
67         if hWTSAPI32DLL > 0 then
68           FreeLibrary(hWTSAPI32DLL);
69       end;
70     end;
71  end;
72  
73  function UnRegisterSessionNotification(Wnd: HWND): Boolean;
74  // The RegisterSessionNotification function unregisters the specified window
75  // Parameters:
76  // hWnd: Handle to the window
77  type
78     TWTSUnRegisterSessionNotification = function(Wnd: HWND): BOOL; stdcall;
79  var
80     hWTSapi32dll: THandle;
81     WTSUnRegisterSessionNotification: TWTSUnRegisterSessionNotification;
82  begin
83     Result := False;
84     hWTSAPI32DLL := LoadLibrary('Wtsapi32.dll');
85     if (hWTSAPI32DLL > 0) then
86     begin
87       try
88         @WTSUnRegisterSessionNotification := 
89                 GetProcAddress(hWTSAPI32DLL, 'WTSUnRegisterSessionNotification');
90         if Assigned(WTSUnRegisterSessionNotification) then
91           Result := WTSUnRegisterSessionNotification(Wnd);
92       finally
93         if hWTSAPI32DLL > 0 then
94           FreeLibrary(hWTSAPI32DLL);
95       end;
96     end;
97  end;
98  
99  function GetCurrentSessionID: Integer;
100 // Getting the session id from the current process 
101 type
102    TProcessIdToSessionId = function(dwProcessId: DWORD; pSessionId: DWORD): BOOL; 
103 stdcall;
104 var
105    ProcessIdToSessionId: TProcessIdToSessionId;
106    hWTSapi32dll: THandle;
107    Lib : THandle;
108    pSessionId : DWord;
109 begin
110    Result := 0;
111    Lib := GetModuleHandle('kernel32');
112    if Lib <> 0 then
113    begin
114      ProcessIdToSessionId := GetProcAddress(Lib, 'ProcessIdToSessionId');
115      if Assigned(ProcessIdToSessionId) then
116      begin
117        ProcessIdToSessionId(GetCurrentProcessId(), DWORD(@pSessionId));
118        Result:= pSessionId;
119      end;
120    end;
121 end;
122 
123 end.

--------------------------------------------------------

So if you simply want to check if running on TS you can write:

124   // check if under Terminal Server
125   if (GetCurrentSessionID > 0) then
126     ShowMessage('TS detected !');



Hope all this can be useful to someone.

Comments, corrections and amplifications welcome as always at 
alexza@mail.nauta.it.

			
Vote: How useful do you find this Article/Tip?
Bad Excellent
1 2 3 4 5 6 7 8 9 10

 

Advertisement
Share this page
Advertisement
Download from Google

Copyright © Mendozi Enterprises LLC