I have code that uses Parameter.IsReadOnly. In 99% of cases it works fine. On a specific customer's computer, on a specific family in a specific project, it fails with a System.AccessViolationException. I am able to get on to the customer's computer. What kinds of tests should I run or things should I look for?
The full error message reads:
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at Element.isParameterModifiable(Element*, ElementId, Boolean, Boolean )
at Autodesk.Revit.DB.Parameter.get_IsReadOnly()
...
The specific code that triggers this error:
//Function to copy parameters from one FamilyInstance to another.
public static void CopyParameters(FamilyInstance familyDestination, FamilyInstance familySource)
{
//Look at all parameters on the source FamilyInstance
foreach (Parameter paramSource in familySource.Parameters)
{
//Get the definition of the parameter.
Definition d = paramSource.Definition;
//Try to get a matching parameter from the destination FamilyInstance
Parameter paramDest = familyDestination.get_Parameter(d);
//If we don't find a match by defintion, look for a match by name
if (paramDest == null)
{
if (familyDestination.ParametersMap.Contains(d.Name))
{
paramDest = familyDestination.ParametersMap.get_Item(d.Name);
}
}
//Make sure we have a parameter and it is not read-only
if (paramDest != null && !paramDest.IsReadOnly) // Error happens here
{
//Copy the value from the source to the parameter
if (paramDest.StorageType == StorageType.Integer)
{
paramDest.Set(paramSource.AsInteger());
}
else if (paramDest.StorageType == StorageType.Double)
{
paramDest.Set(paramSource.AsDouble());
}
else if (paramDest.StorageType == StorageType.String)
{
paramDest.Set(paramSource.AsString());
}
else if (paramDest.StorageType == StorageType.ElementId)
{
paramDest.Set(paramSource.AsElementId());
}
}
}
}
I have code that uses Parameter.IsReadOnly. In 99% of cases it works fine. On a specific customer's computer, on a specific family in a specific project, it fails with a System.AccessViolationException. I am able to get on to the customer's computer. What kinds of tests should I run or things should I look for?
The full error message reads:
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at Element.isParameterModifiable(Element*, ElementId, Boolean, Boolean )
at Autodesk.Revit.DB.Parameter.get_IsReadOnly()
...
The specific code that triggers this error:
//Function to copy parameters from one FamilyInstance to another.
public static void CopyParameters(FamilyInstance familyDestination, FamilyInstance familySource)
{
//Look at all parameters on the source FamilyInstance
foreach (Parameter paramSource in familySource.Parameters)
{
//Get the definition of the parameter.
Definition d = paramSource.Definition;
//Try to get a matching parameter from the destination FamilyInstance
Parameter paramDest = familyDestination.get_Parameter(d);
//If we don't find a match by defintion, look for a match by name
if (paramDest == null)
{
if (familyDestination.ParametersMap.Contains(d.Name))
{
paramDest = familyDestination.ParametersMap.get_Item(d.Name);
}
}
//Make sure we have a parameter and it is not read-only
if (paramDest != null && !paramDest.IsReadOnly) // Error happens here
{
//Copy the value from the source to the parameter
if (paramDest.StorageType == StorageType.Integer)
{
paramDest.Set(paramSource.AsInteger());
}
else if (paramDest.StorageType == StorageType.Double)
{
paramDest.Set(paramSource.AsDouble());
}
else if (paramDest.StorageType == StorageType.String)
{
paramDest.Set(paramSource.AsString());
}
else if (paramDest.StorageType == StorageType.ElementId)
{
paramDest.Set(paramSource.AsElementId());
}
}
}
}
Your code looks just like what I would do, but if you are trying to narrow it down, I would typically use a TaskDialog to give me the d.Name before each write call so I know what the parameter is that makes it fail.
Also, is there any chance that there could be more than one parameter with the same name that the code could actually be attempting to change twice during the same run? Looking around it appears this exception usually has to do with trying to modify data of an object that is no longer valid.
Solved: Temporary Transaction Trick Exception - Autodesk Community - Revit Products
AccessViolationException on new GetParameters() in 2015 API - Autodesk Community - Revit Products
Your code looks just like what I would do, but if you are trying to narrow it down, I would typically use a TaskDialog to give me the d.Name before each write call so I know what the parameter is that makes it fail.
Also, is there any chance that there could be more than one parameter with the same name that the code could actually be attempting to change twice during the same run? Looking around it appears this exception usually has to do with trying to modify data of an object that is no longer valid.
Solved: Temporary Transaction Trick Exception - Autodesk Community - Revit Products
AccessViolationException on new GetParameters() in 2015 API - Autodesk Community - Revit Products
I think the following may help you based on what @Moustafa_K wrote and what I have done in the past. I had forgotten about the check for formula, but its pretty straight forward.
//Check to see if the source param is a formula or not
if(paramSource.Formula != null)
{
//If you use 'is' statement it can consolidate your if's
if(familyDesintination.get_Parameter(d) is Parameter paramDest && !paramDest.IsReadOnly)
{
//Do work here
}
}
I think the following may help you based on what @Moustafa_K wrote and what I have done in the past. I had forgotten about the check for formula, but its pretty straight forward.
//Check to see if the source param is a formula or not
if(paramSource.Formula != null)
{
//If you use 'is' statement it can consolidate your if's
if(familyDesintination.get_Parameter(d) is Parameter paramDest && !paramDest.IsReadOnly)
{
//Do work here
}
}
Thank you for the suggestions, those were helpful for thinking about what could be going wrong.
It was the built-in ELEM_FAMILY_AND_TYPE_PARAM parameter that was causing the error. I changed the code to check for UserModifiable before IsReadOnly and that fixed the error.
paramDest.UserModifiable && !paramDest.IsReadOnly
Not a completely satisfying solution, but it works.
Thank you for the suggestions, those were helpful for thinking about what could be going wrong.
It was the built-in ELEM_FAMILY_AND_TYPE_PARAM parameter that was causing the error. I changed the code to check for UserModifiable before IsReadOnly and that fixed the error.
paramDest.UserModifiable && !paramDest.IsReadOnly
Not a completely satisfying solution, but it works.
Can't find what you're looking for? Ask the community or share your knowledge.