Re: ExcelDna addin/assembly life cycle

1,616 views
Skip to first unread message

Govert van Drimmelen

unread,
Jun 20, 2012, 6:30:03 PM6/20/12
to Excel-DNA
Hi Naju,


* One approach is not to worry about the locked files, by putting
different versions of the add-in into different subdirectories. Then
your .dna file (which is never locked) can just be changed to point to
another directory.

So you have:

...\MyAddin\
MyAdd.Xll
MyAddIn.dna with
<DnaLibrary ... >
<ExternalLibrary Path="Version1\AddInStuff.dna" />
<DnaLibrary>
\Version1\
MyFunctionsVer1.dll
AddInStuff.dna with
<DnaLibrary ... >
<ExternalLibrary Path="MyFunctionsVer1.dll" />
<DnaLibrary>

You'll see that the ExternalLibrary can be a .dna file too, and so you
can add extra files to a new directory, update the main .dna file to
point to the new version and prompt the user to restart.

* Another suggested architecture for managing different add-in
versions is to have a master add-in that does not change, and it loads
and unloads other add-ins. I know of one or two places doing this
successfully.

There are some tricks to get the unloading to work properly - the last
post here
https://groups.google.com/group/exceldna/browse_frm/thread/9e9474de89eccdd/7f5084c6822d2475?lnk=gst&q=meta+add-in#7f5084c6822d2475
has an attachment that shows how you could make a host add-in that
loads and unloads other add-ins. I also have some concern that RTD
servers in and add-in would not be reloaded, so this might not be the
universal solution.

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

Now to your questions:

- You are right that the .xll file be locked by Excel, but one .xll
can load and unload another .xll file. The .dna file is never locked.
ExcelDna.Integration.dll should not be in your output directory.

There are two settings that affect the locking of your other
assemblies:
- For ExternalLibrary assemblies, you need to set
LoadFromBytes='true' attribute to ensure they are not locked.
<ExternalLibrary Path="MyFunctions.dll" LoadFromBytes="true" />

Excel-DNA explicitly loads the ExternalLibrary assemblies, and
choosing the LoadFromBytes options means these will be read into
memory and loaded from there, thus not locking the file.

- The problem might be the other assemblies that "MyFunctions.dll"
depend on. Say you also have "MyLibrary.dll" - this is not loaded
explicitly by Excel-DNA, but by the .NET runtime. And so we have less
control over what happens.

- If you set the add-in to ShadowCopyFiles='true', the corresponding
flag is set on the add-in's AppDomain, and then other referenced
assemblies should not be locked when loaded by the runtime. But Excel-
DNA has no control in this case.

- The problematic case is if you have an assembly that is both a set
of Excel UDFs and being referenced by another assembly. The
LaodFromBytes scheme would then lead to the file being loaded twice,
which can cause some confusion: https://groups.google.com/group/exceldna/browse_frm/thread/ebb8ae85ad897017.

- If everything you need could be packed into a single .xll file
that you can load and unload, most of these issues disappear since
Excel-DNA then controls all loading of the assemblies. This still
leaves problems if you have mixed or native assemblies, and the RTD
servers and ribbon customizations might have issues.

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

- Both ExcelDna.Loader.dll and ExcelDna.Integration.dll are always
packed into the ExcelDna.xll file. While you might need to reference
ExcelDna.Integration in your own add-in library, you should mark the
Reference as "Copy Local = false", so that it won't be copied to your
output directory. You never need to redistribute
ExcelDna.Integration.dll, and having the extra copy in your add-in
directory can sometimes cause trouble. Unfortunately I don't yet know
how to make it a pure 'reference assembly' to prevent it from being
loaded from the file by mistake.

I know it's a bit confusing, but it's the best compromise I have at
the moment.

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

- Stepping through the native code is sometimes a bit tricky to enable
- I think Visual Studio has some internal debugger settings that
confuse me. Once it work, it works great until I clean up the extra
files again.

This is what I tried now, and it worked fine:
1. Rebuild everything, and put an ExcelDna.dna file in the ExcelDna
\Debug output directory, next to ExcelDna.xll.
2. Set a breakpoint in ExcelDnaLoader.cpp, line 100.
3. Run Excel.
4. Attach to the Excel process, with the Native code debugger
selected.
5. Load the ExcelDna.xll
6. The breakpoint is hit and I'm debugging...

So the debugging works fine now, but I've had problems in the past
which did require some fiddling to get the debugging working.
One issue is certainly that Visual Studio by default would only load
the managed debuggers.


Please write back if you have more questions, or to let us know what
you decide to do.

Regards,
Govert







On Jun 20, 10:15 pm, ngm <naju.manche...@gmail.com> wrote:
> Hi,
>
> I'm a bit confused about addin loading/deployment:
>
> What I'd like to do:
>
> - I want to avoid packing, since I want to leave as little locked as
> possible. I think Excel will lock the .xll file, so that much is
> unavoidable. However, I *think* that by turning on ShadowCopyFiles, I can
> keep Excel from locking my managed assemblies (ExternalLibraries,
> ExcelDna.Integration, etc).
>
> - I want the addin code to reference ExternalLibraries stored on the local
> disk. However, I'd also like (maybe in AutoOpen) to check for available
> updated assemblies (new files on some file share). If new files are found,
> the addin should copy those files somewhere to the local disk, rewrite the
> .dna XML file to make sure the *next* started instance of Excel will load
> the new, updated assemblies, and pop open a message box to the user to
> indicate that a new version is available and he should restart Excel to use
> it. [I currently do this for our ManagedXLL-supported addin].
>
> What I'm not sure about:
>
> - I'm not completely sure how the ExcelDna.Integration and ExcelDna.Loader
> code is used by the addin.
>
> - For example, when I develop my ExternalLibrary (a VS2010 Class Library),
> I need to add a reference to ExcelDna.Integration before I can use the
> types defined there (e.g. XlCall). I've done this by creating a solution
> with both my Class Library and the ExcelDna.Integration project. I then add
> a project reference. However (and this is a source of major confusion for
> me), if I delete the ExcelDna.Integration.dll file from my deploy
> directory, my addin still seems to work. Why does the runtime not raise
> some "cannot resolve assembly" or "cannot resolve type" error as soon as my
> code path tries to load/use those types?
>
> - Further, when I read the ExcelDna C++ code, I see it loading the
> ExcelDna.Loader assembly, getting a reference to the
> ExcelDna.Loader.XlAddIn type, and invoking the Initialize32 method on it.
> How does this code run when I don't have any ExcelDna.Loader.dll assembly
> in my deployment directory?
>
> - Is it possible to step through the C++ code with the VS2010 debugger?
> I've tried adding the C++ project to my solution, putting in breakpoints,
> and telling VS to start an external program (Excel.EXE). It properly loads
> the addin, however, it does not hit my breakpoint.
>
> Thank you

Govert van Drimmelen

unread,
Jun 22, 2012, 6:30:17 PM6/22/12
to Excel-DNA
Hi Naju,

I don't usually have issues debugging the managed add-in's user-
defined functions and commands.

Debugging the managed Excel-DNA integration libraries can be a bit
tricky sometimes.
When recompiling (only for the Debug - Win32 configuration), you'll
see the ExcelDna.Loader.dll and ExcelDna.Integration.dll copied to the
output (Source\ExcelDna\Debug) directory. Then, when the add-in is
loaded from there, these assemblies are loaded from the files and not
the packed versions. So you need not fiddle with the packing for the
debugging to work - you just need those assemblies as files next to
the .xll - then the files are loaded and the packed versions ignored.
They have to be up-to-date though, else the debugger won't match your
code with the loaded .dlls.

The following works for me:

- Make sure you rebuild everything - when you set up
'ExcelDna.Integration' for debugging, the ExcelDna project might not
rebuild, so the ExcelDna.Integration in the (Source\ExcelDna\Debug)
directory might not be updated. When in doubt I just press Build-
>Batch Build->Rebuild All, and then I'm sure it's OK.

- I start Excel on its own, then attach the debugger, then load the
add-in. This seems more reliable than starting the debugger

- Another trick I have use sometimes is to put a Debug.Assert(false)
somewhere in the loading path - this allows

One issue that I don't have a grip on is how Visual Studio selects the
debugger options to use when debugging a process. This is persisted
somewhere, and I suspect affected by the choice you make when
attachnig to the process, but also by which managed runtimes it
detects in the Excel process.

I think some combination of the following factors makes for the tricky
debugging experiences:
- The target process is a native process, that may have managed code
running in it (in .NET 2.0, .NET 4 or both) .
- The solution has native and managed assemblies.
- The managed assemblies are compiled targeting .NET 2.0, but the
might be loaded and run under .NET 4 (with the RuntimeVersion tag in
the .dna file).
- The version of the managed assemblies loaded by the .xll (from
packed or file) might not match the compiled version - e.g. Visual
Studio might not rebuild the native ExcelDna project when you are
trying to debug the managed ExcelDna.Integration project.

In summary - this is a problematic part for me too, but I seem to
manage OK. I find the packing feature very valuable, even though it
adds significant complexity, but the mix of native and managed is more
likely the cause of problems, and that I can't avoid.

If you have some better ideas on how I can structure the solution to
make debugging better, I'd be happy to hear about it. Also, if you
have too much trouble getting it going, write back and I'd be happy to
investigate further.

Regards,
Govert


On Jun 22, 10:36 pm, ngm <naju.manche...@gmail.com> wrote:
> OK, I've solved most of my managed debugging problems. Once I blew away
> some old assemblies and made sure to load the ones in \bin\Debug\, it now
> works fine. VS properly hits breakpoints in ExcelFunctions and
> ExcelCommands.
>
> One last, tiny difficulty: My managed breakpoints in ExcelDna.Integration
> and ExcelDna.Loader still don't seem to be hit (even though the ones in my
> ExternalLibrary assemblies are). I think this is due to the weird way these
> are released (copied into the .xll file).
>
> Is there some way to step through this code?
> Maybe I can turn off the .xll packing and copy these to \bin\Debug?
> Or maybe get VS to compile the assemblies and them copy them into the .xll
> (if it's a byte code difference).
>
> Thanks

Govert van Drimmelen

unread,
Jun 22, 2012, 7:19:25 PM6/22/12
to Excel-DNA
This is fine if you are have are debugging the ExcelDna.Loader and
ExcelDna.Integration assemblies, and have a combined solution with
your add-in project and the Excel-DNA code.

But in general your add-in would never reference ExcelDna.Loader.dll,
and you should set the ExcelDna.Integration.dll to Copy Local=false
when developing your add-in library on its own.

Also, you should think carefully before starting to use a custom
version of Excel-DNA - I really can't support you if you run into
anything funny with a modified version.

-Govert


On Jun 23, 12:49 am, ngm <naju.manche...@gmail.com> wrote:
> Awesome! Your "copy .dlls to sit next to .xll" suggestion worked!
>
> For future reference, I modified my DnaAddin.csproj project references. The
> references to ExcelDna.Loader and ExcelDna.Integration now have
> CopyLocal=true.
>
> From the stuff Govert mentioned earlier, you may want to avoid this in the
> release version, especially if there's a danger that the code in the copied
> .dlls drifts from the packed ones.

Aman Saraswat

unread,
Sep 23, 2021, 6:27:30 AM9/23/21
to Excel-DNA
Hi Gov. ,
I am adding my C# UDF project to an existing addin. I want to use the user login information from the existing addin for API access in my UDF project so at the time of addin initialization I register my UDF addin and initializes an object in the UDF project with the API login information. But every time I call  a UDF function from excel the login information gets null. 

Can you please help me out in this?

Thank you

Govert van Drimmelen

unread,
Sep 23, 2021, 6:33:16 AM9/23/21
to exce...@googlegroups.com

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

Excel-DNA is now registered on GitHub Sponsors.

You can add Excel-DNA support with easy billing through a corporate GitHub account.

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

 

Hi Amman,

 

How is the existing add-in built?

From your question, I’m wondering whether it is a VSTO add-in.

If so, your Excel-DNA and VSTO add-in can’t communicate easily 0 they will live in different AppDomains.

So to share something like login information, you have to use a mechanism that is not through direct .NET calls.

For example, you can write to an environment variable from the one add-in, and read that from the other.

 

-Govert

--
You received this message because you are subscribed to the Google Groups "Excel-DNA" group.
To unsubscribe from this group and stop receiving emails from it, send an email to exceldna+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/exceldna/52376a8e-9041-4b67-a33d-c8fe829eb0a2n%40googlegroups.com.

Reply all
Reply to author
Forward
0 new messages