Jump to content
aehimself

How to open a file in the already running IDE?

Recommended Posts

si vous avez un problème avec votre virilité ce n'est pas mon problème ! Résoudre!
Je suis aussi un homme et je n'aime que les femmes !
Le mot "mon cher" n'est qu'une ironie, pas une déclaration de genre !
Enfin, si Google renvoie le mauvais contexte, je ne suis pas responsable ! Même parce que je ne parle pas français du tout !
Mon chéri!

C'est fini pour moi ! Je ne répondrai plus aux railleries ! C'est la fin!

---

if you have a problem with your manhood it's not my problem! Resolve!
I'm also a man, and I only like women!
The word "my dear" is just an irony, not a gender statement!
Finally, if Google is returning the wrong context, I'm not responsible! Even because I don't speak French at all!
Mon cherie!

It's over for me! I will no longer respond to taunts! It's the end!

Share this post


Link to post
3 minutes ago, David Heffernan said:

I am male, as you can infer from my forename.

Of course, that would be assuming one's gender which isn't great. The French to their great credit have extended their language to include non-gendered pronouns. 

 

https://coucoufrenchclasses.com/the-coucou-guide-to-inclusive-and-gender-neutral-french/

 

https://blog.lingoda.com/en/french-gender-neutral-pronouns/

Share this post


Link to post
1 minute ago, programmerdelphi2k said:

si vous avez un problème avec votre virilité ce n'est pas mon problème ! Résoudre!
Je suis aussi un homme et je n'aime que les femmes !
Le mot "mon cher" n'est qu'une ironie, pas une déclaration de genre !
Enfin, si Google renvoie le mauvais contexte, je ne suis pas responsable ! Même parce que je ne parle pas français du tout !
Mon chéri!

C'est fini pour moi ! Je ne répondrai plus aux railleries ! C'est la fin!

---

if you have a problem with your manhood it's not my problem! Resolve!
I'm also a man, and I only like women!
The word "my dear" is just an irony, not a gender statement!
Finally, if Google is returning the wrong context, I'm not responsible! Even because I don't speak French at all!
Mon cherie!

It's over for me! I will no longer respond to taunts! It's the end!

Just don't put my name near a call to ShellExecute and everything will be fine!! 😉

Share this post


Link to post
1 minute ago, David Heffernan said:

Of course, that would be assuming one's gender which isn't great. The French to their great credit have extended their language to include non-gendered pronouns.

I do believe that's more than enough, please try not to steer the conversation away. Can we get back to the topic, please?

Share this post


Link to post
4 minutes ago, aehimself said:

I do believe that's more than enough, please try not to steer the conversation away. Can we get back to the topic, please?

I'm very sorry!! I got carried away. 

 

Is it possible that DDE is being used? That was how this would have been done in the old days. 

  • Like 1

Share this post


Link to post
4 minutes ago, David Heffernan said:

Is it possible that DDE is being used? That was how this would have been done in the old days. 

My guess was on some tricky Windows messages, but DDE is a valid option as well. As I have no source for BDSLauncher I can not say.

I took a peek at @dummzeuch's dzBdsLauncher but that also is executing a direct bds.exe call, probably resulting in a new IDE.

 

Finding the method and replicating it would be the goal of this topic.

Share this post


Link to post

Getting close 🙂 Never worked with DDE so it'll take some attempts to succeed I believe.

 

So far I have the following code:

 Memo1.Lines.Add(sLineBreak + '----------------------------------------');
 Memo1.Lines.Add('Opening ' + Edit1.Text);
 // DDEClientConv1.ServiceApplication := '"C:\Program Files (x86)\Embarcadero\Studio\22.0\bin\bdsLauncher.exe" "C:\Program Files (x86)\Embarcadero\Studio\22.0\bin\bds.exe" /np';
 DDEClientConv1.ServiceApplication := 'C:\Program Files (x86)\Embarcadero\Studio\22.0\bin\bdsLauncher.exe';

 Memo1.Lines.Add('Setting DDE link...');
 If Not DDEClientConv1.SetLink('bdsLauncher', 'system') Then
 Begin
   Memo1.Lines.Add('Setting link failed!');
   Exit;
 End;

 Memo1.Lines.Add('Opening DDE link...');
 If Not DDEClientConv1.OpenLink Then
 Begin
   Memo1.Lines.Add('Opening link failed!');
   Exit;
 End;

 Try
   Memo1.Lines.Add('Invoking DDE command...');

   If Not DDEClientConv1.ExecuteMacro(PAnsiChar('[open("' + Edit1.Text + '")]'), False) Then
   Begin
     Memo1.Lines.Add('Invoking command failed!');
     Exit;
   End;

 Finally
   Memo1.Lines.Add('Closing DDE link...');
   DDEClientConv1.CloseLink;
 End;

No errors are shown but nothing gets executed and I get a ding sound. No popups, no entries in the event log.

Anyone has experience debugging DDE, where should I look for errors?

 

I took all the keywords from the registry, HKCU\BDE.pas. ServiceApplication came from Command\Default, SetLink parameters from ddeexec\application\Default and ddeexec\topic\Default, the macro from ddeexec\default.

Share this post


Link to post
9 hours ago, aehimself said:

I took a peek at @dummzeuch's dzBdsLauncher but that also is executing a direct bds.exe call, probably resulting in a new IDE.

That was actually one of the points for this tool: To open a project in a new instance of the IDE rather than in an existing one. For me that latter has always been an annoying anti feature.

 

I was under the impression that Delphi's BdsLauncher simply was a wrapper that can be called with the file to open as a parameter which then  would check whether bds.exe was already running and either start it or pass the file name to it to open it. But that doesn't seem to be the case.

 

As @Fr0sT.Brutal already wrote: According to the registry entries it is DDE.

  • Like 1

Share this post


Link to post

When stepping in .ExecuteMacro, a message box actually pops up but disappears right after the line

 

  hdata := DdeClientTransaction(Pointer(hszCmd), DWORD(-1), FConv, 0, FDdeFmt,
     XTYP_EXECUTE, TIMEOUT_ASYNC, @ddeRslt);
 

What it said:

image.png.289e19636ae1234d12f28e6d113302f1.png

 

So I guess the command is incorrect, Delphi really didn't like the casting. Now attempting to properly build my command, because with

Var
  pac: PAnsiChar;
  s: AnsiString;
begin
  s := '[open("' + Edit1.Text + '")]';
  pac := PAnsiChar(s);

  If Not DDEClientConv1.ExecuteMacro(pac, False) Then Begin

my result is:

 

image.png.6b44a3f9824cbca8eb49612aa2182488.png

 

🙂

Share this post


Link to post
32 minutes ago, aehimself said:

  If Not DDEClientConv1.ExecuteMacro(PAnsiChar('[open("' + Edit1.Text + '")]'), False) Then

are you sure it's PAnsiChar?

 

 

 

Edited by Attila Kovacs

Share this post


Link to post
2 minutes ago, Attila Kovacs said:

are you sure its PAnsiChar?

Strange to me too, but yes, I am:

image.png.305c22e4532a3e926ebf2fd4dcda9b39.png

Share this post


Link to post

I remember seeing it on a really old newslist that TDDEClientConv heavily suffers from bad coding and I tend to believe something is not right with it in this case. I already tried with simple casting, StrPCopy, sending @PAnsiString[1] instead of PAnsiChar, even like this:

Var
 pac: PAnsiChar;
 s: String;
 tb: TBytes;
 len: Integer;
begin
  s := '[open("' + Edit1.Text + '")]';
  tb := TEncoding.Default.GetBytes(s);
  len := Length(tb);

  GetMem(pac, len + 1);
  ZeroMemory(pac, len + 1);
  Move(tb[0], pac^, len);

... but BDSLauncher always replies with some Chinese characters what it tried to execute as a command. I can not get more PAnsiChar than this.

 

I'll try to find a different component to check.

Share this post


Link to post

@aehimself How is the bdslauncher answering your query anyway? It's not a resident application, do you have some ghost processes of it? It's bdsLauncher which should detect if bds is running and if yes, send a dde to bds, otherwise start it. AFAIK. Am I Wrong?

Share this post


Link to post

this opens me the file in the running IDE

 

  DdeClientConv1.ServiceApplication := '"C:\Program Files (x86)\Embarcadero\Studio\18.0\bin\bds.exe"';

  Memo1.Lines.Add('Setting DDE link...');
  If Not DdeClientConv1.SetLink('bds', 'system') then
  begin
    Memo1.Lines.Add('Setting link failed!');
    Exit;
  end;

  // Memo1.Lines.Add('Opening DDE link...');
  // If Not DdeClientConv1.OpenLink then
  // begin
  // Memo1.Lines.Add('Opening link failed!');
  // Exit;
  // end;

  try
    Memo1.Lines.Add('Invoking DDE command...');

    if Not DdeClientConv1.ExecuteMacro(PAnsiChar('[open("C:\Temp\tmp\a.pas")]'), False) then
    begin
      Memo1.Lines.Add('Invoking command failed!');
      Exit;
    end;

  finally
    Memo1.Lines.Add('Closing DDE link...');
    DdeClientConv1.CloseLink;
  end;

 

Share this post


Link to post
14 minutes ago, Attila Kovacs said:

this opens me the file in the running IDE

How...?! It's the same garbage here, only it appears in the IDE. I thought autoconnecting makes a difference, but that doesn't seem to be the case...

 

image.thumb.png.67aaa2663d7e97907561c55c416e9e43.png

 

51 minutes ago, Fr0sT.Brutal said:

Why not try pure winapi? The functions are quite straightforward AFAICT

I did not find the needed WinApi calls yet. I might look into it, seems something is broken in TDDEClientConv between XE4 and 11.2...

Share this post


Link to post

Here.

 

This queries all the running bde's and opens a file in every one.

This is a good start, you have to find out which is which version somehow, I have no more time for that.

DDE-test.7z

  • Thanks 1

Share this post


Link to post

ooooooooo **** me running. This helped to fix my problem opening files by doublekingkong on them in the explorer.

At some point, I set bds.exe itself to run as administrator, not just a shortcut, the exe! No clue why, but from that point I could only open files from the IDE, of course.

I noticed that the program above works only from the IDE, which made me think.

Share this post


Link to post

Yeah, but now, I want my bdsLaucher2, where one can define, from which folder which IDE should spawn or open the file!

  • Haha 1

Share this post


Link to post

my bet would be "verify if a [process] is running and call it with your params", else, run the process!

that way, you avoid any Conflict of interests!

Share this post


Link to post
1 hour ago, programmerdelphi2k said:

my bet would be "verify if a [process] is running and call it with your params", else, run the process!

that way, you avoid any Conflict of interests!

Why wouldn't you do it with DDE. That's precisely what it's for. 

Share this post


Link to post
4 hours ago, Attila Kovacs said:

Here.

 

This queries all the running bde's and opens a file in every one.

This is a good start, you have to find out which is which version somehow, I have no more time for that.

DDE-test.7z

Perfection, works like a charm. It triggered my antivirus though, hope won't happen in the real application 🙂

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×