Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 518
  • Last Modified:

Delphi detection with JclIDETools fails on VirtualBox

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
Marco Gasi
Asked:
Marco Gasi
  • 16
  • 8
1 Solution
 
Sinisa VukCommented:
This can help you to detect delphi version:
detecting-installed-delphi-versions
0
 
Marco GasiFreelancerAuthor Commented:
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
 
lomo74Commented:
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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
Marco GasiFreelancerAuthor Commented:
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
 
lomo74Commented:
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
 
Marco GasiFreelancerAuthor Commented:
Okay, thanks a lot.
0
 
Marco GasiFreelancerAuthor Commented:
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
 
lomo74Commented:
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
 
Marco GasiFreelancerAuthor Commented:
Perfect! I'll do immediately. Thank you.
0
 
Marco GasiFreelancerAuthor Commented:
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
 
lomo74Commented:
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
 
Marco GasiFreelancerAuthor Commented:
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
 
lomo74Commented:
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
 
Marco GasiFreelancerAuthor Commented:
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
 
Marco GasiFreelancerAuthor Commented:
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
 
Marco GasiFreelancerAuthor Commented:
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
 
lomo74Commented:
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
 
Marco GasiFreelancerAuthor Commented:
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
 
lomo74Commented:
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
 
Marco GasiFreelancerAuthor Commented:
Thanks, Lorenzo: I'll wait and I'll watch it. I'll let you know the results :)
0
 
Marco GasiFreelancerAuthor Commented:
Lorenzo, I tried to see your movie but it doesn't work: have you installed Jcl ;)?
0
 
Marco GasiFreelancerAuthor Commented:
Ooops, I had to download it. I had simply clicked on the link... I'm going to watch it. Cheers
0
 
Marco GasiFreelancerAuthor Commented:
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
 
Marco GasiFreelancerAuthor Commented:
Thanks, Lorenzo. You find explanations in my last comment.
Cheers
0
 
lomo74Commented:
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

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 16
  • 8
Tackle projects and never again get stuck behind a technical roadblock.
Join Now