Author Topic: Experimenting with P/INVOKE etc  (Read 4621 times)

0 Members and 1 Guest are viewing this topic.

Peter Jamtgaard

  • Guest
Experimenting with P/INVOKE etc
« on: June 05, 2010, 01:34:48 PM »
Swamp,

I don't know if there is another version of this routine out there...

This routine is similar to the (findfile ) expression in LISP.

I wrote this from scratch using the other examples (from Daniel, TonyT, Gile, etc...) for package invoke entry points for guidance.

I included the LISPFunction attribute for testing.

Do you think the string in string out overload of the function would be useful to .NET?

Would it be useful to create a library of acad.exe entry points like the old ads commands?

Constructive criticism is gratefully appreciated.

PeterJ


Code: [Select]
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.Runtime
Imports System.Runtime.InteropServices 'for DllImport()
Imports System.Security
Imports System.Text.StringBuilder

Public Class vbvlClass
    <System.Security.SuppressUnmanagedCodeSecurity(), DllImport("acad.exe", _
    CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.Cdecl, EntryPoint:="acedFindFile")> _
    Private Shared Function acedFindFile(ByVal strEnvironmentName As String, _
        ByVal stbReturnValue As System.Text.StringBuilder) As Integer
    End Function

    ' Function that performs like the the (findfile "filename.txt") lisp expression.
    ' The Findfile1 function returns a (resultbuffer) list instead of a string.
    ' It searches the support path for a provided file name.

    <LispFunction("FindFile1")> _
    Public Shared Function FindFile1(ByVal rbfFileName As ResultBuffer) As ResultBuffer
        Dim rbfReturn As New ResultBuffer
        Try
            If Not IsNothing(rbfFileName) Then
                Dim strFileName As String = rbfFileName.AsArray(0).Value.ToString
                rbfReturn.Add(New TypedValue(&H138D, FindFile1(strFileName)))
            Else
                rbfReturn.Add(New TypedValue(&H138D, "Error: too few arguments"))
            End If
        Catch Ex As Exception
            rbfReturn.Add(New TypedValue(&H138D, "Error " & Ex.Message))
        Finally
            rbfFileName.Dispose()
        End Try
        Return rbfReturn
    End Function

    ' Overload of the findfile1 function that accepts a string and returns a string

    Public Shared Function FindFile1(ByVal strFileName As String) As String
        Dim stbReturn As New System.Text.StringBuilder(1024)
        Try
            If Not IsNothing(strFileName) Then
                acedFindFile(strFileName, stbReturn)
                Return stbReturn.ToString
            Else
                Return "Error: too few arguments"
            End If
        Catch Ex As Exception
            Return "Error " & Ex.Message
        Finally
        End Try
    End Function
End Class

sinc

  • Guest
Experimenting with P/INVOKE etc
« Reply #1 on: June 05, 2010, 01:42:15 PM »
HostApplicationServices.Current.FindFile()...?

Peter Jamtgaard

  • Guest
Experimenting with P/INVOKE etc
« Reply #2 on: June 05, 2010, 05:44:10 PM »
Sinc,

The purpose of writing and posting the function above was to learn how to expose
other package invoke entry points not necessarily to use the findfile expression.

I can't learn .net without practicing.

I figured there was a exposed function for this entry point for findfile.

The lispfunction attribute is for testing.

So the findfile function should be something like:

Code: [Select]
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Runtime

Public Class vbvlClass
    <LispFunction("FindFile1")> _
    Public Shared Function FindFile1(ByVal rbfFileName As ResultBuffer) As ResultBuffer
        Dim rbfReturn As New ResultBuffer
        Try
            If rbfFileName = Nothing Then
                rbfReturn.Add(New TypedValue(&H138D, "Error: No Arguments"))
            Else
                Dim strReturn As String = FindFile1(rbfFileName.AsArray(0).Value.ToString)
                rbfReturn.Add(New TypedValue(&H138D, strReturn))
                rbfFileName.Dispose()
            End If
        Catch Ex As Exception
            rbfReturn.Add(New TypedValue(&H138D, "Error: " & Ex.Message))
            rbfFileName.Dispose()
        End Try
        Return rbfReturn
    End Function

    Public Shared Function Findfile1(ByVal strFileName) As String
        Try
            If Not strFileName = "" Then
                Dim docThisDrawing As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
                Dim strPath As String = HostApplicationServices.Current.FindFile(strFileName, docThisDrawing.Database, FindFileHint.Default)
                Return strPath.ToString
            Else
                Return "Error: File Not Found"
            End If
        Catch Ex As Exception
            Return "Error " & Ex.Message
        End Try
    End Function
End Class

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Experimenting with P/INVOKE etc
« Reply #3 on: June 05, 2010, 07:09:06 PM »
Peter,

From Lisp, how does the calling Lisp routine know there has been an error ??
Wont it think the error message is the qualified filename. ?

kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Peter Jamtgaard

  • Guest
Experimenting with P/INVOKE etc
« Reply #4 on: June 05, 2010, 07:53:46 PM »
Kerry,

Good point, but I was trying to be consistent and have it return something,
I suppose a nil would be more appropriate.

What would you suggest?

I would appreciate any suggestions you might have to improve the template style.

The first 6 letters "Error:" which couldn't be a file name could easily be tested for?

OK here is a different one I cooked using the other examples for guidance,
using the acedMenuCmd entry point, it executes but this entry point doesn't
return a value.

Is there an exposed .NET method for MenuCmd?

(Also this is just an exercise to practice calling the P/Invoke entry points)

Code: [Select]
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.Runtime
Imports System.Runtime.InteropServices 'for DllImport()
Imports System.Security


Public Class vbvlClass
    <System.Security.SuppressUnmanagedCodeSecurity(), DllImport("acad.exe", _
    CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.Cdecl, EntryPoint:="acedMenuCmd")> _
    Private Shared Function acedMenuCmd(ByVal strMenuCommand As String) As Integer
    End Function

    ' Function that performs like the the (menucmd "m=$(getvar,dimscale)") lisp expression.
    ' The MenuCMD1 function returns a (resultbuffer) list instead of a string.
    ' It searches the support path for a provided file name.

    <CommandMethod("TestMenuCmd")> _
    Public Shared Sub TestMenuCmd()
        ' Should display the Osnap Popup Menu
        MenuCMD1("P0=Pop0")
        MenuCMD1("P0=*")
    End Sub

    <LispFunction("MenuCMD1")> _
    Public Shared Function MenuCMD1(ByVal rbfMenuCommand As ResultBuffer) As ResultBuffer
        Dim rbfReturn As New ResultBuffer
        Try
            If Not IsNothing(rbfMenuCommand) Then
                Dim strFileName As String = rbfMenuCommand.AsArray(0).Value.ToString
                rbfReturn.Add(New TypedValue(&H138D, MenuCMD1(strFileName)))
            Else
                rbfReturn.Add(New TypedValue(&H138D, "Error: too few arguments"))
            End If
        Catch Ex As Exception
            rbfReturn.Add(New TypedValue(&H138D, "Error: " & Ex.Message))
        Finally
            rbfMenuCommand.Dispose()
        End Try
        Return rbfReturn
    End Function

    ' Overload of the menuCMD function that accepts a string and returns a string

    Public Shared Function MenuCMD1(ByVal strCommandName As String) As String
        Try
            If Not IsNothing(strCommandName) Then
                Dim intStatus As Integer = acedMenuCmd(strCommandName)
                Return intStatus.ToString
            Else
                Return "Error: too few arguments"
            End If
        Catch Ex As Exception
            Return "Error: " & Ex.Message
        Finally
        End Try
    End Function
End Class

Peter Jamtgaard

  • Guest
Experimenting with P/INVOKE etc
« Reply #5 on: June 05, 2010, 07:56:37 PM »
Kerry or Sinc (Swamp),

Is there any entry point(s) that you think would be useful to expose (that so far has not been)?

Peter

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Experimenting with P/INVOKE etc
« Reply #6 on: June 05, 2010, 08:01:36 PM »

Quote
The first 6 letters "Error:" which couldn't be a file name could easily be tested for?

YUK!!

nil would be preferable
.. or look at the 'out' keyword.

Quote
Is there an exposed .NET method for MenuCmd?
Have you looked ?
Have you tried COM from managed code. ?

kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Experimenting with P/INVOKE etc
« Reply #7 on: June 05, 2010, 08:24:40 PM »

From the .NET Reference
Quote
The AutoCAD .NET API is a cross implementation of ObjectARX and ActiveX Automation. While you can access ActiveX Automation from ObjectARX, .NET API makes working with the two rather seamless. As you work with objects using the native .NET API, you can access the equivalent COM object from a property. In some cases, the COM object is the only way to access an AutoCAD feature programmatically. Some examples of properties that expose COM objects through the .NET API are, Preferences, Menubar, MenuGroups, AcadObject and AcadApplication.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Peter Jamtgaard

  • Guest
Re: Experimenting with P/INVOKE etc
« Reply #8 on: June 05, 2010, 08:31:54 PM »
I did a search for menucmd.

I didn't see it listed in my search in the object browser.

I saw some references to "internal.IPECommand..."

Is there one somewhere I missed?

I think I have tried using COM from managed code?

Isn't that

imports acadApp = ... 

Can you share a link to some good examples of what you are talking about?

Also are there any other entry points that would be useful to expose?

Peter





Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Experimenting with P/INVOKE etc
« Reply #9 on: June 05, 2010, 08:34:45 PM »
Quote
Can you share a link to some good examples of what you are talking about?


Peter, Have you worked through the Labs ?


kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Experimenting with P/INVOKE etc
« Reply #10 on: June 05, 2010, 08:38:48 PM »
Long answer short.

I haven't tried to look for the equivalent of MenuCMD.

What are you trying to do explicitly. ?

kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Experimenting with P/INVOKE etc
« Reply #11 on: June 05, 2010, 09:21:44 PM »

Peter,
You may want to look at this :
// Module AcCui.dll
Location: K:\ObjectARX_SDK\ObjectARX 2011\inc\AcCui.dll
Size: 204800 Bytes
Target Runtime: v2.0.50727
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Peter Jamtgaard

  • Guest
Re: Experimenting with P/INVOKE etc
« Reply #12 on: June 06, 2010, 05:26:48 PM »
Quote
Peter, Have you worked through the Labs ?

Are you talking about the arx sdk examples?

Peter

If not do you have a URL?

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Experimenting with P/INVOKE etc
« Reply #13 on: June 06, 2010, 05:50:52 PM »
AutoCAD .NET Labs
   AutoCAD 2010 .Net Training.zip (zip - 706Kb)
http://images.autodesk.com/adsk/files/autocad_2010_dotnet_training.zip



listed in the .NET Getting Started thread
http://www.theswamp.org/index.php?topic=32381.msg378888#msg378888


I have a memory of some menu stuff being mentioned in one of the later Labs.


The AcCui assembly may be your best bet, I haven't looked though ...

[added:] just looked.
Yes, the namespace 'Autodesk.AutoCAD.Customization' should help you.

// Module AcCui.dll
// Module AcCustomize.dll
« Last Edit: June 06, 2010, 06:07:22 PM by Kerry Brown »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Experimenting with P/INVOKE etc
« Reply #14 on: June 06, 2010, 06:14:58 PM »
Also, a quick search revealed :

Loading a partial CUI and making its toolbars visible through .NET
http://through-the-interface.typepad.com/through_the_interface/2006/11/loading_a_parti.html

Creating a partial CUI file using .NET and loading it inside AutoCAD
http://through-the-interface.typepad.com/through_the_interface/2007/05/creating_a_part.html
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.