Rubberduck: CompileProject not working properly if 'Compile On Demand' is set

Created on 1 Mar 2018  路  9Comments  路  Source: rubberduck-vba/Rubberduck

So I couldn't stay away, as I found an issue with the TypeLib API...

The new CompileProject feature of the TypeLib API has an interesting quirk when 'Compile On Demand' is set inside the VBE options.

When 'Compile On Demand' is ON (the default), our CompileProject call seemingly only does a minimal compilation, meaning that procedure level source code is not compiled until the procedure is actually called into at runtime. Seemingly, only code outside of procedures (e.g. member declarations and such) are being actually checked for compilation errors when this option is on. As an example, the code below would not fail the CompileProject check when 'Compile On Demand' is ON, even if BlahBlahBlah is not defined:

Option Explicit Public Sub Foo() BlahBlahBlah End Sub

If you turn off 'Compile On Demand' then all is well, and our CompileProject test works as expected.

Slightly more concerning is that even though this is bad code, after calling CompileProject the 'Compile' option in the VBE Debug menu is then greyed out... as if a full compilation did occur.

We need to somehow enforce the 'Compile On Demand' option to OFF, at least whilst we call CompileProject.

bug

Most helpful comment

I did a quick look, and as expected that setting isn't exposed via the VBIDE API.

Google says that it's a registry settings, which implies to me that it may be only read once at the startup, or at most, be periodically read, either which means we can't just do a registry lookup/write as part of running the procedure.

If there are no other programmatic means of getting VBE to modify its behavior, then the best option is that at the time of setting the CompileBeforeParse setting is to enforce a registry write to the Compile On Demand setting as well a check on the startup.

All 9 comments

I did a quick look, and as expected that setting isn't exposed via the VBIDE API.

Google says that it's a registry settings, which implies to me that it may be only read once at the startup, or at most, be periodically read, either which means we can't just do a registry lookup/write as part of running the procedure.

If there are no other programmatic means of getting VBE to modify its behavior, then the best option is that at the time of setting the CompileBeforeParse setting is to enforce a registry write to the Compile On Demand setting as well a check on the startup.

I think I know where the internal API for this setting is. I'll have a look to see if I can get you access to it easily. If not, checking the registry at those points seems a sensible solution.

At this stage, it looks to be a no go.

So I need some suggestion on what would be the best way to determine the correct registry path.

It could be either:

HKEY_CURRENT_USER\Software\Microsoft\VBA\7.0\Common

or

HKEY_CURRENT_USER\Software\Microsoft\VBA\6.0\Common

In the PR #3798, we can determine the DLL version by trying to load them, preferring the newest version before the older version. However, it is also possible to have both installed in which case, I have to match the actual version.

I can find out the version by using VBE.Version, which may return 7.00 (and presumably 6.00 for older Office versions). What does throw me off a bit is that there's also a 7.1 version with its own VBE7.dll in this path:

C:\Program Files (x86)\Common Files\microsoft shared\VBA\VBA7.1\VBE7.dll

In my Office 2010 installation, I have this loaded (note not the 7.1):

C:\Program Files (x86)\Common Files\microsoft shared\VBA\VBA7\VBE7.dll

So I am not sure if loading 7.1 will result in a 7.1 registry key being created. This currently does not exist in my registry but just because it doesn't exist, doesn't mean it won't exist when the 7.1 DLL is actually loaded.

Can anyone else provide suggestion to avoid ambiguity in this case or confirm that I'm worrying for nothing?

I'd keep it simple and set keys for both versions, since RD will run in both environments this keeps it consistent.

With regards to the registry entry, it is just the 6.0 and 7.0 entries, regardless of whether it is v6.5, v7.1 etc.

Hmm. I just noticed now that the AddIns path only exists under the VBE\6.0; there's no VBE\7.0. Hooray for Microsoft's consistency? 馃槅 I think you're right that checking both path is safer.

Thanks!

@WaynePhillipsEA I had a thought (a belated one!).... Right now the implementation simply does a compilation on the project level. However, the TypeLib APIs also provide a mean of compiling per component individually.

Could we find out if we were to do a basically foreach(var c in Components) { CompileComponent(c); }, would that offer us a full compilation irrespective of the Compile On Demand setting?

Unfortunately, the CompileComponent feature has the same quirk. I guess it might avoid the VBE Debug > Compile option from getting greyed out inappropriately though.

Bummer. I was hoping that a foreach of component-level component followed by a project-level compilation would have avoided that. But at least we know. Thanks for confirming!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

eteichm picture eteichm  路  4Comments

Gener4tor picture Gener4tor  路  3Comments

retailcoder picture retailcoder  路  3Comments

retailcoder picture retailcoder  路  3Comments

susnick picture susnick  路  3Comments