Two copies of a single DLL in a single process (Excel) - how to avoid?

Two copies of a single DLL in a single process (Excel) - how to avoid?

Post by Neil Mowbra » Tue, 26 Jan 1999 04:00:00



Hi Folks,

I have a process (Excel.exe) that seems to map a certain custom DLL into
memory twice.  What I need is a single copy, with a single set of data.  If
anyone can help with any of the following questions I would be most
grateful.

1.    What are the NT rules for loading multiple copies of the same DLL into
    the address space of a single process?

    I have played with multiple class to LoadLibrary() and it seems to force
    a single copy.

2.    What series of calls could cause the DLL be loaded twice?

Is possible (probably) that I'm missing the fundamental NT process/module
management knowledge.

My specific problem is:

I have a DLL which is both a COM inprocess server and an Excel C++ Addin
(xll).
I do this because I want to add VBA behaviour and Excel worksheet functions
to
a common set of data (that's in the DLL).  Excel loads the DLL twice, once
as a
COM server and once as a Excel Addin, but the result is two copies of the
DLL
in Excel's address space (and so no common data set).  In this case the DLL
is loaded by actions:

    1.    Excel's COM because of VBA dim new statement
    2.    By VBA code calling Application.RegisterXLL("full path of COM
server DLL")

I tried breaking the DLL into two, 1) a COM server 2) as Excel Addin DLL
with
is merely a stub for calls to the COM server DLL

    1.    Excel's COM because of VBA dim new statement
    2.    By VBA code calling Application.RegisterXLL("Stub DLL") which
            then goes no to load the COM DLL because it has a link time
dependency.

Thanks for any assistance, Neil


 
 
 

Two copies of a single DLL in a single process (Excel) - how to avoid?

Post by Neil Mowbra » Tue, 26 Jan 1999 04:00:00


I think I have found a work-around which is to have two stub DLLs which
load the common functional DLL, that is,

FooXlStub.dll            which is an Excel Addin
FooComStub.dll       which is an in process COM server

both of which load (via the NT loader)

FooActualGoodies.dll

The stubs just contain wrappers for each entry point of FooActualGoodies.

I still don't understand why the orginal single DLL approach didn't work or
if
the tri-DLL approach is robust, if someone knows I would appreciate learning
more.  My guess would be that one or both of the COM load or Excel
RegisterXLL
load mechanisms aren't using LoadLibrary() (if thats, possible ???).

Thanks for any assistance, Neil



 
 
 

Two copies of a single DLL in a single process (Excel) - how to avoid?

Post by Joe Delekt » Tue, 26 Jan 1999 04:00:00


    Greets Neil,

        If you are developing an Excel add-in which is used to create an
instance (and only one instance) of your COM object, then your best bet is
to create two components as you have started to do:  1)  The Excel add-in
.DLL which creates an instance of your COM object;  and 2)  An
out-of-process COM .EXE server that implements your interface.  In order to
make sure that only one instance of your object is launched when you create
a new instance of the object, then you need to make sure that your object
uses a singleton classfactory.  If you are using ATL to create this object,
adding DECLARE_CLASSFACTORY_SINGLETON() to the class definition should be
what you need.

Joe

---------------------------------------


>Hi Folks,

>I have a process (Excel.exe) that seems to map a certain custom DLL into
>memory twice.  What I need is a single copy, with a single set of data.  If
>anyone can help with any of the following questions I would be most
>grateful.

>1.    What are the NT rules for loading multiple copies of the same DLL
into
>    the address space of a single process?

>    I have played with multiple class to LoadLibrary() and it seems to
force
>    a single copy.

>2.    What series of calls could cause the DLL be loaded twice?

>Is possible (probably) that I'm missing the fundamental NT process/module
>management knowledge.

>My specific problem is:

>I have a DLL which is both a COM inprocess server and an Excel C++ Addin
>(xll).
>I do this because I want to add VBA behaviour and Excel worksheet functions
>to
>a common set of data (that's in the DLL).  Excel loads the DLL twice, once
>as a
>COM server and once as a Excel Addin, but the result is two copies of the
>DLL
>in Excel's address space (and so no common data set).  In this case the DLL
>is loaded by actions:

>    1.    Excel's COM because of VBA dim new statement
>    2.    By VBA code calling Application.RegisterXLL("full path of COM
>server DLL")

>I tried breaking the DLL into two, 1) a COM server 2) as Excel Addin DLL
>with
>is merely a stub for calls to the COM server DLL

>    1.    Excel's COM because of VBA dim new statement
>    2.    By VBA code calling Application.RegisterXLL("Stub DLL") which
>            then goes no to load the COM DLL because it has a link time
>dependency.

>Thanks for any assistance, Neil



 
 
 

Two copies of a single DLL in a single process (Excel) - how to avoid?

Post by Don Grasberg » Tue, 26 Jan 1999 04:00:00


The only possibility that comes to mind for actually loading a dll
twice would be if LoadLibary() were called with a full path to the dll
that differed in some way, either case, or by using different mappings
to the same network drive, or by using short vs. long filenames. In
this case LoadLibrary() might not recognize that it is the same DLL.

If COM is loading the dll and the registry contains entries that use
different strings for different COM objects in the same DLL, that
could be the problem.

On Mon, 25 Jan 1999 16:37:42 +0800, "Neil Mowbray"


>I think I have found a work-around which is to have two stub DLLs which
>load the common functional DLL, that is,

>FooXlStub.dll            which is an Excel Addin
>FooComStub.dll       which is an in process COM server

>both of which load (via the NT loader)

>FooActualGoodies.dll

>The stubs just contain wrappers for each entry point of FooActualGoodies.

>I still don't understand why the orginal single DLL approach didn't work or
>if
>the tri-DLL approach is robust, if someone knows I would appreciate learning
>more.  My guess would be that one or both of the COM load or Excel
>RegisterXLL
>load mechanisms aren't using LoadLibrary() (if thats, possible ???).

>Thanks for any assistance, Neil



Don Grasberger
(remove --- from address to e-mail)
 
 
 

Two copies of a single DLL in a single process (Excel) - how to avoid?

Post by Jim Conyngha » Wed, 27 Jan 1999 04:00:00


Hello Neil,

NT will load two different copies of a DLL, with different global data
segments if one is loaded by the long file name and one is loaded by the
short file name.

It sounds like you've hit the same "gotcha" that bit me a few months
ago.  COM objects build with VC5 ATL registered themselves with their
long file names, but on lots of NT systems, long file names containing
blanks in the registry didn't work, unless the strings were
double-quoted.  (I'm not sure which versions of NT or which installed
software combinations were effected.)

Anyway, VC6 ATL, "fixed" the problem by registering the DLL's short file
name.  (Check the source code for
AtlModuleUpdateRegistryFromResourceD(), or just scan the ATL source for
"GetShortPathName".)  If you check your registry, I'll bet you find the
short file name.

Unfortunately the fix broke code like mine and your where you have a DLL
with a long file name that is both an ATL COM object and something
else.  Now COM will load one copy via the short file name and (in your
case) Exel will load a completely independant copy via the long file
name.  The two copies have separate copies of the global variables,
because NT is treating them as different modules.

IMHO, this is another bug in NT 4.  The loader should discriminate based
on the file's 64-bit "unique identifier" in it's
BY_HANDLE_FILE_INFORMATION, not just on the pathname string.

The easiest fix is just to use a short 8.3 file name.

Good Luck,


> Hi Folks,

> I have a process (Excel.exe) that seems to map a certain custom DLL into
> memory twice.  What I need is a single copy, with a single set of data.  If
> anyone can help with any of the following questions I would be most
> grateful.

> 1.    What are the NT rules for loading multiple copies of the same DLL into
>     the address space of a single process?

>     I have played with multiple class to LoadLibrary() and it seems to force
>     a single copy.

> 2.    What series of calls could cause the DLL be loaded twice?

> Is possible (probably) that I'm missing the fundamental NT process/module
> management knowledge.

> My specific problem is:

> I have a DLL which is both a COM inprocess server and an Excel C++ Addin
> (xll).
> I do this because I want to add VBA behaviour and Excel worksheet functions
> to
> a common set of data (that's in the DLL).  Excel loads the DLL twice, once
> as a
> COM server and once as a Excel Addin, but the result is two copies of the
> DLL
> in Excel's address space (and so no common data set).  In this case the DLL
> is loaded by actions:

>     1.    Excel's COM because of VBA dim new statement
>     2.    By VBA code calling Application.RegisterXLL("full path of COM
> server DLL")

> I tried breaking the DLL into two, 1) a COM server 2) as Excel Addin DLL
> with
> is merely a stub for calls to the COM server DLL

>     1.    Excel's COM because of VBA dim new statement
>     2.    By VBA code calling Application.RegisterXLL("Stub DLL") which
>             then goes no to load the COM DLL because it has a link time
> dependency.

> Thanks for any assistance, Neil



--
Jim Conyngham
MTS, Software Engineer
AMD
Mail Stop 585
5900 E. Ben White Blvd.
Austin, TX  78741
(512) 602-5002