Using Dllimport for AutoCAD2020

Using Dllimport for AutoCAD2020

gyanendra.gurung4NKYM
Participant Participant
2 757 Visites
6 Réponses
Message 1 sur 7

Using Dllimport for AutoCAD2020

gyanendra.gurung4NKYM
Participant
Participant

Dear Mentors  @_gile ,

 

1. I am trying to create a viewport through C# and I was testing the code available on Autodesk 
http://help.autodesk.com/view/ACD/2016/ENU/?guid=GUID-61C22902-F63B-4204-86EC-FA37312D1B6E

 

2. When I run this program with AUTOCAD 2020, I get this error

Capture.PNG 

 

3. I tried replacing "acad.exe" with "acdb23.dll" or "accoremgd.dll" and it did not work. 

 

4. As a novice, the use of DLLIMPORT and ENTRYPOINT are both very new to me and I am really excited to learn more about it. But, at the same time I also want to know WHERE and HOW do I figure out the ENTRYPOINTs of acad.exe in my computer? Does AUTODESK have a reference on the website? 

 

Many many thanks 

Kenny

using System.Runtime.InteropServices;
 
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
 
[DllImport("acad.exe", CallingConvention = CallingConvention.Cdecl,
 EntryPoint = "?acedSetCurrentVPort@@YA?AW4ErrorStatus@Acad@@PBVAcDbViewport@@@Z")]
extern static private int acedSetCurrentVPort(IntPtr AcDbVport);
 
[CommandMethod("CreateFloatingViewport")]
public static void CreateFloatingViewport()
{
    // Get the current document and database, and start a transaction
    Document acDoc = Application.DocumentManager.MdiActiveDocument;
    Database acCurDb = acDoc.Database;

    using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
    {
        // Open the Block table for read
        BlockTable acBlkTbl;
        acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId,
                                     OpenMode.ForRead) as BlockTable;

        // Open the Block table record Paper space for write
        BlockTableRecord acBlkTblRec;
        acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.PaperSpace],
                                        OpenMode.ForWrite) as BlockTableRecord;

        // Switch to the previous Paper space layout
        Application.SetSystemVariable("TILEMODE", 0);
        acDoc.Editor.SwitchToPaperSpace();

        // Create a Viewport
        using (Viewport acVport = new Viewport())
        {
            acVport.CenterPoint = new Point3d(3.25, 3, 0);
            acVport.Width = 6;
            acVport.Height = 5;

            // Add the new object to the block table record and the transaction
            acBlkTblRec.AppendEntity(acVport);
            acTrans.AddNewlyCreatedDBObject(acVport, true);

            // Change the view direction
            acVport.ViewDirection = new Vector3d(1, 1, 1);

            // Enable the viewport
            acVport.On = true;

            // Activate model space in the viewport
            acDoc.Editor.SwitchToModelSpace();

            // Set the new viewport current via an imported ObjectARX function
            acedSetCurrentVPort(acVport.UnmanagedObject);
        }

        // Save the new objects to the database
        acTrans.Commit();
    }
}
0 J'aime
Solutions acceptées (3)
2 758 Visites
6 Réponses
Replies (6)
Message 2 sur 7

_gile
Consultant
Consultant
Solution acceptée

Hi,

 

Since A2013, the first argument should be "accore.dll", but the EntryPoint might change at each major version.

You should be able to avoid P/Invoking acedSetCurrentVPort by changing the CVPORT system variable with the ViewPort.Number:

 

Application.SetSystemVariable("CVPORT", acVPort.Number);


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 sur 7

gyanendra.gurung4NKYM
Participant
Participant

Dear @_gile 

 

1. I wanted to take some time to read more about DLLIMPORT and try out your solution (and also understand it). But, I could not resolve my issue. However, the only workaround my issues was to run a short lisp script inside the .net code. However, you have written several times to many members on this forum about the problems/dangers of running lisp code with .net. But, I just could not find any other solution to convert my lisp code to a .net code. 

 

2. This is what I want to do in .net. It is part of an alignment sheet program that I originally wrote in Autolisp. At the moment, I am trying to convert everything into C#. 

;; Creates a viewport with input central coordinates and dimensions. 
;; Then, it zooms into the center point of the modelspace object to 
;; view in the viewport. Then, it scales the viewport assuming that 
;; 1 unit in paperspace = 1 mm and 1 unit in modelspace = 1 meter. 

(defun c:create_zoom_and_rotate_viewport ( / input_as_string delim param_lst, 
                                          midpt_x midpt_y planRotationAng 
                                          planViewPortHeight planViewPortLength
                                          psBandCenterX psBandCenterY
                                          magnificationValue psMapScaleFactor)
  
  (setq acDoc (vla-get-activeDocument (vlax-get-acad-Object )))
  
  ;; ---------- I N P U T   P A R A M E T E R S ----------;;
  ;; Get input parameters as a long concatenated string
  ;; (setq input_as_string (getstring T "")) 

  (setq input_as_string "1682,1227,200,50,140,115,10,-5,100")
  (setq param_lst (sparse_string input_as_string)) ;; string to list  
  
  ;; Central coordinates (in modelspace units) of object to view 
  ;; through viewport
  (setq midpt_x (atof (nth 0 param_lst)))
  (setq midpt_y (atof (nth 1 param_lst)))

  ;; Dimension of Viewport (in paperspace units)
  (setq planViewPortLength (atof (nth 2 param_lst)))
  (setq planViewPortHeight (atof (nth 3 param_lst)))

  ;; Central coordinates (in paperspace units) of viewport
  (setq psBandCenterX (atof (nth 4 param_lst)))
  (setq psBandCenterY (atof (nth 5 param_lst)))  
  
  ;; Zoom level, rotation angle, and map scale value
  (setq magnificationValue (atof (nth 6 param_lst))) 
  (setq planRotationAng (atof (nth 7 param_lst)))
  (setq psMapScaleFactor (atof (nth 8 param_lst)))
  
  ;; -----------------------------------------------------;;
  (foreach layout (layoutlist)
    
    (setvar "ctab" layout)
    
    ;; Center point of ViewPort                                      ;;
    (setq centerPt (vlax-3d-point psBandCenterX psBandCenterY 0) )  
    
    ;; Set paperspace
    (vla-put-ActiveSpace acDoc acPaperSpace)
    (setq pspace (vla-get-PaperSpace acDoc)) 
    
    ;; Prepare viewport object    
    (setq planViewPort (vla-addPViewPort pspace centerPt planViewPortLength planViewPortHeight )) 
    (vla-Display planViewPort :vlax-true)    
    
    ;; Before making a paper space Viewport active, the mspace 
    ;; property needs to be True
    (vla-put-MSpace acDoc :vlax-true)
    (vla-put-ActivePViewport acDoc planViewPort)
    
    ;; TEST OUTPUT ;;
    (print "Plan Viewport activated")
    
    (setq zcenter (vlax-3d-point midpt_x midpt_y 0))
    (vla-ZoomCenter (vlax-get-acad-object) zcenter magnificationValue)
    
    ;; TEST OUTPUT ;;
    (print "Zoomed to Midpoint of Plan View")      
    
    ;; Rotate model inside viewport as per the rotation of North Arrow
    (command "_.DVIEW" ""  "_TW" planRotationAng "") 
    
    ;; TEST OUTPUT ;;
    (print "Map rotated")	        
    
    ;; Calculate "Custom Scale" of viewport 
    ;; for metric units, assuming 1 unit = 1 mm in paperspace
    ;; and 1 unit = 1 meter in modelspace
    (setq custom_Scale (/ 1000 psMapScaleFactor))
    
    ;; Close and lock modelspace of viewport
    (vla-put-MSpace acDoc :vlax-false)
    (vla-put-CustomScale planViewPort custom_Scale)
    (vlax-put-property planViewPort 'DisplayLocked :vlax-true)     
  )  
)

;; Function to sparse string into list 
(defun sparse_string (input_string )
(while (setq working_string (vl-string-search "," input_string))
(setq out_list (cons (substr input_string 1 working_string) out_list))
(setq input_string (substr input_string (+ working_string 2)))
)
(reverse (cons input_string out_list))
)

3. To run this, I simply use:

AcAp.DocumentManager.MdiActiveDocument.SendStringToExecute("._CREATE_ZOOM_AND_ROTATE_VIEWPORT ", true, false, false);

(*NOTE: I found the autolisp function is called LAST(AT-THE-END), i.e. after all of the C# code is executed)

 

4. If I avoid AutoLISP, then I can do it partially by defining the four corners of the viewport with this:

Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
ed.Command("MVIEW", "P", "99,110", "99,195", "415,195", "415,110", "C");

 

5. Now, the help file on creating a viewport on Autodesk's website (which I included in my original post) seem to be the best option to use, but it does not work, mainly because 
(a) I do not know what is the ENTRY POINT for Viewport is in AutoCad 2021

(b) I would like to find/search the ENTRY POINT on my own, but I cannot find any references on how I can accomplish this. How do I find the entry point name for the dlls in AutoCAD? I have seen so many other posts by others using DLLIMPORT for other functions, but no one says where and how to find the STRING NAME of the entry point. 

 

Once again, thank you very much for your patience and answer. 

 

Kenny

 

 

 

 

 

 

 

0 J'aime
Message 4 sur 7

Solution acceptée

@gyanendra.gurung4NKYM 

(b) https://adndevblog.typepad.com/autocad/2012/07/decorated-names-with-dependency-walker-tool.html

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

Message 5 sur 7

gyanendra.gurung4NKYM
Participant
Participant

Hi Alexander, 

 

Many thanks for your reply. I shall try this out and reply in this post later. 

 

Kenny

0 J'aime
Message 6 sur 7

Solution acceptée

Other method is using dumpbin.exe (this file in Visual Studio) in order to get Export Table of lib-file from ObjectARX SDK or exe/dll from AutoCAD

For example, attached file with result of command line (from ObjectARX SDK 2021\lib-x64\accore.lib) :

dumpbin.exe /exports accore.lib > accore.lib.txt

 

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

Message 7 sur 7

gyanendra.gurung4NKYM
Participant
Participant

Hi @Alexander.Rivilis 

 

Thank you very much for your prompt reply and additional suggestions. I finally found the correct ENTRYPOINT.

 

To use the AutoCAD example  for AutoCAD 2021 to create a viewport with C#.NET,  we should change the following code (in the example):

 

[DllImport("acad.exe", CallingConvention = CallingConvention.Cdecl,
 EntryPoint = "?acedSetCurrentVPort@@YA?AW4ErrorStatus@Acad@@PBVAcDbViewport@@@Z")]

 

to the following:

 

[DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl, 
EntryPoint = "?acedSetCurrentVPort@@YA?AW4ErrorStatus@Acad@@PEBVAcDbViewport@@@Z")]

 

By doing so, one can easily create viewports. This is so exciting !

 

Many many thanks to the mentors: @Alexander.Rivilis  for the sending me the link to the Dependency Walker program, and to @_gile  for showing me the correct the dll ("accore.dll") to use. .

 

 

0 J'aime