Тема: Вопрос Н.Н.Полещуку по VB.NET

Уважаемый, Николай Николаевич, в аннотации к вашей книге -
"AutoCAD: разработка приложений, настройка и адаптация"
упоминается и VB.NET, поэтому обращаюсь к вам с вопросом, ответ на который не могу найти в других источниках.
    Возможно ли в принципе создание на VB.NET клиентского Приложения под AutoCAD, где как, например, в оффисных Приложениях создается объект AutoCAD.Application, и его свойства используются для доступа к объектам чертежа.
Дело в том, что мои попытки создать такое Приложение постоянно натыкаются на исключение (ошибку), сообщение о котором не поддаются адекватной интерпретации (думаю, что врет отладчик...). С другой стороны, этот же код прекрасно работает, будучи загружен в AutoCAD командой NETLOAD в качестве компонента-сервера. И все примеры кода под AutoCAD, которые мне удалось найти, расчитаны именно на этод способ применения. Однако, применим такой подход только для AutoCAD2005 и выше, где есть команда NETLOAD.
В этой связи, вопрос: Может быть разработчики AutoCAD и VB.NET сознательно ограничили применимость языка VB.NET, оставив для него только более поздние версии  AutoCAD'а?
Возможно, вам что-либо известно об этом?
Спасибо.

Re: Вопрос Н.Н.Полещуку по VB.NET

> LeonidSN
Создать такое приложение возможно (для всех ли версий - не знаю). В главе 7 есть раздел "Метод CreateObject. Доступ к AutoCAD". Привожу из него пример для VB.NET 2002. Это приложение (собирается в exe-файл), которое после старта открывает свое окно, после щелчка по кнопке запускает AutoCAD 2006, создает DWG-файл, строит в нем объект.

' Н.Н.Полещук, Глава 07\Book11\VbNetAcadAccess.vb
' В книге "AutoCAD: разработка приложений, настройка и адаптация"
' (издательство "БХВ-Петербург", 2005)
'
Imports Autodesk.AutoCAD.Interop
Imports Autodesk.AutoCAD.Interop.Common
Public Class Form1
    Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
    Public Sub New()
        MyBase.New()
        'This call is required by the Windows Form Designer.
        InitializeComponent()
        'Add any initialization after the InitializeComponent() call
    End Sub
    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub
    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer
    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.
    'Do not modify it using the code editor.
    Friend WithEvents Button1 As System.Windows.Forms.Button
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.Button1 = New System.Windows.Forms.Button()
        Me.SuspendLayout()
        '
        'Button1
        '
        Me.Button1.Location = New System.Drawing.Point(104, 104)
        Me.Button1.Name = "Button1"
        Me.Button1.TabIndex = 0
        Me.Button1.Text = "Button1"
        '
        'Form1
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(292, 273)
        Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.Button1})
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.ResumeLayout(False)
    End Sub
#End Region
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        AcadAccess()
    End Sub
    Public Sub AcadAccess()
        On Error Resume Next
        Dim AcadApp As AcadApplication
        Dim ActDoc As AcadDocument
        ' Проверка открытого окна AutoCAD
        AcadApp = GetObject(, "AutoCAD.Application.16.2")
        If Err.Number <> 0 Then
            Err.Clear()
            AcadApp = CreateObject("AutoCAD.Application.16.2")
        End If
        ' Видимость
        AcadApp.Visible = True
        ' Активный рисунок
        ActDoc = AcadApp.ActiveDocument
        Dim lineObj As AcadLine
        ' Точки
        Dim StartPoint(2) As Double
        Dim EndPoint(2) As Double
        StartPoint(0) = 1.0#
        StartPoint(1) = 1.0#
        StartPoint(2) = 0.0#
        EndPoint(0) = 250.0#
        EndPoint(1) = 250.0#
        EndPoint(2) = 50.0#
        ' Построение отрезка
        lineObj = ActDoc.ModelSpace.AddLine(StartPoint, EndPoint)
    End Sub
End Class

Re: Вопрос Н.Н.Полещуку по VB.NET

> Н.Н.Полещук
Код сработал, причем скомпилирован он был на VS.NET2003.
Большое спасибо!
Однако попытки создать Приложение под ACAD2002,ACAD2003 (соответственно, версии 15.06 и 16.0) заканчиваются сообщением об ошибке:Cannot create AtiveX component.
Видимо, VB.NET это инструмент только для ACAD2005 и выше. А жаль... Ведь в ходу еще много Автокадов предыдущих поколений. Может быть удастся сочинить какой-нибудь переходник?
Например, от VBA к VB.NET.

Re: Вопрос Н.Н.Полещуку по VB.NET

В предыдущий пост вкралась ошибка - конечно, ACAD2002,ACAD2004

Re: Вопрос Н.Н.Полещуку по VB.NET

> LeonidSN
Возможно я чего-то недопонял, так как очень далек от VBA и VB.NET
Тем не менее вот этот код я скомпилировал в VB.NET 2002, получил exe-файл, который благополучно запустил AutoCAD 2002, отрисовал отрезок, сохранил чертеж и завершил работу AutoCAD:

Imports AutoCAD
    Public Sub AcadAccess()
        On Error Resume Next
        Dim AcadApp As AcadApplication
        Dim ActDocs As AcadDocuments
        Dim ActDoc As AcadDocument
        AcadApp = CreateObject("AutoCAD.Application.15")
        ' Видимость
        AcadApp.Visible = True
        ActDocs = AcadApp.Documents
        ActDoc = ActDocs.Add
        Modelspace = ActDoc.ModelSpace
        Dim lineObj As AcadLine
        ' Точки
        Dim StartPoint(2) As Double
        Dim EndPoint(2) As Double
        StartPoint(0) = 1.0#
        StartPoint(1) = 1.0#
        StartPoint(2) = 0.0#
        EndPoint(0) = 250.0#
        EndPoint(1) = 250.0#
        EndPoint(2) = 50.0#
        ' Построение отрезка
        lineObj = ActDoc.ModelSpace.AddLine(StartPoint, EndPoint)
        ActDoc.SaveAs("C:\Test.dwg")
        AcadApp.Quit()
    End Sub

Что-то не так?

Re: Вопрос Н.Н.Полещуку по VB.NET

> Александр Ривилис
В таком случае моя проблема, по-видимому, упирается в набор библиотек обслуживающих AutoCAD. У меня стоят acmgd.dll & acdbmgd.dll версии: 16.2.54.0, а у вас?

Re: Вопрос Н.Н.Полещуку по VB.NET

> LeonidSN
Я просто подключил не .NET, а COM-библиотеку acad.tlb, а она сама генерирует Interop.AutoCAD.dll
Очевидно, что с .NET библиотеками от AutoCAD 2005-2006 в AutoCAD 2002,2004 ничего работать не будет.

Re: Вопрос Н.Н.Полещуку по VB.NET

Наконец, стало что-то получаться, большое спасибо тем, кто помог.

> Александр Ривилис
Насчет "очевидности" могу сказать, что для меня такой ход как подключить " не .NET, а COM-библиотеку acad.tlb, а она сама генерирует Interop.AutoCAD.dll" был далеко не очевиден.
Кроме того, предполагал что библиотеки для последующих версий продукта (AutoCAD) будут обеспечивать обратную совместимость...Однако, увы!

Re: Вопрос Н.Н.Полещуку по VB.NET

LeonidSN пишет:

Кроме того, предполагал что библиотеки для последующих версий продукта (AutoCAD) будут обеспечивать обратную совместимость...

Скажу честно, что обратная совместимость на уровне dll-файлов мне даже в голову не приходила. Это настолько сложно реализовать (если вообще возможно), что (IMHO) у Autodesk даже мыслей об этом возникать не должно было. :) И для будующих версий AutoCAD этого ожидать не следует.

Re: Вопрос Н.Н.Полещуку по VB.NET

Извините какие библиотеки .NET вы подключаете для создания следуещего приложения если можно то
подробнее. Заранее спасибо.
Imports AutoCAD
    Public Sub AcadAccess()
        On Error Resume Next
        Dim AcadApp As AcadApplication
        Dim ActDocs As AcadDocuments
        Dim ActDoc As AcadDocument
        AcadApp = CreateObject("AutoCAD.Application.15")
        ' Видимость
        AcadApp.Visible = True
        ActDocs = AcadApp.Documents
        ActDoc = ActDocs.Add
        Modelspace = ActDoc.ModelSpace
        Dim lineObj As AcadLine
        ' Точки
        Dim StartPoint(2) As Double
        Dim EndPoint(2) As Double
        StartPoint(0) = 1.0#
        StartPoint(1) = 1.0#
        StartPoint(2) = 0.0#
        EndPoint(0) = 250.0#
        EndPoint(1) = 250.0#
        EndPoint(2) = 50.0#
        ' Построение отрезка
        lineObj = ActDoc.ModelSpace.AddLine(StartPoint, EndPoint)
        ActDoc.SaveAs("C:\Test.dwg")
        AcadApp.Quit()
    End Sub

Re: Вопрос Н.Н.Полещуку по VB.NET

ой извините я не тот код вставил
' Н.Н.Полещук, Глава 07\Book11\VbNetAcadAccess.vb
' В книге "AutoCAD: разработка приложений, настройка и адаптация"
' (издательство "БХВ-Петербург", 2005)
'
Imports Autodesk.AutoCAD.Interop
Imports Autodesk.AutoCAD.Interop.Common
Public Class Form1
    Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
    Public Sub New()
        MyBase.New()
        'This call is required by the Windows Form Designer.
        InitializeComponent()
        'Add any initialization after the InitializeComponent() call
    End Sub
    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub
    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer
    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.
    'Do not modify it using the code editor.
    Friend WithEvents Button1 As System.Windows.Forms.Button
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.Button1 = New System.Windows.Forms.Button()
        Me.SuspendLayout()
        '
        'Button1
        '
        Me.Button1.Location = New System.Drawing.Point(104, 104)
        Me.Button1.Name = "Button1"
        Me.Button1.TabIndex = 0
        Me.Button1.Text = "Button1"
        '
        'Form1
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(292, 273)
        Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.Button1})
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.ResumeLayout(False)
    End Sub
#End Region
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        AcadAccess()
    End Sub
    Public Sub AcadAccess()
        On Error Resume Next
        Dim AcadApp As AcadApplication
        Dim ActDoc As AcadDocument
        ' Проверка открытого окна AutoCAD
        AcadApp = GetObject(, "AutoCAD.Application.16.2")
        If Err.Number <> 0 Then
            Err.Clear()
            AcadApp = CreateObject("AutoCAD.Application.16.2")
        End If
        ' Видимость
        AcadApp.Visible = True
        ' Активный рисунок
        ActDoc = AcadApp.ActiveDocument
        Dim lineObj As AcadLine
        ' Точки
        Dim StartPoint(2) As Double
        Dim EndPoint(2) As Double
        StartPoint(0) = 1.0#
        StartPoint(1) = 1.0#
        StartPoint(2) = 0.0#
        EndPoint(0) = 250.0#
        EndPoint(1) = 250.0#
        EndPoint(2) = 50.0#
        ' Построение отрезка
        lineObj = ActDoc.ModelSpace.AddLine(StartPoint, EndPoint)
    End Sub
End Class

Re: Вопрос Н.Н.Полещуку по VB.NET

Для AutoCAD'а 200X (где X - 4,5,6):
AutoCAD 200X Type Library и AutoCAD/ObjectDBX Common 16.0 Type Library
Для AutoCAD 2007:
AutoCAD 2007 Type Library и AutoCAD/ObjectDBX Common 17.0 Type Library

Re: Вопрос Н.Н.Полещуку по VB.NET

P.S.: Так как в коде есть строка

AcadApp = GetObject(, "AutoCAD.Application.16.2")

то речь идет об AutoCAD 2006

Re: Вопрос Н.Н.Полещуку по VB.NET

Спасибо. Добавил в проект указанные вами библиотеки но после запуска приложения и нажатия кнопки Автокад не запускается а если вручную запускаешь то не вычерчивается указанная линия. У меня стоит AutoCAD 2005.
Я так думаю в строке
AcadApp = GetObject(, "AutoCAD.Application.16.2")
неправильно указанна версия? Помогите разобраться. Заранее спасибо.

Re: Вопрос Н.Н.Полещуку по VB.NET

Ой извините уже разобрался (вообще убрал номер версии) большое спасибо.

Re: Вопрос Н.Н.Полещуку по VB.NET

Для AutoCAD 2005 можно еще указать:

AcadApp = GetObject(, "AutoCAD.Application.16.1")

Re: Вопрос Н.Н.Полещуку по VB.NET

Господа!
Я только начал разбираться с доступом к AutoCAD через COM. Подскажите, как получить доступ к ссылкам на определенный блок в чертеже. Затем нужно из этих ссылок извлечь значение определенных атрибуты. В VisualStudio2008 я сделал такую штуку:

Imports System.IO
Imports Autodesk.AutoCAD.Interop
Imports Autodesk.AutoCAD.Interop.Common
Public Class mainForm
    Dim ndFile, ndAttr, ndSpace As TreeNode
    Dim acaddwg As IAcadDocument 'переменная для работы с активным чертежом
    Dim dwgblocks As IAcadBlocks 'переменная для работы с коллекцией блоков в чертеже
    Dim dwgcurrblock As IAcadBlock 'переменная для работы с отдельным блоком в чертеже
    Dim dwgcurrblockref As IAcadBlockReference 'переменная для работы со ссылкой на блок
    Dim blockattrs As Object
    Dim acadapp As IAcadApplication 'переменная для работы с приложением AutoCAD
    Private Sub DwgOpenLbl_LinkClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) Handles DwgOpenLbl.LinkClicked
        Select Case OpenDwgDialog.ShowDialog()
            Case Windows.Forms.DialogResult.OK
                AddFileToTreeView()
            Case Windows.Forms.DialogResult.Cancel
                Exit Sub
        End Select
    End Sub
    Private Sub AppendAttributesToDwg()
        acadapp = GetAcadApplication(True)
        acaddwg = acadapp.ActiveDocument
        dwgblocks = acaddwg.Blocks
        dwgcurrblock = dwgblocks.Item("Kr_MultiPosiciaLeader")
        dwgcurrblockref = dwgcurrblock.Item(1)'ВОТ ЗДЕСЬ ПРОБЛЕМА! Как получить ссылки на определенные блок. Потом уже просто. Определяем их количество и в цикле читаем значения атрибутов.
        blockattrs = dwgcurrblockref.GetAttributes
        Dim strattr As String = ""
        For i As Integer = LBound(blockattrs) To UBound(blockattrs)
            strattr = strattr + " Tag: " + blockattrs(i).TagString + vbCrLf + _
            " Value: " + blockattrs(i).textString
        Next
        MsgBox("Атрибуты для блока " & dwgcurrblockref.Name & " такие: " & vbCrLf & strattr)
    End Sub
    Private Sub AddFileToTreeView()
        ndFile = New TreeNode(Path.GetFullPath(OpenDwgDialog.FileName), 0, 0)
        DwgTreeView.Nodes.Add(ndFile)
        AppendAttributesToDwg()
    End Sub
    Private Function GetAcadApplication(ByVal visible As Boolean) As IAcadApplication
        Dim v As Object
        Try
            v = GetObject(, "AutoCAD.Application")
        Catch ex As Exception
            v = CreateObject("AutoCAD.Application")
        End Try
        Return v
        v.Visible = visible
    End Function
End Class

К приложению доступ есть, документ открывается, блоки в документе вижу и могу работать с ними, а вот ссылки на блоки не получается достать. В help к AutoCAD прочитал, что доступ к ссылке на блок можно получить через:

ModelSpace.Item
PaperSpace.Item
Block.Item

Но как — не написано. Если перебирать все элементы чертежа по типу, то при большом чертеже это будет геморроем.
Надеюсь на помощь спецов, думаю не одному мне эта тема интересна.