| Message |
I am using VB.NET to create various geoprocessing tools within stand-alone apps, intended for command-line execution. Each application uses a combination of ESRI Tools, each of which is embedded in its own class that uses a "ToolHelper" to set parameters and manage the execution. The ToolHelper class is included below.
In general, this has worked pretty well, even for looping Identity operations. However, I'm seeing issues similar to those posted here in my wrapper for the Clip Tool. Looping clip operations do complete, but result in the dreaded "The instruction at... memory could not be 'read'..." error on exit, or they simply leave the process hanging on exit.
I've tried every conceivable combination of disposal methods for all apparent AO references: CoFreeUnusedLibraries, Marshal.ReleaseComObject, AOUninitialize.Shutdown, and Utility.COMSupport.AOUninitialize.Shutdown. I'm pretty sure there are no un-disposed references, if for no other reason than the other two applications I've developed this way had no such problem (and one of these uses Identity).
The test system is 9.1 sp 1, with the Feb 16th geometry performance patch. The patch was installed today, and seems to have made no difference at all.
This seems to me to be a bug. And I'm wondering if the problems described in this thread have been resolved with the latest patch.
|
| |
Public Class ToolHelper
Implements IDisposable
#Region " Identifiers "
Private Const mc_moduleName As String = fc_projectName & _
".ToolboxHelper.ToolHelper"
Protected m_toolBox As Geoprocessing.IGPToolbox
Protected m_tool As Geoprocessing.IGPTool
Protected m_params As esriSystem.IArray
Protected m_paramIndex As Int32 = 0
#End Region
#Region " Properties "
Public ReadOnly Property ParameterCount() As Int32
Get
Return m_params.Count
End Get
End Property
#End Region
#Region " Initialization and disposal "
Public Sub New(ByVal toolBox As Geoprocessing.IGPToolbox, _
ByVal toolName As String)
m_toolBox = toolBox
m_tool = m_toolBox.OpenTool(toolName)
m_params = m_tool.ParameterInfo
End Sub
Public Overridable Sub Dispose() Implements System.IDisposable.Dispose
ReleaseComObject(DirectCast(m_toolBox, Object))
ReleaseComObject(DirectCast(m_tool, Object))
ReleaseComObject(DirectCast(m_params, Object))
End Sub
#End Region
#Region " SetParameter and Execute functions "
Public Overridable Overloads Function SetParameter( _
ByVal value As String) As Boolean
Dim param As Geoprocessing.IGPParameter
Dim paramEdit As Geoprocessing.IGPParameterEdit
Dim paramDataType As Geodatabase.IGPDataType
Try
If m_paramIndex < m_tool.ParameterInfo.Count() Then
param = DirectCast(m_params.Element(m_paramIndex), _
Geoprocessing.IGPParameter)
paramEdit = DirectCast(param, _
Geoprocessing.IGPParameterEdit)
paramDataType = param.DataType
paramEdit.Value = paramDataType.CreateValue(value)
m_paramIndex += 1
Return True
Else
'out of range...
End If
Finally
ReleaseComObject(DirectCast(param, Object))
ReleaseComObject(DirectCast(paramEdit, Object))
ReleaseComObject(DirectCast(paramDataType, Object))
End Try
End Function
Public Overridable Overloads Function SetParameter(ByVal index As Int32, _
ByVal value As String) As Boolean
Dim param As Geoprocessing.IGPParameter
Dim paramEdit As Geoprocessing.IGPParameterEdit
Dim paramDataType As Geodatabase.IGPDataType
Try
If index < m_tool.ParameterInfo.Count() Then
param = DirectCast(m_params.Element(index), _
Geoprocessing.IGPParameter)
paramEdit = DirectCast(param, _
Geoprocessing.IGPParameterEdit)
paramDataType = param.DataType
paramEdit.Value = paramDataType.CreateValue(value)
Return True
Else
'out of range...
End If
Finally
ReleaseComObject(DirectCast(param, Object))
ReleaseComObject(DirectCast(paramEdit, Object))
ReleaseComObject(DirectCast(paramDataType, Object))
End Try
End Function
Public Overridable Function Execute(ByRef msg As String, _
Optional ByVal msgToIgnore As String = "", _
Optional ByVal msgDelimiter As String = ";", _
Optional ByVal useCancelTracker As Boolean = False, _
Optional ByVal errorCode As Integer = 0) _
As Boolean
Dim gpMsgs As Geodatabase.IGPMessages
Dim gpMsg As Geodatabase.IGPMessage
Try
gpMsgs = DirectCast(New Geodatabase.GPMessagesClass, _
Geodatabase.IGPMessages)
m_tool.Execute(m_params, Nothing, Nothing, gpMsgs)
'get any resulting error from the messages collection.
'this seems to provide the primary message of interest,
'when it is an error.
gpMsg = DirectCast(gpMsgs, Geodatabase.IGPMessage)
If gpMsg.IsError Then
errorCode = gpMsg.ErrorCode
End If
'prepare to evaluate each message inside the collection.
msg = ""
Dim l As Int32
For l = 0 To gpMsgs.Messages.Count() - 1
're-use the msg reference to get each individual message.
gpMsg = DirectCast(gpMsgs.Messages.Element(l), _
Geodatabase.IGPMessage)
Dim str As String = gpMsg.Description
If Not (str Is Nothing) AndAlso str.Length > 0 AndAlso _
str.Trim() <> msgToIgnore Then
'the gp is reporting something other than the
'message to ignore.
msg = msg & str & msgDelimiter
End If
Next
If msg.Length = 0 Then
Return True
End If
Finally
ReleaseComObject(DirectCast(gpMsgs, Object))
ReleaseComObject(DirectCast(gpMsg, Object))
End Try
End Function
#End Region
End Class
|