Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Dimension pre and suffix leads to crash revit 2014/2015

11 REPLIES 11
SOLVED
Reply
Message 1 of 12
R.van.den.Bor
848 Views, 11 Replies

Dimension pre and suffix leads to crash revit 2014/2015

Hi There,

 

I have noticed something strange with revit dimensions in Revit 2014 and 2015.

I make a collection of dimensions and what I want to acchieve is to read if a prefix or suffix is used. When a value is found, put the value in a textbox.

The problem lies in the dim(seg).Prefix != null and  dim(seg).Suffix != null part.

 

lets say a dimension has a suffix "mm". When asking for dim.Prefix it will return "" (empty string).

BUT, when no prefix or suffix is used, Revit will give a AccesViolation error and you closes revit without a warning!!

So, you can ask dim.Prefix or dim.Suffix when no pre- or suffixes are used. The value will not be an empty string, it just crashes revit.

 

The workaround I use now, is to check wheter the dim.value is a double. If not, I know a prefix or suffix is used. If the value can be parsed to a double, I bypass the dim.prefix call (which leads to crashing revit).

 

Does anybody know how to solve this in a proper way ?

 

foreach (Element el in elemset)
{
if (el.Category.Name.Equals("Dimensions"))
{
Dimension dim = el as Dimension;

if (dim.Segments.Size == 0)
{
if (string.IsNullOrEmpty(txtPrefix.Text) && dim.Prefix != null) txtPrefix.Text = dim.Prefix;
if (string.IsNullOrEmpty(txtSuffix.Text) && dim.Suffix != null) txtSuffix.Text = dim.Suffix;
}
else
{
foreach (DimensionSegment dimseg in dim.Segments)
{
if (string.IsNullOrEmpty(txtPrefix.Text) && dimseg.Prefix != null) txtPrefix.Text = dimseg.Prefix;
if (string.IsNullOrEmpty(txtSuffix.Text) && dimseg.Suffix != null) txtSuffix.Text = dimseg.Suffix;
}
}
}
}

 

Kind regards,
Remy van den Bor
ICN Solutions B.V.
Liked this post or found it usefull, don't forget the Kudo It won't hurt (at least not me).
11 REPLIES 11
Message 2 of 12

Dear Remy,

 

Thank you for your query.

 

I find this rather hard to believe.

 

I would suggest that, for your own peace and clarity of mind, you split up your long lines of code into simpler statements.

 

Maybe something completely different is going on.

 

For instance, you could simply implement intermediate variables, each initialised in its own statement on its own line of code, e.g.

 

  Dimension dim = el as Dimension;

  if (dim.Segments.Size == 0)
  {
    string spre = dim.Prefix;
    string ssuf = dim.Suffix;
    if (string.IsNullOrEmpty(txtPrefix.Text) && spre != null) txtPrefix.Text = spre;
    if (string.IsNullOrEmpty(txtSuffix.Text) && ssuf != null) txtSuffix.Text = ssuf;
  }
  else
  {
    foreach (DimensionSegment dimseg in dim.Segments)
    {
      string spre = dimseg.Prefix;
      string ssuf = dimseg.Suffix;
      if (string.IsNullOrEmpty(txtPrefix.Text) && spre != null) txtPrefix.Text = spre;
      if (string.IsNullOrEmpty(txtSuffix.Text) && ssuf != null) txtSuffix.Text = ssuf;
    }
  }

 

Then you might more easily determine what is really causing the problem.

 

Actually, you could even go a step further to significantly reduce the error probability, by implementing a single helper function to handle your assignment in all cases:

 

  static void UpdateTarget( ref string target, string source )
  {
    if (string.IsNullOrEmpty(target) && source != null)
    {
      target = source;
    }
  }
  
  if (dim.Segments.Size == 0)
  {
    UpdateTarget( txtPrefix.Text, dim.Prefix );
    UpdateTarget( txtSuffix.Text, dim.Suffix );
  }
  else
  {
    foreach (DimensionSegment dimseg in dim.Segments)
    {
      UpdateTarget( txtPrefix.Text, dimseg.Prefix );
      UpdateTarget( txtSuffix.Text, dimseg.Suffix );
    }
  }

 

That looks a little bit more readable to me, as well.

 

However, this code is untested and may not even compile.

 

Still, I hope you get the idea.

 

If the problem persists, I would suggest that you send us a reproducible case so that we can easily check what is going on our end:

 

http://thebuildingcoder.typepad.com/blog/about-the-author.html#1b

 

I hope this helps.

 

Best regards,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 3 of 12
jeremytammik
in reply to: jeremytammik

By the way, re-reading your query, I wonder whether you mean 'cannot' when you say 'So, you can ask dim.Prefix or dim.Suffix when no pre- or suffixes are used'...



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 4 of 12

Hi Jeremy,
Thanks for your suggestions, but it doesn't solve my problem. Even in your first example, string spre = dimseg.Prefix; will lead to the accesviolation error and close revit without warning. Like I said, the problem occurs when NO prefix or suffix if used in a selected dimension. (so I mean cannot indeed).

And if you add the routine for selecting dimensions, there you have the reproducable code 🙂 So for completeness sake :

 

UIDocument uidoc = _commandData.Application.ActiveUIDocument;
Document doc = uidoc.Document;
List<ElementId> thelist = uidoc.Selection.GetElementIds().ToList();
Element elem = null;
List<Element> elemset = new List<Element>();
foreach (ElementId elid in thelist)
{
elem = doc.GetElement(elid);
if (elem != null) elemset.Add(elem);
}
foreach (Element el in elemset)
{
if (el.Category.Name.Equals("Dimensions"))
{
Dimension dim = el as Dimension;

if (dim.Segments.Size == 0)
{

if (string.IsNullOrEmpty(txtPrefix.Text)) txtPrefix.Text = dim.Prefix;
if (string.IsNullOrEmpty(txtSuffix.Text)) txtSuffix.Text = dim.Suffix;
}
else
{
foreach (DimensionSegment dimseg in dim.Segments)
{
if (string.IsNullOrEmpty(txtPrefix.Text)) txtPrefix.Text = dimseg.Prefix;
if (string.IsNullOrEmpty(txtSuffix.Text)) txtSuffix.Text = dimseg.Suffix;
}
}
}
}

Kind regards,
Remy van den Bor
ICN Solutions B.V.
Liked this post or found it usefull, don't forget the Kudo It won't hurt (at least not me).
Message 5 of 12

Oh wow, I tried out your test code and yeah, as soon as you try to access the prefix / suffix properties of the segments Revit crashes to desktop instantly.

 

Stepping through with the debugger I can see that the Prefix, Suffix and ValueOverrride properties all throw a System.AccessViolationException with the inner message stating "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

 

To be certain, I also tried accessing the segments using the ForwardIterator and got the same result.

 

Oddly enough though, if you open up the dimension text edit window in the UI  for each segment of the dimension and simply click OK without modifying anything, the dimension will then behave correctly. No exceptions will be thrown.

 

Smells like an API bug to me. Uninitialised pointers I would suspect.

 

If I had to guess what was happening I would say that the API is expecting the internal unmanaged pointers related to these properties to be already initialised, it checks for 0 value and if not it treats it as a valid pointer and hands it to the API object.

 

Message 6 of 12
jeremytammik
in reply to: Scott_Wilson

Dear Scott,

 

Thank you very much for your professional checking!

 

Dear Remy,

 

I stand corrected 🙂

 

I logged the issue REVIT-48282 [DimensionSegment Prefix and Suffix crash Revit if empty] with our development team for this on your behalf as it requires further exploration and possibly a modification to our software. Please make a note of this number for future reference.

 

Thank you very much for reporting this.

 

I am very glad that you have a workaround in place.

 

Best regards,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 7 of 12

@Jeremy: Thanks, good to know 🙂 

 

@Scott,

 

Thanks for your reply, I suspected this to be one of  two things. Being a bug or a fast way to close Revit without 'anoying save your work' questions 🙂

 

Like I've said before, I found a workaround that seems to work. I do a check to see whether the dimseg.value is a string. If not, the crash can be avoided.

 

if (CheckVal(dimseg.ValueString))
{
if (string.IsNullOrEmpty(txtPrefix.Text)) txtPrefix.Text = dimseg.Prefix;
if (string.IsNullOrEmpty(txtSuffix.Text)) txtSuffix.Text = dimseg.Suffix;
}

 

 

private bool CheckVal(string val)
{
foreach (char c in val)
{
if (!char.IsDigit(c) && c != '.')
{
return true;
}
}
return false;
}

 

 

Kind regards,
Remy van den Bor
ICN Solutions B.V.
Liked this post or found it usefull, don't forget the Kudo It won't hurt (at least not me).
Message 8 of 12

I have just devised a couple of work arounds for avoiding the crash while we wait for it to get looked at and hopefully remedied.

 

The first was quite tedious and involved indepentantly building the dimension string exactly as you would get from ValueText using the dimension type properties and then checking that against the segment to determine whether any text modifiers existed.

 

That would be painful to implement and thankfully you don't have to, there's a much better way. If you assign a value to any of the text properties, it gives the API enough of a nudge that it wakes up and fixes the faulty properties in a similar way to what I was seeing with the UI editor.

 

So, before you attempt to access any of the 3 potentially bugged properties, simply take one of the well behaved ones (such as .Above ) and re-assign its value to itself (so that no information is lost) and you're all good, no more crashing. I hope...

 

Change the last part of your code to:

 

foreach(DimensionSegment dimseg in dim.Segments)
{
    dimseg.Above = dimseg.Above; // Hello API, are you awake?

    if(string.IsNullOrEmpty(txtPrefix.Text)) txtPrefix.Text = dimseg.Prefix;
    if(string.IsNullOrEmpty(txtSuffix.Text)) txtSuffix.Text = dimseg.Suffix;
}

 

 Edit: Oh I see you already have a work around 🙂 Oh well, here's another!

 

By the way, simply checking for non-numerics in the ValueText is likely to include any segments that contain text due to unit suffixes and alternate units. These segments will still crash if accessed. Unless you have full control over the environment and are certain that no text could be present unless added manually, then I wouldn't use it in production code.

Message 9 of 12
jeremytammik
in reply to: Scott_Wilson

Thanks again for this, guys!

 

I published a summary of the problem and your workarounds:

 

http://thebuildingcoder.typepad.com/blog/2014/09/revit-2015-r2-ur4-and-dimension-prefix-suffix.html#...

 

Cheers,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 10 of 12

I've tried scotts "// Hello API, are you awake?" in Revit 2014, but here it results to the same crash. So scotts workaround only works for revit 2015.
Kind regards,
Remy van den Bor
ICN Solutions B.V.
Liked this post or found it usefull, don't forget the Kudo It won't hurt (at least not me).
Message 11 of 12

Oh, that's a shame. Has anyone else tried it for 2015? Hopefully I didn't just imagine that I fixed it.
Message 12 of 12

yes, I did and your workaround does work for revit 2015, but not for 2014 🙂
Kind regards,
Remy van den Bor
ICN Solutions B.V.
Liked this post or found it usefull, don't forget the Kudo It won't hurt (at least not me).

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Rail Community