VB.Net getting eLockViolation error with OpenMode.ForWrite

VB.Net getting eLockViolation error with OpenMode.ForWrite

Jedimaster
Collaborator Collaborator
3,750 Views
2 Replies
Message 1 of 3

VB.Net getting eLockViolation error with OpenMode.ForWrite

Jedimaster
Collaborator
Collaborator

I have a VB.NET routine that is supposed to batch process drawing files finding and replacing text. I am having the user create select drawing files the routine writes the file names and locations to a text file. Once the drawing list written, it is opened and the drawings are processed one by one. The processing is handled by a subroutine that collect all text and mtext entities. Then the routine searches and replaces all matches, save and close. If I manually open and run the findandreplace subroutine it works fine. If it runs though the BatchRoutine I'm getting eLockViolation error on the OpenMode.ForWrite portion of the routine. I can resume on error and it does not crash out but does not make changes. In some of the other posts I was reading about AcAxDocLock but only found examples of C++.

 

Any help or insight would be much appreciated.

 

 

Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.ApplicationServices.DocumentCollectionExtension
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Windows
Imports System.IO
Public Class Main
<Autodesk.AutoCAD.Runtime.CommandMethod("Test")>
Public Sub BatchRoutine()
If File.Exists(FileList) Then
If File.ReadAllLines(FileList).Length = 0 Then
MsgBox("No drawing files found!" & vbCrLf & "Aborting!")
Exit Sub
Else
Dim sr = New StreamReader(FileList)
Dim CurrentDrawingFile As String
Do While sr.Peek() >= 0
CurrentDrawingFile = sr.ReadLine()
If File.Exists(CurrentDrawingFile) Then
Dim dm As DocumentCollection = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager
Dim doc As Document = dm.Open(CurrentDrawingFile, False)
Dim ActiveDrawing As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
If ActiveDrawing.IsReadOnly = False And ActiveDrawing.IsActive = True Then
Call FindandReplace()
Else
MsgBox(ActiveDrawing.Name & " is Read Only")
End If
ActiveDrawing.SendStringToExecute("QSAVE" & vbCr & "QSAVE" & vbCr, True, False, False)
DocumentExtension.CloseAndDiscard(ActiveDrawing)
End If
Loop
sr.Close()
End If
Else
MsgBox("File list was not found!" & vbCrLf & "Aborting!")
Exit Sub
End If
End Sub
Public Sub FindandReplace()
Dim CurrentFind As String = "TEXT TO FIND"
Dim CurrentReplace As String = "TEXT TO REPLACE"
Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
Dim acTypValAr(3) As TypedValue
acTypValAr.SetValue(New TypedValue(DxfCode.Operator, "<or"), 0)
acTypValAr.SetValue(New TypedValue(DxfCode.Start, "TEXT"), 1)
acTypValAr.SetValue(New TypedValue(DxfCode.Start, "MTEXT"), 2)
acTypValAr.SetValue(New TypedValue(DxfCode.Operator, "or>"), 3)
Dim acSelFtr As SelectionFilter = New SelectionFilter(acTypValAr)
Dim acSSPrompt As PromptSelectionResult
acSSPrompt = ed.SelectAll(acSelFtr)
If acSSPrompt.Status = PromptStatus.OK Then
Dim acSSet As SelectionSet = acSSPrompt.Value
Dim trans As Transaction = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction
For Each selObj In acSSet
Select Case selObj.ObjectId.ObjectClass.Name
Case "AcDbText"
Dim WtextObj As DBText = trans.GetObject(selObj.ObjectId, OpenMode.ForWrite, False, True)
Dim RtextObj As DBText = trans.GetObject(selObj.ObjectId, OpenMode.ForRead, False, True)
Dim OldTextString As String = RtextObj.TextString
Dim NewTextString As String = Replace(OldTextString, CurrentFind, CurrentReplace, 1, -1, CompareMethod.Text)
RtextObj.Dispose()
If OldTextString <> NewTextString Then
WtextObj.TextString = NewTextString
End If
WtextObj.Dispose()
Case "AcDbMText"
Dim WmtextObj As MText = trans.GetObject(selObj.ObjectId, OpenMode.ForWrite, False, True)
Dim RmtextObj As MText = trans.GetObject(selObj.ObjectId, OpenMode.ForRead, False, True)
Dim OldTextString As String = RmtextObj.Contents
Dim NewTextString As String = Replace(OldTextString, CurrentFind, CurrentReplace, 1, -1, CompareMethod.Text)
RmtextObj.Dispose()
If OldTextString <> NewTextString Then
WmtextObj.Contents = NewTextString
End If
WmtextObj.Dispose()
End Select
Next selObj
trans.Commit()
End If
End Sub
End Class

 

 

 

0 Likes
Accepted solutions (1)
3,751 Views
2 Replies
Replies (2)
Message 2 of 3

_gile
Consultant
Consultant
Accepted solution

Hi,

 

I cannot attentively read your code (unformated VB is too much for me) but if you want to be able to open multiple documents in the editor you have to use the CommandFlags.Session argument in the CommandMethod attribute and lock each document you want to edit.

See here and there.

 

<Autodesk.AutoCAD.Runtime.CommandMethod("Test", CommandFlags.Session)>
Public Sub BatchRoutine()
    ...
    Dim doc As Document = dm.Open(CurrentDrawingFile, False)
    Using(doc.LockDocument())
        ' edit the document here
        ...
    End Using
    ...
End Sub

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 3

Anonymous
Not applicable

What  @_gile said will fix the problem you are facing ( eLockViola tion) but I'd make two more changes in your code:

 

1) Make sure MdiActiveDocument is set:

Dim doc As Document = dm.Open(CurrentDrawingFile, False)
					
Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument = doc

2) Add an using statement to your transaction to make sure it's properly disposed.

Not ending a transaction leads to weird errors in AutoCad Interface (see this😞

      Using tr As Transaction = db.TransactionManager.StartTransaction
        tr.Commit()
      End Using

 

0 Likes