Google Answers Logo
View Question
 
Q: Using a .net COM dll from VBA across a network ( No Answer,   4 Comments )
Question  
Subject: Using a .net COM dll from VBA across a network
Category: Computers > Programming
Asked by: plucktick-ga
List Price: $100.00
Posted: 29 Mar 2006 08:42 PST
Expires: 02 Apr 2006 09:16 PDT
Question ID: 713180
We currently have a product which happily runs across a network by
having various COM dlls installed on a shared network folder and
various client pcs use these dlls via an VB6 exe and also Excel
(2000/XP/2003) VBA.  We don't have to install anything on the client
pcs apart from having to register the COM dlls (via regsvr32
"//server/sharedfolder/COMDll.dll") so that Excel (which runs locally
on each client pc) knows where to find them (i.e. on the shared
network folder).

We now want to start using .net dlls (exposed for COM via the "Make
assembly COM visible" checkbox) for any new code. My question is,
after installing the .net dlls on the server in the shared network
folder (//server/sharedfolder/), how can we most easily make them
available to client pcs?

My understanding is that we need registry entries to be added on each
client pc for each ClassID, ProgIDs etc exposed by the .net COM dll,
the assembly location etc.  This is one of the things that a setup
program would do if we installed our application locally on each
client pc.  But the whole
point of the network installation is that we don't want to have to
install the dlls locally on each pc.

I've already tried using regasm
"//serverpath/sharedfolder/DotNetCOM.dll" /codebase instead of
regsvr32 to register the .net COM dlls on the client pcs.  In fact
what I have done more precisely is to use regasm
"//serverpath/sharedfolder/DotNetCOM.dll" /codebase
/regfile:"file.reg" to create a .reg file (file.reg) which can be run
on each client pc.  This is probably better because otherwise problems
will arise if the version of regasm on the client pcs is different
from that on the server.

However: after testing this across the network using Excel 2003
VBA, I get an error message "Error 430: class does not support
Automation or does not support expected interface" the first time I
instantiate an object in VBA:

Dim obj as MyClass

set obj = New MyClass ' error 430 occurs here when the dll is across
network (but - see below - code works fine if dll is local)

Interestingly the error 430 disappears and VBA interacts happily with
the dll (I can call its methods etc.) if DotNetCOM.dll is moved to be
local to that pc (e.g. C:\localfolder\DotNetCOM.dll) and regasm rerun
(or the file.reg altered so that the path is changed to the local one,
or simplest of all, simply changing the codebase key value in the
registry to point to C:\localfolder\DotNetCOM.dll rather than
//serverpath/sharedfolder/DotNetCOM.dll).

Further information: I posted this question 3 days ago on an MSDN
forum (see http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=317267&SiteID=1),
but so far it doesn't look as if I'm going to get an answer from
there, and this is an important issue to us, hence am posting it here.
 At the moment the DotNetCOM.dll assembly is not signed, and has not
been put into the GAC (Global Assembly Cache).  This is because this
is not necessary as shown by the fact that calling DotNetCOM.dll from
VBA works fine with DotNetCOM.dll manually installed to local folder
C:\localfolder\DotNetCOM.dll as shown above.  DotNetCOM.dll is a
Visual Studio 2005 C# dll which I created to test this (working across
the network) issue, with a very simple interface, with one method, Add
which adds two doubles together.  I also know that the client machine
I am testing on has the .net 2 framework runtime expected by
DotNetCOM.dll, mscoree.dll version 2.0.50727.  (I realise that if the
client pc only had an earlier version of the .net framework, then as
well as creating the registry entries via file.reg, I would also need
to install the newer version of the .net framework, but that is
obviously not contributing to the problem here since a) the .net
version on the client pc is up to date, and b) the dll works fine when
placed locally).  The fact that the dll works locally presumably means
that the fact that so far I am not using a shim, i.e. the
InProcServer32 default key value is mscoree.dll, is not an issue
either. Another point is that marshalling, multi threading, cross
processes should not be an issue here, since the dll is an extremely
simple one (it is not an exe), and should simply be running inside
Excel.exe's process.  I had always thought that to Windows, a shared
network folder is simply another drive, so I can't understand at the
moment why my simple dll works locally, but not when moved to the
shared network folder?

Clarification of Question by plucktick-ga on 02 Apr 2006 01:24 PST
Given that I am no nearer a solution after 4 days, in spite of having
spent a lot of time on this myself, I am increasing the price of the
question from $50 to $100, and expanding its scope to answer what I
think is a related subquestion:

How (with ease of deployment and maintenance, updating etc. in mind)
is a pure managed (i.e. not exposed to COM) component supposed to be
deployed for use across a network?  Is there a better alternative to
putting a copy of the component in each client pc's GAC (Global
Assembly Cache)?
At the moment, I think that the person or persons who know about this
subquestion will probably help shed light on my original (.net COM
component) question.

Clarification of Question by plucktick-ga on 02 Apr 2006 09:15 PDT
After a lot of reading and experimentation, I've found the answers to
my own question!

jiangsheng-ga: Thanks for being the only person to comment on this. 
If you want to how I solved my problem,, contact me ( p dot j dot  
lee at btconnect dot com) and I will let you know!  Regards
Answer  
There is no answer at this time.

Comments  
Subject: Re: Using a .net COM dll from VBA across a network
From: jiangsheng-ga on 29 Mar 2006 14:19 PST
 
If your project is not signed, sign it anyway. 
Reference
http://blog.danbartels.com/archive/2004/09/07/180.aspx
http://www.codeproject.com/vb/net/MusaExposingCOM.asp
http://msdn2.microsoft.com/en-us/library/xwb8f617(VS.80).aspx
Subject: Re: Using a .net COM dll from VBA across a network
From: plucktick-ga on 30 Mar 2006 06:37 PST
 
jiangsheng-ga:
Thanks for the comment, but unless you're saying that the reason that
the dll works locally but not across the network is that it is not
signed, then I don't think this helps? I'm trying to keep things as
simple as possible, and while we may well end up signing the dlls, I
want to understand why the unsigned dll works locally but not across
the network, even though there are no complex marshalling or other
cross process issues involved.
Subject: Re: Using a .net COM dll from VBA across a network
From: jiangsheng-ga on 30 Mar 2006 19:30 PST
 
I don't have .net 2.0, so I can not reproduce your problem. But I
remember strong name is suggested when exposing COM interface from
managed assembly.

from http://www.codeproject.com/vb/net/MusaExposingCOM.asp

"It is important to note that you can avoid strong naming your
assembly. however, I would advise you against it. If you do not want
to use the strong name, then keep your component and the calling
client in the same directory."

You can also use filemon
(http://www.sysinternals.com/Utilities/Filemon.html) to look for error
message such as "access denied".
Subject: Re: Using a .net COM dll from VBA across a network
From: plucktick-ga on 02 Apr 2006 01:18 PST
 
jiangsheng-ga: thanks for the further comment.  I have carried out a
further experiment in which I have signed the project (more precisely
I have turned it into a strongly named assembly) but the same problem
occurs.   I've also set the ClassInterface type attribute to none for
the class exposed by my C# project (see
http://msdn2.microsoft.com/en-us/library/ms182205(VS.80).aspx):

// START of my code Class1.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices; // added by hand PJL so that can
set ClassInterface below, also needed to use Guids

namespace TestCSharpFromVBA3
{
    [Guid("654426BF-CE5F-4ec5-9017-960CEC88928E")] // added (although
not sure whether strictly necessary)
    public interface IForClass1 
    {
        double DoubleIt(double d1);
    }

    // added this setting of ClassInterface as recommended to prevent
COM from creating a hidden _Class1 interface which can confuse VBA and
other COM clients
    // (it is also unstable if this .net project is modified which can
also break COM clients through unintended reliance on a hidden and
changing interface)
    [ClassInterface(ClassInterfaceType.None)]
    [Guid("0EB3FF9B-4336-4175-8990-07C7330BAD9A")] // added (although
not sure whether strictly necessary because regasm seems to create a
guid if one isn't specified)
    public class Class1 : IForClass1
    {
        public Class1() // added because apparently classes should
have a public default constructor if they are going to be used by COM
clients
        { }
        
        public double DoubleIt(double d1)
        {
            return 2 * d1;
        }

    }
}
// END of my code Class1.cs

However, none of this helps, I get exactly the same problem as before
("Error 430: class does not support Automation or does not support
expected interface" when I try to instantiate an object, i.e. Set obj
= New Class1).

I know that VBA is finding the dll across the network ok, because if I
change the codebase key in the registry
(HKEY_CLASSES_ROOT\CLSID\{0EB3FF9B-4336-4175-8990-07C7330BAD9A}\InprocServer32\1.0.0.0
from "file://serverpath/sharedfolder/DotNetCOM.dll" to
"file://serverpath/sharedfolder/DotNetCOM(renamed).dll" (i.e. a file
which doesn't exist) I get "The system cannot find the file specified"
as error message, which disappears when I correct the codebase key
back to "file://serverpath/sharedfolder/DotNetCOM.dll".  So I'm not
sure that filemon will help here.

It looks instead as if VBA or mscoree.dll does something funny in
interpreting the type library when the dll is on another pc (perhaps
it regards the dll as being loaded from the intranet or internet with
some different behaviour?).  After all the error messsage I get says
"class does not support Automation or does not support expected
interface" : it seems more likely to me that VBA thinks the former
(Automation not supported) than the latter, because obj is already a
Class1??
(One thing I haven't tried yet is using
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] and setting
[DispId(1)] etc. as in http://www.codeproject.com/dotnet/nettocom.asp,
this might just help make VBA realise that Automation is supported!)

By the way, exactly the same problem occurs with Visual Studio 2003,
so you don't have to have .net 2.0 to reproduce the problem.

I'm beginning to wonder whether Microsoft have deliberately designed
things in .net so that shared components (whether pure managed or .net
COM) have to be installed on each pc (e.g. in the Global Assembly
Cache).  If so, this is a big and unadvertised change from the COM
world, and seems to make deploying applications across a network more
troublesome!

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy