![]() |
Datenaustausch (Message o.Ä.) von Terminalserver an Client
Hallo zusammen,
ich habe ein ![]() Im Prinzip liest das Programm derzeit bein Drücken eines Hotkeys den selektierten Text aus der aktiven Anwendung aus, prüft ob darin eine sinnvolle Telefonnummer steht und wählt diese über TAPI. Alles schön und gut, aber ein Kunde möchte das Tool jetzt auch mit einer Terminalserver-Applikation verwenden. Wenn die Terminalserver-App aktiv ist und ich den Hotkey drücke, dann wird dieser nicht an mein lokales System gesendet sondern an den Terminalserver. Nun frage ich mich ob es möglich ist, ein kleines "Helper-Programm" auf dem Terminalserver laufen zu lassen, das beim Drücken des Hotkeys (in der Terminalsitzung) eine Message o.Ä. an die CTI-Applikation dem Client-PC sendet, damit diese dann die Rufnummer über die TAPI Schnittstelle des Clients wählt ... Ich habe absolut keine Idee wie man das sinnvoll lösen könnte. Notfalls mache ich das über eine TCP-Message die das Helper-Programm auf dem Terminaserver an den Client-PC sendet. Wirklich gut gefällt mir die Idee jedoch nicht, weil der administrative Aufwand extrem hoch ist (Port-Forwarding auf jedem Client-Router konfigurieren, Firewalls konfigurieren ...) und weil durch den zusätzlich geöffneten Port auch noch die Sicherheit leidet. Wie kann man das Problem professionell lösen ? Ich bin für jeden Hinweis dankbar. Schöne Grüße, Jens :hi: |
Re: Datenaustausch (Message o.Ä.) von Terminalserver an Clie
Läßt sich das in deinem Fall vielleicht mit Virtual Channels erleichtern?
Guck dir mal die WTSVirtualChannel*-Funktionen an - z.B ![]() |
Re: Datenaustausch (Message o.Ä.) von Terminalserver an Clie
der offizielle Weg sind die VirtualChannels. Darüber wird auch das SharedClipboard des Terminalservers realisiert.
1. der einfache, jedoch unelegante Weg ist, die Zwischenablage zu verwenden. Ok da ist dein Vorschlag mit dem extra TCP-Server doch besser. 2. ich sag mal wie es bei uns läuft. Wir haben auf dem Client nen Barcodescanner laufen, der seine Daten auf den Server übertragen soll. Also hab ich mit RdpClient-ActiveX ein Clienttool geschrieben, welches per CreateVirtualChannels einen Kanal zum Server aufbaut. Auf dem Server läuft ein Thread, der per WTSVirtualChannelRead liest, ob auf den Channel was geschrieben wurde und die Daten nötigenfalls übernimmt. Bei Dir wär das zwar die andere Richtung aber im wesentlichen ja dasselbe. |
Re: Datenaustausch (Message o.Ä.) von Terminalserver an Clie
Hallo Jens,
wenn du vor dem Probieren ein wenig Studieren möchtest - hier der passende Grundlagenartikel aus dem MSJ: ![]() Grüße vom marabu |
Re: Datenaustausch (Message o.Ä.) von Terminalserver an Clie
Ich lese mich da rein und werde mal ein paar Versuche starten.
Vermutlich werden dann noch ein paar Fragen kommen .... Ich danke Euch erstmal für die Infos. Schöne Grüße, Jens :hi: |
Re: Datenaustausch (Message o.Ä.) von Terminalserver an Clie
So, jetzt gehts los ... ich und API und obendrauf noch C Syntax. Da habe ich mir was vorgenommen :oops:
Zum Verständnis für Diejenigen, die auch einmal Daten zwischen Terminalserver und Terminalclient über Virtual Channels austauschen müssen, hier einmal knapp die grobe Funktion. Die um VirtuelChannels nutzen zu können, wird auf den Terminalclient eine DLL als Addin an den Terminalclient gebunden. Diese DLL wird dem Terminalclient über einen RegistryKey bekanntgegeben und geladen, sobald eine Terminalsitzung aufgebaut wird. Der Client initialisiert den/die Virtual Channel. Auf den Terminalserver läuft eine kleine Applikation in der Clientsitzung, die den Virtual Channel öffnet. Sobald ein Kanal steht können beide Seiten (Server-Applikation und Client-Addin) mit WTSVirtualChannelRead / WTSVirtualChannelWrite über diesen Kanal Daten austauschen. Insgesamt können bis max. 28 VChannels geöffnet werden. Jetzt zu meinem ersten Problem: Um das Terminalserverhandle herauszufinden (benötigt um mit WTSEnumerateSessions die aktuellen SitzungsID zu ermitteln) werden die beiden DLL-Funktionen WTSOpenServer und WTSCloseServer aus der wtsapi32.dll benötigt. Die DLL habe ich dynamisch geladen und die DLL Funktionen in der Server-Applikation wie folgt zugewiesen:
Delphi-Quellcode:
WTSCloseServer wird erfolgreich zugewiesen, WTSOpenServer jedoch nicht.
type
TWTSAPI32_WTSOpenServer=function (pServerName:Pointer):THandle; stdcall; TWTSAPI32_WTSCloseServer=procedure (hServer:Pointer); stdcall; ... private WTSAPI32_WTSOpenServer:TWTSAPI32_WTSOpenServer; WTSAPI32_WTSCloseServer:TWTSAPI32_WTSCloseServer; var implementation ... @WTSAPI32_WTSOpenServer := GetProcaddress(HDL_WTSAPI32_DLL,pchar('WTSOpenServer')); if @WTSAPI32_WTSOpenServer = NIL then begin log.lines.add('WTSAPI32.DLL - Funktion WTSOpenServer wurde nicht gefunden oder ist falsch deklariert'); end else begin log.lines.add('WTSAPI32.DLL - Funktion WTSOpenServer erfolgreich initialisiert'); end; @WTSAPI32_WTSCloseServer := GetProcaddress(HDL_WTSAPI32_DLL,pchar('WTSCloseServer')); if @WTSAPI32_WTSCloseServer = NIL then begin log.lines.add('WTSAPI32.DLL - Prozedur WTSCloseServer wurde nicht gefunden oder ist falsch deklariert'); end else begin log.lines.add('WTSAPI32.DLL - Prozedur WTSCloseServer erfolgreich initialisiert'); end; ... Laut ![]()
Delphi-Quellcode:
Was ist hieran falsch ? :gruebel:
HANDLE WTSOpenServer(
LPTSTR pServerName );
Delphi-Quellcode:
Schöne Grüße,
TWTSAPI32_WTSOpenServer=function (pServerName:Pointer):THandle; stdcall;
Jens :hi: |
Re: Datenaustausch (Message o.Ä.) von Terminalserver an Clie
Moin moin,
Zitat:
Delphi-Quellcode:
type
... @WTSAPI32_WTSOpenServer := GetProcaddress(HDL_WTSAPI32_DLL,pchar('WTSOpenServerA')); ... Zitat:
|
Re: Datenaustausch (Message o.Ä.) von Terminalserver an Clie
Genial, das wars ...
Danke |
Re: Datenaustausch (Message o.Ä.) von Terminalserver an Clie
Hallo,
Hier ist mein nächstes Problem, an dem ich nun schon fast den ganzen Tag experimentiere. ![]() ![]()
Delphi-Quellcode:
Nachdem ich
typedef struct _WTS_SESSION_INFO
{ DWORD SessionId; LPTSTR pWinStationName; WTS_CONNECTSTATE_CLASS State; } WTS_SESSION_INFO, PWTS_SESSION_INFO; typedef enum _WTS_CONNECTSTATE_CLASS { WTSActive, WTSConnected, WTSConnectQuery, WTSShadow, WTSDisconnected, WTSIdle, WTSListen, WTSReset, WTSDown, WTSInit } WTS_CONNECTSTATE_CLASS; BOOL WTSEnumerateSessions( HANDLE hServer, DWORD Reserved, DWORD Version, PWTS_SESSION_INFO* ppSessionInfo, DWORD* pCount ); ![]()
Delphi-Quellcode:
Leider ist das Ergebnis von WTSAPI32_WTSEnumerateSessions immer false :roll:
type
WTS_CONNECTSTATE_CLASS = LongInt; const WTSActive = WTS_CONNECTSTATE_CLASS(1); WTSConnected = WTS_CONNECTSTATE_CLASS(2); WTSConnectQuery = WTS_CONNECTSTATE_CLASS(3); WTSShadow = WTS_CONNECTSTATE_CLASS(4); WTSDisconnected = WTS_CONNECTSTATE_CLASS(5); WTSIdle = WTS_CONNECTSTATE_CLASS(6); WTSListen = WTS_CONNECTSTATE_CLASS(7); WTSReset = WTS_CONNECTSTATE_CLASS(8); WTSDown = WTS_CONNECTSTATE_CLASS(9); WTSInit = WTS_CONNECTSTATE_CLASS(10); type _WTS_SESSION_INFO = record SessionId: DWORD; pWinStationName: LPTSTR; State: WTS_CONNECTSTATE_CLASS; end; WTS_SESSION_INFO = _WTS_SESSION_INFO; PWTS_SESSION_INFO = ^_WTS_SESSION_INFO; type TWTSAPI32_WTSEnumerateSessions = function(hServer: THandle; Reserved: DWORD; Version: DWORD; ppSessionInfo: pWTS_SESSION_INFO; pCount: pDWORD): BOOL; stdcall; TWTSAPI32_WTSFreeMemory = procedure(pMemory: Pointer); // zum Freigben des Speichers von pPWTS_SESSION_INFO Type TMain = Class(TForm) ... ... private // Rückgabewerte von WTSEnumerateSessions ARR_WTS_SESSION_INFO : ARRAY OF WTS_SESSION_INFO; pPWTS_SESSION_INFO : Pointer = @ARR_WTS_SESSION_INFO; WTS_SESSION_COUNT : Integer; pCount : Pointer = @WTS_SESSION_COUNT; WTSAPI32_WTSEnumerateSessions: TWTSAPI32_WTSEnumerateSessions; WTSAPI32_WTSFreeMemory: TWTSAPI32_WTSFreeMemory; ... ... implementation ... if NOT WTSAPI32_WTSEnumerateSessions(WTS_Server_Handle, 0, 1, pPWTS_SESSION_INFO, pCount) then begin log.Lines.Add('TerminalserverSessions konnten nicht ausgelesen werden'); FreeLibrary(HDL_WTSAPI32_DLL); HDL_WTSAPI32_DLL := 0; WTSAPI32_WTSFreeMemory(pPWTS_SESSION_INFO); exit; end else begin log.Lines.Add(' TerminalserverSessions wurden ermittelt'); WTSAPI32_WTSFreeMemory(pPWTS_SESSION_INFO); end; ... Der Aufruf von WTSAPI32_WTSFreeMemory(pPWTS_SESSION_INFO) bringt eine AV, wahrscheinlich weil der Pointer ins Nirvana zeigt ... :oops: [EDIT] Ich habe eben noch ein GetLastError eingebaut ... Unter Win2000 Server (aus einer Terminalsession) bekomme ich als Fehler "Klasse nicht vorhanden" und unter WinXP Pro "Zugriff verweigert". Das "Zugriff verweigert" kommt sicher daher, das ich unter WinXP keine Möglichkeit finde, das TS Recht "Query Information" zu setzen ... [/EDIT] Ich brauche Hilfe bei der Übersetzung der C Header und Typen ... Wäre wirklich nett, wenn ihr mir dabei helfen würdet. Danke und schöne Grüße, Jens :hi: |
Re: Datenaustausch (Message o.Ä.) von Terminalserver an Clie
Moin moin,
Delphi-Quellcode:
so würde ich es machen, aber keine Garantie dafür. Vielleicht fehlt bei dir ja auch nur das stdcall bei
//..
type TWtsConnectStateClass = (WTSActive, WTSConnected, WTSConnectQuery, WTSShadow, WTSDisconnected, WTSIdle, WTSListen, WTSReset, WTSDown, WTSInit); type PWtsSessionInfo = ^TWtsSessionInfo; _WTS_SESSION_INFOA = packed record SessionId : DWORD; pWinStationName : LPTSTR; State : TWtsConnectStateClass; end; TWtsSessionInfo = _WTS_SESSION_INFOA; const WTS_CURRENT_SERVER_HANDLE = 0; type TFNWtsEnumerateSessions = function (hServer: THandle; Reserved: DWORD; Version: DWORD; out ppSessionInfo: PWtsSessionInfo; out pCount: PDWORD): BOOL; stdcall; TFNWtsFreeMemory = procedure(pMemory: Pointer); stdcall; //.. function ConStateToStr(const conState: TWTSConnectStateClass): String; begin case conState of WTSActive : Result := 'WTSActive'; WTSConnected : Result := 'WTSConnected'; WTSConnectQuery : Result := 'WTSConnectQuery'; WTSShadow : Result := 'WTSShadow'; WTSDisconnected : Result := 'WTSDisconnected'; WTSIdle : Result := 'WTSIdle'; WTSListen : Result := 'WTSListen'; WTSReset : Result := 'WTSReset'; WTSDown : Result := 'WTSDown'; WTSInit : Result := 'WTSInit'; else Result := 'Unknown'; end; end; //.. var count : PDWord; SessionInfo : PWtsSessionInfo; begin try Win32Check(WtsEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, SessionInfo, count)); ShowMessage('State=' + ConStateToStr(SessionInfo.State) + #13#10 + 'SessionID=' + IntToStr(SessionInfo.SessionId) + #13#10 + 'pWinStationName=' + SessionInfo.pWinStationName); WtsFreeMemory(SessionInfo); except On E: Exception do //.. end; end; der Typedeklaration von TWTSAPI32_WTSFreeMemory. Sprech evtl. mal ![]() der hat da eher nen Plan davon und hilft immer gerne... (Bestimmt auch noch andere, bei Olli kann ich aber aus Erfahrung sprechen) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:46 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz