Solved

Interaction between Delphi and VB Aplication

Posted on 2004-09-03
8
889 Views
Last Modified: 2008-03-10
Hi,

I have problem, I will try to Explain it.

I have an application A in Delphi and another application B in Visual Basic. Application A has an interface from where I can have multiple Employee search screen. From Each employee search screen I want to open Application B where a form is loaded with the employee related information in Application B. Here B is a very large application, If I open more than one Application B the systems memory is exhausted. So what we want to do is open only one Application B and send messages from A to B accordingly refresh the data on the form in application B.

So my question

1.Is it possible to send messages to a running application from another application. If so how.

2.Do we have any way by which we can interact with between both the application.

3.If any body has sample code ,please pass it on

Please help me it is very urgent. Thanks in Advance

0
Comment
Question by:giriky99
8 Comments
 
LVL 2

Expert Comment

by:Discofish
ID: 11976110
What about writting a DLL using the key functions in the application?  Then you could just use the DLL inside of your delphi app without loading the entire VB application.

http://awc.al-williams.com/tips/tip30.htm

Also, take a look at the windows message loop.  You might be able to hack something together with this.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/Windowing/MessagesandMessageQueues/MessagesandMessageQueuesReference/MessagesandMessageQueuesFunctions/SendMessage.asp
0
 
LVL 7

Expert Comment

by:jacobhoover
ID: 11977276
How much data are you in need of passing?
COM objects such as recordsets would be nearly impossible to pass between the two.

If it's a small amount of data you could use a small helper DLL with a shared data segment to pass the payload and something like a named event or a broadcast message to signal the receiving application that it should check for an update.

<Shared Data Segment DLL>
http://www.codeproject.com/dll/data_seg_share.asp

Jake
0
 
LVL 4

Expert Comment

by:Sicos
ID: 11977604
Just use a mailslot... to send data from App A to B...

I've included some code to add mailslot functionality to your programs...

This is the code for youre delphi program... you have to search the code for VB yourself... try looking for that on http://www.planetsourcecode.com

{***************************************************}
{                                                   }
{              Made by Kees van Spelde              }
{                                                   }
{               MailSlot Component                  }
{                                                   }
{***************************************************}

unit MailSlot;

interface

{$R *.RES}

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

type
  TMailSender = record
     ComputerName: string;
     AppHandle   : THandle;
  end;

  TMailID = record
    ID_1 : integer;
    ID_2 : integer;
  end;

  TMail = record
    Sender: TMailSender;
    MailID: TMailID;
    Mail: string;
  end;

  TMailEvent    = procedure(Sender: TMailSender; Mail: string) of object;
  TSendEvent    = procedure(Successful: boolean) of object;

  EMailException = class(Exception);

  { TMailSlot}

  TMailSlot = class(TComponent)
  private
    FActive        : boolean;
    FInterval      : Cardinal;
    FMailChannel   : string;
    FNoDuplicates  : boolean;
    FOnMailIncoming: TMailEvent;
    FOnMailSended  : TSendEvent;
    FWindowHandle  : HWND;
    procedure UpdateTimer;
    procedure SetMailChannel(Value: string);
    procedure SetNoDuplicates(Value: boolean);
    procedure SetActive(Value: boolean);
    procedure SetInterval(Value: Cardinal);
    procedure WndProc(var Msg: TMessage);
    function MailToPack(Mail: string): TMail;
    function PackToMail(Mail: string): string;
  protected
    MailHandle : THandle;
    LastMailID : TMailID;
    UserList: TStringList;
    function ReadMail: string;
    procedure ExtractMail(Mail: string);
    procedure CreateConnection;
    procedure CloseConnection;
    procedure Execute; dynamic;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property Active: boolean read FActive write SetActive default False;
    procedure SendMail(TargetComputer: string; Mail: string);
    procedure RefreshUserlist;
    procedure ClearUserList;
    function GetUserList: TStringList;
  published
    property Interval: Cardinal read FInterval write SetInterval default 1000;
    property MailChannel: string read FMailChannel write SetMailChannel;
    property NoDuplicates: boolean read FNoDuplicates write SetNoDuplicates default true;
    property OnMailIncoming: TMailEvent read FOnMailIncoming write FOnMailIncoming;
    property OnMailSended: TSendEvent read FOnMailSended write FOnMailSended;
    procedure SendAllUsers(Mail: String);
  end;

var gsLocalComputerName: String = 'UNKNOWN';  

procedure Register;

implementation

const

{ Errors }

  ERANDOMERROR  = 'Error while try to create a custom identifier';
  ECONNECTERROR = 'Error while try to open mailslot channel';
  ECHANNELERROR = 'The "MailChannel" is not a valid value';
  ECLOSEERROR   = 'Error while try to close the mailslot';
  EWRITEERROR   = 'Error while try to send the mail';
  EPACKTOMAIL   = 'Error when the package convert to mail';
  EGETCOMPUTER  = 'Error while try to read the computer name';
  ETIMERERROR   = 'Not enough timers available';

{ Special functions }

function GetLocalComputerName: string;
var
  Buffer : PChar;
  Size   : DWORD;
begin
  Result := '';
  Buffer := StrAlloc(MAX_COMPUTERNAME_LENGTH + 1);
  Size   := MAX_COMPUTERNAME_LENGTH + 1;
  if GetComputerName(Buffer, Size) then
    begin
      Result := String(Buffer);
      StrDispose(Buffer);
    end
  else
    begin
      StrDispose(Buffer);
      raise EMailException.Create(EGETCOMPUTER);
    end;
end;

function CreateMailID: TMailID;
begin
  try
    Randomize;
    Result.ID_1 := Random(MaxInt);
    Result.ID_2 := Random(MaxInt);
  except
    raise EMailException.Create(ERANDOMERROR);
  end;
end;

// Ontvangen mail
function TMailSlot.MailToPack(Mail: string): TMail;
var
  S: TStringList;
  MailText: String;
begin
  S := TStringList.Create;
  S.Text := Mail;
  MailText := S.Values['TEXT'];
  if (MailText = '#WHOISONLINE') or (MailText = '#HELLO') then
    begin
      if MailText = '#HELLO' then UserList.Add(S.Values['COMPUTER']);
      if MailText = '#WHOISONLINE' then SendMail(S.Values['COMPUTER'], '#HELLO');
    end
  else
    begin
      Result.MailID.ID_1         := StrToInt(S.Values['ID_1']);
      Result.MailID.ID_2         := StrToInt(S.Values['ID_2']);
      Result.Sender.ComputerName := S.Values['COMPUTER'];
      UserList.Add(S.Values['COMPUTER']);
      Result.Mail                := S.Values['TEXT'];
    end;
  S.Free;
end;

function TMailSlot.PackToMail(Mail: string): string;
var
  S: TStringList;
begin
  Result := '';
  S := TStringList.Create;
  try
    with S do
      begin
        Add('[IDENTIFY]');
        Add('ID_1=' + IntToStr(CreateMailID.ID_1));
        Add('ID_2=' + IntToStr(CreateMailID.ID_2));
        Add('[SENDER]');
        Add('COMPUTER=' + gsLocalComputerName);
        Add('[MAIL]');
        Add('TEXT=' + Mail);
        Add('[END]');
        Result := s.Text;
      end;
  except
    S.Free;
    raise EMailException.Create(EPACKTOMAIL);
  end;
  S.Free;
end;

{ TMailSlot}

function TMailSlot.ReadMail: string;
var
  Size   : DWORD;
  Buffer : PChar;
  Getted : Boolean;
  Count  : DWORD;
begin
  Result := '';
  Getted := GetMailSlotInfo(MailHandle, nil, Size, @Count, nil);
  if (Getted) and (Size <> MAILSLOT_NO_MESSAGE) and (Count > 0) then
    begin
      Buffer := StrAlloc(Size + 1);
      ReadFile(MailHandle, Buffer^, Size, Size ,nil);
      Result := String(Buffer);
      StrDispose(Buffer);
    end;
end;

procedure TMailSlot.Execute;
var
  Mail : string;
begin
  Mail := ReadMail;
  if Mail <> '' then
    begin
      ExtractMail(Mail);
      Mail := '';
    end;
end;

procedure TMailSlot.ExtractMail(Mail: string);
var
  Pack: TMail;
begin
  Pack := MailToPack(Mail);
  if (FNoDuplicates) and (Pack.MailID.ID_1 = LastMailID.ID_1) and (Pack.MailID.ID_2 = LastMailID.ID_2) then
    Exit
  else
    begin
      LastMailID.ID_1 := Pack.MailID.ID_1;
      LastMailID.ID_2 := Pack.MailID.ID_2;
      if Assigned(FOnMailIncoming) then
        FOnMailIncoming(Pack.Sender, Pack.Mail);
    end;
end;

constructor TMailSlot.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FWindowHandle := AllocateHWnd(WndProc);
  FMailChannel := 'MailSlot';
  FNoDuplicates := True;
  FInterval := 1000;
  UserList := TStringList.Create;
  UserList.Sorted := True;
  UserList.Duplicates := dupIgnore;
  gsLocalComputerName := GetLocalComputerName;
end;

destructor TMailSlot.Destroy;
begin
  UpdateTimer;
  UserList.Free;
  DeallocateHWnd(FWindowHandle);
  if FActive then CloseHandle(MailHandle);
  inherited Destroy;
end;

procedure TMailSlot.CreateConnection;
var
  Handle: THandle;
begin
  try
    Handle := CreateMailSlot(PChar('\\.\mailslot\' + FMailChannel), 0, 0, nil);
    if (Handle = INVALID_HANDLE_VALUE) then
      raise EMailException.Create(ECONNECTERROR)
    else
      MailHandle := Handle;
  except
    raise EMailException.Create(ECONNECTERROR)
  end;
end;

procedure TMailSlot.CloseConnection;
begin
  try
    CloseHandle(MailHandle);
  except
    raise EMailException.Create(ECLOSEERROR);
  end;
end;

procedure TMailSlot.SetMailChannel(Value: string);
begin
  if Value <> FMailChannel then
    FMailChannel := Value;
end;

procedure TMailSlot.SetActive(Value: boolean);
begin
  if Value <> FActive then
    begin
      if Value then
        CreateConnection
      else
        CloseConnection;
      FActive := Value;
      UpdateTimer;
   end;
end;

procedure TMailSlot.SetNoDuplicates(Value: boolean);
begin
  if Value <> FNoDuplicates then
    FNoDuplicates := Value;
end;

procedure TMailSlot.SetInterval(Value: Cardinal);
begin
  if FInterval <> Value then
    begin
      FInterval := Value;
      UpdateTimer;
    end;
end;

function TMailSlot.GetUserList: TStringList;
begin
  result := Userlist;
end;

procedure TMailSlot.ClearUserList;
begin
  Userlist.Clear;
end;

procedure TMailSlot.RefreshUserlist;
begin
  SendAllUsers('*');
end;

procedure TMailSlot.SendAllUsers(Mail: String);
var I: Integer;
begin
  for I := 0 to Userlist.Count -1 do
    SendMail(Userlist[I], Mail);
end;

procedure TMailSlot.SendMail(TargetComputer: string; Mail: string);
var
  Size             : DWORD;
  SendMailHandle   : THandle;
begin
  Mail := PackToMail(Mail);

  TargetComputer := '\\' + TargetComputer + '\mailslot\' + FMailChannel;
  SendMailHandle := CreateFile(PChar(TargetComputer),
                               GENERIC_WRITE,
                               FILE_SHARE_READ,
                               nil,
                               OPEN_EXISTING,
                               FILE_ATTRIBUTE_NORMAL,
                               0);

  if (SendMailHandle <> INVALID_HANDLE_VALUE) then
    begin
      Size   := Length(Mail)+1;
      WriteFile(SendMailHandle, PChar(Mail)^, Size, Size, nil);
      CloseHandle(SendMailHandle);
      if Assigned(FOnMailSended) then FOnMailSended(True);
    end
  else
    if Assigned(FOnMailSended) then FOnMailSended(False);
//  CloseHandle(SendMailHandle);
end;

procedure TMailSlot.UpdateTimer;
begin
  KillTimer(FWindowHandle, 1);
  if (FInterval <> 0) and FActive then
    if SetTimer(FWindowHandle, 1, FInterval, nil) = 0 then
      raise EOutOfResources.Create(ETIMERERROR);
end;

procedure TMailSlot.WndProc(var Msg: TMessage);
begin
  with Msg do
    if Msg = WM_TIMER then
      try
        Execute;
      except
        Application.HandleException(Self);
      end
    else
  Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam);  //01-01-2002
end;

procedure Register;
begin
  RegisterComponents('Samples', [TMailSlot]);
end;

end.

0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 6

Expert Comment

by:SCDMETA
ID: 11982672
A couple of ideas:
If you can modify application B (the VB app), then compile it as an ActiveX exe.  Expose a public class that supports functions like Public Sub DisplayEmployee(x).  Application A can then create an instance of Application B and programatically call it's DisplayEmployee function via COM.

If you can not modify application B, then check to see if it already exposes a COM interface.  It might already have public classes and methods for doing what you want.

If application B does not expose a COM interface, then consider going at the data directly and avoid application B altogether.  For example, application B could be storing it's data in a SQL database.  See if you can open the database from app A (read only mode) and query and display the information.

Another, alternative, if application B does not expose a COM interface, then you might try using DDE or SendKey functions.  These are very crude ways of linking two applications but sometimes it is the only option.  From App A, write a program that gives App B focus and then sends key strokes to it.  You would have to figure out the correct keys stokes and pauses.  (I did say it was a crude way of linking two apps.)

Another, out on a limb possiblity.  Some applications have alternate web interfaces that allow retrieving data in a browser.  If so, Application A could launch a browser window, with the URL into Application B's web interface. A well crafted querystring or posted data might get the browser to display the correct information.

0
 
LVL 1

Author Comment

by:giriky99
ID: 12197026
Hi Experts,

I have answered my question my self.
Please see bellow the Answer
=========================================
Question :Interaction between Delphi and VB application
http://www.experts-exchange.com/Programming/Q_21118128.html#12169434

============================================================
01. Create an ActiveX EXE and set the instancing property of ActiveX EXE to MultiUse.
      Create an instance of a class ( say Sharing class ) at module level, so that the members/methods of it can be shared by each instance of the ActiveX EXE.
       Methods of Sharing Class:
        Init(AppName): Initiailises the application. Should be unique, i.e., the name can not be used by other applications.
        SendMessage ( ToAppName, FromAppName, Message ) to send the message from one application to other.
       Event:
        MsgReceived( FromAppName, Message ) -  This is to handle the incoming messages from sender applications.
 
02. Create two standard EXEs ( say App A and App B ) by giving the ref., of the ActiveX EXE.
           
In App A
 
Private Sub Form_Load()
   
    Set objShare = New clsShare
    objShare.Init "ServerApplication"    
   
End Sub
   
Private Sub cmdSend_Click()
    objShare.SendMessage "ClientApplication", "ServerApplication" , Text1.Text
End Sub
 
Private Sub objConnector_MsgReceived(strFromApp As String, strMsg As String)
    Text2.Text = "Received from the Application" & strFromApp & ": And the message is: " & strMsg
End Sub
     
In App B
 
Private Sub Form_Load()
   
    Set objShare = New clsShare
    objShare.Init "ClientApplication"    
   
End Sub
   
Private Sub cmdSend_Click()
    objShare.SendMessage "ServerApplication", "ClientApplication" , Text1.Text
End Sub
 
Private Sub objConnector_MsgReceived(strFromApp As String, strMsg As String)
    Text2.Text = "Received from the Application" & strFromApp & ": And the message is: " & strMsg
End Sub
0
 

Accepted Solution

by:
ee_ai_construct earned 0 total points
ID: 12222357
Question answered by asker or dialog valuable.
Closed, 125 points refunded.
ee_ai_construct (replacement part #xm34)
Community Support Admin
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
countX 22 70
array220 challenge 8 46
word0 challenge 4 53
base64 decode encode 12 96
A short article about a problem I had getting the GPS LocationListener working.
Although it can be difficult to imagine, someday your child will have a career of his or her own. He or she will likely start a family, buy a home and start having their own children. So, while being a kid is still extremely important, it’s also …
In this fourth video of the Xpdf series, we discuss and demonstrate the PDFinfo utility, which retrieves the contents of a PDF's Info Dictionary, as well as some other information, including the page count. We show how to isolate the page count in a…
In this fifth video of the Xpdf series, we discuss and demonstrate the PDFdetach utility, which is able to list and, more importantly, extract attachments that are embedded in PDF files. It does this via a command line interface, making it suitable …

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now