Hi, I'm trying to get the properties for these 3 object types: IsoArrowSymbol; IsoSphereSymbol;
IsoStartPointSymbol;
Visibly in the drawing, they have properties, but when trying to obtain these properties through the API, it says that the object has no links to the Database, and the properties within PartSizeProperties are also empty/null.
I need a way to get this.
Does anyone know what could fix this?
My code:
if (acEnt is IsoArrowSymbol isoArrowSymbol)
{
System.Collections.Specialized.StringCollection propNames = isoArrowSymbol.PartSizeProperties.PropNames;
if (propNames.Count > 0)
{
foreach (var propName in propNames)
{
if (propName == "LineNumberTag")
{
string lineNumberTag = isoArrowSymbol.PartSizeProperties.PropValue(propName).ToString();
MessageBox.Show(lineNumberTag);
}
}
}
}
Solved! Go to Solution.
Solved by quan_hm. Go to Solution.
Hi,
The arrow informatino is not available to read in C#, you can only access it direction, length. A workaround is to read its through properties tab.
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Internal.PropertyInspector;
using Autodesk.AutoCAD.Runtime;
namespace Namespace1
{
public static class OPMPropsExample
{
/// Example: Dumps the OPM properties of a selected object to the console:
[CommandMethod("OPMPROPS")]
public static void ListOpmProps()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
var psr = ed.GetEntity("\nSelect object: ");
if(psr.Status != PromptStatus.OK)
return;
var props = GetOPMProperties(psr.ObjectId);
if(props.Count == 0)
{
ed.WriteMessage("\nNo properties found.");
return;
}
ed.WriteMessage("\n\n");
foreach(var pair in props)
{
ed.WriteMessage("\n {0} = {1}", pair.Key, pair.Value);
if(Marshal.IsComObject(pair.Value))
Marshal.ReleaseComObject(pair.Value);
}
}
/// Gets the names and values of OPM properties for the given object
public static IDictionary<string, object> GetOPMProperties(ObjectId id)
{
Dictionary<string, object> map = new Dictionary<string, object>();
IntPtr pUnk = ObjectPropertyManagerPropertyUtility.GetIUnknownFromObjectId(id);
if(pUnk != IntPtr.Zero)
{
using(CollectionVector properties = ObjectPropertyManagerProperties.GetProperties(id, false, false))
{
int cnt = properties.Count();
if(cnt != 0)
{
using(CategoryCollectable category = properties.Item(0) as CategoryCollectable)
{
CollectionVector props = category.Properties;
int propCount = props.Count();
for(int j = 0; j < propCount; j++)
{
using(PropertyCollectable prop = props.Item(j) as PropertyCollectable)
{
if(prop == null)
continue;
object value = null;
if(prop.GetValue(pUnk, ref value) && value != null)
{
if(!map.ContainsKey(prop.Name))
map[prop.Name] = value;
}
}
}
}
}
}
Marshal.Release(pUnk);
}
return map;
}
}
}
Credit: ActivistInvestor
Hello, thank you for your response regarding this issue. I was able to obtain the properties I needed; however, with my current code, which I adapted to use your provided method, the software is crashing, and I am unable to identify the problem. Can you take a look?
It performs a simple operation, in theory, it should obtain the value of the properties:
And check if the value of each one exists in my list of strings (rowValues).
My code:
public static void IsolateSelectedObjects(List<string> rowValues)
{
try
{
Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
if (acDoc != null)
{
acDoc.LockDocument();
Database db = acDoc.Database;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
foreach (ObjectId id in btr)
{
try
{
Entity entity = tr.GetObject(id, OpenMode.ForWrite) as Entity;
if (entity == null)
{
continue;
}
bool found = false;
bool shouldBeVisible = false;
if (entity is IsoArrowSymbol || entity is IsoSphereSymbol || entity is IsoStartPointSymbol)
{
//MessageBox.Show("Entrou no bloco de verificação de IsoArrowSymbol, IsoSphereSymbol ou IsoStartPointSymbol");
try
{
IDictionary<string, object> properties = GetOPMProperties(id);
var propertyDictionary = new Dictionary<string, string>();
if (properties != null && properties.Count > 0)
{
Thread.Sleep(1500);
//MessageBox.Show("Propriedades obtidas com sucesso.");
foreach (var property in properties)
{
string key = property.Key;
string value = string.Empty;
try
{
value = property.Value?.ToString();
//MessageBox.Show($"Propriedade: {key} = {value}");
}
catch (System.Exception ex)
{
MessageBox.Show($"Erro ao converter valor da propriedade para string: {ex.Message}");
continue;
}
if (key == "Line Number Tag" || key == "Service" || key == "Spec")
{
if (!string.IsNullOrEmpty(value))
{
if (rowValues.Contains(value))
{
shouldBeVisible = true;
found = true;
//MessageBox.Show("Encontrou a propriedade necessária e está visível.");
break;
}
}
}
}
}
else
{
MessageBox.Show("Nenhuma propriedade encontrada.");
}
}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
MessageBox.Show($"Erro do AutoCAD ao processar propriedades: {ex.Message}", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (System.Exception ex)
{
MessageBox.Show($"Erro inesperado ao processar propriedades: {ex.Message}", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
if (entity is Connector)
{
Connector connector = (Connector)entity;
if (connector != null)
{
SubPartCollection subPartsOfConnector = connector.AllSubParts;
foreach (SubPart subPart in subPartsOfConnector)
{
if (subPart != null)
{
foreach (var prop in subPart.PartSizeProperties.PropNames)
{
if (prop == "LineNumberTag" || prop == "Spec" || prop == "Service")
{
try
{
if (rowValues.Contains(subPart.PartSizeProperties.PropValue(prop).ToString()))
{
shouldBeVisible = true;
found = true;
break;
}
}
catch
{
continue;
}
}
}
}
}
}
}
if (!found)
{
PlantProject currentProj = PlantApplication.CurrentProject;
PipingProject pipingProj = currentProj.ProjectParts["Piping"] as PipingProject;
DataLinksManager dlm = pipingProj.DataLinksManager;
if (!dlm.HasLinks(id))
{
entity.Visible = false;
continue;
}
int rowId = dlm.FindAcPpRowId(id);
if (rowId == -1)
{
entity.Visible = false;
continue;
}
List<KeyValuePair<string, string>> properties = dlm.GetAllProperties(rowId, true);
foreach (var property in properties)
{
if (rowValues.Contains(property.Value))
{
shouldBeVisible = true;
break;
}
}
}
entity.Visible = shouldBeVisible;
}
catch (System.Exception ex)
{
MessageBox.Show($"Ocorreu um erro inesperado ao tentar listar na tabela o objeto com ID '{id}'.\nErro: {ex.Message}", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
continue;
}
}
tr.Commit();
}
acDoc.Editor.Regen();
}
}
catch (System.Exception ex)
{
if (ex.Message != "eOnLockedLayer")
{
MessageBox.Show($"Ocorreu um erro ao tentar isolar os objetos selecionados.\nErro: {ex.Message}", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
MessageBox.Show("LineNumber selecionado(s) contém itens congelados/bloqueados.", "Item congelado/bloqueado", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
}
public static IDictionary<string, object> GetOPMProperties(ObjectId id)
{
Dictionary<string, object> map = new Dictionary<string, object>();
IntPtr pUnk = IntPtr.Zero;
try
{
pUnk = ObjectPropertyManagerPropertyUtility.GetIUnknownFromObjectId(id);
if (pUnk != IntPtr.Zero)
{
using (CollectionVector properties = ObjectPropertyManagerProperties.GetProperties(id, false, false))
{
int cnt = properties.Count();
if (cnt != 0)
{
using (CategoryCollectable category = properties.Item(0) as CategoryCollectable)
{
if (category != null)
{
CollectionVector props = category.Properties;
int propCount = props.Count();
for (int j = 0; j < propCount; j++)
{
using (PropertyCollectable prop = props.Item(j) as PropertyCollectable)
{
if (prop == null)
continue;
object value = null;
if (prop.GetValue(pUnk, ref value) && value != null)
{
if (!map.ContainsKey(prop.Name))
map[prop.Name] = value;
}
}
}
}
}
}
}
}
}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
MessageBox.Show($"Erro do AutoCAD ao obter propriedades: {ex.Message}");
}
catch (System.Exception ex)
{
MessageBox.Show($"Erro inesperado ao obter propriedades: {ex.Message}");
}
finally
{
if (pUnk != IntPtr.Zero)
{
Marshal.Release(pUnk);
}
}
return map;
}
Hello, it's me again.
I tested your code several times and discovered that the software crash was caused by this line:
Marshal.Release(pUnk);
After commenting out that line, I no longer experienced sudden crashes in the software. Thank you very much for your help; it was of great importance and allowed me to move forward with my project.
Great to hear that, you're welcome :))
Can't find what you're looking for? Ask the community or share your knowledge.