RTD in UDF not remembering value on open file

720 views
Skip to first unread message

Serge

unread,
Dec 6, 2010, 1:08:47 AM12/6/10
to Excel-Dna
I am using a vanilla RTD server in a UDF function like this:

public static object GETVALUE()
{
return XlCall.RTD("MyServer", null, "MyValue");
}

My ConnectData is ConnectData(int TopicID, ref Array args, ref bool
newValue). The issue is that newValue is always True, even after I
save and re-open the file.

Any ideas on how to enable the RTD to save the values when the file is
saved and re-opened so that newValue is set to false and the previous
saved value is shown (as per the documentation)?

Thanks!

Serge

Serge

unread,
Dec 6, 2010, 11:35:11 PM12/6/10
to Excel-Dna
I confirmed this behavior with Samples\RTD\TestRTD.dna. Using
GetTestItem("EUR"), the worksheet does not show the saved value on
opening -- instead it shows "Queued". Is there any way to save the
value when using RTD in ExcelDNA?

Thanks.

Govert van Drimmelen

unread,
Dec 7, 2010, 12:43:14 AM12/7/10
to Excel-Dna
Hi Serge,

Just for reference - there is a nice article on "A Topic's Initial
Value" here: http://weblogs.asp.net/kennykerr/archive/2008/12/18/Rtd9.aspx.

I suspect this has to do with how I register the RTD COM server with
Excel - I generate unique names for the CLSID and PROGID on the fly
(This happens in the ExcelRtd.RTD method in ExcelRtd.cs. Maybe the
value Excel stores is against the one of these volatile identifiers -
hence Excel ignores the cached value.

So I suspect there is no way around this in the current version. I've
created an issue on Codeplex - http://exceldna.codeplex.com/workitem/5902.

Regards,
Govert

Serge

unread,
Dec 7, 2010, 12:56:01 AM12/7/10
to Excel-Dna
That was my suspicion as well. When I created my own RTD COM using a
defined CLSID/PROGID, the initial value worked fine.

Will this be a hard fix for ExcelDNA? This feature is key for some of
my users. I am happy to test or help in any way I can.

Thanks!

Best,
Serge

On Dec 7, 12:43 am, Govert van Drimmelen <gov...@icon.co.za> wrote:
> Hi Serge,
>
> Just for reference - there is a nice article on "A Topic's Initial
> Value" here:http://weblogs.asp.net/kennykerr/archive/2008/12/18/Rtd9.aspx.
>
> I suspect this has to do with how I register the RTD COM server with
> Excel - I generate unique names for the CLSID and PROGID on the fly
> (This happens in the ExcelRtd.RTD method in ExcelRtd.cs. Maybe the
> value Excel stores is against the one of these volatile identifiers -
> hence Excel ignores the cached value.
>
> So I suspect there is no way around this in the current version. I've
> created an issue on Codeplex -http://exceldna.codeplex.com/workitem/5902.

Govert van Drimmelen

unread,
Dec 7, 2010, 1:32:46 AM12/7/10
to Excel-Dna
OK Serge,

Here's what you can do:

1. Check that a stable GUID for the RTD server really solves our
problem:
a) Check that you can recompile Excel-Dna and everything still
works.
b) Change line 60 in ExcelDna.Integration\ExcelRtd.cs from
CLSID clsId = Guid.NewGuid();
to
CLSID clsId = .... /* <- Pick some unique, fixed Guid just
to test.*/
c) See if your problem is then fixed for this .xll.

If this goes well, you can try to find a real fix:

2. Find a better way to get a Guid per add-in.
a) The only stable identifier he have for each add-in is the full
path.
b) Do some Googling for a way to get a stable and unique Guid from
a string - some hashing story, I presume.
c) Get a C# implementation of the string-> Guid hash.
d) Replace the fix above with one that uses the new Guids.
e) Check that everything works.

Regards,
Govert

Serge

unread,
Dec 7, 2010, 10:08:21 AM12/7/10
to Excel-Dna
I'll try this later today. Thanks, Govert.

Serge

Serge

unread,
Dec 7, 2010, 11:48:30 PM12/7/10
to Excel-Dna
a) I was able to compile and run MyRTDServers.TestServer from
TestRTD.dna from the examples without a problem (I erased the time
server section for testing).
b) I made the change.
c) I open excel, load the xll, start a new worksheet, enter
=GetEurOnd() into A1, enter =GetTestItem("EUR") into A2, save the file
as test.xls, close excel, re-open excel, re-load the xll, start a new
worksheet, enter =GetEurOnd() into A1 (to load the RTD), then open
test.xls. In test.xls, A1 is loaded with the latest date, and A2
loads with the previous saved date. A few seconds later it updates.
This shows that the initial value is working perfectly. Without the
change test.xls shows the value in A1 but Queued in A2. However, if I
re-open excel, re-load the xll, and open text.xls directly, both A1
and A2 display #N/A. Add-Ins shows that the RTD was not loaded.
Opening a new worksheet and trying =GetEurOnd() there does not help.
The only way to get the RTD to load is to close excel, re-open, re-
load the xll, and use =GetEurOnd() in a new worksheet first. Opening
test.xls without the change just shows "Queued" in both A1 and A2.

I tried commenting out lines 45-49 to see if the RTD call was getting
passed to Excel, but that had no effect. Any ideas?

Thanks!

Serge

rleth...@gmail.com

unread,
Dec 9, 2010, 4:08:03 AM12/9/10
to Excel-Dna
Regarding 2b/c, here's a quick way to turn the path string into a
GUID:

string path = @"D:\Files\CSharp\Excel\ExcelDna\SomeExampleXll.xll";
//byte[] tmp = System.Text.Encoding.Unicode.GetBytes(path);
byte[] tmp = System.Text.Encoding.ASCII.GetBytes(path);
byte[] hash =
System.Security.Cryptography.MD5.Create().ComputeHash(tmp);
Guid g = new Guid(hash);

Not sure if you need the unicode bytes of the path string or whether
ASCII is sufficient, as I have no experience of non-English windows.
Unicode can't hurt in this instance.

Govert van Drimmelen

unread,
Dec 9, 2010, 6:02:07 PM12/9/10
to Excel-Dna
Hi Serge,

I'm not too clear on the scenario that gives a problem:
1. You open Excel and open the .xll, then create a new sheet and call
the RTD wrapper function, then open a sheet that had the right values
in before, and all is OK, vs.
2. You open Excel and open the .xll, then open a sheet that had the
right values in before, and you get #N/A? Does the #N/A go away when
you re-enter the function (press F2 on the cell)?

Maybe you can compare that with the behaviour when Excel-Dna is not
involved:
1. Compile another instance of RTD server in C# (no Excel-Dna
involved), which you register as usual.
2. Check that it works using the =RTD(...) from a cell.
3. Make a VBA wrapper UDF that calls your RTD using
Application.WorksheetFunction.RTD.
4. Repeat the tests.

I can imagine it being different if Excel checks the Registry and
tried to load the RTD server without ever calling the Excel-Dna UDF.
And then once Excel has decided the RTD server is not available, it
never retries.

If all of this is the case, Excel-Dna will have to register all the
RTD servers on startup, instead of on demand.....
(Should this be an option, rather than always happening?)

Maybe you could trigger that in your code by calling XlCall.RTD for
your servers in the AutoOpen?

-Govert

Serge

unread,
Dec 9, 2010, 8:14:35 PM12/9/10
to Excel-Dna
Thanks, Govert.

You got the problematic scenario right. I'd emphasize on #1 that this
solves the GetNewValues problem (the sheet is pre-populated with
values before the save). On #2, the #N/A does not go away when I
enter a new function. The RTD server does not load (I'm checking via
Add-Ins). It doesn't even load if I start a new workbook and use the
wrapper function there.

Serge

unread,
Dec 9, 2010, 8:39:39 PM12/9/10
to Excel-Dna
Pressed send by accident.

I tried compiling an RTD server in C# and it works fine in all cases.
GetNewValues also works fine in both RTD() and VBA-wrapper mode.

I tried triggering the RTD server with XlCall.RTD in AutoOpen, but
that has no effect. What's interesting is that the following code...

public class MyAddIn : IExcelAddIn
{
public void AutoOpen()
{
string xllDir =
Path.GetDirectoryName((string)XlCall.Excel(XlCall.xlGetName));
string dataPath = Path.Combine(xllDir, "Test.xml");
object x = XlCall.RTD("MyRTDServers.TestServer", null, dataPath, "EUR/
OND");
MessageBox.Show("Now opening: "+x.ToString());
}
}

...produces the popup "Now opening: Queued" on opening up Excel.
However, the RTD server still doesn't start (I check in Add-Ins).
Then opening the saved xls results in #N/A but starting a new workbook
works fine (same as before). As before, opening the saved xls after
starting a new workbook with some RTD UDFs in there also works fine.
Just opening the xls directly doesn't work. Keep in mind that in this
test and in other tests, if the xls sheet I open doesn't call the same
RTD server (as defined by the progId), then everything works fine.
It's only when the progId of the RTD is the same as that of the saved
workbook that the #N/A comes up.

It seems like, as you say, Excel expects the RTD server with the
progId of the one saved in the xls file to already be loaded and
doesn't bother loading it dynamically. How else can I try to get
ExcelDna to force the RTD server to register?

Serge

Govert van Drimmelen

unread,
Dec 12, 2010, 3:54:17 AM12/12/10
to Excel-Dna
Hi Serge,

Thanks for letting us know what you found.

It's not about getting Excel-Dna to load the RTD server, it's about
getting Excel itself to load it. During the XlCall.RTD(...) call the
right registry entries are there. It just looks like Excel is not
trying to do this when this is called from AutoOpne?
If the AutoOpen does not give us a context in which we can get the RTD
servers loaded, it looks like there won't be an easy solution now.


I can't spend too much time digging into this now, but I have added a
ticket on CodePlex, so I won't forget. But unless I have a brainwave
this is not likely to get serious effort from me in the next few
months. If you really want to dig further, I'm of course happy to
help. You should get a registry monitor like the Process Monitor for
SysInternals - that allows you to see exactly when Excel probes for
the registration entries.



To really support the old values I'd have to change how the registry
entries are made so the RTD server can be accessed by Excel anytime
the .xll is loaded. This is not impossible, and might have the
advantage that Excel-Dna based RTD servers could also work from the
worksheet function =RTD(...). My main issue there is that I won't be
able to remove the entries from the registry, which I don't like so
much. I can't even remove the registry entries when Excel is closing,
since there might be other instances of Excel requiring the same
CLSIDs. So then we go down an install/uninstall road that I am
strongly trying to avoid.

If you're happy leaving the registry changes, you could just try to
write the registration entries from your AutoOpen. Inside ExcelRtd.cs
there are the classes to do this - just copy them and get rid of the
cleanup that happens when the objects get disposed, or keep references
in your add-in class.


I'm not sure if there are any COM gurus listening, but there are two
other ways to intercept the ProdId/ClsId lookup and the COM class
activation:
1. The Activation Context API, which I could never get to work cleanly
for the in-memory case,
2. Hooking the Registry API, which is not hard be feels like a truly
ugly hack.

Neither of these seem better than what I'm doing now, which is to
write to the registry only when needed, and clean up immediately.

So what you have found might be a restriction on the Excel-Dna support
for no-registration RTD servers. I suggest you register your RTD
server as a regular COM class, perhaps even automatically in your
AutoOpen. I would always use wrapper functions to access the RTD -
this gives you a lot of flexibility in future. You can either call
XlCall.Excel(XlCall.xlfRtd,...) directly (to skip the Excel-Dna
support) or still call XlCall.RTD(...) which uses the Excel-Dna path,
but will work with regular registered RTD servers too.
With your function wrapper you still get Descriptions and Categories
etc.


Please keep us updated to what you find and do. And thank you for
reporting and spending time on this tricky bug in Excel-Dna.

Kind regards,
Govert

Serge

unread,
Dec 12, 2010, 9:25:36 PM12/12/10
to Excel-Dna
Thanks for the detailed reply, Govert.

I tried your advice to write the registration entries in the AutoOpen
and not do any cleanup. It took me a while as I've never done COM
registration, but it worked out. I had to change from
REGCLS_SINGLEUSE to REGCLS_MULTIPLEUSE to get it to work. I added the
following function to ExcelRtd.cs and call it via a XlCall shortcut in
my AutoOpen:

public static void RegisterPermanentRTD(string progId,CLSID clsId){
Type rtdServerType = registeredRtdServerTypes[progId];
object rtdServer = Activator.CreateInstance(rtdServerType);
RtdServerWrapper rtdServerWrapper = new RtdServerWrapper(rtdServer,
progId);
DWORD CLSCTX_INPROC_SERVER = 0x1;
DWORD REGCLS_SINGLEUSE = 0;
DWORD REGCLS_MULTIPLEUSE = 1;
DWORD _classRegister;
SingletonClassFactory factory = new
SingletonClassFactory(rtdServerWrapper);
IntPtr pFactory = Marshal.GetIUnknownForObject(factory);
HRESULT result = ComAPI.CoRegisterClassObject(ref clsId, pFactory,
CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, out _classRegister);
Registry.SetValue(@"HKEY_CURRENT_USER\Software\Classes\" + progId +
@"\CLSID", null, clsId.ToString("B"), RegistryValueKind.String);
Registry.SetValue(@"HKEY_CURRENT_USER\Software\Classes\CLSID\" +
clsId.ToString("B") + @"\InProcServer32", null, DnaLibrary.XllPath,
RegistryValueKind.String);
loadedRtdServers[progId] = progId;
}

Based on my tests, the clsId can still be random -- what's important
is that the progId stays the same. With the code above, the RTD
server has to have the same internal [namespace.classname] as progId,
but I think that can be separated easily.

The downside, as you pointed out, is that the progid/clsId stays in
the Registry, but that's OK for my users for now. Let me know if you
have any brainwaves or if you want me to do any testing a couple
months down the road.

Best,
Serge
> ...
>
> read more »

xinno

unread,
Dec 24, 2010, 6:07:50 PM12/24/10
to Excel-Dna
I've tried your posted solution, however, I'm sure it's because of my
lack of knowledge that I can't seem to get it to work.
My compiled code with your function for ExcelDNA works fine for the
sample GetInstrument/SetInstrument code.
However, My Excel instance keeps crashing when I try to load the code
while calling RegisterPermanentRTD in the AutoOpen

I'm not quite sure how to use XlCall to call it either.


System.Guid guid = new System.Guid("9B4278D3-BA9D-445B-9E14-
D2213C6AB88B");
// first try:
ExcelRtd.RegisterPermanentRTD("mytest.myprogid", guid);
// second try:
XlCall.Excel(XlCall.RegisterPermanentRTD("mytest.myprogid",
guid));

Any tips or info would be very much appreciated, as I would like to
switch my RTD COM addin to an ExcelDNA based add-in.
However, same as the issues you ran into, this will not work for me if
the values show up as #N/A, and since I don't have that issue with a
standard RTD addin.
> ...
>
> read more »

Serge

unread,
Dec 24, 2010, 7:11:53 PM12/24/10
to Excel-Dna
Xinno,

So the compiled ExcelDNA with the changes works well for the same
GetInstrument/SetInstrument? When you save,close, and re-open, you
still see the values? If that's the case, it sounds like your RTD
server is the issue. Can you post a simplified .dna file that you're
testing on?

My notes above weren't detailed enough. I added code in only two
places in ExcelDNA. The first is ExcelRtd.cs. I added this function:
---------------------------------------
ExcelRtd.cs-----------------------
public static void RegisterRTD(string internalProgId, string
registryProgId)
{
//internalProgId is the [namespace.class] ExcelDNA path
//registryProgId is the HKEY_CURRENT_USER\Software\Classes\
[registryProgId] path -- this can be anything as long as its
consistent
CLSID clsId = Guid.NewGuid(); //random clsId each time
Type rtdServerType =
registeredRtdServerTypes[internalProgId];
object rtdServer =
Activator.CreateInstance(rtdServerType);
RtdServerWrapper rtdServerWrapper = new
RtdServerWrapper(rtdServer, internalProgId);
loadedRtdServers[internalProgId] = registryProgId;
DWORD CLSCTX_INPROC_SERVER = 0x1;
DWORD REGCLS_SINGLEUSE = 0;
DWORD REGCLS_MULTIPLEUSE = 1;
DWORD _classRegister;
SingletonClassFactory factory = new
SingletonClassFactory(rtdServerWrapper);
IntPtr pFactory = Marshal.GetIUnknownForObject(factory);
HRESULT result = ComAPI.CoRegisterClassObject(ref clsId,
pFactory, CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, out
_classRegister);
Registry.SetValue(@"HKEY_CURRENT_USER\Software\Classes\" +
registryProgId + @"\CLSID", null, clsId.ToString("B"),
RegistryValueKind.String);
Registry.SetValue(@"HKEY_CURRENT_USER\Software\Classes
\CLSID\" + clsId.ToString("B") + @"\InProcServer32", null,
DnaLibrary.XllPath, RegistryValueKind.String);
}

In XlCall.cs, I added this function:
---------------------------------------
XlCall.cs-----------------------
public static void RegisterRTD(string internalProgId, string
registryProgId)
{
Rtd.ExcelRtd.RegisterRTD(internalProgId, registryProgId);
}

Then, in my AutoOpen, this is the way I call it:

XlCall.RegisterRTD("Namespace.ClassID","PROGID");

What's key is that the Namespace.ClassID string matches your ExcelDNA
namespace and classID (or just skip the namespace if you don't use
it). The ProgID can be anything you want. This is what's stored in
the registry.

Hope this is is helpful. Let me know what you find.
> ...
>
> read more »

xinno

unread,
Dec 25, 2010, 12:55:06 PM12/25/10
to Excel-Dna
Thanks for your help and for getting back to me so quickly.

I should clarify, The original GetInstrument/SetInstrument code works
fine, with the re-compiled ExcelDNA that contains the RegisterRTD
code.

When I try to add the Autoopen code to the GetInstrument/
SetInstrument, that is when it was crashing.

With your latest post, it no longer crashes, and it runs the Auto_Open
code just fine.

XlCall.RegisterRTD("9B4278D3-BA9D-445B-9E59-D2137C6AB88B",
"9B4278D3-BA9D-445B-9E59-D2137C6AB88B");

I am getting a given key not found in dictionary. I am probably not
passing the right value for the internalProgId.

Please bear with me, I am new to com programming and some of this
stuff.
When making the XlCall.RegisterRTD, I know what the namespace is for
the first parameter, but what is the class Id?
How can I set the class id on the GetInstrument/SetInstrument, so that
I can pass it in?
I've used ComClassAttribute("mykey-guid"......) in attempt to set the
class Id right above the Get/SetInstrument class, but somehow I
continue to get the key error.

XlCall.RegisterRTD("mykey-guid", "another guid");

my get/setinstrument source modified.
public class MyAddIn : IExcelAddIn
{
public void AutoOpen()
{
MessageBox.Show("Now in AutoOpen.");
try {
XlCall.RegisterRTD("9B4278D3-BA9D-445B-9E59-D2137C6AB88B",
"9B4278D3-BA9D-445B-9E59-D2137C6AB88B");
} catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
MessageBox.Show("2. Now in AutoOpen.");
}

public void AutoClose()
{
MessageBox.Show("Now in AutoClose.");
}
}

public delegate void InstrumentHandler(Instrument instrument);

[ComClassAttribute("9B4278D3-BA9D-445B-9E59-D2137C6AB88B", "9B4278D3-
BA9D-445B-9E59-D2137C6AB88D", "9B4278D3-BA9D-445B-9E59-D2137C6AB88C")]
public static class StaticIBag {
> ...
>
> read more »

Serge

unread,
Dec 25, 2010, 8:08:13 PM12/25/10
to Excel-Dna
Hi Xinno,

If you are using the get/set instrument example from 0.28
(RTDObjectWrapper.dna), it should be:

XlCall.RegisterRTD("StaticRTD","myFavProgId");

You have to use "StaticRTD" because that is what the RTD class is
called. If it was in a namespace, you would use
[Namespace].StaticRTD.

Try that and let us know what happens.

Serge
> ...
>
> read more »

xinno

unread,
Dec 26, 2010, 11:16:33 AM12/26/10
to Excel-Dna
Hi Serge,
It works just fine now once I'd corrected the RegisterRTD call.

It seems to work perfectly as long as an instance of Excel is already
running when I open my Excel file calling the Get/Set Instrument
formulas.
It appears to run well enough for me to try switching my RTD plugin
back over to ExcelDNA. I'll continue to do some more thorough testing
around it.

Thank you for sorting that all out explicitly for me.
> ...
>
> read more »

Chezky

unread,
Feb 1, 2011, 10:49:18 PM2/1/11
to Excel-Dna
I have a C# class that I compile into a dll, and have correctly
configured ExcelDna to access it: i.e., my auto open, and functions
get called correctly. I also implemented IRtdServer, and have
registered it successfully, so that when I fill in a cell with
=RTD("xyz.abc",...), it works fine, starts my server, etc. However,
when I try to call XlCall.RTD("xyz.abc",...), it gives me a null
object. I've verified with Regdllview that my RTD Server is
registered, and my direct worksheet call confirms this. Any idea why
the XllCall wouldn't work? Any tips on how to debug this further?

Thanks,
Chezky
> > > > > > On Dec 12, 3:54 am, Govert van Drimmelen <gov...@icon.co.za> wrote:...
>
> read more »

Govert van Drimmelen

unread,
Feb 3, 2011, 9:19:16 AM2/3/11
to Excel-DNA
Hi Chezky,

Are you running the distributed version of Excel-DNA, or have you made
the changes referred to in this thread?

If your RTD server works from the worksheet, you might rather run it
from your code using something like:

object result;
XlCall.XlReturn retval = XlCall.TryExcel(XlCall.xlfRtd, out result,
progId, server, topicId1, topicId2);
if (retval == XlCall.XlReturn.XlReturnSuccess)
{
// ... use result here

}
else
{
Debug.Print("RTD Call failed. Excel returned {0}", retval);
/// .... ????
}

Regards,
Govert
> > > > > > > Registry.SetValue(@"HKEY_CURRENT_USER\Software\Classes\" + progId...
>
> read more »

Arnas

unread,
Feb 6, 2012, 4:59:02 AM2/6/12
to exce...@googlegroups.com
Hi
Ill resurect this thread.
Solution provided works. And I have couple quries:

1. Why:


CLSID clsId = Guid.NewGuid(); //random clsId each time

Stable Id works as good and doesnt trash registry.

2. ServertTerminte in RtdServerWrapper calls UnregisterRTDServer which removes current instance from loaded servers list. Is there any particular reason for that? It lead to situation when excel calls directly into wrapper, but XlCall.RTD activates new instance. I solved this by not unregistering instance, it works fine. I believe this implementation works for original implementation when each time when rtd instance not found new one is created, so this place is just for cleanup?

Regards,
Arnas

Govert van Drimmelen

unread,
Feb 6, 2012, 6:30:25 AM2/6/12
to Excel-DNA
Hi Arnas,

1. My initial plan was exactly _not_ to trash the registry, but having
the registry entries in place for as short as possible. This means a
new Guid every time should not be a problem, since nothing is left in
the registry after the class is activated.
However, as this thread explains, there is an issue with the
reactivation of RTD servers and retrieving the previous values - since
the RTD server name is stored in the Excel file.

So the new version added support for having a stable RTD server GUID
and Name, and have these registered separately, either via
Regsvr32.exe of a call to ComServer.DllRegisterServer(). These truly-
registered RTD servers should not be accessed through the code path
you refer to (XlCall.RTD) but directly through a call to Excel's RTD
function (XlCall.Excel(xlfRtd, ...)). So for the stable ProgId / Guid
case, Excel-DNA will not be allocating new guids every time, and for
the 'transient' case, the registration is removed immediately from the
registry.

If you have a scenario with the current version that 'trashes' the
registry, thus leaves any entries in the registry after the RTD server
is loaded up, that's a bug and I'd like to know about it.

Another possible design, which is not currently implemented, would be
automatically register against a fixed guid and progid, and leave the
registration in the registry. But then the issue becomes when to clean
up the registry, and how to deal with the same add-in placed in
different locations on a machine.

2. When ServerTerminate is called on an RTD server, I want to do all
clean-up to get to the state before the RTD server was loaded. The
instance of the RTD server will be shut down (as it would be for an
RTD server called directly from Excel) and I need to remove it from
the internal list of 'active' RTD server instances. I think that's the
right behaviour - why is it a concern to you?

Regards,
Govert

Arnas

unread,
Feb 6, 2012, 7:21:10 AM2/6/12
to exce...@googlegroups.com
Hi Govert,

1. I was referring to Serges solution where he registers RtdServerWrapper with RegisterRTD method. Its nice solution just and it works, just I noticed it trashed registry with clsids. However it works and I can use same id each time so no big deal.
2. If I use solution above, when server terminates it cleans instance created by solution above. thats my concern.

Regarding registering rtd as com, i am comming from this solution implemented using com. If I register it as HKEY_CURRENT_USER it just doesnt work with UAC enabled (win7 x64, office 2010 32)! So i need admin to deploy RTD, which causes headache, so reg free deployment (or autoregister w/o admin priviledge) would be my preference.

Regards,
Arnas

Govert van Drimmelen

unread,
Feb 6, 2012, 7:36:35 AM2/6/12
to Excel-DNA
Hi Arnas,

Could you please start a new thread with your questions, based on the
current version (0.29).

As far as I know the HKEY_CURRENT_USER registration works fine on 64-
bit Windows with 32-bit Excel, and no admin is needed.

So, let's start a new discussion with explaining what you want to do
and what problems you run into when using the built-in COM Server
support.

Thanks,
Govert

Arnas

unread,
Feb 6, 2012, 8:36:03 AM2/6/12
to exce...@googlegroups.com
Hi Govert,

All I need to do get newValues flag set correctly (newValues == false) when I open existing workbook. So it is completely relevant to this thread as solution provided by Serge is almost perfect, so I just needed to clarify couple of questions arose. I just want to finalize solution described by Serge, I dont see need to go back to non wrapped Rtd server.

Regards,
Arnas

Govert van Drimmelen

unread,
Feb 6, 2012, 8:53:31 AM2/6/12
to Excel-DNA
Hi Arnas,

It's certainly appropriate to this thread, but the discussion was
based on a previous version of Excel-DNA and suggest a solution that
is based on a customised version of Excel-DNA and that is still
problematic (as you point out). Subsequently (in May 2011) I added
some features to Excel-DNA - released in v 0.29 - that should solve
this problem comprehensively. This RTD problem was one of the
motivations for the COM Server support that was introduced in Excel-
DNA 0.29.

The new features allow you to expose the RTD from within an Excel-DNA
add-in, where it is activated via COM, but under control of the Excel-
DNA unmanaged host so that the RTD server is hosted in the same
AppDomain as the rest of the add-in. From the worksheet the RTD server
can be called either directly, via the "=RTD(...)" worksheet function,
of from a wrapping UDF implemented in your Excel-DNA add-in or
elsewhere, via XlCall.Excel(xlfRtd,...).

Registration of the (stable ProgId and Guid) into the
HKEY_CURRENT_USER hive allows non-admin installation, allows your RTD
server to be activated even before the add-in is explicitly loaded,
and allows the 'old values' to work right. Registration can be either
by a Regsvr32.exe or a call to ComServer.DllRegisterServer() which you
can put in your AutoOpen. Registration under 32-bit / 64-bit Windows
should not be an issue as long as you match ExcelDna.xll with 32-bit
Excel and use ExcelDna64.xll for 64-bit Excel.

So - it is not about going back to a non-wrapper RTD server. But
instead of trying to fix the partial solution initially presented here
based on an older version of Excel-DNA, I am happy to help you use the
more complete solution that is built into the current version of the
library.

Regards,
Govert

Serge

unread,
Feb 6, 2012, 10:15:57 PM2/6/12
to exce...@googlegroups.com
Arnas,

My solution is .28-specific because I didn't have the luxury of using Govert's improvements to .29. That said, I haven't felt the need to upgrade to .29 to take advantage of the new RTD stuff because my method has been extremely stable for my users. To answer your question-- I did not actually use the random CLSID and instead hardcode the CLSID for my RTD. I never delete that from the registry. Thus all of my users have that one entry in their registry forever. This works fine for my users since they never remove my xll, but even if they did the damage is only one registry entry (or two, I don't remember exactly). I'm planning on refactoring my excelDNA xll and will try to upgrade to .29 to make use of Govert's improvements. Will update this thread with my findings when I do.

Serge

Reply all
Reply to author
Forward
0 new messages