Club Delphi  
    Paypal   FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Coloboración Paypal con ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 10-04-2017
Avatar de hgiacobone
hgiacobone hgiacobone is offline
Miembro
 
Registrado: may 2003
Ubicación: La Plata, Bs. As., Argentina
Posts: 165
Poder: 24
hgiacobone Va por buen camino
Red face

Amigo GluGlu, finalmente has encontrado alguna solución a esto?... Estoy por pasar por este mismo inconveniente.

Tengo una aplicación "MyApp.exe" donde cada usuario levanta una instancia de ella, con conexiones de Escritorio Remoto. Incluso, en la sesion del Administrador en el propio servidor (WinServer2008) ciertas veces existe tambien otra instancia en ejecución de dicho programa.

Además de esto, un segundo ejecutable "Monitor.exe", está siempre en funcionamiento en la sesion del Administrador y realiza un proceso donde las distintas etapas del mismo deben ser notificadas a la/las instancias del programa "MyApp.exe"

Actualmente lo tenía resuelto mediante el uso de Messages de Windows, esto es:
Desde el programa "Monitor.exe" cada vez que se necesita notificar algo, se invoca la función SendAppMessage() que hace esto:
Código Delphi [-]
type
    TMonitor1: class(TForm)
    ...
    private
    function SendAppMessage(mensaje:string):Boolean;
    ...
end;
///--------------------------------------
function TMonitor.SendAppMessage(mensaje:string):Boolean;
var
 CopyDataStruct : TCopyDataStruct;
 hReceptor: THandle;
 Respuesta: integer;
begin
  Result:= False;
  CopyDataStruct.dwData := 0; //utilizado para identificar el contenido del mensaje
  CopyDataStruct.cbData := Length( mensaje )+1;
  CopyDataStruct.lpData := PChar( mensaje );
  // Comprobamos si existe el receptor
  hReceptor := FindWindow( PChar('CORE') , nil );
  if hReceptor = 0 then
  begin
   {ShowMessage( 'No se ha encontrado al receptor.' );}
   Exit;
  end;
  // Enviamos el mensaje
  Respuesta := SendMessage( hReceptor, WM_COPYDATA, Integer( Handle ),
   Integer( @CopyDataStruct ) ) ;
// si nos interesa recogemos la respuesta del receptor
  {if Respuesta = 1 then ShowMessage( 'El mensaje ha sido recibido satisfactoriamente.' );}
  Result := (Respuesta = 1);
end;

//Ejemplo:
    if (sTime='18:00') then SendAppMessage('Happy Hour... vamos por una cerveza fría !');

Por otro lado, el programa "MyApp.exe", siempre está "a la escucha" de esos mensajes mediante un evento que se dispara de forma automática cuando aparece un mensaje invocando al proceso RecibirAppAmessage() que es este:
Código Delphi [-]
type
    TForm1: class(TForm)
    ...
    procedure RecibirAppMessage( var Msg: TWMCopyData ); message WM_COPYDATA;
    ...
end;
///------------------------
procedure TForm1.RecibirAppMessage( var Msg: TWMCopyData );
var
  s1:string;
begin
  s1:= PChar( Msg.CopyDataStruct.lpData );
  if bShowMessage 
    then ShowMessage( s1 )
    else StatusBar1.Panels[3].Text := s1;
  Msg.Result := 1; //como respuesta que se ha recibido el mensaje
end;



Lo malo de esto es que, una vez que "MyApp.exe" "publica" el mensaje, lo toma la primera sesion abierta de "MyApp.exe" que logra mostrar el mensaje en su pantalla, pero el resto de las instancias no reciben nada. O sea, lo consume la primera instancia abierta y "se borra" para el resto.

Debido a esto, estaba pensando en realizar mensajes UDP, pero me encuentro con el problema planteado aqui de las instancias de Escritorio Remoto y el problema de la apertura del PORT.

Como has resuelto esto?
__________________
Gracias de antemano por vuestra ayuda.
·.:*:.·Yako·.:*:.·
Responder Con Cita
  #2  
Antiguo 10-04-2017
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.210
Poder: 22
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
El problema lo tienes porque usas FindWindow para localizar el Handle de la ventana donde enviarás el mensaje. Debes enumerarlas todas y enviar el mensaje a las que correspondan con tu App, normalmente las conocerás por el nombre de la clase de ventana. Revisa EnumWindows y GetClassName.


Saludos.
Responder Con Cita
  #3  
Antiguo 10-04-2017
Avatar de hgiacobone
hgiacobone hgiacobone is offline
Miembro
 
Registrado: may 2003
Ubicación: La Plata, Bs. As., Argentina
Posts: 165
Poder: 24
hgiacobone Va por buen camino
Cita:
Empezado por escafandra Ver Mensaje
El problema lo tienes porque usas FindWindow para localizar el Handle de la ventana...
Gracias por responder escafandra, pero sucede que el Handle es unico, me refiero que es un unico EXE.
Todas las instancias de RDP levantan el mismo "MyApp.exe". En el ejemplo quedó el verdadero nombre, pero digamos que lo que se intenta con esa linea es enviar el mensaje a ese EXE y no a otro.
Sería algomo como esto:
Código Delphi [-]
hReceptor := FindWindow( PChar('MyApp') , nil );
Tal vez esto no sea la mejor solución con RDP y es por eso mi consulta, para saber si hay algo mejor.
__________________
Gracias de antemano por vuestra ayuda.
·.:*:.·Yako·.:*:.·
Responder Con Cita
  #4  
Antiguo 10-04-2017
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.210
Poder: 22
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Cita:
Empezado por hgiacobone Ver Mensaje
Todas las instancias de RDP levantan el mismo "MyApp.exe". En el ejemplo quedó el verdadero nombre, pero digamos que lo que se intenta con esa linea es enviar el mensaje a ese EXE y no a otro.
Cuando envías un mensaje lo haces a un thread o a una ventana, no a un ejecutable. Cuando tienes varias instancias de un ejecutable, cada una con ventanas, los Handles no son los mismos. Una forma de enviar un mensaje a todas las ventanas es usar como Handle HWND_BROADCAST, pero entonces tendrás que tener un filtro en MyApp

Otra solución con sockets es implementar en MyApp un hilo con un cliente y que Monitor.exe sea un servidor. Si el protocolo es UDP no hace falta conexión previa u puedes enviar un datagrama UDP a la IP Broadcast con lo que todas las instancias de MyApp, lo recibirán. Previamente has de calcular la dirección Broadcast de tu red.


Saludos.
Responder Con Cita
  #5  
Antiguo 10-04-2017
Avatar de hgiacobone
hgiacobone hgiacobone is offline
Miembro
 
Registrado: may 2003
Ubicación: La Plata, Bs. As., Argentina
Posts: 165
Poder: 24
hgiacobone Va por buen camino
Cita:
Empezado por escafandra Ver Mensaje
...Cuando tienes varias instancias de un ejecutable, cada una con ventanas, los Handles no son los mismos...
Ah, ok.... o sea, Windows tomará un ID diferente aunque sea el mismo EXE?

Cita:
Empezado por escafandra Ver Mensaje
...Si el protocolo es UDP no hace falta conexión previa u puedes enviar un datagrama UDP a la IP Broadcast con lo que todas las instancias de MyApp, lo recibirán...
Entiendo, pero lo planteado en este foro hizo que dudara por el uso del port.
¿Entoneces es posible utilizar UDP aunque haya varias instancias RDP ?
__________________
Gracias de antemano por vuestra ayuda.
·.:*:.·Yako·.:*:.·
Responder Con Cita
  #6  
Antiguo 12-04-2017
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.210
Poder: 22
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Es posible tener varios servidores escuchando en la misma máquina por el mismo puerto, no es una situación común pero no es un imposible. Para esto está el Multicast.

Te pongo un ejemplo de servidor socket multicast en un thread para poder compaginarlo con una app de ventanas:
Código Delphi [-]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, WinSock;

type
  TServer = class(TThread)
  private
  protected
    procedure Execute; override;
  public
  end;


  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    Server: TServer;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}



//---------------------------------------------------------------------------
// Establecer y ejecutar Timeout en winsock recv / recvfrom
// retorna como winSock.Select
//  -1: si error
//   0: fuera de tiempo
// > 0: Datos listos para leer
function TimeoutSocket(Sock: WinSock.TSOCKET; TimeOut: integer): integer;
var
  FDSet: WinSock.TFDSET;
  TimeVal: WinSock.TTIMEVAL;
begin
  TimeVal.tv_sec:= TimeOut div 1000;
  TimeVal.tv_usec:= TimeOut mod 1000;
  FD_ZERO(FDSet);
  FD_SET(Sock, FDSet);
  Result:= WinSock.Select(0, @FDSet, nil, nil, @TimeVal)
end;


procedure TServer.Execute;
const
  BufferSize = 1024;
  Port = 9090;
var
  WSA: WinSock.TWSADATA;
  Sock: WinSock.TSOCKET;
  Addr: WinSock.sockaddr_in;
  Buffer: array[0..BufferSize-1] of AnsiChar;
  Len, AddrSize: integer;
  dwTime: DWORD;
  ValMulticast: AnsiCHAR;
begin
  if (WinSock.WSAStartup(MakeWord(2, 2), WSA) <> 0) then exit;
  Sock := WinSock.socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
  if (Sock <> INVALID_SOCKET) then
  begin
    dwTime:= 1000;
    ValMulticast:= #1;
    setsockopt(Sock, SOL_SOCKET, SO_RCVTIMEO, PCHAR(@dwTime), sizeof(dwTime));
    setsockopt(Sock, SOL_SOCKET, SO_REUSEADDR, @ValMulticast, sizeof(ValMulticast));
    setsockopt(Sock, IPPROTO_IP, IP_MULTICAST_LOOP, 0, 1);
    Addr.sin_family := AF_INET;
    Addr.sin_addr.s_addr := INADDR_ANY;
    Addr.sin_port := WinSock.htons(Port);
    AddrSize := sizeof(Addr);

    // Asociamos el socket al puerto y a escuchar
    if (bind(Sock, Addr, AddrSize) <> -1) then
    begin
      // Bucle de escucha...
      while not Terminated do
      begin
        Len := 0;

        // Comprobamos si ha recibido algun mensaje que leer
        if TimeoutSocket(Sock, 500) > 0 then
        begin
          ZeroMemory(@Buffer[0], BufferSize);
          Len := WinSock.recvfrom(Sock, Buffer, BufferSize-1, 0, Addr, AddrSize);
          // Leemos el paquete enviado
          if (Len > 0) and (Len < BufferSize) then
          begin
            Windows.Beep(1000, 100);
            MessageBox(0, Buffer, 'Eureka',0);
          end;
        end;
      end;
    end;
    WinSock.closesocket(Sock);
  end;
  WinSock.WSACleanUp;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Server:= TServer.Create(false);
end;

end.

Este servidor se pone a la escucha en el puerto 9090 y podemos tener varios en ejecución.

Ahora el cliente debe enviar mensajes UDP al Broadcast por el puerto 9090, para ello debemos calcular esa dirección. Te pongo un ejemplo de cliente que envía un mensaje a todos los servidores a la vez, estén o no en la misma máquina:
Código Delphi [-]
unit Unit2;

interface

uses
  Windows, WinSock, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm2 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

TMIB_IPADDRROW = packed record
  dwAddr: DWORD;
  dwIndex: DWORD;
  dwMask: DWORD;
  dwBCastAddr: DWORD;
  dwReasmSize: DWORD;
  unused1: SmallInt;
  wType: SmallInt;
end;

TMIB_IPADDRTABLE = record
  dwNumEntries: DWORD;
  table: array[0..0] of TMIB_IPADDRROW;
end;
PMIB_IPADDRTABLE = ^TMIB_IPADDRTABLE;


function GetIpAddrTable(IpAddrTable: PMIB_IPADDRTABLE; pdwSize: PULONG;
  Order: BOOL): DWORD; stdcall; external 'iphlpapi.dll' name 'GetIpAddrTable';

var
  Form2: TForm2;

implementation

{$R *.dfm}
function GetCurrentIP: DWORD;
var
  Wsa: WSADATA;
  Name: array[0..255] of char;
  hostinfo: PHOSTENT;
begin
  Result:= 0;
  FillChar(Wsa, SizeOf(WSAData), 0);
  if WSAStartup(MAKEWORD(2, 2), Wsa) = 0 then
  begin
    if gethostname(Name, SizeOf(Name)) = 0 then
    begin
      hostinfo:= gethostbyname(Name);
      if hostinfo <> nil then
        Result:= PDWORD(hostinfo^.h_addr_list^)^;
    WSACleanup;
    end;
  end;
end; 
 
function GetBrodcastAddress: String;
var
  pIPAddrTable: PMIB_IPADDRTABLE;
  dwSize: DWORD;
  i: integer;
  BroadCastInAddr: IN_ADDR;
begin
  BroadCastInAddr.S_addr:= 0;
  dwSize:= 0;
  GetIpAddrTable(nil, @dwSize, true);
  GetMem(pIPAddrTable, dwSize);
  if pIPAddrTable<>nil then
  begin
    if GetIpAddrTable(pIPAddrTable, @dwSize, true) = NO_ERROR then
      for i:=0 to  pIPAddrTable^.dwNumEntries-1 do
      begin
        if GetCurrentIP = pIPAddrTable^.table[i].dwAddr then
        begin
          BroadCastInAddr.S_addr:= pIPAddrTable^.table[i].dwAddr or not pIPAddrTable^.table[i].dwMask;
          break;
        end;
      end;
    FreeMem(pIPAddrTable);
  end;
  Result:= inet_ntoa(BroadCastInAddr);
end;

procedure SendUDP(Msg: AnsiString; IP: String; Port: WORD);
var
 Wsa: WSADATA;
 S: TSocket;
 Addr: WinSock.sockaddr_in;
 Host: PHostent;
 IPAddr: ^integer;
begin
  if WSAStartup(MAKEWORD(2, 2), Wsa) = 0 then
  try
    S:= Socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if S <> INVALID_SOCKET then
    begin
      Host:= gethostbyname(PAnsiCHAR(IP));
      IPAddr:= @Host.h_addr_list^[0];
      Addr.sin_family:= AF_INET;
      Addr.sin_addr.S_addr:= IPAddr^;
      Addr.sin_port:= htons(Port);
      Sendto(S, PAnsiChar(Msg)^, Length(Msg), 0, Addr, SizeOf(sockaddr_in));
     end;
  finally
    WSACleanup();
  end;
end;

procedure TForm2.Button1Click(Sender: TObject);
begin
  SendUDP('Hola', GetBrodcastAddress, 9090);
end;

end.

Probado en Win10 y compilado con Delphi 7


Espero que resuelva tu duda y en general la duda que originó ente hilo.


Saludos.
Responder Con Cita
  #7  
Antiguo 13-04-2017
Avatar de hgiacobone
hgiacobone hgiacobone is offline
Miembro
 
Registrado: may 2003
Ubicación: La Plata, Bs. As., Argentina
Posts: 165
Poder: 24
hgiacobone Va por buen camino
Muchas, pero muchas, gracias a migo escafandra... pero esto es muy elevado para mi entendimiento

Primero, porque creo yo tengo un error de concepto:
-En este caso, existe un pequeño ejecutable que monitorea un proceso. Llamemos a este "2do.exe"
-Luego está la aplicacion principal, que cada usurario levanta mediante una conexion RDP (Windows). Llamemos "1ro.exe". O sea, hay varios "1ro.exe" y un solo "2do.exe"

Entonces, el programa monitor (2do.exe) cada vez que realiza una operación, debería enviar a modo de mensaje de texto, ese resultado a cada instancia del programa (1ro.exe) y este, cuando lo reciba, lo mostrará en pantalla o como se prefiera. Yo pensaba que el monitor debería ser el Servidor y las otras aplicaciones los clientes, pero parece que es a la inversa, no?

Segundo, observo que utilizas la unidad WinSock. ¿Es una unidad estandar de Delphi o solo si adquieres el paquete Indy de las versiones Archictect/Professional?

Tercero: he instalado por sugerencia de varios, unos componentes "free" denominados Overbyte ICS que tienen infinidad de componentes de conexion TCP/UDP entre ellos:
> OverbyteIcsWSocket.pas Winsock component - TCP, UDP, DNS,...
> OverbyteIcsWSocketE.pas Register procedure and property editor for TWSocket
> OverbyteIcsWSocketS.pas Winsock component for building servers
> OverbyteIcsWSocketTS.pas Winsock component for building multithreaded servers
> OverbyteIcsDnsQuery DNS lookup component - useful for getting MX records

...que aun no se ni cómo utilizarlos.
¿Supones que podría reemplazar los WinSocks por ellos o no es conveniente?
__________________
Gracias de antemano por vuestra ayuda.
·.:*:.·Yako·.:*:.·
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Dos instancias de SQL Server parecen ser la misma Faust MS SQL Server 2 21-10-2011 23:13:07
¿Cómo usar mutex e impedir dos instancias de la misma app? Blaster OOP 1 11-08-2008 04:05:29
Cuantas instancias de nuestro exe están corriendo seoane Trucos 3 06-03-2007 01:58:41
Compartir "objetos" entre varias instancias mafebresv Varios 4 16-01-2006 23:38:23
Como evitar 2 instancias de una misma ventana hija edgusano .NET 5 12-12-2005 16:40:40


La franja horaria es GMT +2. Ahora son las 11:57:24.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi