.NET

Reply
Contributor
dj-nemo
Posts: 16
Registered: ‎08-17-2012
Message 1 of 26 (923 Views)

plugin problem in vb .net

923 Views, 25 Replies
08-18-2012 03:10 AM

Hi everyone

 

I want to make plugin for AutoCAD but i have some problems. 

 

I want to make plugin that connect to server, send there current image and then server do something with it and send back results.

So I am actualy making 2 plugins. One on server side, other on client side.

 

Server side code: 

Imports System.Net.Sockets
Imports System.Text
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports System.Net
Imports System.Threading
Imports Autodesk.AutoCAD.EditorInput

Namespace serverACDrendering

    Public Class Commands
        Dim close As Boolean = False
        Dim MAX_CLIENTS As Integer = 5
        Dim queue(MAX_CLIENTS) As ClientWrapper
        Dim currentClient As Integer = 0

        <CommandMethod("StartServer")>
        Public Sub StartServer()
            For i As Integer = 0 To MAX_CLIENTS
                queue(i) = Nothing
            Next
            Dim receiverThread As Thread = New Thread(AddressOf receiver)
            Dim transmitterThread As Thread = New Thread(AddressOf transmitter)
            receiverThread.Start()
            Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
            ed.WriteMessage("\nreceiver thread started\n}")
            transmitterThread.Start()
            ed.WriteMessage("\ntransmitter thread Started\n")
            While (Not close)
                ed.WriteMessage("\nCreated both threads... Time to rock ...\n")
            End While
        End Sub

 

 <CommandMethod("StopServer")>
        Public Sub StopServer()
            close = False
        End Sub
    End Class

 

So i have two more threads receiver thread and transmitter thread. First is getting  clients and get file from them, second send results back to them. 

 

The problem 

 While (Not close)
          ed.WriteMessage("\nCreated both threads... Time to rock ...\n")
 End While

 In this while loop i shold take one client and do something with it.

When this loop starts i cant stop it from autocad with StopServer command (I think because autocad is busy). 

I can't do this in seperate thread because autoCAD don't do multithreading.

 

What can i do to put this work in background ?

 

Regards Domen

 

 

Mentor
khoa.ho
Posts: 224
Registered: ‎09-15-2011
Message 2 of 26 (898 Views)

Re: plugin problem in vb .net

08-18-2012 10:13 AM in reply to: dj-nemo

You make AutoCAD to work as a server for both a receiver (get files from clients) and a transmitter (send results back to clients). When you start the server, both two methods receiver() and transmitter() send to execution at nearly the same time. Then the code goes to an infinite loop, write to the editor and keeps AutoCAD non-stopped busy. So there is no chance to enter the command StopServer on AutoCAD, as the editor is busy.

To stop the server, you may think to use the Timer (instead of while loop), set an interval time to check the clients. By that way, the method StartServer will have chance to avoid the infinite loop that does not allow this command to finish.

Because AutoCAD .NET API is single-threaded, make sure that there is a lock key to switch between receiver() and transmitter(). This static variable will allow only one method (receiver OR transmitter) to execute AutoCAD .NET functions at the time. We cannot let AutoCAD go multithreading.

-Khoa

Contributor
dj-nemo
Posts: 16
Registered: ‎08-17-2012
Message 3 of 26 (860 Views)

Re: plugin problem in vb .net

08-20-2012 12:57 AM in reply to: dj-nemo

Thanks for answer i repair it but ...

 

I put timer in code but i got another error: eNotApplicable

 

    Public Class Commands
        Dim close As Boolean = False
        Dim MAX_CLIENTS As Integer = 5
        Dim queue(MAX_CLIENTS) As ClientWrapper
        Dim currentClient As Integer = 0
        Dim timer As New System.Timers.Timer
        Dim editor As Editor = Application.DocumentManager.MdiActiveDocument.Editor

        <CommandMethod("StartServer")>
        Public Sub StartServer()
            For i As Integer = 0 To MAX_CLIENTS
                queue(i) = Nothing
            Next
            Dim receiverThread As Thread = New Thread(AddressOf Receiver)
            Dim transmitterThread As Thread = New Thread(AddressOf Transmitter)
            receiverThread.Start()
            editor.WriteMessage(vbNewLine & " receiver thread started" & vbNewLine)
            transmitterThread.Start()
            editor.WriteMessage(vbNewLine & " transmitter thread Started" & vbNewLine)
            timer.Enabled = True
            timer.Interval = 15000 'every 15 seconds
            AddHandler timer.Elapsed, AddressOf Work
        End Sub


        Private Sub Work()
            editor.WriteMessage(vbNewLine & "working ..." & vbNewLine)
        End Sub

 Error is rised in line "End Sub" from subroutine Work()

The Subroutines Receiver and Transmitter are empty functions for now

 

I would like that Receiver work non-stop so it can get clients all the time. Is there any way to do this?

 

Mentor
khoa.ho
Posts: 224
Registered: ‎09-15-2011
Message 4 of 26 (822 Views)

Re: plugin problem in vb .net

08-20-2012 12:42 PM in reply to: dj-nemo

I think the problem "eNotApplicable" came from the Timer running on another thread to trigger the time event. When it hit the time, this non-AutoCAD thread calls the AutoCAD editor and causes the thread violation with the current AutoCAD thread. We cannot have two threads refer to the same AutoCAD instance.

AutoCAD .NET (ObjectARX wrapper) is single-threaded (as it is not fully .NET managed code), so only one main thread allows to run per AutoCAD instance. I did a test without the Timer; it also caused an error of "CrossThreadMessagingException". So the problem is not from the Timer, it was from the new thread.

Using threads in AutoCAD .NET is very dangerous because it actually calls ObjectARX native code behind the scene. I would not use threads to call AutoCAD .NET functions. I don't know it may have another solution from official Autodesk developers.

You may try to remove threads from your code, and use TWO AutoCAD instances. One AutoCAD will work as a receiver; another AutoCAD will work as a transmitter. Then you open two AutoCAD and run different commands, one for receiver to get files from clients, another for transmitter to send results back to clients. Those two AutoCAD plugins refer to another DLL file just for data communication (non-AutoCAD code) between two AutoCAD instances. You may use While Loop again instead of Timer (as Timer may cause thread issue).

Hope it may help.
-Khoa

Contributor
dj-nemo
Posts: 16
Registered: ‎08-17-2012
Message 5 of 26 (781 Views)

Re: plugin problem in vb .net

08-21-2012 11:04 AM in reply to: dj-nemo

Thanks it helped me a lot. 

So i decided to make plugin that will work for only one client at the time, when client connected i will render his file and send back photos.

 

I make some progress but got problem with socket. When i want read from socket on client side it say it's closed.

 

 

Sorry for having so much work with me

 

Server Side code:

Imports System.Net.Sockets
Imports System.Text
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports System.Net
Imports System.IO
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD

Namespace serverACDrendering

    Public Class Command
        Dim close As Boolean = False 'when true server ends
        Dim client As ClientWrapper 'queue that holds clients and their files
        Dim editor As Editor = Application.DocumentManager.MdiActiveDocument.Editor 'editor for writing to command line
        Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
        Private Const portNum = 8000
        Private Const ipServer = "127.0.0.1"
        Private PACKET_SIZE As UInt16 = 4096
        Dim path As String = "c:\renderPluginACD\redering.dwg"

        <CommandMethod("StartServer")>
        Public Sub StartServer()
            editor.WriteMessage(vbNewLine & "starting ..." & vbNewLine)
            ' While (Not close)
            client = New ClientWrapper
            Receiver()
            Render()
            Transmitter()
            System.Threading.Thread.Sleep(2000)
            ' End While
        End Sub

        Private Sub Render()
            Dim Mstream As MemoryStream = client.GetFile
            If (Not Directory.Exists("c:\renderPluginACD")) Then
                Directory.CreateDirectory("c:\renderPluginACD")
            End If
            If (File.Exists(path)) Then
                File.Delete(path)
            End If
            Dim fs As FileStream = File.OpenWrite(path)
            Mstream.WriteTo(fs)
            client.SetResult(fs)
            fs.Close()
        End Sub

        'receive connection and put file in queue
        Private Sub Receiver()
            Dim tcpListener As TcpListener
            Dim ip As IPAddress = IPAddress.Parse(ipServer)
            tcpListener = New TcpListener(ip, portNum)
            tcpListener.Start()
            Try
                Dim TcpClient = tcpListener.AcceptTcpClient()
                If (TcpClient.Connected) Then
                    client.SetTcpClient(TcpClient)

                    Dim Reader As BinaryReader
                    Dim ReadBuffer(PACKET_SIZE) As Byte
                    Dim NData As Int32
                    Dim MStream As MemoryStream
                    Dim LData As Int32

                    Reader = New BinaryReader(TcpClient.GetStream)
                    NData = Reader.ReadInt32
                    MStream = New MemoryStream
                    While NData > 0
                        LData = TcpClient.GetStream.Read(ReadBuffer, 0, PACKET_SIZE)
                        MStream.Write(ReadBuffer, 0, LData)
                        NData -= LData
                    End While
                    editor.WriteMessage(vbNewLine & "received file ..." & vbNewLine)
                    client.SetFile(MStream)
                End If
            Catch e As Exception
            End Try
            'tcpListener.Stop()
        End Sub

        'send back the resutls
        Private Sub Transmitter()
            Dim fs As FileStream = New FileStream(path, FileMode.Open, FileAccess.Read)
            Dim length As Integer = CType(fs.Length, Integer)
            Dim reader As New BinaryReader(fs)
            Dim buffer() As Byte ' Data buffer

            Dim Writer As New BinaryWriter(client.GetTcpClient.GetStream)
            Writer.Write(length)
            Do
                'read data from file
                buffer = reader.ReadBytes(PACKET_SIZE)
                'write data to Network Stream
                Writer.Write(buffer)
            Loop While buffer.Length = PACKET_SIZE
            Writer.Flush()
            Writer.Close()
            reader.Close()
            fs.Close()
        End Sub

        'stops server
        <CommandMethod("StopServer")>
        Public Sub StopServer()
            close = False
        End Sub
    End Class


    'wrapper for clients in queue
    Public Class ClientWrapper
        Dim tcpClient As TcpClient
        Dim file As Object
        Dim result As Object
        Dim flag As Integer

        Public Function GetTcpClient() As TcpClient
            Return tcpClient
        End Function

        Public Sub SetTcpClient(_tcpClient As TcpClient)
            tcpClient = _tcpClient
        End Sub

        Public Function GetFile() As Object
            Return file
        End Function

        Public Sub SetFile(_file As Object)
            file = _file
        End Sub

        Public Function GetResult() As Object
            Return result
        End Function

        Public Sub SetResult(_result As Object)
            result = _result
        End Sub

    End Class
End Namespace

 

 

Client side Code:

Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.ApplicationServices
Imports System.Net.Sockets
Imports System.Text
Imports System
Imports System.IO
Imports Autodesk.AutoCAD.DatabaseServices

Imports app = Autodesk.AutoCAD.ApplicationServices.Application

Namespace Plugin1

    Public Class Commands
        Private Const portNum = 8000
        Private Const ipServer = "127.0.0.1"
        Private Const BUFFER_SIZE As Integer = 8192
        Dim isActive As Boolean = False
        Dim acDoc As Document
        Dim receive As Object
        Private PACKET_SIZE As UInt16 = 4096
        Dim tcpClient As New System.Net.Sockets.TcpClient()

        <CommandMethod("RenderOnHPC")>
        Public Sub SendToRenderer()
            Save()
            Connect()
            Send()
            ReceivePhoto()
        End Sub

        Private Sub Save()
            acDoc = Application.DocumentManager.MdiActiveDocument
            Dim strDWGName As String = acDoc.Name
            Dim obj As Object = Application.GetSystemVariable("DWGTITLED")
            strDWGName = "c:\renderPluginACD\MyDrawing.dwg"
            'Save the active drawing 
            If (Not Directory.Exists("c:\renderPluginACD")) Then
                Directory.CreateDirectory("c:\renderPluginACD")
            End If
            acDoc.Database.SaveAs(strDWGName, False, DwgVersion.Current, acDoc.Database.SecurityParameters)
            acDoc.Database.Dispose()
        End Sub

        Private Sub Connect()
            tcpClient.Connect(ipServer, portNum)
        End Sub

        Private Sub Send()
            Dim fs As FileStream = New FileStream("c:\renderPluginACD\MyDrawing.dwg", FileMode.Open, FileAccess.Read)
            Dim length As Integer = CType(fs.Length, Integer)
            Dim reader As New BinaryReader(fs)
            Dim buffer() As Byte ' Data buffer
            Try
                tcpClient.GetStream()
                Dim Writer As New BinaryWriter(tcpClient.GetStream())
                Writer.Write(length)
                Do
                    'read data from file
                    buffer = reader.ReadBytes(PACKET_SIZE)
                    'write data to Network Stream
                    Writer.Write(buffer)
                Loop While buffer.Length = PACKET_SIZE
                Writer.Flush()
                Writer.Close()
                reader.Close()
            Catch ex As System.Exception
                ' Handle errors
            End Try
            fs.Close()
        End Sub

        Private Sub ReceivePhoto()
            Dim renderedPath As String = "c:\renderPluginACD\return.dwg"
            Dim reader2 As BinaryReader
            Dim readBuffer(PACKET_SIZE) As Byte
            Dim nData As Int32
            Dim mStream As MemoryStream
            Dim lData As Int32

            reader2 = New BinaryReader(tcpClient.GetStream())
            nData = reader2.ReadInt32
            MStream = New MemoryStream
            While NData > 0
                LData = tcpClient.GetStream.Read(ReadBuffer, 0, PACKET_SIZE)
                MStream.Write(ReadBuffer, 0, LData)
                NData -= LData
            End While
            If (File.Exists(RenderedPath)) Then
                File.Delete(RenderedPath)
            End If
            Dim fs As FileStream = File.OpenWrite(RenderedPath)
            MStream.WriteTo(fs)
        End Sub

    End Class
End Namespace

 

 

 

Mentor
khoa.ho
Posts: 224
Registered: ‎09-15-2011
Message 6 of 26 (762 Views)

Re: plugin problem in vb .net

08-21-2012 06:20 PM in reply to: dj-nemo

Hi,

I ran your code and saw the error came from the disconnected TcpClient. On the client Send() function, when you close the BinaryWriter, it will also dispose the NetworkStream and close the reference TcpClient connection. So just comment out writer.Close() and it's good to go.

We need to open two AutoCAD instances, one types the command "StartServer", another types the command "RenderOnHPC" and we will see how the client saves DWG files.

It is interesting to make two AutoCAD working as a server and a client, and then they communicate each other by network streams using TCP (http://127.0.0.1:8000). With the TCP listening event, it does not need to use While Loop. I am guessing it still has a lot of work with this idea.

I copied your code, did some minor changes and had the final working code:

Public Class ServerPlugin
	Private Const PortNum As Integer = 8000
	Private Const IpServer As String = "127.0.0.1"
	Private Const PACKET_SIZE As UInt16 = 4096
	'when true server ends
	Private close As Boolean = False
	'queue that holds clients and their files
	Private client As ClientWrapper
	'editor for writing to command line
	Private ReadOnly editor As Editor = Application.DocumentManager.MdiActiveDocument.Editor
	Private acDoc As Document = Application.DocumentManager.MdiActiveDocument
	Private path As String = "c:\renderPluginACD\rendering.dwg"
	Private tcpClient As System.Net.Sockets.TcpClient

	<CommandMethod("StartServer")> _
	Public Sub StartServer()
		editor.WriteMessage(vbLf + "starting ..." + vbLf)
		' While (Not close)
		client = New ClientWrapper()
		Receiver()
		Render()
		Transmitter()
		Disconnect()
		System.Threading.Thread.Sleep(2000)
		' End While
	End Sub

	'receive connection and put file in queue
	Private Sub Receiver()
		Dim ip As IPAddress = IPAddress.Parse(IpServer)
		Dim tcpListener = New TcpListener(ip, PortNum)
		tcpListener.Start()
		Try
			' perform a blocking call to accept requests
			tcpClient = tcpListener.AcceptTcpClient()
			' keep waiting until a client is connected at http://127.0.0.1:8000
			If tcpClient.Connected Then
				client.SetTcpClient(tcpClient)

				Dim readBuffer = New Byte(PACKET_SIZE) {}

				Dim reader = New BinaryReader(tcpClient.GetStream())
				Dim nData As Integer = reader.ReadInt32()
				Dim mStream = New MemoryStream()
				While nData > 0
					Dim lData As Integer = tcpClient.GetStream().Read(readBuffer, 0, PACKET_SIZE)
					mStream.Write(readBuffer, 0, lData)
					nData -= lData
				End While
				editor.WriteMessage(vbLf + "received file ..." + vbLf)
				client.SetFile(mStream)
			End If
		Catch e As System.Exception
		End Try
		'tcpListener.Stop()
	End Sub

	Private Sub Render()
		Dim mStream = DirectCast(client.GetFile(), MemoryStream)
		If Not Directory.Exists("c:\renderPluginACD") Then
			Directory.CreateDirectory("c:\renderPluginACD")
		End If
		If File.Exists(path) Then
			File.Delete(path)
		End If
		Dim fs As FileStream = File.OpenWrite(path)
		mStream.WriteTo(fs)
		client.SetResult(fs)
		fs.Close()
	End Sub

	'send back the resutls
	Private Sub Transmitter()
		Dim fs = New FileStream(path, FileMode.Open, FileAccess.Read)
		Dim length As Integer = Convert.ToInt32(fs.Length)
		Dim reader = New BinaryReader(fs)
		Dim buffer As Byte()
		' Data buffer
		Dim writer = New BinaryWriter(client.GetTcpClient().GetStream())
		writer.Write(length)
		Do
			'read data from file
			buffer = reader.ReadBytes(PACKET_SIZE)
			'write data to Network Stream
			writer.Write(buffer)
		Loop While buffer.Length = PACKET_SIZE
		writer.Flush()
		writer.Close()
		reader.Close()
		fs.Close()
	End Sub

	Private Sub Disconnect()
		' shutdown and end connection
		tcpClient.Close()
	End Sub

	'stops server
	<CommandMethod("StopServer")> _
	Public Sub StopServer()
		close = False
	End Sub
End Class

'wrapper for clients in queue
Public Class ClientWrapper
	Private tcpClient As TcpClient
	Private file As Object
	Private result As Object
	Private flag As Integer

	Public Function GetTcpClient() As TcpClient
		Return tcpClient
	End Function

	Public Sub SetTcpClient(_tcpClient As TcpClient)
		tcpClient = _tcpClient
	End Sub

	Public Function GetFile() As Object
		Return file
	End Function

	Public Sub SetFile(_file As Object)
		file = _file
	End Sub

	Public Function GetResult() As Object
		Return result
	End Function

	Public Sub SetResult(_result As Object)
		result = _result
	End Sub
End Class

Public Class ClientPlugin
	Private Const PortNum As Integer = 8000
	Private Const IpServer As String = "127.0.0.1"
	Private Const BUFFER_SIZE As Integer = 8192
	Private Const PACKET_SIZE As UInt16 = 4096
	Private isActive As Boolean = False
	Private receive As Object
	Private tcpClient As System.Net.Sockets.TcpClient

	<CommandMethod("RenderOnHPC")> _
	Public Sub SendToRenderer()
		Save()
		Connect()
		Send()
		ReceivePhoto()
		Disconnect()
	End Sub

	Private Sub Save()
		Dim doc As Document = Application.DocumentManager.MdiActiveDocument
		Dim db As Database = doc.Database
		Using db
			Dim strDWGName As String = doc.Name
			Dim obj As Object = Application.GetSystemVariable("DWGTITLED")
			strDWGName = "c:\renderPluginACD\MyDrawing.dwg"
			'Save the active drawing 
			If Not Directory.Exists("c:\renderPluginACD") Then
				Directory.CreateDirectory("c:\renderPluginACD")
			End If
			db.SaveAs(strDWGName, False, DwgVersion.Current, doc.Database.SecurityParameters)
		End Using
	End Sub

	Private Sub Connect()
		tcpClient = New System.Net.Sockets.TcpClient()
		tcpClient.Connect(IpServer, PortNum)
	End Sub

	Private Sub Disconnect()
		' shutdown and end connection
		tcpClient.Close()
	End Sub

	Private Sub Send()
		Dim fs = New FileStream("c:\renderPluginACD\MyDrawing.dwg", FileMode.Open, FileAccess.Read)
		Dim length As Integer = Convert.ToInt32(fs.Length)
		Dim reader = New BinaryReader(fs)
		' Data buffer
		Try
			Dim stream As NetworkStream = tcpClient.GetStream()
			Dim writer = New BinaryWriter(stream)
			writer.Write(length)
			Dim buffer As Byte()
			Do
				'read data from file
				buffer = reader.ReadBytes(PACKET_SIZE)
				'write data to Network Stream
				writer.Write(buffer)
			Loop While buffer.Length = PACKET_SIZE
			writer.Flush()
			'writer.Close();	// do not close the TcpClient connection
			reader.Close()
				' Handle errors
		Catch ex As System.Exception
		End Try
		fs.Close()
	End Sub

	Private Sub ReceivePhoto()
		Dim renderedPath As String = "c:\renderPluginACD\return.dwg"
		Dim readBuffer = New Byte(PACKET_SIZE) {}

		Dim reader2 = New BinaryReader(Me.tcpClient.GetStream())
		Dim nData As Integer = reader2.ReadInt32()
		Using mStream = New MemoryStream()
			While nData > 0
				Dim lData As Integer = Me.tcpClient.GetStream().Read(readBuffer, 0, PACKET_SIZE)
				mStream.Write(readBuffer, 0, lData)
				nData -= lData
			End While
			If File.Exists(renderedPath) Then
				File.Delete(renderedPath)
			End If
			Dim fs As FileStream = File.OpenWrite(renderedPath)
			mStream.WriteTo(fs)
			fs.Close()
		End Using
	End Sub
End Class

 

-Khoa

Contributor
dj-nemo
Posts: 16
Registered: ‎08-17-2012
Message 7 of 26 (747 Views)

Re: plugin problem in vb .net

08-22-2012 04:21 AM in reply to: khoa.ho

Thanks it works great.

 

Now i want to upgrade code that it will actualy render file and instead returning dwg send back picture.

I was looking throu internet for some exsamples and found only one useful link. So i try use it and do following:

 

        Private Sub Render()
            Dim mStream = DirectCast(client.GetFile(), MemoryStream)
            If Not Directory.Exists("c:\renderPluginACD") Then
                Directory.CreateDirectory("c:\renderPluginACD")
            End If
            If File.Exists(path) Then
                File.Delete(path)
            End If
            Dim fs As FileStream = File.OpenWrite(path)
            mStream.WriteTo(fs)
            fs.Close()
'i saved file to here
' now i want to open it and render it Dim doc As Document = Application.DocumentManager.MdiActiveDocument doc.Database.ReadDwgFile(path, FileOpenMode.OpenTryForReadShare, True, Nothing) Dim fileName As String = "c:\renderPluginACD\picture.png" Dim vpn As Integer = System.Convert.ToInt32(Application.GetSystemVariable("CVPORT")) Dim gsv As View = doc.GraphicsManager.GetGsView(vpn, True) Dim view As View = gsv.Clone(True, True) Dim dev As Device = doc.GraphicsManager.CreateAutoCADOffScreenDevice() 'dev.OnSize(doc.GraphicsManager.DeviceIndependentDisplaySize) dev.DeviceRenderType = RendererType.FullRender dev.Add(view) Dim bitmap As Bitmap = view.RenderToImage bitmap.Save(fileName) fs = File.OpenRead(fileName) client.SetResult(fs) End Sub

 

The problems occurs with reading dwg file. 

Mentor
khoa.ho
Posts: 224
Registered: ‎09-15-2011
Message 8 of 26 (712 Views)

Re: plugin problem in vb .net

08-22-2012 05:26 PM in reply to: dj-nemo

I am a bit late to answer as I am working at day time (US CST).

There are some points to solve the problem:

1. You should not use ReadDwgFile() from the current database of MdiActiveDocument as it will cause "eRepeatedDwgRead" error. Reading an external DWG file from the current DWG file is not allowed. It's better to use database.Insert method. Instead, we will use Application.DocumentManager.Open(dwgPath).

2. There is nothing to render on the DWG source file (c:\renderPluginACD\rendering.dwg). This file should not be empty or have no Modelling entities. The DWG rendering file should have some Modelling objects (Sphere, Box, Cylinder...) to render. Otherwise, it will cause error at view.RenderToImage() method. I already added the code to check this exception error (view.BackgroundId == ObjectId.Null).

3. If I put some Modelling entities on rendering.dwg, the code will output an image (picture.png) correctly. So you have to work to pass entities to render. There is nothing to render now so you won't see anything.

 

4. You should use Using to wrap the code to release unmanaged objects after finishing the method. I put the code with Using from Kean's code back.

Please see my fixed code:

Private Sub Render()
	Dim mStream = DirectCast(client.GetFile(), MemoryStream)
	If Not Directory.Exists("c:\renderPluginACD") Then
		Directory.CreateDirectory("c:\renderPluginACD")
	End If
	If File.Exists(path) Then
		File.Delete(path)
	End If
	Dim fs As FileStream = File.OpenWrite(path)
	mStream.WriteTo(fs)
	fs.Close()
	'i saved file to here
	' now i want to open it and render it
	Dim doc As Document = Application.DocumentManager.Open(path)

	Dim fileName As String = "c:\renderPluginACD\picture.png"
	Dim vpn As Integer = System.Convert.ToInt32(Application.GetSystemVariable("CVPORT"))
	Dim gsv As GraphicsSystem.View = doc.GraphicsManager.GetGsView(vpn, True)
	Using view As GraphicsSystem.View = gsv.Clone(True, True)
		' Do not render the drawing if there are no rendering objects
		If view.BackgroundId = ObjectId.Null Then
			Return
		End If

		Using dev As Device = doc.GraphicsManager.CreateAutoCADOffScreenDevice()
			'dev.OnSize(doc.GraphicsManager.DeviceIndependentDisplaySize)
			dev.DeviceRenderType = RendererType.FullRender
			dev.Add(view)
			Using bitmap As Bitmap = view.RenderToImage()
				bitmap.Save(fileName)
				fs = File.OpenRead(fileName)
				client.SetResult(fs)
			End Using
		End Using
	End Using
End Sub

 

-Khoa

Contributor
dj-nemo
Posts: 16
Registered: ‎08-17-2012
Message 9 of 26 (693 Views)

Re: plugin problem in vb .net

08-23-2012 02:14 AM in reply to: khoa.ho

Hi

 

the solution you wrote don't work for me because i am working on AutoCAD 2013 and therefor ObjectARX for AutoCAD 2013. 

 

I repaired in this way:

Private Sub Render()
            Dim mStream = DirectCast(client.GetFile(), MemoryStream)
            If Not Directory.Exists("c:\renderPluginACD") Then
                Directory.CreateDirectory("c:\renderPluginACD")
            End If
            If File.Exists(path) Then
                File.Delete(path)
            End If
            Dim fs As FileStream = File.OpenWrite(path)
            mStream.WriteTo(fs)
            fs.Close()
            Dim docCol As DocumentCollection = Application.DocumentManager
            Dim doc As Document
            doc = DocumentCollectionExtension.Open(docCol, path)
            Dim fileName As String = "c:\renderPluginACD\picture.png"
            Dim vpn As Integer = System.Convert.ToInt32(Application.GetSystemVariable("CVPORT"))
            Dim gsv As GraphicsSystem.View = doc.GraphicsManager.GetGsView(vpn, True)
            Using view As GraphicsSystem.View = gsv.Clone(True, True)
                ' Do not render the drawing if there are no rendering objects
                If view.BackgroundId = ObjectId.Null Then
                    Return
                End If
                Using dev As Device = doc.GraphicsManager.CreateAutoCADOffScreenDevice()
                    dev.DeviceRenderType = RendererType.FullRender
                    dev.Add(view)
                    Using bitmap As Bitmap = view.RenderToImage()
                        bitmap.Save(fileName)
                        fs = File.OpenRead(fileName)
                        client.SetResult(fs)
                    End Using
                End Using
            End Using
        End Sub

 

Problem happens when it's called renderToImage() function. I think that's because on server they are actualy opened 2 files. First is empty drawing that is there from the start and another drawing that i send from the client(it openes in new window)

 

Mentor
khoa.ho
Posts: 224
Registered: ‎09-15-2011
Message 10 of 26 (685 Views)

Re: plugin problem in vb .net

08-23-2012 07:45 AM in reply to: dj-nemo

I use AutoCAD 2009 at work so I did not test it with 2013. The code was from C# that converted to VB.

 

To bypass the error of RenderToImage() function, you need to put some modelling entities in the file rendering.dwg to render. I have to use breakpoints on VS debugging to stop the code execution, open file rendering.dwg in AutoCAD, draw some 3D objects, save and close it. Then release the breakpoint to allow .NET code to continue. It works for me to produce an image (picture.png).

 

I will review the whole code by the end of the day. The code is not completed so I have to debug and insert something during the whole process to make it works.

 

-Khoa

Post to the Community

Have questions about Autodesk products? Ask the community.

New Post
Announcements
Are You Going To Be @ AU 2014? Feel free to drop by our AU topic post and share your plans, plug a class that you're teaching, or simply check out who else from the community might be in attendance. Ohh and don't forgot to stop by the Autodesk Help | Learn | Collaborate booths in the Exhibit Hall and meet our community team if you get a chance!