COMInterop - System cannot find file - IDE only - com

I've an old VB6 program which I have haven't used for several months. The program references numerous C# assemblies (.NetFramework 4.8). Running the programs as binaries, it all works fine.
I have opened the VB6 ide to step some of my code and I am now encountering an automation error "The system cannot find the file specified." (Err 80070002) when trying to instantiate one of the COM Interop classes. This didn't used to happen.
Private Sub InitMessageStore()
Dim l_oBusFactory As IfxBusService.BusFactory <= COM Interop reference
Set l_oBusFactory = New IfxBusService.BusFactory <= ERROR here
l_oBusFactory.InitialiseMessageStore GetConnection(m_oIfxsys.Dbase.Database.Definition)
End Sub
The COM Interop decls
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof(IBusFactory))]
[Guid("200C6C26-6881-4CB5-A8E7-E0E5532D6D5F")]
public class BusFactory : IBusFactory
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[Guid("5531BD20-2C7B-452B-A7D7-2D05E39EB83E")]
public interface IBusFactory
I have rechecked the registry registrations for the above ... the salient one being
and the file is in the folder location as specified in the registry.
I'm using Win10 Version 10.0.19044 Build 19044. I'm running everything as administrator. I have DEP switched to essential Windows programs and services only.
As I said above, everything works fine when run as binaries, but, to me, it looks like the OS is stopping the VB6 ide from loading a COM Interop assembly.
Any suggestions as to how I can get stepping through (but not necessarily into) my COM Interop code working again.

In the end, I missed that there were 2 entries under the InprocServer32, one of which pointed to the correct file (1.0.0.0), but the other one (5.80.0.111 - which is actually the version no of our com binaries) didn't point to a file:///, but rather the pure .net assembly. Once I deleted the incorrect one, it all started working ok.
Still not sure where the wrong one came from!

Related

Why does Imports System not give access to Windows namespace in vbc.exe?

I manage an application that allows the users to automate tasks by writing their own VB code. The user code is compiled using the VBCodeProvider and invoked against the running instance of the application. We've been doing this for a few years now starting with .NET 2.
Traditionally, we have imported the System namespace in the compiler settings so users wouldn't have to write System. all the time. When we went to .NET 4, however, we found that statements like Windows.Forms.Form wouldn't compile anymore. The error was "Type 'Windows.Forms.Form' is not defined." This is odd because other namespaces work. IO.Stream and Reflection.Assembly do not have an error without the System at the beginning.
I've created a simple example. I've put the below code into a file. Then I compiled this file with vbc.exe from both the .NET2 and .NET4 directories. The 2 version works fine. The 4 version will not compile unless you comment out the variable f2.
Imports System
Public Class MyClassName
Public Shared Sub Main
'this works in v2 and v4
Dim f As New System.Windows.Forms.Form
f.ShowDialog
'this does not work in v4
Dim f2 As New Windows.Forms.Form
f2.ShowDialog
End Sub
End Class
Does anyone know how to get this to compile in vbc.exe version 4? And before you say "Just tell the users to type System.Windows.Forms" I will agree that it would be great if they would do that, but users do what users do and I have to work it out.
UPDATE:
I've found that the Windows.Foundation.Diagnostics namespace is causing a collision with the abbreviated use of Window.Forms. Is there any way to hide this namespace from my compilation? Visual Studio 2010 does not have the same conflict, so it must be getting around it somehow.

Runtime error 429 in VBA, but class is registered

I'm trying to recreate a program that uses javascript to open a connection to a PLC and then display all sorts of information on a web page. I'd rather have it in a form in MS Access for various reasons, and have spent forever trying to find the right dll to use (Jet32X.dll, if anyone is curious). I finally tracked the CLSID called out in the javascript back to a registered class for the PLC, and I'm trying to create that object in VB code. It won't get any further than the Dim As New line, however, throwing runtime error 429: "Active X Component Cannot Create Object." Really wish I had some more information about why.
I know the class is registered, since that's how I found it in the first place. I know the DLL file isn't corrupted, since the program runs fine from the JS version. I have a sneaky suspicion that there's some sort of incompatibility going on here, since the PLC and supporting software is pretty old, and I'm working in Microsoft Access 2013 (and its associated VBA). I can't really think of a good way to verify this, however. Does anyone have any other ideas? Could anything else be causing this problem?
Figured it out; in case anyone else runs into this sort of issue:
32bit COM dlls will not run in 64bit applications. If you don't want to go back and reinstall 32bit versions of whichever application you're using, one of the easiest workarounds is using dllhost.exe as a surrogate.
You can read a little about it here, but I found this tutorial easier to follow.
I send a new reply just to recap the information and avoid anyone that stumbles in the same problem again after me wasting precious time. All the steps involved assume that you already correctly registered the dll you are trying to use.
How to make a 32bit COM Dll work in a 64bit application
The "easy" solutions involve using the Dll Surrogate method, which runs dllhost.exe and as an intermediary process in 64bit to expose the underlying 32bit dll. When done correctly this works seamlessly without any special measure needing to be taken in neither in the 32bit dll nor in the 64bit application.
There are two main approaches to this:
Using Oleview.exe (i.e. using a GUI)
Oleview can be obtained downloading the Window 10 SDK.
In order to use Oleview it you have to:
Download the Window 10 SDK at the following link:
https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/
Go to C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x86 to find the 32bit version of oleview.exe
ONLY THE FIRST TIME: run it as administrator to avoid see the message related to the impossibility to load iviewer.dll
In the left pane, Object Classes -> All Objects and find your dll name.
WARNING: you may find many entries for your dll. In particular each class has got its own entry such as YourProjectName.YourClassName
In the right pane, go to Implementation -> Inproc Server, and tick Use Surrogate Process. Leave the Path to Custom Surrogate empty to use the system default surrogate, that is dllhost.exe.
You can check the procedure went correctly by returning to the Registry tab, always in the right pane of the Oleviewer and make sure that now under CLSID = {yourAppIdHere} [DllSurrogate] = is listed among the entries.
Edit manually the Windows Registry
The Oleview method is recommended, but the manual method may be ok if you need to do this only once. The tutorial that NickGlowsinDark mentions was moved to https://techtalk.gfi.com/32bit-object-64bit-environment/ .
In order to avoid problems in the future with the page going offline I copy and paste here the most important steps involved. All credit goes to Emmanuel Carabott that is the original author of the tutorial, I added the first two steps in order to facilitate you in the process.
Open the Registry Editor (Windows+R -> regedit), and follow the following steps:
You first need to find your dll GUIDs. You will probably have many GUIDs, one for each of the classes that your dll exports. I find it's easier to find the GUIDs if you go to HKEY_CLASSES_ROOT\YourProjectName.YouClassName. It is the (Default) String Value you find under the Clsid key.
I recommend you find all the GUIDs first and make a note of them in order to have an easier time with the steps after this one.
Then, as Emmanuel Carabott kindly explains in his article, you have to do the following for each of the GUIDs you found:
Locate your COM object GUID under the HKey_Classes_Root\Wow6432Node\CLSID\[GUID]
Once located add a new REG_SZ (string) Value. Name should be AppID and data should be the same COM object GUID you have just searched for.
Add a new key under HKey_Classes_Root\Wow6432Node\AppID\
The new key should be called the same as the com object GUID
Under the new key you just added, add a new REG_SZ (string) Value, and call it DllSurrogate. Leave the value empty.
Create a new Key under HKey_Local_Machine\Software\Classes\AppID\
Again the new key should be called the same as the COM object’s GUID. No values are necessary to be added under this key.
That’s it, your COM Object should now be accessible from a 64bit environment and can be used like a regular COM Object.

Interop Error 430 Class Does Not Support Automation

I have a VB.NET assembly that I have registered for Interop. I am using a class in this assembly in my VB6 projects.
In an existing VB6 project I added a reference to the type library and run the following code:
Dim vizDataSingleton As Vizual_Data.Singleton
Set vizDataSingleton = New Vizual_Data.Singleton
The second line errors "Run-time error 430: Class does not support Automation or does not support expected interface"
However if I start a blank VB6 project and add the reference, the exact same code works fine.
I checked the reference to the tlb in the vbp file and they are both identical.
Reference=*\G{BDB20DDF-D3B7-4484-8950-35D67DED45EC}#4.2#0#..\Vizual.Data\Vizual.Data\bin\Debug\Vizual.Data.tlb#VMS Data Structure Library
I tried using late binding as well:
Set vizDataSingleton = CreateObject("Vizual.Data.Singleton")
This errors in the existing project with "Type mismatch" but again works in the new project
Any ideas why this fails in one project but works in another?
I found the cause of this error in the end.
I had another .NET Interop assembly (Vizual_Lib) that was dependant on the original .NET assembly (Vizual_Data).
In the VB6 application that failed it was referencing both of these, but my new application only referenced Vizual_Data. Recompiling Vizual_Lib solved the issue.
This was a strange error was the failure happened when using the Vizual_Data class not the other Vizual_Lib class.

vb.net compile error 'abc' is ambiguous in the namespace 'xyz'

I have a VB.Net solution that another developer created and I'm trying to compile it on our build machine (it compiles on their machine) but with one of the projects I get an error saying something along the lines of:
Imyinterface is ambiguous in the namespace anamespaceassembly.
I have tried with no success:
examined the references to see any obvious errors
removed and re-added the assembly in question
searched the system for the same dll
attempted to compile the original deve's src (.v the source control version)
examined the assembly with ildasm.exe
I usually code in C# and have not seen this error before (in this form at least), not that it is VB.Net specific but the UI for adding/viewing references is slightly different so I thought maybe VB.Net might do something different with references.
I also tried to compile on another machine, and it compiles ok. So I assume it is something with the build machine but I'm not sure what. Other conflicting assemblies somehow not referenced by the project, is that possible??
Any ideas?
Check your references if you have two versions of the same reference (eg. Microsoft.ReportViewer.Webforms version 10.0.0.0 and Microsoft.ReportViewer.Webforms 8.0.0.0) You will get this error. Delete the oldest and you should be good. I do this to myself all of the time.
There can be a few causes for this error. In VB, you should be aware that more names then you're used to from C# are available without class specification. Also, case does not matter in VB, which can further liken the chances on collisions.
Even in the event that you don't find the actual conflicting issue, you can resolve this in the same way you would in C#: rename it in the Imports statement:
Imports IM = yourAssembly.Imyinterface
Then change the code such that uses of Imyinterface are replace with IM.
NOTE: If the error does not point to a particular line, the conflict may be out of your hand. Normally, a full Clean Solution and Rebuild helps a lot, but occasionally a misbehaving file (i.e., another error) causes this error to popup first without clear source. Try to rollback recent changes to the place where it did work.
You also say it worked on another machine. Chances are that your machine is having a different version of MS Visual Studio or .NET. Check and compare the exact versions.
I was facing same issue. I upgraded my application from vb6 to vb.net and when i change the build configuration from DEBUG to RELEASE then i got AMBIGUOUS errors.
I found dulicate references folder in solution Explorer. I removed those duplicate referecnces and Build sucessfully. I Hope it may help others.
Thanks for the responses! I tried each but still was having issues.
One point of info I left out of the original question was that the VB.net projects are upgrades from VB6 projects. At the time I did not think that was relevant.
After investigating further the build machine was used to build the VB6 projects also. So I ran 'reg32 /u' on the vb6 dlls and that seemed to fix the VB.net issue.
Not exactly sure why this fixed it since I was not referencing the VB6 dlls, I'm guessing something to do with ambiguous entries in the registry confusing the vb.net project.

"System.IO.FileNotFoundException: Could not load file or assembly" when the assembly does in fact exist

As part of our migration from .net 1.1 to .net 3.5, we had to change out a few vender DLLs.
One of them is giving us trouble in only 1 spot out of the 4 spots we use it at:
The trouble spot is a windows form project that uses reflection to dynamically load some DLLs that run long running processes. One of these long running processes is an agent that relies on one of our vender DLLs
We're getting the missing assembly exception at the point where we first enter a function that references the library. I already checked the silly things such as if we had forgotten to move a reference from the old version to the new version, but that's not the case. I also checked the bin directory of the project and the assembly is there.
Has anyone encountered a situation in which .net 2.0 runtime refuses to load an assembly like that? And if so, how could we fix the issue.
Additional Information:
The specific vendor in this case is dtSearch and this is the boundry where the error gets thrown:
Private Sub BuildIndex()
SetIndexOptions()
ExecuteIndexJob()
End Sub
Private Sub SetIndexOptions()
'Body removed for brevity
End Sub
The library is referenced in SetIndexOptions. BuildIndex() gets entered, but the exception happens when SetIndexOptions gets called. The function is never actually entered.
If you are still having problems you can use the Assembly Binding Log Viewer (Fuslogvw.exe) to identify which assemblies are loaded by your application. This tool is part of the .NET Framework. This will provide you with details on all dependent assemblies.
I have used this in the past when working with third party assemblies, very usefull
The FileNotFoundException can be raised even when the assembly does exist if one of the dependent assemblies couldn't be loaded.
Try using Dependency Walker to check and see that all dependent assemblies are also present.
Turns out the default compile option changed from VS2003 to VS2008 and it was compiling in the wrong bitness :\ Now I feel a bit silly!