Hello,
I created a post a few months ago at this location: https://forums.autodesk.com/t5/net/bug-when-successively-launching-a-function-i-ve-created/m-p/12340... , which I validated too quickly by mistake... As it happens, the problem still persists.
In the same project session, when I try again to touch ObjectData (by importing them, or if I want to reread the "records" a second time), I always get the error :
Application does not support just-in-time (JIT)
debugging. See the end of this message for details.
************** Exception Text **************
Autodesk.Gis.Map.MapImportExportException: Exception of type 'Autodesk.Gis.Map.MapImportExportException' was thrown.
at Autodesk.Gis.Map.ImportExport.Importer.Init(String formatName, String fileName)
at AEPCreateProfile.MyCommandsAEP.AEPImportShape() in C:\Users\maxime.chavet\Documents\RDC29\VISUAL_STUDIO\Profile\Profile\Class1.cs:line 68
at Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorker(MethodInfo mi, Object commandObject, Boolean bLispFunction)
at Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorkerWithExceptionFilter(MethodInfo mi, Object commandObject, Boolean bLispFunction)
at Autodesk.AutoCAD.Runtime.PerDocumentCommandClass.Invoke(MethodInfo mi, Boolean bLispFunction)
at Autodesk.AutoCAD.Runtime.CommandClass.CommandThunk.Invoke()
Here is the first code to import shapefile:
[CommandMethod("SHP2")]
static public void SHP2()
{
Autodesk.AutoCAD.Windows.OpenFileDialog ofd = new Autodesk.AutoCAD.Windows.OpenFileDialog(
"Select SHP File", null, "shp", "Select shp", Autodesk.AutoCAD.Windows.OpenFileDialog.OpenFileDialogFlags.AllowAnyExtension);
if (ofd.ShowDialog() == DialogResult.OK)
{
string shpname = ofd.Filename;
Import2(shpname);
}//
}//acad command - SHP2
private static void Import2(string shpname)
{
string fname = Path.GetFileNameWithoutExtension(shpname).Replace(" ", "");
MapApplication mapApp = HostMapApplicationServices.Application;
Importer importer = mapApp.Importer;
try
{
importer.Init("SHP", shpname);
foreach (InputLayer il in importer)
{
il.SetLayerName(LayerNameType.LayerNameDirect, fname);
il.SetDataMapping(ImportDataMapping.NewObjectDataOnly, fname);
}// foreach shp layer
importer.ImportPolygonsAsClosedPolylines = true;
ImportResults ir = importer.Import(true);
}
catch { }
finally { };
}// Import2
Problem is at :
il.SetDataMapping(ImportDataMapping.NewObjectDataOnly, fname);
And for the second :
using(DocumentLock lk = doc.LockDocument())
{
if (psr.Status == PromptStatus.OK)
{
foreach (SelectedObject so in psr.Value)
{
using (Records records = tables.GetObjectRecords(0, so.ObjectId, Autodesk.Gis.Map.Constants.OpenMode.OpenForWrite, false))
{
foreach (Record record in records) //Error at this line
Problem is at the last line
public static Dictionary<string, List<ObjectId>> listprofilepl()
{
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
Tables tables = HostMapApplicationServices.Application.ActiveProject.ODTables;
TypedValue[] filterList = new TypedValue[]
{
new TypedValue((int)DxfCode.Operator, "<or"),
new TypedValue((int)DxfCode.Start, "LWPOLYLINE"),
new TypedValue((int)DxfCode.Start, "LINE"),
new TypedValue((int)DxfCode.Start, "POLYLINE"),
new TypedValue((int)DxfCode.Operator, "or>")
};
SelectionFilter filter = new SelectionFilter(filterList);
PromptSelectionResult psr = ed.SelectAll(filter);
//HashSet<String> ExistingProfile = new HashSet<String>();
//List<ObjectId> idprofile = new List<ObjectId>();
Dictionary<string, List<ObjectId>> profileObjectIdMap = new Dictionary<string, List<ObjectId>>();
using(DocumentLock lk = doc.LockDocument())
{
if (psr.Status == PromptStatus.OK)
{
foreach (SelectedObject so in psr.Value)
{
using (Records records = tables.GetObjectRecords(0, so.ObjectId, Autodesk.Gis.Map.Constants.OpenMode.OpenForRead, false))
{
//records.RemoveRecord;
foreach (Record record in records) //Error at this line
{
for (int i = 0; i < record.Count; i++)
{
MapValue val = record[i];
Autodesk.Gis.Map.ObjectData.Table table = tables[record.TableName];
FieldDefinition fieldDef = table.FieldDefinitions[i];
if (fieldDef.Name == "Profil")
{
string profil = val.StrValue;
// Vérifiez si le profil est vide ou "0" et ignorez-le
if (!string.IsNullOrWhiteSpace(profil) && profil != "0")
{
// Si le profil n'existe pas dans le dictionnaire, ajoutez-le
if (!profileObjectIdMap.ContainsKey(profil))
{
profileObjectIdMap[profil] = new List<ObjectId>();
}
// Ajoutez l'ObjectId correspondant au profil dans la liste
profileObjectIdMap[profil].Add(so.ObjectId);
}
}
//tables.UpdateTable(table.Name, table.FieldDefinitions);
//table.AddRecord(record,so.ObjectId);
}
//records.UpdateRecord(record);
}
//tables.Add("bla", table.FieldDefinitions, "blabla", true);
profileObjectIdMap.Remove("");
profileObjectIdMap.Remove("0");
//records.Dispose();
}
}
return profileObjectIdMap;
}
else
{
return profileObjectIdMap;
}
}
}
"Records" can be opened several times in a row when I run a function with a loop.
However, if a function is run a second time, independently of the first time, I get the error mentioned above.
It seems that this is due to the fact that the "records" extracted from the "tables" are empty during the second independent execution. I don't understand why, in the same session, the "records" become "empty" after being opened the first time, whereas if I run the same function in a new 3D civil session, everything works.
I hope my problem is clear to anyone reading this...
You can't run the importer on the same file more than once. My guess is a duplicate records problem. If you use "mapimport" from the command line, acad happily creates duplicates. The managedmap api import does not (again - my guess is the "NewObjectDataOnly" property).
In the second "records" issue, you need to check that records.Count > 0 before the foreach. Again - my guess is an entity in the selection does not return any records.
In the future, include complete code samples and data if you can (you may have your own small set of test data?), with what you are trying to achieve - before and after.
Thank you for your reply
I can't even import different files (not necessarily the same) in the session C3D session..
Yes, indeed, records are empty in the next launch although OD of all the geometries are still present in C3D after a first launch. But with the same geometries selected, the read of OD work the first time. I tried to (re)add and update record/records in the table/tables :
tables.UpdateTable(table.Name, table.FieldDefinitions);
table.AddRecord(record,so.ObjectId);
records.UpdateRecord(record);
tables.Add(table.Name, table.FieldDefinitions, "blabla", true);
it doesn't work and the error is the same than mentionned before
And:
il.SetDataMapping(ImportDataMapping.ExistingObjectDataOnly, fname);
Here is some data in shapefile: https://we.tl/t-v5CpnAEEc1
So, the idea may be to duplicate and register "records" somewhere else?
Check the following against yours - or just try mine. You can import multiple shp files as long as the data does not exist. I don't understand why you would want to import the same data again.
Also - List<ObjectId> should just be ObjectId - no list required (1 to 1 relationship entity to OD record)
[CommandMethod("SHP2")]
static public void SHP2()
{
_debug = true;
string msg = "BoundaryClass - SHP2";
Autodesk.AutoCAD.Windows.OpenFileDialog ofd = new Autodesk.AutoCAD.Windows.OpenFileDialog(
"Select SHP File", null, "shp", "Select shp", Autodesk.AutoCAD.Windows.OpenFileDialog.OpenFileDialogFlags.AllowAnyExtension);
if (ofd.ShowDialog() == DialogResult.OK)
{
string shpname = ofd.Filename;
// MapClass.Import2(shpname);
Import2(shpname);
}//
if (_debug)
MessageBox.Show(msg);
}// SHP2
private static void Import2(string shpname)
{
string msg = "BoundaryClass - Import2 - local test only";
msg += "\nimporting " + shpname;
string fname = Path.GetFileNameWithoutExtension(shpname).Replace(" ", "");
MapApplication mapApp = HostMapApplicationServices.Application;
Importer importer = mapApp.Importer;
try
{
importer.Init("SHP", shpname);
foreach (InputLayer il in importer)
{
il.SetLayerName(LayerNameType.LayerNameDirect, fname);
// if you want to catch the error check if Tables contains fname - you would // have to change it if it exists
il.SetDataMapping(ImportDataMapping.NewObjectDataOnly, fname);
}// foreach shp layer
importer.ImportPolygonsAsClosedPolylines = true;
ImportResults ir = importer.Import(true);
}
catch (Autodesk.Gis.Map.MapImportExportException mapieex)
{
msg += "\nmap importexport exception\n" + mapieex.Message;
msg += "\nerror code\n" + mapieex.ErrorCode;
// msg += "\nmore? " + Autodesk.Gis.Map.ImportExport.ImportExportErrorCode;
}// catch mapimport
catch (MapException mapex2)
{
msg += "\nmap exception\n" + mapex2.Message;
msg += "\nerror code\n" + mapex2.ErrorCode;
}// catch map
catch (System.Exception sysex)
{
msg += "\nexception:\n" + sysex.Message;
}
finally { };
if (_debug)
MessageBox.Show(msg);
}// Import2
// you can change void to Dictionary<string, List<ObjectId>> listprofilepl()
// and modify accordingly
public static void ListProfilePl()
{
string msg = "TestingClass - ListProfilePl";
acapp.Document doc = acapp.Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
TypedValue[] filterList = new TypedValue[]
{
new TypedValue((int)DxfCode.Operator, "<or"),
new TypedValue((int)DxfCode.Start, "LWPOLYLINE"),
new TypedValue((int)DxfCode.Start, "LINE"),
new TypedValue((int)DxfCode.Start, "POLYLINE"),
new TypedValue((int)DxfCode.Operator, "or>")
};
SelectionFilter filter = new SelectionFilter(filterList);
PromptSelectionResult psr = ed.SelectAll(filter);
if (psr.Status == PromptStatus.OK)
{
msg += "\nselected " + psr.Value.Count;
Tables tables = HostMapApplicationServices.Application.ActiveProject.ODTables;
Dictionary<string, List<ObjectId>> profileObjectIdMap = new Dictionary<string, List<ObjectId>>();
foreach (SelectedObject so in psr.Value)
{
using (Records records = tables.GetObjectRecords(0, so.ObjectId, Autodesk.Gis.Map.Constants.OpenMode.OpenForRead, false))
{
msg += "\nrecords " + records.Count;
if (records.Count > 0)
{
foreach (Record record in records)
{
Autodesk.Gis.Map.ObjectData.Table table = tables[record.TableName];
FieldDefinitions fielddefs = table.FieldDefinitions;
for (int i = 0; i < fielddefs.Count; i++)
{
if (fielddefs[i].Name == "Profil")
{
MapValue val = record[i];
string profil = val.StrValue;
if (!profileObjectIdMap.ContainsKey(profil) && profil != "0")
{
profileObjectIdMap.Add(profil, new List<ObjectId>() { so.ObjectId });
msg += "\nprofile added to list " + profil;
}// add to list
}// check fielddef name
}// foreach field def
}// foreach record
}// any records
}// using records
}// foreach object
}// prompt ok
if (BoundaryClass._debug)
MessageBox.Show(msg);
}// ListProfilePl
That code isn't %100 correct. It is using the field definitions to determine if the field name is "Profil". You are not guaranteed that field name doesn't exist in some other table. IMO you should check the table name first, before getting the field definitions.
Hello,
Thank you!
But with the "if records.Count>0", I will be not allowed to launch successvely my function in C3D, it will never work, because I get this error, this problem of records empties in all cases
If there are no others solutions, I will create a function that create an excel file with all the values of each field for each alignement, instead of directly with the OD, somewhere in the pc root. Then, my others functions that manage with all the profiles will find the required values there. Because it what I need, and it seems I'm not allowed to call these records two times, nobody has the answer...
You should post your entire solution - there is no reason for " Because it what I need, and it seems I'm not allowed to call these records two times". My code will call your data as many times as necessary.
With this code, I don't have anymore error when launching command twice or more.
using _AcDb = Autodesk.AutoCAD.DatabaseServices;
using _AcAp = Autodesk.AutoCAD.ApplicationServices;
using _AcRx = Autodesk.AutoCAD.Runtime;
using _AcGe = Autodesk.AutoCAD.Geometry;
using _AcEd = Autodesk.AutoCAD.EditorInput;
using _AcCo = Autodesk.AutoCAD.Colors;
using _AcMp = Autodesk.Gis.Map;
using _AmCt = Autodesk.Gis.Map.Constants;
using _AmUt = Autodesk.Gis.Map.Utilities;
using _AmOd = Autodesk.Gis.Map.ObjectData;
[_AcRx.CommandMethodAttribute("TEST_OD")]
public void TEST_OD()
{
_AcAp.Document doc = _AcAp.Application.DocumentManager.MdiActiveDocument;
_AcEd.Editor ed = doc.Editor;
Dictionary<string, List<_AcDb.ObjectId>> dctProfil = listprofilepl();
foreach(string sProfil in dctProfil.Keys)
{
ed.WriteMessage("\nProfil : " + sProfil);
foreach(_AcDb.ObjectId id in dctProfil[sProfil])
ed.WriteMessage("\n Handle : " + id.Handle.ToString());
}
}
public static Dictionary<string, List<_AcDb.ObjectId>> listprofilepl()
{
_AcAp.Document doc = _AcAp.Application.DocumentManager.MdiActiveDocument;
_AcEd.Editor ed = doc.Editor;
_AcDb.Database db = doc.Database;
_AmOd.Tables tables = _AcMp.HostMapApplicationServices.Application.ActiveProject.ODTables;
Dictionary<string, List<_AcDb.ObjectId>> profileObjectIdMap = new Dictionary<string, List<_AcDb.ObjectId>>();
_AcDb.TypedValue[] filterList = new _AcDb.TypedValue[]
{
new _AcDb.TypedValue((int)_AcDb.DxfCode.Start, "LINE,*POLYLINE")
};
_AcEd.PromptSelectionResult psr = ed.SelectAll(new _AcEd.SelectionFilter(filterList));
// SI la sélection est non valide, on sort tout de suite
if (psr.Status != _AcEd.PromptStatus.OK)
return profileObjectIdMap;
//HashSet<String> ExistingProfile = new HashSet<String>();
//List<ObjectId> idprofile = new List<ObjectId>();
// Utile seulement si demandé depuis un dialogue non modal
using (_AcAp.DocumentLock lk = doc.LockDocument())
{
foreach (_AcEd.SelectedObject so in psr.Value)
{
// _AcDb.ObjectId id = so.ObjectId;
using (_AmOd.Records records = tables.GetObjectRecords(0, so.ObjectId, _AmCt.OpenMode.OpenForRead, false))
{
//records.RemoveRecord;
foreach (_AmOd.Record record in records) //Error at this line
{
for (int i = 0; i < record.Count; i++)
{
using (_AmOd.Table table = tables[record.TableName])
{
_AmOd.FieldDefinition fieldDef = table.FieldDefinitions[i];
if (fieldDef.Name == "Profil")
{
_AmUt.MapValue val = record[i];
string profil = val.StrValue;
// Vérifiez si le profil est vide ou "0" et ignorez-le
if (!string.IsNullOrWhiteSpace(profil) && profil != "0")
{
// Si le profil n'existe pas dans le dictionnaire, ajoutez-le
if (!profileObjectIdMap.ContainsKey(profil))
{
profileObjectIdMap[profil] = new List<_AcDb.ObjectId>();
}
// Ajoutez l'ObjectId correspondant au profil dans la liste
profileObjectIdMap[profil].Add(so.ObjectId);
}
}
}
//tables.UpdateTable(table.Name, table.FieldDefinitions);
//table.AddRecord(record,so.ObjectId);
}
//records.UpdateRecord(record);
}
//tables.Add("bla", table.FieldDefinitions, "blabla", true);
// Inutile puisque déjà exclu dans le test de la valeur du profil
//profileObjectIdMap.Remove("");
//profileObjectIdMap.Remove("0");
//records.Dispose();
}
}
return profileObjectIdMap;
}
}
Olivier Eckmann
Can't find what you're looking for? Ask the community or share your knowledge.