RTD, Loading initial values

Mar 8, 2012 at 2:50 PM

Hi Govert,

in your posting http://exceldna.codeplex.com/workitem/5902 (Initial values for RTD servers) you comes up with a solution for the problem about the missing initial values when a rtd-server starts.

I tried your suggestion, but it seems that i am missing something. I am not able to start the RTD-Server.

The .XLL is registered in Excel. I start the project via VS 2010 (F5 launches Excel.exe). The class ist not marked as "COM-Interop". In the project i have placed some Debug-Prints. The only ony displayed ist the one in the AutoOpen-Function.

Do you have any idea what i have missed? My System ist Windows7 (German), Excel 2007 (SP3).

Cheers
Carsten

Here is the code (all placed in one sourcecode-file and compiled in one DLL):

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

using ExcelDna.Integration;
using ExcelDna.Integration.Rtd;

    public class TestRtdFunctions : IExcelAddIn
    {

        public void AutoClose() {}

        public void AutoOpen()
        {
            System.Diagnostics.Debug.Print("AutoOpen");
            ExcelDna.ComInterop.ComServer.DllRegisterServer();
            //ExcelDna.ComInterop.ComServer.DllUnregisterServer();
        }
   
        public static object WhatTimeIsIt()
        {
            // This call is good.
            //object myResult = XlCall.RTD("MyRTDServers.TimeServer", null, "NOW");
           
            // This call fails.
            object myResult = XlCall.Excel(XlCall.xlfRtd, "TestComServer.TimeServer", null, "NOW");

            System.Diagnostics.Debug.Print("myResult: {0}", myResult);
            return myResult;
        }
    }

namespace MyRTDServers
{

    // Need Guid here to support direct =RTD(...).
    // Call Regsvr32 <MyAddin>.xll
    // or ComServer.DllRegisterServer()
    // to register.
    [ProgId("TestComServer.TimeServer"),
    Guid("3DF50E8D-2296-40A2-90F9-5B827AA5D07B")]
    public class TimeServer : IRtdServer
    {
        private IRTDUpdateEvent _callback;
        private Timer _timer;
        private int _topicId;

        const bool StartTimer = true;

        #region IRtdServer Members

        public object ConnectData(int topicId, ref Array Strings, ref bool GetNewValues)
        {

            System.Diagnostics.Debug.Print("ConnectData");

            GetNewValues = false;

            _topicId = topicId;
            if (StartTimer)
                _timer.Start();

            return GetTime();
        }

        public void DisconnectData(int topicId)
        { _timer.Stop(); }

        public int Heartbeat()
        { return 1; }

        public Array RefreshData(ref int topicCount)
        {
            object[,] results = new object[2, 1];
            results[0, 0] = _topicId;
            results[1, 0] = GetTime();

            topicCount = 1;
            if (StartTimer)
                _timer.Start();

            return results;
        }

        public int ServerStart(IRTDUpdateEvent CallbackObject)
        {

            System.Diagnostics.Debug.Print("ServerStart");

            _callback = CallbackObject;
            _timer = new Timer();
            _timer.Tick += Callback;
            _timer.Interval = 3000;
            return 1;
        }

        public void ServerTerminate()
        {
            if (_timer != null)
            {
                _timer.Dispose();
                _timer = null;
            }
        }

        #endregion

        private void Callback(object sender, EventArgs e)
        {
            _timer.Stop();
            _callback.UpdateNotify();
        }

        private string GetTime()
        { return DateTime.Now.ToString("HH:mm:ss.fff"); }
    }
}

 

Coordinator
Mar 8, 2012 at 7:53 PM

Hi Carsten,

You need to switch on "Make assembly COM-Visible", but keep off "Register types for COM Interop".

That type implementing IRtdServer needs to be COM Visible. This can be done by:

- setting the assembly to be COM Visible, either by editing the AsebmlyInfo.cs file which has the [assembly:ComVisible(...)] attribute, or

- overriding the assembly default, by marking the type 

[ComVisible(true)]
[...]
public class TimeServer : IRtdServer

Once this is in place, I'm think in the .dna file you might need to add the ComServer attribute to the ExternalLibrary tag:

<ExternalLibrary Path="..." ComServer="true" />

 

If these changes don't work, write back and I'll take a closer look.

Cheers,

Govert

Mar 9, 2012 at 7:52 AM

Hi Govert,

thank you for the fast answer. That was it, works like a charm :-)

Keep up the good work. If you need help for testing don't hesitate to contact me. I'll be glad if i can help.

Have a nice weekend, best regards

Carsten

P.S.

I donated a dime via Paypal in appreciation for the good job you are doing.

 

Coordinator
Mar 9, 2012 at 8:13 AM

Hi Carsten,

Thank you very much for the donation!

Please write back if you have any further questions, comments or suggestions for the library.

Kind regards,

Govert