I was tracking down an issue where "Outlook.exe" remains listed in TaskManager even though the Outlook Application object had been released and disposed by the TypeLibrary.
The calling Code is in C++ Builder. TComInterface is used to instantiate the TypeLib.
What I noticed is that even though the Dialog Box (This is where the code is called from) is closed (user has clicked "Ok" or "Cancel") and the TComInterface object goes out of scope, "Release" is not called.
Release is never called until we exit the application entirely.
Is there another way to get TComInterface to call release when it goes out of scope?
After digging some more, I found that the variable had global scope.
I changed the scope and now Release is being called.
Related
I have created a VB.Net program that uses the following code to send balloon tip notifications to the systray:
notify = New NotifyIcon
notify.Visible = True
notify.BalloonTipTitle = title
notify.BalloonTipText = body
notify.Icon = SystemIcons.Application
notify.ShowBalloonTip(100000)
However, the icon for this notification remains in the sys tray after the user has closed the application, and there seems to be no simple way to remove it by clicking on it.
How might I dead with this issue?
It's because you are not disposing the NotifyIcon object. Why exactly are you creating it in code in the first place? Unless you have a specific reason not to, you should be adding it to the form in the designer and then just setting properties and calling methods in code. That way, the object will be disposed when your form is. Failing that, you need to dispose it yourself when you're done with it, which means retaining a reference as long as required and calling Dispose explicitly.
I'm trying to save a appointment series subject. This works as expected but after the save, When I performed move/edit the calendar item, I get this error.
Code to reproduce error.
public void OnMyButtonClickContext(Office.IRibbonControl control)
{
var sel = control.Context as Microsoft.Office.Interop.Outlook.Selection;
var i = sel[1] as Microsoft.Office.Interop.Outlook.AppointmentItem;
i.Parent.Subject = i.Parent.Subject + " [CONFIRMED]";
i.Parent.Save();
}
I've tried setting i to null, using Marhsal.ReleaseComObject(i). Neither of which seems to help.
I don't see any release COM objects statements in the code. What objects exactly did you try to release?
Why do you always use the Parent property of the AppointmentItem class?
Each time you call the Parent property you get the reference counter increased. And then you need to release such objects in the code.
Use System.Runtime.InteropServices.Marshal.ReleaseComObject to release an Outlook object when you have finished using it. Then set a variable to Nothing in Visual Basic (null in C#) to release the reference to the object.
Read more about that in the Systematically Releasing Objects article.
Here is what MSDN states for that:
When you work with recurring appointment items, you should release any prior references, obtain new references to the recurring appointment item before you access or modify the item, and release these references as soon as you are finished and have saved the changes. This practice applies to the recurring AppointmentItem object, and any Exception or RecurrencePattern object. To release a reference in Visual Basic for Applications (VBA) or Visual Basic, set that existing object to Nothing. In C#, explicitly release the memory for that object.
Note that even after you release your reference and attempt to obtain a new reference, if there is still an active reference, held by another add-in or Outlook, to one of the above objects, your new reference will still point to an out-of-date copy of the object. Therefore, it is important that you release your references as soon as you are finished with the recurring appointment.
Looks like you didn't release all underlying COM objects in the code.
I have written a wxWidget gui application. Depending on the parameters, a gui is displayed in some cases, but when the program is run in silent mode, it will just perform it's task without opening a window.
I could return false in my App::OnInit() override, and the application will terminate, but then the exit code is also set to indicate that something went wrong.
So how do I properly exit in such a case, resp. how can I set the returncode?
If you enter the main event loop, as it happens if you return true from YourApp::OnInit(), you must exit it to terminate the application. This is done using ExitMainLoop() which is usually called when the last top level window is deleted, but can also be called manually.
If you don't enter the main loop event at all, then returning false from YourApp::OnInit() is the simplest way to exit the program immediately but, as you already know, this indicates a failure to initialize the application, from wxWidgets point of view, and so by default the program exits with non-zero exit code. To return your own exit code, continue to return true from OnInit() and override OnRun(), which is called next if OnInit() succeeded, and simply return the code from there, without doing anything, especially not calling the base class version which would enter the main event loop.
Check the documentation here: http://docs.wxwidgets.org/2.8/wx_wxappoverview.html
I think wxExit might be what you're looking for, though the documentation says to only use it in emergencies.
When an object is created in the .Designer.vb file from the Windows Form Designer, is a Dispose() call generated automatically for each object or must this be done manually?
Specifically, I have an object that uses unmanaged resources (by calling ShowDialog(), requiring a call to Dispose()) that is created in the Windows Form Designer. Do I still need to call Dispose() on that object?
Note: It is advised not to call Dispose() more than once on the same object.
While I dont know the answer, let me tell you how you can get the answer and learn a neat trick for designing components for winforms (might work for others but haven't tried).
Assuming you have a project that already references your component, create a new project and set the "Start External Program" to "C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe" (change this based on your version of visual studio, this is from 2005)
Run this project, which will then run another instance of VS. You have now opened VS in debug mode. Now open your project you are using to build/test your component (from the second instance of VS), set a break-point and test it. You should be able to see it hit your break-point in the dispose code.
This is great for testing VS Add-ins and designer components.
This was one of those questions where the answer is "because that is the way it works", but then you realize you don't actually know how it is implemented. So I spent a few moments to dig up the details.
Anything that is a Control (button, textbox, whatever) that is added to the Controls collection is disposed for you automatically. This implementation is inherited all the way back from the Control class itself.
Anything that is a non-graphical Component (like a Timer for example) that is added to the auto-generated components object in the MyForm.Designer.vb file is also disposed for you. In this case, components object, while implementing the System.ComponentModel.IContainer interface, will be an instance of System.ComponentModel.Container that handles the actual Dispose.
I have a UI element in my application where a Panel is used to host one of several potential custom UserControls. The Panel itself is hosted in a standardised UserControl that I am using something like a non-modal dialog that I'm calling a 'pane'.
The method I use is to instantiate a new instance of the standard pane, then with logic instantiate one of the several optional hosted controls inside it using Panel.Controls.Add(control). I then add the new pane to the interface control in a set location, again with a Control.Controls.Add(control), followed by a control.BringToFront() to maximise its z position.
This all works well, however when the time comes to hide the pane and destroy it, I cannot seem to fully get rid of it. Originally I was simply using Control.Controls.Remove(control) and for good measure setting the pane's Parent property to Nothing. This would have the desired effect of making the pane disappear, and my assumption was that now the control was unreferenced, that GC would dispose of it.
What I am seeing however is that the control still blits instantaneously onto the screen when the next outer hosting TabControl changes tab page, implying it still exists somewhere. I can confirm that this is not a graphical issue and the pane object persists using the VS Watch window's 'Make Object ID'. (At least I think this is proof, that without a code-accessible reference I can still directly see the object and its properties continue to exist.)
I have tried replacing
Control.Controls.Remove(pane)
pane.Parent = Nothing
with
pane.Dispose()
GC.Collect()
where the Dispose call I can confirm both removes the control from its parent's Controls collection and sets its Parent property to Nothing, but appears to do no more. It persists after forced GC and still blits onscreen occasionally.
This all leads to my original question, what is the proper way to remove and fully destroy controls after they have served their purpose?
According to this article from MSDN it seems like you might be experiencing side affects from the object being on the finalization queue.
A Dispose method should call the GC.SuppressFinalize method for the object it is disposing. If the object is currently on the finalization queue, GC.SuppressFinalize prevents its Finalize method from being called.
Translation: The finalize method isn't being called, and so the resources associated with your control are not being released. After a bit more digging, I found that you should
Always call Dispose before you release your last reference to the Component. Otherwise, the resources it is using will not be freed until the garbage collector calls the Component object's Finalize method.
From this article.
So either you need to release your last reference OR you need to call the components finalize method directly so your GC.Collect() will work.