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