Eng-Tips is the largest engineering community on the Internet

Intelligent Work Forums for Engineering Professionals

  • Congratulations waross on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Properly ending a Macro 1

Status
Not open for further replies.

Creigbm

Mechanical
Aug 1, 2003
161
0
0
US
I know I brought this up before, but I was wondering if anyone has run into this. After I run a macro, it stays in memory and doesnt 'end' properly which leads to it crashing if I run too many macros in a row. Any comments? Thanks in advance.
 
Replies continue below

Recommended for you

This is how to check the memory usage.

1. Open "Task Manager" and click "Performance" tab.
2. Record a value at "Total" under "Commit Charge (K)
3. Run a macro and notice "Total" goes up.
4. Close the macro and "Total" should go back to the previous.

As long as a macro releases the memory usage each time, it's up to total memory you have how many macro (program) you can run.

I am not an expert of Macro, but this is a simplest one.

Sub main()
Set swApp = Application.SldWorks
Set Part = swApp.ActiveDoc
End Sub

It doesn't do anything, but it goes out from the memory. Even if a macro is terminated by "Cancel" it will release memory by hitting "End" when you get "Run-time error".

Make sure if your macro releases the memory first.
 
I tried this and it did indeed release some of the memory, but not all. Is there a way in Visual Basic to clear the memory? Thanks
 
Creigbm,
I believe it is a general statement. My Visual Basic teacher, a few years ago required us to put this in every VB program we gave him. He said it removed the program from memory.

Bradley
 
Creigbm,

This is from VB help.

+++++
Note The End statement stops code execution abruptly, without invoking the Unload, QueryUnload, or Terminate event, or any other Visual Basic code. Code you have placed in the Unload, QueryUnload, and Terminate events of forms and class modules is not executed. Objects created from class modules are destroyed, files opened using the Open statement are closed, and memory used by your program is freed. Object references held by other programs are invalidated.

The End statement provides a way to force your program to halt. For normal termination of a Visual Basic program, you should unload all forms. Your program closes as soon as there are no other programs holding references to objects created from your public class modules and no code executing.
+++++
 
Unload Statement Example
The following example assumes two UserForms in a program. In UserForm1's Initialize event, UserForm2 is loaded and shown. When the user clicks UserForm2, it is unloaded and UserForm1 appears. When UserForm1 is clicked, it is unloaded in turn.

' This is the Initialize event procedure for UserForm1
Private Sub UserForm_Initialize()
Load UserForm2
UserForm2.Show
End Sub
' This is the Click event for UserForm2
Private Sub UserForm_Click()
Unload UserForm2
End Sub

' This is the Click event for UserForm1
Private Sub UserForm_Click()
Unload UserForm1
End Sub

 
Sounds like an API issue to me. CAD APIs are normally quite buggy in my exerience. I think it's going to be nearly impossible to solve without seeing the code. Are you willing to share your code with the rest of the world?
 
Bug hunt time; it may well be an unreleased Object.

Step thru your routines and find any 'set Object =' type statements that do not have matching 'set Object = nothing' statements. Just because the object was created locally in a sub/function does not (necessarily) mean it does not still exist, Objects are treated a little differently.

Also Make sure to check that any objects created in a sub are set to nothing before a premature exit:

Sub Test
Dim MyDoc as ModelDoc2
Dim FeatMgr as Featuremanager


Set MyDoc = swapp.ActiveDoc
Set FeatMgr = MyDoc.Featuremanager

if FeatMgr is nothing then
Set MyDoc = nothing ' gotta add these too!
Set FeatMgr = nothing ' so objects are cleared!
Exit Sub
end if

Set MyDoc = nothing ' most ppl will add these at end
Set FeatMgr = nothing ' of routine for housekeeping

end sub


 
Here is one example:

Code:
Dim swApp As Object
Dim Part As Object
Dim boolstatus As Boolean
Dim longstatus As Long
Dim Annotation As Object
Dim Gtol As Object
Dim DatumTag As Object
Dim FeatureData As Object
Dim retval As Variant
Dim Error1 As Variant
Dim success As Variant
Dim Feature As Object
Dim WorkingDirectory As String
Dim Component As Object
Sub main()

Set swApp = Application.SldWorks

WorkingDirectory = "\\Wal7\Adept\Integration\SolidWorks\SW_Adept.dll"

retval = swApp.LoadAddIn(WorkingDirectory)

If retval = -1 Then
    Error1 = MsgBox("The filepath name is wrong, check to see if it has changed", vbExclamation, "Adept Macro")
    End
End If

If retval = 2 Then
    swApp.UnloadAddIn (WorkingDirectory)
End If

End Sub

I have tried to unload me, set everything to nothing, but it still remains in memory. I am thinking that it is a problem with the VBA editor with SolidWorks. Any commets?
 
I think your memory leak is happening because your program isn't loading and unloading your addin properly.

Too be honest, your program needs a bit of work. For a start, you should declare all your variables inside a subroutine or function to limit their scope. Declaring variables at the module level should only be used if you REALLY need another sub/function/userform to access the variable. Use the Option Explicit statement to stop VB creating variables without you knowing about them. You're also using way too many variants. Variants are evil and should be avoided at all costs. They allow people to write really bad code, which can end up producing very obscure errors. Finally, you aren't checking all the return values for the loadaddin and unloadaddin functions.

I have to question the necessity of loading and unloading an addin programatically. If you need to use it all the time, then just leave it loaded all the time. Anyway, I've modified your code to load and unload PhotoWorks. It seems to work fine on my computer. You should be able to modify it to do want you want. :)

Option Explicit
Sub main()
Dim swApp As Object
Dim WorkingDirectory As String

Set swApp = Application.SldWorks

WorkingDirectory = "C:\Program Files\SolidWorks\photoworks\pworks.dll"

Select Case swApp.LoadAddIn(WorkingDirectory)
Case -1
MsgBox "Addin not loaded. Error generated"
Case 0
MsgBox "Addin loaded"
Case 1
MsgBox "Addin not loaded"
Case 2
Select Case swApp.UnloadAddIn(WorkingDirectory)
Case 0
MsgBox "Addin unloaded"
Case 1
MsgBox "Addin not unloaded"
End Select
End Select

End Sub

PS: Using 'unload' for objects is generally considered good form, but is often not that necessary. When a sub terminates, it will release all the memory allocated for it. There are a few instances where 'unload' should be used IMO, databases are a prime example.
 
Nathan,

think that was a really bad example to give. My programming skills are not ideal by any means, I am learning as I go along. If I want to simply have a userform load and then close it out, it is still left in memory no matter if I set the objects to nothing or not. Maybe I need to take a step back from this macro trouble and go back to basics. If I have two objects and 3 variables, do I need to specifically say:

Set Object1 = Nothing
Set Object2 = Nothing
Set Var1 = Nothing
Set Var2 = Nothing
etc...

All I want is for the program to close out and clear all variables, objects, etc. so that it is no longer in memory and interfering with other tasks. Maybe that is a better way to define the problem.
 
Not normally. You'll notice that the program I gave doesn't explicitly set swApp = nothing. In fact, I hardly ever do it. There are very few instances where you do need to do this. It's not the big problem everyone else has made it out to be.

Userforms are a bit different from objects declared at the subroutine level. The most common way to get rid of them is to use the unload(userform_name) function. This will completely remove the userform from the memory and return control to the calling subroutine.
 
>>You'll notice that the program I gave doesn't explicitly
>>set swApp = nothing. In fact, I hardly ever do it. There
>>are very few instances where you do need to do this.
>>It's not the big problem everyone else has made it out to
>>be.

Not if you're only running apps with a few hundred lines of code. You start activating multiple applications, recursing thru objects, etc, and you'll find it as necessary as "Option Explicit". Besides, it's like praying: what have you got to lose?
 
Has anyone else come across this same issue that I am talking about. For those who don't know quite what I am talking about, first run a macro. Then open up a different macro and see if it is still loaded in the memory by looking in the PROJECT window. Setting objects to nothing does not seem to solve the problem. I have been in contact with my SW distributor and their custom programming department is looking into it to see if its a flaw in VBA.
 
This is something that started with SW2003. My impression was it was by design. That may be a flawed idea. I have never questioned SW about it. I took it to be a minor annoyance. Although it does come in handy copying code from one macro to another.
 
Status
Not open for further replies.
Back
Top