Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Problem with the DBGrid32.ocx from 2010 2

Status
Not open for further replies.

CP60

Programmer
Oct 16, 2008
145
0
0
DE

I have been using and installing on customer machines the DBGrid32.ocx from 1999 v. 5.1.81.4

There was a security update in 2012 for several VB6 components, which could be downloaded and installed.

I found out that there seems to be a bug in this DBGrid32.ocx from 2010 v. 5.1.98.13, which causes an error 3265 when referencing the column by it's field name rather than an index:

DBGrid1.Columns.Item("SomeField").Value​

I always reference the column by the field name, so that if the query/table field order changes, all the references do not need to be changed.

The program has worked fine fpr years on hundreds of customers machines, because I always install the older version.

One of our newer customers uses GeoMedia, and this application also uses the DBGrid32.ocx. But the developers of GeoMedia have obviously downloaded the security package and distribute the newer Ocx - then my program stops working properly.

When the customer manually removes the newer ocx (de-register) and replaces it with the older one, all programs work fine again.
And, the customer should be required to do this, and is complaing about it.

GeoMedia confirmed their program will work with the older ocx, but rightfully says that they are using the newest version of the ocx.
However, that would be the case, if there was a further update of the ocx coming, which isn't the case. MS will evidently not be fixing this.
(There were similar problems with other ocxs, like the mscomctl.ocx, which MS did give a correction for.)

So, does anyone have an idea how to best handle a situation like this?
Maybe the older ocx could just be installed isolated?

Thank you for any help!


So, does anyone maybe have an idea how
 
This OCX was included in the ill fated "Security Rollup" issued by Microsoft a long time ago (as in Demceber 2008 or so). They have "ready fire aimed" themselves with this many times, trying to fix it and reissue it.

The last one I tested was from April 2012 I believe.

Many of these controls have strange "off by 1" errors in them. Some are very blatant: Winsock.RemoteHost returns values truncated by 1 character for example. Others are somewhat subtle and related to collection indexing. Your problem seems to be one of those.

There isn't any workaround: just never install these "Rollups." As far as I know none of them can be safely uninstalled once installed, certainly the earlier attempts craftily leave no uninstall info behind so you can't delete them through the normal Control Panel Programs & Features applet.


The way I survive this is to use clean dvelopment machines that do not have these "Rollups" installed. Then I use reg-free COM packaging to isolate these OCXs.

What this does is use manifests to provide an Activation Context for these OCXs. That allows my programs to have private copies of working versions of such OCXs that do not need to be registered on target machines.

Then it doesn't matter if a user installs one of the "Rollup" attempts or a 3rd party program that installs a flawed OCX. It also helps protect your applications from other applications packaged using the evil "InnoSetup" which often doesn't manage ActiveX registration properly and thus can break other applications through DLL Hell.

Just say "No! No!" to "Inno!"

To use reg-free COM additional tools are needed. Use MMM if you can find it anymore (the author's web hosting went away). Or consider the commercial Side-By-Side Manifest Maker.
 
BTW:

The one from April 2012 (VB60SP6-KB2641426-x86-ENU.msi) seems to still do everything my test program uses, plus:

Code:
MsgBox dbgrdData.Columns.Item("Last Name").Value

... is working fine.

This one reports its version (.AboutBox method) as: [tt]5.01.9813[/tt]

I have not retested the other OCXs in the package though.

As far as I can tell this is the one available at Microsoft Visual Basic 6.0 Service Pack 6 Security Rollup Update.

And you still would need to use Reg-Free COM/SxS Assembly Isolation to deploy and use this version reliably.


But all of that said...

This seems to be the same version that is giving you fits.
 


Thank you for your response, dilettante!

I use Advanced Installer.
It has an option - which I have never used or tested - "Components Isolated with this component". (see attached)

I guess this is what you mean.

I do get the errors on the same version you mentioned.

I need to make a correction with what I reported.
There are three different errors, and they do not happen on all underlying tables, which a grid's datasource ist based on. And, a table in another database with the same structure works fine.

1. Error 3265: It wasn't DBGrid1.Columns.Item("SomeField").Value, but instead DBGrid1.Columns.Item("SomeField").Caption
Sorry about that.
This error only happens sometimes.

2. Another problem, is that DBGrid1.Columns.Item("SomeField").Value will return an error "Column not found"

3. Yet, another problem, is some lists will show empty field values in all the rows - if there are less than 10 rows!

4. Still yet another problem is some lists will return a truncated DataField value (only the first 3 letters)



With some databases, this may happen on the same tables, or may happen on different tables.

Now, my first thought - and probably yours also - will be that something is wrong with the table structure, or the data, or how the code is written.
This isn't the case.

As I stated, none of these problems have ever happend with the older Ocx version.


I only use the DataControl as a data source object for the grid (no properties or connections set on the control). But the recordsets are created separately using the same connection/database object, and then are asigned to the DataControl's Recordset property.
I use DAO 3.6 but the databases are in Jet 3.5 format. I also tried it in Jet 4 format.
I compacted the db using the Access compact method, and the JetComp.exe from MS.
I removed all fields but one, removed all indexes and contraints, etc.
Nothing helps.

I'll put together a project and load it up.
 
 http://files.engineering.com/getfile.aspx?folder=2f81fa1b-cd09-47a8-908c-bfd5f65332a4&file=AI_Snippet.JPG
Here is the sample project. Please test it just to see if the problem also happens for you.

There are two buttons which will set the grid to different tables.

With tblTest2, there are 10 records. If one more record is removed, then the grid will 9 empty rows.
Clicking on the buttons below the grid crashes on the same error.

Of the 4 errors mentioned in the previous post, only number 2 and 3 are shown in the sample.

So, apparently there is something very strange happening here.

Using the older Ocx, everything here works as expected.

But, instead of trying to figure what and why, I will try to use the isolation function.
 
 http://files.engineering.com/getfile.aspx?folder=813834af-1ecb-462c-a8ba-12c6f70430f6&file=TestDBG.zip

Oh, and if one record is removed from tblTest2, then not only it shows blank rows, but also it also crashes like tblTest1 when the buttons below the grid are clicked.
 
Sorry, I didn't mean to suggest that version 5.01.9813/5.1.98.13 isn't buggy. I just didn't trip over a bug when I tried a simple test.

One issue you're going to have is that almost nobody uses DAO, and thus those hoary old DAO controls like DBGrid left over from early VB though deprecated in 1998 when VB6 came out. So you won't find many people to help with this. The only example I have on hand myself only uses the DBGrid because it can be used "unbound" unlike the modern DataGrid. Even then it isn't very useful, so as I said I have just the one demo and no real applications.

So to make a long story short I don't doubt you've hit an issue or two.


I tried to figure out your "Advanced Installer" though the documentation is quite the wumpus hunt. It is pretty reticent about the topic, probably expecting users to be blind appliance operators slapping at brightly colored buttons of their pachinko-like product. The way it covers other topics suggests this too.

What little it does say on the subject suggests that it might do what's needed here. However it also says something scary:

When creating an install package you can specify if the installer should copy some files used by a certain application, in the application's folder rather than in a shared location.

If it really does do that it is dangerous to use with VB6 programs.

When VB6 uses an isolated assembly you never want them deployed to the application's folder. It is only safe to deploy them to a subfolder within the application's folder or some entirely different folder like one under [tt]Programs\Common Files[/tt].

Failing to do this can result in your program causing more DLL Hell when it is run, since it could end up registering such components where they were deployed as isolated. This is a bad thing and you risk breaking other applications on the machine. You have no control over it, this is something the VB6 runtime will "do for you" when it finds a compent library in the app folder - and it hazardous that it's a crime those "Advanced" guys don't spell it out in huge blinking red letters.

Hopefully this "Advanced" installer gives you the option of choosing a deployment target aside from the application's folder. However it is very scary to think it defaults there. That makes it almost as dangerous as "No-No-Setup" can be.
 

Advanced Installer isn't doing it's "own thing" here, but uses the MSI guidelines, and builds the MSI package based on that.
I have tried PDW, Wise Installer for Windows Installer, InnoSetup, VS Studio, among several others, (though it has been years since) and have found AI (professional or architech) to best suitable for MSI package creation. Along side the fact that AI has a less expensive maintenance plan for our small company.

Everything can be done with AI which is based on the MSI setup guideline requirements, and much more. If someone doesn't agree with those MSI guidelines, that is a different thing.
I have been using it for about 8 years and have had very little problem installing our huge program (and what problems there have been, they have responded with a soulution within two days, or an update within a relative short time).

Advanced Installer says that - about copying the isolated file to the application folder - because that is just what the IsolatedComponents action in MSI says:
On the MSDN site: MSDN: IsolateComponents Action
The installer installs the files of Component_Shared into the same directory as Component_Application.

But, it simply doesn't just do that. AI doesn't get into the depth of what it does, because it uses the MSI guidelines when building the MSI, and any one who is interested can look at those specific guidelines on the MSDN site.

This is what I now found about the MSI IsolatedComponents action, and what I have see, AI does just that:
And, here is what MSI does Installation of Isolated Components
and why: IsolatedComponents
I haven't done any thing with IsolatedComponents yet, and was concerned if this at all is the right thing to do here, or if there was a different solution to the problem.

Anyways, I really appreciate all the time you have taken here for this.
And I am still looking for the dangers you have mentioned on the MSDN site and will heed your warnings.
I will also check into that Side-BY-Side Manifest Maker. Thanks for the tip.

 
Ok, I was able to check the actual Installer documentation and it makes it very clear this won't help you at all.

Isolated Components

Because the current implementation of COM keeps a single full path in the registry for each CLSID/Context pair, it forces all applications to use the same version of a shared DLL. To enable an application to keep a private copy of a COM server, the system loader in Windows 2000 checks for the presence of a .LOCAL file in the application's folder. If the system loader detects a .LOCAL file, it alters its search logic to prefer DLLs located in the same folder as the application.

There are other requirements for .LOCAL DLL/COM Redirection not spelled out there, and those prevent the mechansim from working unless a component library was written to observe them. The biggest issue is the logic used in self-registration entrypoints which must accomodate .LOCAL scenarios by not trying to register within the HKLM registry hive.

.LOCAL "isolation" is an obsolete approach that never applied to components shipped with VB6 or those created in VB6 (ActiveX Project types). It is actually dangerous to use with VB6 because everything involved there forces HKLM registration.

.LOCAL was replaced by Side-By-Side Isolation due to its limitations and only remains in Windows for legacy compatibility.

You will need another tool to create the required .manifest files or embedded manifest resources. A conventional packaging tool generally doesn't do this, though I'm sure there could be exceptions. However even then they probably only create manifests for newly created components and not things like the OCXs that ship with VB6.
 
I'd be tempted to use SxS as recommended by dilettante. A manifest maker, I like MMM although it's no longer available for download, will likely give you a manifest file contents something like this;

Code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <!-- Make My Manifest 0.9.305 -->
  <assemblyIdentity name="My.Soft.Computer.Software.Project1" processorArchitecture="X86" type="win32" version="1.0.0.0" />
  
  <file name="DEP\DBGRID32.OCX">
    <typelib tlbid="{00028C01-0000-0000-0000-000000000046}" version="1.0" flags="control" helpdir="" />
    <comClass clsid="{00028C00-0000-0000-0000-000000000046}" tlbid="{00028C01-0000-0000-0000-000000000046}" progid="MSDBGrid.DBGrid" description="The main grid object" />
  </file>
</assembly>

for a project1.exe/.vbf file pair including DBGRID32.OCX 5.1.81.4.

Copy the code above into a text file called YOUREXENAME.exe.manifest and put it next to your YOUREXENAME.exe
Place a copy of the DBGRID32.OCX 5.1.81.4 into a sub folder called DEP in the folder containing the exe and the manifest file.

The exe will now use the copy of DBGRID32.OCX 5.1.81.4 in the DEP folder rather than a registered one elsewhere, if one exists at all.
Seems to work here, Process Explorer seems to agree; but I have no DBGrid based code to test it with.
 
I just hope the improved 0.13 I'm helping to alpha test gets released someday. But when a guy has moved to Android development it is hard to get him excited about old VB6 code.
 
Hi HughLerwill,

It worked just fine.
Thank you!
 
Good, and now you know where to get MMM you may have the whole app running from a memory stick by the end of the week!
 
Correct me it sounds too simple but if, when you recomplile, you put your old OCX in the same folder path that will contain your .exe.
Then in components, change the source of that OCX (with Browse) to that folder, I would have though your re-complied app would use that version rather than the one in System32.
This happens if you don't have a copy in System32 at all but I'm not sure what happens if you have it in both.
You might even give it a different name? (DBGrid32OLD.ocx)and regsvr and change the source in the Components dialog before recompiling.
 
>You might even give it a different name? (DBGrid32OLD.ocx)and regsvr
diletantte will already have an answer on file for you but here's my attempt at one
Consider that when you register an OCX you are not registering the file name (although of course that is saved and associated in the registry); you are primarily registering the names of the objects within it (ref. progid="MSDBGrid.DBGrid" in the manifest above); when your code uses the 'progid' the registry looks for it, finds it, loads the file associated with it and executes the call. The registry though can only store unique 'progid's so an OCX containing a given 'progid' ,or set of them, can only be effectively registered once with a single file association. Of course it can be physically registered more than once but only the last registration will prevail (if successful).
 
Strange.

I tested several times by de-registering the older ocx and replacing it with the newer one and registering that one (all using Admin rights).

1. On my W7 dev machine (the application isn't installed there through an Installer program) all works using the manifest, no matter where the application is located (with in C\Program Files (x86)\ or outside of a protected folder . After removing the manifest, then the errors happen.

2. On a VM XP, where the Program is installed with Windows Installer, it also works with no problem. Remove the manifest, then the errors happen.

3. On a work colleague's machine with W7, when the application is installed with Windows Installer and started directly from the \Program Files (x86) MyApplication\ folder (with and without Admin rights), the erros still happen. (also, no Application Compatibility Flags are set).

I remotely checked everything, and did all copying and registering again, but the same problem.

However, when he copies the Application exe, manifest, and DEP folder containig the older OCX into a different, from non-protected folder such as C:\MyApp\, it works.

Any ideas what could be causing this?
 
Don't think I can suggest much but ...
>.. the errors ...
I guess you mean the errors consistent with use of the unwanted version of DBGrid32.OCX, but have you actually verified the version of DBGrid32.OCX being used in each case using Process Explorer when the app is running, or by using a call to DBGrid's AboutBox method in your code.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top