Author Topic: Expose Methods across Mangaged DLLs  (Read 3572 times)

0 Members and 1 Guest are viewing this topic.

SomeCallMeDave

  • Guest
Expose Methods across Mangaged DLLs
« on: July 23, 2009, 09:39:31 AM »
Hi All,

I was wondering if there is a way to expose method(s) from one managed DLL loaded in acad to another managed DLL loaded in acad.  Similar to the way methods can be exposed from a managed DLL to LISP.

I would like to provide access without having to reference the other DLL at compile time.

Is this possible?

Thanks,
David

troga

  • Guest
Re: Expose Methods across Mangaged DLLs
« Reply #1 on: July 23, 2009, 10:36:23 AM »
Hi All,

I was wondering if there is a way to expose method(s) from one managed DLL loaded in acad to another managed DLL loaded in acad.  Similar to the way methods can be exposed from a managed DLL to LISP.

I would like to provide access without having to reference the other DLL at compile time.

Is this possible?

Thanks,
David


I think it could work with exposing the function from both dll´s to lisp and call the functions through->.NET ... sample:
    doc.SendStringToExecute( "theFunctionYouWantToCall", params.., .., );


a usefull link: http://through-the-interface.typepad.com/through_the_interface/2006/08/calling_command.html

I think that there is a far better way to do that, but if it works... who cares :-)


cheers.


Draftek

  • Guest
Re: Expose Methods across Mangaged DLLs
« Reply #2 on: July 23, 2009, 12:05:40 PM »
If the client code is not too difficult, you could expose the server as com and use late binding.

SomeCallMeDave

  • Guest
Re: Expose Methods across Mangaged DLLs
« Reply #3 on: July 23, 2009, 12:20:30 PM »
Troga,
The functions that I want to expose aren't acad command-line commands, but more like a mini-api that users could call from their .net programs.  So I don't think sendSend or its cousins will work (unless I misunderstand their usage, which is very probable).

Draftek,
Do you have an example of how your idea would work?


Thanks both.

Draftek

  • Guest
Re: Expose Methods across Mangaged DLLs
« Reply #4 on: July 23, 2009, 01:03:23 PM »
Probably a bit more than you need but you get the idea:

Quote
        // method to insert a drawing file into autocad using late binding.
        // Tested for versions 2000 to 2010
        public static void InsertDrawingLB(string sDwgName)
        {
            object acadApp = null;
            object[] parameters;
            object cmd = null;
            if (!File.Exists(sDwgName))
            {
                throw new System.ArgumentException("Drawing does not exist", "sDwgName");
            }
            // try to open an existing instance
            try
            {
                acadApp = (object)Marshal.GetActiveObject("AutoCAD.Application");
            }
            catch // if not successful try to start a new instance
            {
                try
                {
                    StartUpAcadDialog frm = new StartUpAcadDialog();
                    frm.Show();
                    frm.Height = 67;
                    Application.DoEvents();
                    acadApp = (object)Microsoft.VisualBasic.Interaction.CreateObject(
                            "AutoCAD.Application", null);
                    parameters = new object[1];
                    parameters[0] = true;
                    cmd = acadApp.GetType().InvokeMember("Visible",
                        BindingFlags.SetProperty, null, acadApp, parameters);
                    frm.Close();
                }
                catch // you don't even have autocad installed
                {
                    throw new System.Exception("Could Not find AutoCAD to open"); 
                }
            }
            try // need to make autocad active and the top dog
            {
                cmd = acadApp.GetType().InvokeMember("Caption",
                    BindingFlags.GetProperty, null, acadApp, null);
                string caption = (string)cmd;
                Microsoft.VisualBasic.Interaction.AppActivate(caption);
                cmd = acadApp.GetType().InvokeMember("WindowState",
                    BindingFlags.GetProperty, null, acadApp, null);
                parameters = new object[1];
                parameters[0] = 3;
                cmd = acadApp.GetType().InvokeMember("WindowState",
                    BindingFlags.SetProperty, null, acadApp, parameters);
            }
            catch
            {
                throw new System.Exception("Problem forcing the AutoCAD window to Top");
            }
            object dwg = null;
            try // finally, insert the drawing using the newest technology - a script!!!
            {
                // first get the drawing
                try
                {
                    dwg = acadApp.GetType().InvokeMember("ActiveDocument",
                        BindingFlags.GetProperty, null, acadApp, null);
                }
                catch
                {
                    throw new System.Exception("You must have a drawing loaded");
                }
                string sTemp = "(Command " + @"""" + "Insert" + @"""" + " " + @"""" +
                        sDwgName + @"""" + " )" + "\r";
                parameters = new object[1];
                parameters[0] = sTemp;
                cmd = dwg.GetType().InvokeMember("SendCommand",
                    BindingFlags.InvokeMethod, null, dwg, parameters);
            }
            catch
            {
                throw new System.Exception("Could not Insert the drawing");
            }
        }

SomeCallMeDave

  • Guest
Re: Expose Methods across Mangaged DLLs
« Reply #5 on: July 23, 2009, 02:06:28 PM »
Probably a bit more than you need but you get the idea:


Thanks Draftek.  I will check it out

Draftek

  • Guest
Re: Expose Methods across Mangaged DLLs
« Reply #6 on: July 23, 2009, 03:34:04 PM »
Forgot to mention - I'm merely accessing autocad. You will need to expose your dll to com and register it before you can access it from the client.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8776
  • AKA Daniel
Re: Expose Methods across Mangaged DLLs
« Reply #7 on: July 23, 2009, 11:05:15 PM »

SomeCallMeDave

  • Guest
Re: Expose Methods across Mangaged DLLs
« Reply #8 on: July 24, 2009, 08:24:13 AM »
Thanks Daniel.

That looks like what I probably need.

I have a couple more questions, but I need to do some reading and playing before I ask them.


Thanks again to everyone.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8776
  • AKA Daniel
Re: Expose Methods across Mangaged DLLs
« Reply #9 on: July 24, 2009, 09:56:19 AM »
Here is a  hack, if you know the function you want to call, its params and return type
( I haven't tried it with Acad)

this is a function inside a assembly call callee

Code: [Select]
public static class Callee
 {
  public static string Doit (int num)
  {
   return num.ToString();
  }
 }

and here is a method in another exe

Code: [Select]
private void buttonCall_Click(object sender, EventArgs e)
  {
   Assembly ass = Assembly.LoadFrom("..\\..\\..\\Callee\\Bin\\Debug\\Callee.dll");
   MethodInfo meth = ass.GetTypes()[0].GetMethod("Doit");

   if (meth.IsPublic && meth.IsStatic)
   {
    object res = meth.Invoke(null, new object[] { 123 });
    if (res != null)
    {
     if (res is String)
     {
      this.textBox1.Text = res.ToString();
     }
    }
   }
  }
 }

SomeCallMeDave

  • Guest
Re: Expose Methods across Mangaged DLLs
« Reply #10 on: July 24, 2009, 11:33:34 AM »
Woot!

That works for me inside Autocad with only a bit of tweaking.

Thanks Daniel.  I really appreciate the help.


Now, the next questions , if I may get greedy  :-) 

Is there a way to access the DLL that has been already loaded in-process with Autocad, something to the effect of Assembly.LoadFromAutocadProcess rather than Assembly.LoadFrom(filename)?  I would like to be able to do this so that I can share data that has been gathered from the Autocad user by one DLL with the other DLL without resorting to storing that data in the drawing (dictionary, xdata, etc).

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8776
  • AKA Daniel
Re: Expose Methods across Mangaged DLLs
« Reply #11 on: July 24, 2009, 10:58:05 PM »
have a look at this code and see if it will work for what you need.

A lispfunction in a loaded dll

Code: [Select]
namespace Autodesk.AutoCAD.NetInvoke
{
 public class MyCommands
 {
  [LispFunction("MyLispFunction")]
  public ResultBuffer MyLispFunction(ResultBuffer args)
  {
   List<TypedValue> list = new List<TypedValue>(args.AsArray());
   list.Reverse();
   ResultBuffer rb = new ResultBuffer(list.ToArray());
   return rb;
  }
 }
}

and the caller in another loaded dll

Code: [Select]
namespace Autodesk.AutoCAD.NetInvoker
{
 public class MyCommands
 {

  [DllImport("acad.exe", CallingConvention = CallingConvention.Cdecl)]
  extern static int acedInvoke(IntPtr rbIn, out IntPtr rbOut);

  public static ResultBuffer Invoke(ResultBuffer rbIn)
  {
   IntPtr pRb = IntPtr.Zero;
   acedInvoke(rbIn.UnmanagedObject, out pRb);
   return DisposableWrapper.Create(typeof(ResultBuffer), pRb, true) as ResultBuffer;
  }

  [CommandMethod("doit")]
  public void MyCommand()
  {
   ResultBuffer rbOut = new ResultBuffer();
   rbOut.Add(new TypedValue((int)LispDataType.Text, "MyLispFunction"));
   rbOut.Add(new TypedValue((int)LispDataType.Int32, 1));
   rbOut.Add(new TypedValue((int)LispDataType.Int32, 2));
   rbOut.Add(new TypedValue((int)LispDataType.Int32, 3));

   ResultBuffer rbIn = Invoke(rbOut);

   List<TypedValue> list = new List<TypedValue>(rbIn.AsArray());

   list.ForEach( X =>
    ApplicationServices.Application.DocumentManager.
    MdiActiveDocument.Editor.WriteMessage(X.Value.ToString()));
  }
 }
}

edit: added solution
« Last Edit: July 24, 2009, 11:36:29 PM by Daniel »

SomeCallMeDave

  • Guest
Re: Expose Methods across Mangaged DLLs
« Reply #12 on: July 27, 2009, 07:09:38 AM »
Daniel,
Thanks again. 

That looks like what I needed.  After more coffee, lots of studying your code and some play time I will let you know.