13 Replies Latest reply on Oct 21, 2013 4:18 PM by Jacob Corder

    how can I check if solidworks is ready to receive another command, for example insert a feature.

    Jacob Corder

      I am running into an issue where I am adding an array of features to a part. If I add a single feature, the program is fine, I check if it needs rebuild and it does not. It crashes and says solidworks is out of memory sometimes, other times it just crashes. If I pause my debugger it seems to be renaming a sketch everytime. When I continue throught the debugger by hitting play, it continues on. But ultimately crashes somewhere. I am not sure why but I think its running too fast for solidworks.  Any suggestions?

        • Re: how can I check if solidworks is ready to receive another command, for example insert a feature.
          Simon Turner

          I don't think it is possible to run too fast for SolidWorks.

          Can you check if you really are out of memory or not? What size array are you talking about?

           

          If you are not running out of memory, then I would really suspect a bug in your program (sorry!)

          If you are in .Net, put everything in  a Try / Catch block and see if there is an exception.

            • Re: how can I check if solidworks is ready to receive another command, for example insert a feature.
              Jacob Corder

              Im 100 percent sure its a bug in my code. No need to say sorry. I've been programming for a year only. I'm suprised I don't have more bugs, or they havent hatched yet. The program is 15 forms and class modules. Total length so far is 105, 000 lines of code not including the stuff I don't see, like stuff behind forms. (I'm a CAD guy not a programmer, well I guess I am a programmer now)

               

              I have watched my memory consumption and its not even close to 1/2 of my 16gb total ram, although my Standby memory always seems to be a lot, close to half of my ram, I dont know why, but I wish I did. So it cant be running out of memory, unless it can only use so much.

               

              When I put everything in a try catch, it still doesn't catch this error, I have never been able to catch AccessViolationExceptions, even if I catch "av" as AccessViolationException. Its sometimes an AccessViolationException, which I tend to get if im trying to do something that solidworks doesn't want me to at that time, like rename a feature, or in this case I think the error is happening when I am inserting a sketch, since I cant trap the exception, I put a debug message before I tried to insert the sketch and when completed it either tells me it worked or not.  It appears it fails on SketchManager.Insert3dSketch. I am checking if isnothing (MyModelDocObject) = false then isnothing(MyModelDocObject.SketchManager) which are both good to go. Then Yesterday I finally got some more info, I got a first chance exception of something not implemented, this happens when I insert a sketch after my first feature in this array of features is inserted.

               

              The array of features could be a lot. Its like a linear pattern but individual features. So it could be whatever the user decides. Could be 5, could be 500.

               

              They are all MacroFeatures also so I don't know if that matters. The way it regenerates these features is by my code, all material removal from the part is done using temporary bodies and modifying the MacroFeature.EditBodies  with body2.operations and body cut. The tools are built from data in a Sql Database. No sketches are created in the regeneration function nor do any define the profile of the feature.

               

              Sorry for the long posts. Thanks for your help so far.

                • Re: how can I check if solidworks is ready to receive another command, for example insert a feature.
                  Keith Rice

                  You have 105,000 lines of code in just 15 classes?

                   

                  If you really want to monitor RAM usage while your program is running then you should use PerfMon. I have attached a video on how to use with SolidWorks.

                   

                  Keith

                  SolidWorks API Tutorials

                    • Re: how can I check if solidworks is ready to receive another command, for example insert a feature.
                      Jacob Corder

                      Is there a limit to how much code should be in each class module? Im not a programmer by trade so I just write code to do what I want it to. I dont know if its correct or not but it does some pretty awesome stuff. Is there a limit to the number of functions or subs in a class?

                       

                       

                       

                      Thanks.

                        • Re: how can I check if solidworks is ready to receive another command, for example insert a feature.
                          Artem Taturevych

                          There is no limitation for functions/lines of code per class/functions so do not worry about this. What I can suspect is some of your pointers may be invalid that’s why it is crashing. You are using macro features and the bodies. You are returning temporary bodies from macro feature. Perhaps some of these bodies are not valid or destroyed by any reasons. Or these bodies are not temporary. In opposite directions edit bodies for macro feature should be valid (not temporary bodies). Is there any chance that any of these bodies is temporary or for example deleted/non existing body?

                           

                          Another thing to try is to release the pointers to any COM objects using the Marshal::ReleaseComObject function: http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.releasecomobject.aspx

                           

                          Also call the GC.Collect function after macro feature generation. It may be possible that .NET is not cleaning the garbage in time when you are doing the loop insertion.

                          ____________________________________________________

                          Regards,

                          Artem Taturevych, Application Engineer at Intercad (Australia)

                           

                          translationXpert – add-in to translate SolidWorks models

                          myIntercad an integrated tool for SolidWorks Professionals

                          LinkedIn SolidWorks API Education Group

                            • Re: how can I check if solidworks is ready to receive another command, for example insert a feature.
                              Jacob Corder

                              The bodies going into the macrofeature as macrofeature.editbodies are not temporary. It is retrieved by face selection face2.igetbody. the temporary bodies are what is created to do body2.operations body cut to the imacrofeature.editbodies. there arent any possible senerios where the macrofeature.editbodies are temporary.

                               

                              I keep getting a AccessViolationException. The last time I was getting this, I was removing manipulators when I wasnt supposed to be. This problem is happening at isketchmanager.insert3DSketch. Its like solidworks isnt ready for me to insert the sketch. I cant trap it in a try catch. It just wont do it. Ill try releasing com objects with marshaler.

                               

                              One weird thing about this is its using code that I have been using for months. Its calling all of the same functions. The only difference is I am launching this from a windows form button. The other way is started from partdoc_UserSelectionPostNotify event passed to me from solidworks, Can that cause the issue?

                            • Re: how can I check if solidworks is ready to receive another command, for example insert a feature.
                              Keith Rice

                              Jacob, my question wasn't implying that your classes can't handle that many lines. Rather, I was implying that your code is badly "under-modularized" (i.e., it is not properly organized into distinct classes and functions), which is a polite way of saying that isn't well-structured. Poorly structured code becomes a nightmare to maintain and debug --- and some of your struggles might be related to this. Truly, 105,000 lines in just 15 classes is a huge, huge red flag.

                               

                              Some general rules of thumb regarding modularization:

                              • Classes that represent specific objects are better than classes that represent general objects.
                              • Functions should accomplish only one main task.
                              • If a class contains more than 1000 lines of code, you should seriously consider whether it is necessary and, if not, refactor your code.

                               

                              For example, let's say you are writing a basketball simulator. WIth proper modularizing, you would probably have some functions called Run(), Jump(), Shoot(), Pass(), Block() and so on. These would belong to a Player class. You would also have a Ball class, a Basket class, a Court class, a Referee class, a Coach class, a Score class, and so on, all with their own unique purposes.

                               

                              Poor programming practice, on the other hand, would be to have a Player class that tries to represent not only the player but the basketball and the court. And instead of having functions that represent individual key actions (like jumping, passing, shooting), having functions like StealBallAndRunToBasket() or ShootFoulShotAndCallTimeOut().

                               

                              Moreover, you should you be using proper OOP techniques like abstraction, inheritance, and encapsulation to further ensure separation of concerns in your code.

                               

                              I hope you find my comment constructive.

                               

                              Keith

                              SolidWorks API Tutorials

                                • Re: how can I check if solidworks is ready to receive another command, for example insert a feature.
                                  Jacob Corder

                                  I know I have a lot of bad code. I get something to work and move on. I do have a lot of byrefs to return lots of stuff that the function I am calling is using so I figure why not pass it back. Its probably not right but its what the solidworks api functions do a lot so I figured that is the way to do things.

                                   

                                  So if I had to get the definition of a feature and need to get multiple values from that featuredata object and i have to call this from many other functions, would you return one value per call to that function for instance I need values from a hole wizard feature and get the data from wizardholefeaturedata and I need the diameter and depth, would you get the diameter with one call and the depth with another or return both in one function since you are already calling getdefinition?

                                   

                                  I have some functions that are 150 lines long, is this a really bad idea?

                                   

                                  Again I do not know good code from bad code. If I have code that could be called more than once, I make a new function from it so it can be used elsewhere.

                                   

                                  Again any input is very helpful. It wont hurt my feelings. I learned vb from writing this add-in.

                                    • Re: how can I check if solidworks is ready to receive another command, for example insert a feature.
                                      Keith Rice

                                      I am glad you found it helpful. If you didn't check out that link, definitely read it. It's great to be reminded of things like, "The odds of failure for a software project are directly proportional to the size of the project." I for one have a very bad habit of making functions longer than they should be, so this reminder is good for me too.

                                       

                                      Nevertheless, I admire you a lot for just stepping out there and starting something (in this case your add-in). Programming isn't easy so my hat is off to anyone who is self-taught, even if their code isn't great. You want to learn and get better, and that's the key thing. Here's another amazing article on programming, by the way, which I'd highly recommend: Teach Yourself Programming in Ten Years

                                       

                                      If you want to learn about OOP, I'd highly recommend signing up for PluralSight.com for one month and taking one of their entry level VB courses. For example there is a great course called VB.NET Fundamentals by Rob Windsor that covers OOP topics and might teach you a few tricks you didn't know. If you want to go the free route, LearnVisualStudio.net (which was the inspiration for CADSharp.com, actually), has a free C# course that is really good. If you plan on programming for many years to come, C# is a good one to learn and you're already familiar with Visual Studio if you've been using VB.NET.

                                       

                                      Another thing I have done in the past to improve my programming skills is written small programs (less than 1000 lines) and then sent them to friends or colleagues who are professional programmers and asked for their feedback. They told me things like, "Why aren't you using interfaces here?" or "Why are your variables named this?" or "Why are these fields no private?" It helped me a great deal.

                                       

                                      As for your specific questions:

                                       

                                      I don't know if 150 lines is too long. Probably. But you have to consider what your function is doing. Is it trying to accomplish 10 distinct actions that could be broken up and re-used? I have written functions that didn't seem long at the time, but were a nightmare to debug because the logic was so complex. I should have stepped back and asked, "what's a more elegant way to structure this?" and taken the time to refactor. I would have saved myself lots of debugging time later.

                                       

                                      For the scenario you described involving the hole wizard feature data, I would definitely only return one item per call unless I was absolutely certain I would never need to perform those actions again in my program. But when are you that certain? So play it safe and have two functions: one that returns the depth (GetDepth) and another that returns the diameter (GetDiameter). You would probably pass in either the IFeature object or the feature data object to both functions.

                                       

                                      As for the problem you are having right now with your add-in---my suggestion would be to create a small program that repeats only the steps that are causing the crash. See if you can repeat the crash in the small program. Then you can debug it within there. Anything you can do to isolate the problem will make it easier to debug.

                                       

                                      Again, I hope this was helpful.

                                       

                                      Keith

                                      SolidWorks API Tutorials

                                        • Re: how can I check if solidworks is ready to receive another command, for example insert a feature.
                                          Jacob Corder

                                          quick question about proper code writing and passing objects to functions and subs.

                                           

                                          Should i pass the Modeldoc2 object to each function or use Sldworks.IActiveDoc2 to get the ModelDoc2 object for each function?

                                          Same for SketchManager and SelectionMgr.

                                           

                                          then in each function at the end call marshal.releaseComObject for each of these items?

                                           

                                          So

                                           

                                          Function Insert3DSketchPointAtLocation(byval Coordinates() as double, byval SkPtsFace as Face2) as SketchPoint

                                           

                                               Dim ModDoc as ModelDoc2 = Iswapp.iActiveDoc2

                                               Dim SelMgr as SelectionMgr = nothing

                                               Dim SkMgr as SketchManager = nothing

                                               If Isnothing(ModDoc) = False then

                                                    Selmgr  = ModDoc.SelectionManager

                                                    SkMgr = Moddoc.SketchManager

                                               end if

                                           

                                               If IsNothing(SelMgr) = False and IsNothing(SkMgr) = False and IsNothing(ModDoc) = False then

                                               ''' Insert teh sketch point at the location on the face"

                                           

                                               end if

                                           

                                               If IsNothing(ModDoc) = False Then Marshal.ReleaseComObject(ModDoc)

                                               If IsNothing(SelMgr) = False Then Marshal.ReleaseComObject(SelMgr)

                                               If IsNothing(SkMgr) = False Then Marshal.ReleaseComObject(SkMgr)

                                           

                                          End Function

                                           

                                          Or Like this

                                           

                                          Function Insert3DSketchPointAtLocation(ByVal ModDoc as ModelDoc2, Byval Coordinates() as double, byval SkPtsFace as Face2) as SketchPoint

                                               Dim SelMgr as SelectionMgr = nothing

                                               Dim SkMgr as SketchManager = nothing

                                               If Isnothing(ModDoc) = False then

                                                    Selmgr  = ModDoc.SelectionManager

                                                    SkMgr = Moddoc.SketchManager

                                               end if

                                           

                                               If IsNothing(SelMgr) = False and IsNothing(SkMgr) = False and IsNothing(ModDoc) = False then

                                               ''' Insert the sketch point at the location on the face"

                                                end if

                                           

                                               If IsNothing(SelMgr) = False Then Marshal.ReleaseComObject(SelMgr)

                                               If IsNothing(SkMgr) = False Then Marshal.ReleaseComObject(SkMgr)

                                           

                                          End Function

                                            • Re: how can I check if solidworks is ready to receive another command, for example insert a feature.
                                              Jacob Corder

                                              How is the best way to "Dim" Objects like ModelDoc2, SketchManager, and SelectionMgr ECT..?

                                               

                                              ISwapp is SldWorks


                                              Dim ModDoc as modeldoc2

                                              Dim SelMgr as selectionMgr

                                              Dim SkMgr as SketchManager

                                              ModDoc = ISwapp.IActiveDoc2

                                              SelMgr = ModDoc.SelectionManager

                                              SkMgr = ModDoc.SketchManager

                                              Then when im done with them i release with Marshal.ReleaseComObject or just set to nothing?

                                               

                                              or dont Dim them, just use them from ISwApp like this so there is nothing to release

                                               

                                              ISwapp.IActiveDoc2

                                              ISwapp.IActiveDoc2.SelMgr

                                              ISwapp.IActiveDoc2.SkMgr

                                               

                                              or use the "Using Statement"? if so please help me with the Using Statement, it says it must implement idisposable. so a quick

                                               

                                              Using ModDoc as ModelDoc2 = ISwapp.IActiveDoc2

                                               

                                              Thanks again for all of the help. I have already started to break up my functions as you suggested Keith.

                              • Re: how can I check if solidworks is ready to receive another command, for example insert a feature.
                                Jacob Corder

                                Ok Thanks for all the help everyone. By using the marshal.ReleaseCOMObject along with SldWorks_OnIdleNotify i was able to get the application to do what i want. by using the OnIdleNotify, i was able to basically set my program to create the next instance of the array of features that was to be created. then i incremented the array count to be ready for the next SldWorks_OnIdleNotify event to fire. It works great.

                                 

                                Keith. i have split up lots of my functions and re-evaluated some functions to make them more modular.  seems to run a lot smoother.


                                Artem i Selected yours as the correct answer because waiting for Sldworks_OnIdleNotify helped with the problem. the exceptions i was getting was from COM Objects not being released.

                                 

                                JoshBrady. The onidle notify was brilliant. i am going to use that wherever i want to modify the application programmatically. its very stable and that was an issue i was having with other calls to solidworks.

                                 

                                Again Thanks everyone.