Hi guys
Im trying to write some code to create a profile for an alignment using c sharp. I'm using visual Studio 2015 enterprise edition.
I have used the sample code snippet from the following URL ProfileFromSurface
If I use this in a c sharp plugin on its own it works just fine however when i paste it into a different class function in a small app i'm writing it throws an ArgumentException. I have no idea why.
I tried moving it to a separate class of its own, still the same result, I tried different overloaded versions, still the same result.
Im pretty new to this coding stuff so maybe the answer is obvious but I just cant seem to see whats going on.
TIA
Solved! Go to Solution.
Hi guys
Im trying to write some code to create a profile for an alignment using c sharp. I'm using visual Studio 2015 enterprise edition.
I have used the sample code snippet from the following URL ProfileFromSurface
If I use this in a c sharp plugin on its own it works just fine however when i paste it into a different class function in a small app i'm writing it throws an ArgumentException. I have no idea why.
I tried moving it to a separate class of its own, still the same result, I tried different overloaded versions, still the same result.
Im pretty new to this coding stuff so maybe the answer is obvious but I just cant seem to see whats going on.
TIA
Solved! Go to Solution.
Solved by Jeff_M. Go to Solution.
Hi Jeff
Here is the code:
using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.Civil.ApplicationServices; using Autodesk.Civil.DatabaseServices; namespace NJD_C3D_CreateMultipleProfiles { class CreateProfile { public static void CreateMultipleProfiles() { Document acdoc = Application.DocumentManager.MdiActiveDocument; CivilDocument doc = CivilApplication.ActiveDocument; Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; using (Transaction ts = Application.DocumentManager.MdiActiveDocument.Database.TransactionManager.StartTransaction()) { // Ask the user to select an alignment PromptEntityOptions opt = new PromptEntityOptions("\nSelect an Alignment"); opt.SetRejectMessage("\nObject must be an alignment.\n"); opt.AddAllowedClass(typeof(Alignment), true); ObjectId talignID = ed.GetEntity(opt).ObjectId; // get layer id from the alignment Alignment oAlignment = ts.GetObject(talignID, OpenMode.ForRead) as Alignment; ObjectId tlayerId = oAlignment.LayerId; // get first surface in the document ObjectId tsurfaceId = doc.GetSurfaceIds()[0]; // get first style in the document ObjectId tstyleId = doc.Styles.ProfileStyles[0]; // get the first label set style in the document ObjectId tlabelSetId = doc.Styles.LabelSetStyles.ProfileLabelSetStyles[0]; try { ObjectId profileId = Profile.CreateFromSurface("My Profile", talignID, tsurfaceId, tlayerId, tstyleId, tlabelSetId); ts.Commit(); } catch (Autodesk.AutoCAD.Runtime.Exception Ex) { Application.ShowAlertDialog("The following exception was caught:\n" + Ex.Message); } } } } }
This is taken from the Autodesk website. If I run this on its own in its own plugin its fine. in mine....not???
Yes the drawing has a surface, an alignment, styles and labelstyleset. There are other parts of my code that check for all of this.
The error thrown is:
System.ArgumentException occurred HResult=-2147024809 Message=Value does not fall within the expected range. Source=AeccDbMgd StackTrace: at Autodesk.Civil.DatabaseServices.Profile.CreateFromSurface(String profileName, ObjectId alignmentId, ObjectId surfaceId, ObjectId layerId, ObjectId styleId, ObjectId labelSetId, Double offset, Double sampleStart, Double sampleEnd) at Autodesk.Civil.DatabaseServices.Profile.CreateFromSurface(String profileName, ObjectId alignmentId, ObjectId surfaceId, ObjectId layerId, ObjectId styleId, ObjectId labelSetId) at NJD_C3D_CreateMultipleProfiles.CreateProfile.CreateMultipleProfiles() in C:\Users\nikde\Documents\Visual Studio 2015\Projects\C3D\CreateMultiProfile\CreateMultiProfile\CreateProfile.cs:line 40 InnerException:
Hi Jeff
Here is the code:
using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.Civil.ApplicationServices; using Autodesk.Civil.DatabaseServices; namespace NJD_C3D_CreateMultipleProfiles { class CreateProfile { public static void CreateMultipleProfiles() { Document acdoc = Application.DocumentManager.MdiActiveDocument; CivilDocument doc = CivilApplication.ActiveDocument; Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; using (Transaction ts = Application.DocumentManager.MdiActiveDocument.Database.TransactionManager.StartTransaction()) { // Ask the user to select an alignment PromptEntityOptions opt = new PromptEntityOptions("\nSelect an Alignment"); opt.SetRejectMessage("\nObject must be an alignment.\n"); opt.AddAllowedClass(typeof(Alignment), true); ObjectId talignID = ed.GetEntity(opt).ObjectId; // get layer id from the alignment Alignment oAlignment = ts.GetObject(talignID, OpenMode.ForRead) as Alignment; ObjectId tlayerId = oAlignment.LayerId; // get first surface in the document ObjectId tsurfaceId = doc.GetSurfaceIds()[0]; // get first style in the document ObjectId tstyleId = doc.Styles.ProfileStyles[0]; // get the first label set style in the document ObjectId tlabelSetId = doc.Styles.LabelSetStyles.ProfileLabelSetStyles[0]; try { ObjectId profileId = Profile.CreateFromSurface("My Profile", talignID, tsurfaceId, tlayerId, tstyleId, tlabelSetId); ts.Commit(); } catch (Autodesk.AutoCAD.Runtime.Exception Ex) { Application.ShowAlertDialog("The following exception was caught:\n" + Ex.Message); } } } } }
This is taken from the Autodesk website. If I run this on its own in its own plugin its fine. in mine....not???
Yes the drawing has a surface, an alignment, styles and labelstyleset. There are other parts of my code that check for all of this.
The error thrown is:
System.ArgumentException occurred HResult=-2147024809 Message=Value does not fall within the expected range. Source=AeccDbMgd StackTrace: at Autodesk.Civil.DatabaseServices.Profile.CreateFromSurface(String profileName, ObjectId alignmentId, ObjectId surfaceId, ObjectId layerId, ObjectId styleId, ObjectId labelSetId, Double offset, Double sampleStart, Double sampleEnd) at Autodesk.Civil.DatabaseServices.Profile.CreateFromSurface(String profileName, ObjectId alignmentId, ObjectId surfaceId, ObjectId layerId, ObjectId styleId, ObjectId labelSetId) at NJD_C3D_CreateMultipleProfiles.CreateProfile.CreateMultipleProfiles() in C:\Users\nikde\Documents\Visual Studio 2015\Projects\C3D\CreateMultiProfile\CreateMultiProfile\CreateProfile.cs:line 40 InnerException:
For me to test this I added a using Autodesk.AutoCAD.Runtime; ,changed the class to public, and added a [CommandMethod()] . I used the tutorial drawing Profile-4A and it worked without error.
The only time I've encountered that error is when the ProfileLabelSet either didn't exist or it was missing a labelstyle.
For me to test this I added a using Autodesk.AutoCAD.Runtime; ,changed the class to public, and added a [CommandMethod()] . I used the tutorial drawing Profile-4A and it worked without error.
The only time I've encountered that error is when the ProfileLabelSet either didn't exist or it was missing a labelstyle.
Jeff,
I had the same result so tried a couple of things which I found 'interesting'. I did the same as you and found that the code runs just fine. so....
I added the code snippet from the autodesk site as its own class in my app and called it and it runs fine. If I run it by sending arguments from my own app it fails. I compared the arguments I passed to it to the arguments the code snippet generates and they are the same.
In my app I call a SelectAlignments function and convert the ObjectIS's to an array of ID's
public static List<BaseC3DObject> SelectAlignments() { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; PromptSelectionOptions ssPrmpt = new PromptSelectionOptions(); ssPrmpt.MessageForAdding = "\nSelect alignments:"; TypedValue[] fdata = new TypedValue[1]{ new TypedValue((int)DxfCode.Start, "AECC_ALIGNMENT") }; SelectionFilter ssFilter = new SelectionFilter(fdata); PromptSelectionResult ssResult = ed.GetSelection(ssPrmpt, ssFilter); if (ssResult.Status != PromptStatus.OK) { return null; } SelectionSet selSet = ssResult.Value; ObjectId[] objectIDList = selSet.GetObjectIds();
The select alignment function in the Autodesk snippet is singular in selection and uses different methods:
PromptEntityOptions opt = new PromptEntityOptions("\nSelect an Alignment"); opt.SetRejectMessage("\nObject must be an alignment.\n"); opt.AddAllowedClass(typeof(Alignment), true); ObjectId testAlignID = ed.GetEntity(opt).ObjectId; Alignment oAlignment = trans.GetObject(testAlignID, OpenMode.ForRead) as Alignment; ObjectId testLayerID = oAlignment.LayerId; ObjectId testSurfaceId = doc.GetSurfaceIds()[0]; ObjectId testStyleId = doc.Styles.ProfileStyles[0]; ObjectId testLabelSetId = doc.Styles.LabelSetStyles.ProfileLabelSetStyles[0];
even though the ObjectID's generated by the different codes are identical, could the Type be different??
Jeff,
I had the same result so tried a couple of things which I found 'interesting'. I did the same as you and found that the code runs just fine. so....
I added the code snippet from the autodesk site as its own class in my app and called it and it runs fine. If I run it by sending arguments from my own app it fails. I compared the arguments I passed to it to the arguments the code snippet generates and they are the same.
In my app I call a SelectAlignments function and convert the ObjectIS's to an array of ID's
public static List<BaseC3DObject> SelectAlignments() { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; PromptSelectionOptions ssPrmpt = new PromptSelectionOptions(); ssPrmpt.MessageForAdding = "\nSelect alignments:"; TypedValue[] fdata = new TypedValue[1]{ new TypedValue((int)DxfCode.Start, "AECC_ALIGNMENT") }; SelectionFilter ssFilter = new SelectionFilter(fdata); PromptSelectionResult ssResult = ed.GetSelection(ssPrmpt, ssFilter); if (ssResult.Status != PromptStatus.OK) { return null; } SelectionSet selSet = ssResult.Value; ObjectId[] objectIDList = selSet.GetObjectIds();
The select alignment function in the Autodesk snippet is singular in selection and uses different methods:
PromptEntityOptions opt = new PromptEntityOptions("\nSelect an Alignment"); opt.SetRejectMessage("\nObject must be an alignment.\n"); opt.AddAllowedClass(typeof(Alignment), true); ObjectId testAlignID = ed.GetEntity(opt).ObjectId; Alignment oAlignment = trans.GetObject(testAlignID, OpenMode.ForRead) as Alignment; ObjectId testLayerID = oAlignment.LayerId; ObjectId testSurfaceId = doc.GetSurfaceIds()[0]; ObjectId testStyleId = doc.Styles.ProfileStyles[0]; ObjectId testLabelSetId = doc.Styles.LabelSetStyles.ProfileLabelSetStyles[0];
even though the ObjectID's generated by the different codes are identical, could the Type be different??
One other thing, I used the same drawing to test the code snippet on its own and when it was used in my app. One ran okay and the other failed so I'm sure now that the styles and label sets are not the issue.
One other thing, I used the same drawing to test the code snippet on its own and when it was used in my app. One ran okay and the other failed so I'm sure now that the styles and label sets are not the issue.
Jeff
Here is the entire project solution so far, I would have posted it when completed anyway ...might help someone.
Jeff
Here is the entire project solution so far, I would have posted it when completed anyway ...might help someone.
Thanks, @Nik-D . This is a bit of a challenge. There is definitely something about using the WPF form which is tripping it up. I have very similar code which is run from a WinForm and runs perfectly. Even when I use only the variables created in the TestFunction for the newly selected Alignment (thereby not using any of the passed arguments), it fails when run from the WPF form. However, it works fine when called outside of the form.
I've tried changing a number of things around, all with the same end result. I'll keep messing around with it as time permits.
Thanks, @Nik-D . This is a bit of a challenge. There is definitely something about using the WPF form which is tripping it up. I have very similar code which is run from a WinForm and runs perfectly. Even when I use only the variables created in the TestFunction for the newly selected Alignment (thereby not using any of the passed arguments), it fails when run from the WPF form. However, it works fine when called outside of the form.
I've tried changing a number of things around, all with the same end result. I'll keep messing around with it as time permits.
Jeff
Thanks for taking the time for looking at this. Really did not know why it wouldn't run but its interesting you get the same result. Maybe its better to use WinForms in the future but WPF forms seem so much more flexible. I'll wait to hear from you.
Jeff
Thanks for taking the time for looking at this. Really did not know why it wouldn't run but its interesting you get the same result. Maybe its better to use WinForms in the future but WPF forms seem so much more flexible. I'll wait to hear from you.
@Nik-D , I had tried this yesterday but in a different location (it was in the OK button method of the window) and it didn't work. I had a thought this morning to try it in the function and it worked! Adding the DocumentLock is all it took:
public static void TestFunction(string inputName, ObjectId inputAlignID, ObjectId inputSurfaceID, ObjectId inputLayerID, ObjectId inputStyleID, ObjectId inputLabelSetStyle) { CivilDocument doc = CivilApplication.ActiveDocument; Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; var acaddoc = Application.DocumentManager.MdiActiveDocument; using (DocumentLock dl = acaddoc.LockDocument()) { using (Transaction trans = acaddoc.Database.TransactionManager.StartTransaction()) {
@Nik-D , I had tried this yesterday but in a different location (it was in the OK button method of the window) and it didn't work. I had a thought this morning to try it in the function and it worked! Adding the DocumentLock is all it took:
public static void TestFunction(string inputName, ObjectId inputAlignID, ObjectId inputSurfaceID, ObjectId inputLayerID, ObjectId inputStyleID, ObjectId inputLabelSetStyle) { CivilDocument doc = CivilApplication.ActiveDocument; Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; var acaddoc = Application.DocumentManager.MdiActiveDocument; using (DocumentLock dl = acaddoc.LockDocument()) { using (Transaction trans = acaddoc.Database.TransactionManager.StartTransaction()) {
Jeff you are 'The Man' I've spent hours trying different ideas just getting the same results. I'll need to do some thorough reading on the docklock and when it should be used. The Autodesk documentation sometimes uses it and sometimes not so its a bit confusing as to when and how..
Anyway thanks so much.
Nik-D
Jeff you are 'The Man' I've spent hours trying different ideas just getting the same results. I'll need to do some thorough reading on the docklock and when it should be used. The Autodesk documentation sometimes uses it and sometimes not so its a bit confusing as to when and how..
Anyway thanks so much.
Nik-D
I recommend taking a look at this AU 2018 class [Pipe Networks Under the Hood]. It's a good example of how you can structure your code to keep the WPF code clean and simple using the MVVM pattern. It may take a bit of time to get comfortable with that coding pattern but is probably worth it if you stick with WPF.
I recommend taking a look at this AU 2018 class [Pipe Networks Under the Hood]. It's a good example of how you can structure your code to keep the WPF code clean and simple using the MVVM pattern. It may take a bit of time to get comfortable with that coding pattern but is probably worth it if you stick with WPF.
Thanks I will definitely look into that. I am pretty new to this sort of thing, I tinkered around with VBA a few years ago but nothing really, just making simple functions etc.
While researching C sharp code snippets for more understanding and to modify/use in my code I came across MVVM but at this stage I find it slightly overwhelming. I need to spend quite a bit if time I think with my nose in some books/web pages. The WPF forms seem pretty cool so I will definitely stick with them and keep plugging away as they say.
Thanks again for the info.
As promised earlier in this post here is my final code for the create multi-profiles.
The command prompt is NJD_C3D_CreateMultipleProfiles. Its targeted at C3D 2018 x64
Thanks I will definitely look into that. I am pretty new to this sort of thing, I tinkered around with VBA a few years ago but nothing really, just making simple functions etc.
While researching C sharp code snippets for more understanding and to modify/use in my code I came across MVVM but at this stage I find it slightly overwhelming. I need to spend quite a bit if time I think with my nose in some books/web pages. The WPF forms seem pretty cool so I will definitely stick with them and keep plugging away as they say.
Thanks again for the info.
As promised earlier in this post here is my final code for the create multi-profiles.
The command prompt is NJD_C3D_CreateMultipleProfiles. Its targeted at C3D 2018 x64
Can't find what you're looking for? Ask the community or share your knowledge.