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.
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!
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
CompileBeforeParsesetting is to enforce a registry write to theCompile On Demandsetting as well a check on the startup.