Solved

Delphi detection with JclIDETools fails on VirtualBox

Posted on 2013-05-21
25
490 Views
Last Modified: 2013-05-28
Hi all.

I0m trying to improve my small creature replaceing my own Delphi installation detection routine with JclIDETools unit.

This is not a problem and the program works fine in my desktop, but I must test it on other machines and with different Delphi versions, so I installed VirtualBox in order to test my program and install different Delphi versions without affecting my PC..

Unfortunately, when I run my program within Virtualbox it detects Delphi installation using my own code but it fails using JclIDETools unit: the TreeView populated by my code displays correctly Delphi version(s) installed, the one populated by JclIDETools remains empty.

I'm doing many tests to get rid of this beacuse I think to need a better code than mine to detect Delphi but I would like test it without buy another computer or without partitioning my har disk and then reboot it everytime I need to do a test!

Hope someone has some idea about this!!! :(

Thanks to all for any advice.

Cheers
Marco
0
Comment
Question by:Marco Gasi
  • 16
  • 8
25 Comments
 
LVL 25

Expert Comment

by:Sinisa Vuk
Comment Utility
This can help you to detect delphi version:
detecting-installed-delphi-versions
0
 
LVL 30

Author Comment

by:Marco Gasi
Comment Utility
Hi, sinisav.

Yes, I knew that resource, but JclIDETools unit offers a great amount of info about each Delphi installation detected and I would really appreciate to get those infos within my program.

The problem is only within VirtualBox: JclIDETools works great within main system: it fails only in VirtualBox, so I'm wondering if someone can imagine what in VirtualBox could make that code fail...
0
 
LVL 8

Expert Comment

by:lomo74
Comment Utility
Ciao Marco.
You assume the problem is caused by VirtualBox. Where does this certainty come from? Did you try different OS / Delphi combinations with VirtualBox, and verified that all expose the same behaviour?
Did you try other virtualization softwares (e.g. MS Virtual PC or VMware)?
Unless you are absolutely sure that it's a VirtualBox issue, you're possibly looking in the wrong place.
You can also perform some debug - I think you can install Jcl in "developer mode" and step into the routine to see where it is failing and why.
0
 
LVL 30

Author Comment

by:Marco Gasi
Comment Utility
Ciao, Lorenzo.

I have no certainty at all: I simply supposed it were a VirtualBox problem because the code works fine in the 'normal' system (I don't know I can call it...) and it fails within VirtualBox.

That said, I admit I didn't test other virtualization systems nor I installed other OS: I'll do them and I'll come back with more info.

Thank you for your suggestions.

Cheers
0
 
LVL 8

Expert Comment

by:lomo74
Comment Utility
I'm reconsidering my previous answer. I'd go with a debug session inside the VM first.
To do so, open your project, go to options / delphi compiler / compiling and check "use debug .dcus". Then rebuild the project and start the debugger. You should be able to step into Jcl's routines. This way you'll collect relevant information about the failure.
0
 
LVL 30

Author Comment

by:Marco Gasi
Comment Utility
Okay, thanks a lot.
0
 
LVL 30

Author Comment

by:Marco Gasi
Comment Utility
Lorenzo, have I to compile the project within VirtualBox? This would be complicated because I don't have within VirtualBox system all components and resources used by the project, so maybe I have to create another VM with more space to install all components... Or am I missing something?
0
 
LVL 8

Expert Comment

by:lomo74
Comment Utility
yes, the idea is to run the debugger inside the VM.
since you're interested in JclIDETools failures only, you could create a minimal project containing just that component; no need to port your whole project.
0
 
LVL 30

Author Comment

by:Marco Gasi
Comment Utility
Perfect! I'll do immediately. Thank you.
0
 
LVL 30

Author Comment

by:Marco Gasi
Comment Utility
Well, at last I did it. Or better, I installed Jcl and jvcl within VirtualBox and now the program correctly detects Delphi installations: but it should work even without Jcl installed in the end user PC... Have you any idea?
0
 
LVL 8

Accepted Solution

by:
lomo74 earned 500 total points
Comment Utility
maybe some missing runtime module...? but in that case the program wouldn't start at all.
so. I'd proceed as follows:
1) recreate the environment we had at the beginning: a running VM with Delphi and without Jcl.
2) check that the program is failing inside the VM.
3) build the program with debug dcus and remote debug symbols (see how to do this here: http://docwiki.embarcadero.com/RADStudio/XE4/en/Preparing_Files_for_Remote_Debugging).
4) install remote debugger inside the VM (you can download it from Embarcadero website; login and go to your download page).
5) copy .exe and .rsm files to the VM.
6) start remote debugger server inside the VM.
7) in the HOST's IDE, set a breakpoint where the program is supposed to fail.
8) in the HOST's IDE, start the debugger targeting the remote machine (Run > Load Process > Remote). more info here: http://docwiki.embarcadero.com/RADStudio/XE4/en/Establishing_a_Connection_for_Remote_Debugging.

remember: you have to use the HOSTS's IDE to debug.
as you already saw, the presence of Jcl into the VM alters the conditions, so you DON'T have to use it to debug.

if you followed the above steps correctly, you are now debugging the program running into the VM, and you should be able to see what's going wrong.

PS. till now, we can say that it's not a VirtualBox issue.
0
 
LVL 30

Author Comment

by:Marco Gasi
Comment Utility
Hi, Lorenzo.

I'm very sorry for the delay of this post, but a lightning has crashed my PC and I had to work a lot to replace yhe HD and restore the system.

Well, I just tried to follow your instructions, but I have a problem establishing a connection with VM: Delphi says 'Unable to connect to remore host'. I used the DNS found in the network control panel which shows Virtual-Host but that number didn't work.

I'll proceed to search for a solution to this new problem (but if you have one, I'll be happy to hear it from you!)

This post was only to update you abolut the actual status of the thread.

Cheers
Marco
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 8

Expert Comment

by:lomo74
Comment Utility
you have to properly setup tcp/ip before using remote debug.
off the top of my head:
- use bridged networking for the guest OS. don't use NAT; NAT allows the guest to reach the internet and the host, but not the opposite.
- prefer static IP addresses.
- remember to setup firewall rules into the guest, otherwise you won't be able to establish a connection.
- use standard tcp/ip tools to diagnose network problems before trying to debug. If you can't ping, nothing else is going to work.
0
 
LVL 30

Author Comment

by:Marco Gasi
Comment Utility
Hi Lorenzo.
Thanks for the advice. Now I finally the network works: I can ping host from guest and viceversa, I can browse Public documents ot other PC from both host and guest, both host and guest can access the Internet so it should work but... it doesn't work: 'Unable to connect to remote host'

The socket error is 'Connection timed out', but this is not so meaningful...

Any idea? Probably it would be better to open a new question about virtualization, what do you think about?
0
 
LVL 30

Author Comment

by:Marco Gasi
Comment Utility
Oooops! Starting and restarting, I lastly forgot to start even the remote debugger!!! Now I got it: I'll let you know what I'll learn from the debug process.

Anyway, you yet deserve all available points for having let me to learn all these things about remore debugging: thanks, Lorenzo!

Cheers
Marco
0
 
LVL 30

Author Comment

by:Marco Gasi
Comment Utility
Hey there!
Don't know if you know JclIDEUtils unit (if you want, I can post here the full code) but here you can see the core function for Delphi detection:

procedure TJclBorRADToolInstallations.ReadInstallations;
var
  VersionNumbers: TStringList;

  function EnumVersions(const KeyName: string; const Personalities: array of string;
    CreateClass: TJclBorRADToolInstallationClass): Boolean;
  var
    I, J: Integer;
    VersionKeyName, PersonalitiesKeyName: string;
    PersonalitiesList: TStrings;
    Installation: TJclBorRADToolInstallation;
  begin
    Result := False;
    if RegKeyExists(HKEY_LOCAL_MACHINE, KeyName) and
      RegGetKeyNames(HKEY_LOCAL_MACHINE, KeyName, VersionNumbers) then
      for I := 0 to VersionNumbers.Count - 1 do
        if StrIsSubSet(VersionNumbers[I], CharIsFracDigit) then
        begin
          VersionKeyName := KeyName + DirDelimiter + VersionNumbers[I];
          if RegKeyExists(HKEY_LOCAL_MACHINE, VersionKeyName) then
          begin
            ShowMessage(IntToStr(I) + ' Versions: '+VersionKeyName);
            if Length(Personalities) = 0 then
            begin
              try
                Installation := CreateClass.Create(VersionKeyName);
                if Installation.Valid then
                  FList.Add(Installation);
              finally
                Result := True;
              end;
            end
            else
            begin
              PersonalitiesList := TStringList.Create;
              try
                PersonalitiesKeyName := VersionKeyName + '\Personalities';
                ShowMessage(IntToStr(I) + ' Personalities: '+PersonalitiesKeyName);
                if RegKeyExists(HKEY_LOCAL_MACHINE, PersonalitiesKeyName) then
                  RegGetValueNames(HKEY_LOCAL_MACHINE, PersonalitiesKeyName, PersonalitiesList);

                for J := Low(Personalities) to High(Personalities) do
                  if PersonalitiesList.IndexOf(Personalities[J]) >= 0 then
                  begin
                    try
                      Installation := CreateClass.Create(VersionKeyName);
                      if Installation.Valid then
                        FList.Add(Installation)
                      else
                        Installation.Free;
                    finally
                      Result := True;
                    end;
                    Break;
                  end;
              finally
                PersonalitiesList.Free;
              end;
            end;
          end;
        end;
  end;

begin
  FList.Clear;
  VersionNumbers := TStringList.Create;
  try
    EnumVersions(DelphiKeyName, [], TJclDelphiInstallation);
    EnumVersions(BCBKeyName, [], TJclBCBInstallation);
    EnumVersions(BDSKeyName, ['Delphi.Win32', 'BCB', 'Delphi8', 'C#Builder'], TJclBDSInstallation);
    EnumVersions(CDSKeyName, ['Delphi.Win32', 'BCB', 'Delphi8', 'C#Builder'], TJclBDSInstallation);
    EnumVersions(EDSKeyName, ['Delphi.Win32', 'BCB', 'Delphi8', 'C#Builder'], TJclBDSInstallation);
  finally
    VersionNumbers.Free;
  end;
end;

Open in new window


Keeping in mind I call this method in OnShow event of my main form, if I set a breakpoint at line 66 (snippet lines numeration) I get into an understandble mix of Pascal and Assembly which starts in System unit at this point:

procedure TObject.Free;
begin
  if Self <> nil then
{$IFDEF AUTOREFCOUNT}
    __ObjRelease;
{$ELSE}
    Destroy;
{$ENDIF}
end;

Open in new window


Don't understand why when it should create a TStringList object it goes to a Freeing routine but that's all.

Coherently , if I set the breakpoint at line 70, where I think the code should detect BDS XE3, the breakpoint is never reached and the program starts fluently, but with the Delphi list sadly empty.

So what I understand is that instead of creating the TStringList which should hold Delphi installations, it tries to free it and then shows the form: why? This is a question for a greater brain than mine...
0
 
LVL 8

Expert Comment

by:lomo74
Comment Utility
Maybe .exe and .rsm got out of sync. I suggest that you rebuild the whole project (shift+F9), then copy again .exe and .rsm files to the VM and restart the remote debugger.
Another suggestion: set the breakpoint earlier in your code, maybe at OnShow beginning.
Any error occurring before you create the TJclBorRADToolInstallations object will make your code jump over, and your breakpoint would not be reached.
0
 
LVL 30

Author Comment

by:Marco Gasi
Comment Utility
Done. The result changes a few but it remains understandable. There is no error in my own code, only because I'm using a testing program which does nothing but detecting Delphi: here you find the OnShow event

procedure TForm1.FormShow(Sender: TObject);
var
  I, X: Integer;
  TN, SubTn: TTreeNode;
begin
  FDelphiInstallations := TJclBorRADToolInstallations.Create;
  for I := 0 to FDelphiInstallations.Count - 1 do
  begin
    IconIndex := ilDelphiIcons.AddIcon(GetSmallIcon(FDelphiInstallations[I].IdeExeFileName));
    TN := tvDisplay.Items.AddChild(nil, FDelphiInstallations[I].Name);
    TN.ImageIndex := ilDelphiIcons.Count - 1;
    TN.SelectedIndex := ilDelphiIcons.Count - 1;
    with tvDisplay.Items do
    begin
      SubTn := AddChild(TN, 'Description: ' + FDelphiInstallations[I].Description);
      SubTn.ImageIndex := 0;
      SubTn := AddChild(TN, 'Root directory: ' + FDelphiInstallations[I].RootDir);
      SubTn.ImageIndex := 0;
      SubTn := AddChild(TN, 'Projects directory: '+ FDelphiInstallations[i].DefaultProjectsDir);
      SubTn.ImageIndex := 0;
      SubTn := AddChild(TN, 'Common Projects directory: '+ FDelphiInstallations[i].CommonProjectsDir);
      SubTn.ImageIndex := 0;
      SubTn := AddChild(TN, 'Executable File name: '+ FDelphiInstallations[i].IdeExeFileName);
      SubTn.ImageIndex := 0;
      SubTn := AddChild(TN, 'Build number: '+ FDelphiInstallations[i].IdeExeBuildNumber);
      SubTn.ImageIndex := 0;
      SubTn := AddChild(TN, 'VersionNumberStr='+ FDelphiInstallations[i].VersionNumberStr);
      SubTn.ImageIndex := 0;
      SubTn := AddChild(TN, 'Registry key='+ FDelphiInstallations[i].ConfigDataLocation);
      SubTn.ImageIndex := 0;
      for X := 0 to FDelphiInstallations[i].IdePackages.Count - 1 do
      begin
        SubTn := AddChild(TN, 'Description: ' + FDelphiInstallations[I].IdePackages.PackageFileNames[X]);
        SubTn.ImageIndex := 0;
      end;
    end;
  end;
end;

Open in new window


 When program find breakpoint it stops and brings me to the line 4308 of JclIDEUtils unit. Then follow some operations of Assembly code in System unit, then returns to line 4309 in JclIDEUtils.pas: line 4308 is empty, line 4309 is

{$ENDIF MSWINDOWS}

Then return to my code, at the beginning of the loop (for I := 0 to FDelphiInstallations.Count - 1 do), then immediately exits from the loop: that's all.

I tried the same debug with the other VM where I installed Jcl and the difference is that after having done something with assembly, it creates the list with the code of System.Contnrs and goes on creating the list of Delphi installations.

Maybe I should try to ask to Jedi forum, if there is one...
0
 
LVL 8

Expert Comment

by:lomo74
Comment Utility
Marco,
this may provide inspiration. https://dl.dropboxusercontent.com/u/22313850/remote_debug.avi
(currently uploading to dropbox -- will finish upload in ~30 minutes)
0
 
LVL 30

Author Comment

by:Marco Gasi
Comment Utility
Thanks, Lorenzo: I'll wait and I'll watch it. I'll let you know the results :)
0
 
LVL 30

Author Comment

by:Marco Gasi
Comment Utility
Lorenzo, I tried to see your movie but it doesn't work: have you installed Jcl ;)?
0
 
LVL 30

Author Comment

by:Marco Gasi
Comment Utility
Ooops, I had to download it. I had simply clicked on the link... I'm going to watch it. Cheers
0
 
LVL 30

Author Comment

by:Marco Gasi
Comment Utility
Good morning, Lorenzo.

First, thank you for the time and the effort you give to solve my problem: I very appreciate it.

Second I watched your video, but I don't see any different from what I did following your suggestions but...

Third, I get the solution and I have a little fear to say it... I didn't run Delphi in the VM where I was testing without installing Jcl: I simply installed Delphi and then made my tests. Hence, the difference between my two VM wasn't the Jcl installation but the fact that in the first I had run Delphi and in the second I didn't. Now, once I opened Delphi and then closed it, the testing app works!

So I feel stupid for having wasted your time in so complex jobs when it was a stupid problem! But you teached me something very interesting: thanks and thanks again!

One thing leaves me with a doubt: the registry keys in HKEY_LOCAL_MACHINE were correct even before to run Delphi, so what changes running Delphi which is so important to make detection fails?

I'm going to accept your answer about remote debugging.

Cheers
Marco

PS: can I pray you to don't stop to monitor this question? I'm bulding a little algorithm and if I need some help I'll post here a link to the new question :)
Ciao
0
 
LVL 30

Author Closing Comment

by:Marco Gasi
Comment Utility
Thanks, Lorenzo. You find explanations in my last comment.
Cheers
0
 
LVL 8

Expert Comment

by:lomo74
Comment Utility
I also wonder what Delphi does on its first run that made such a difference in your program?
Anyway, glad you solved and learned something new about remote debugging.
I'm going to accept your request and keep monitoring this Q.
Ciao - L -
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
This video discusses moving either the default database or any database to a new volume.
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

743 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

16 Experts available now in Live!

Get 1:1 Help Now