I have written an application which is getting the Icon info of current cursor using GetIconInfo function of user32.dll, It works fine for some time, but after some time it starts providing wrong information in ICONINFO.hbmMask (some negative value), and when on the next line I try to get Bitmap object from Bitmap.HBitmap(bitmask), it throws an exception:
A Generic error occured in GDI+.
From there onwords, it continuously gives this exception, as GetIconInfo always return negative value (all this code is working in a loop)..
Can any one tell me what this problem is? and how to avoid the next iteration exception?
Here is the code
while (true)
{
//DLLimport User32.dll
PlatformInvokeUSER32.ICONINFO temp;
//Get the current cursor
IntPtr curInfo = GetCurrentCursor();
Cursor cur;
Icon ic;
if (curInfo != null && curInfo.ToInt32() != 0 && isOSelected)
{
cur = CheckForCusrors(curInfo);
try
{
//Dllimport User32.dll
//after some time the temp.hbmMask begin to get -ive vlaue from following function call
PlatformInvokeUSER32.GetIconInfo(curInfo, out temp);
if (temp.hbmMask != IntPtr.Zero)
{
//due to negative value of hbmMask the following function generates an exception
Bitmap bitmask = Bitmap.FromHbitmap(temp.hbmMask);
ic = Icon.FromHandle(curInfo);
Bitmap bmpCur = ic.ToBitmap();
}
}
catch (Exception ee)
{
//Exception message is
//A Generic error occured in GDI+
//and this loop begins to throw exception continuously
}
}
}// while ended
How large is your loop? GDI+ resources are OS resources and are limited in availability.
You can find out if this is your problem by monitoring the HANDLEs allocated by your process. If GDI+ starts to complain when a certain handle count (HBITMAP or HICON) reaches a limit, then you know you have to deal with your resources more intelligently. You can start by using Task Manager to do this but might want to switch to more sophisticated software like Process Explorer.
If this is your problem, then you need to read about IDisposable and make sure you call Dispose on your objects after you're done with them (won't be rendered anymore). Bitmaps and Icons and most GDI+ objects implement IDisposable.
Furthermore, it's unclear to me, but you may need to call DeleteObject on some of the raw GDI objects themselves (all depends upon where you got their handles).
Check out this PInvoke sample, are you properly deleting the objects you are pulling in through unmanaged code?
Related
I'm writing an application that accesses the Windows registry in C#.
My question on a high level is: Are there any circumstances that would cause an ObjectDisposedException be thrown when using Registry.LocalMachine.OpenSubKey(key)?
This code would only be run under Administrative privileges in my application and the key is a constant that will never be null. My first instinct would be that an ObjectDisposedException would never be thrown by this static call because the MSDN document (linked here) states that it would only be thrown when the RegistryKey is closed but I can't find in the MSDN whether or not it is possible to ever run into a closed RegistryKey through the static call.
Thanks for any help!
The test is this:
Registry.LocalMachine.Close();
Registry.LocalMachine.Dispose();
var hardwareKey = Registry.LocalMachine.OpenSubKey("HARDWARE");
Registry.LocalMachine returns a RegistryKey. If you can actually close and/or dispose it then the following line should throw an exception, which it won't.
If you do the same thing with another registry key - close it and then try to open a subkey, it will throw an ObjectDisposedException.
var hardwareKey = Registry.LocalMachine.OpenSubKey("HARDWARE");
hardwareKey.Close();
// throws the exception.
var descriptionKey = hardwareKey.OpenSubKey("DESCRIPTION");
Why do they behave differently?
According to the source code, RegistryKey.Close calls Dispose. But the particular RegistryKey returned by Registry.LocalMachine will never be closed.
This isn't documented (other than the source code) so it's up to you whether you want to rely on it. But it makes sense that if you're accessing the registry key via a static method then you shouldn't be able to close/dispose it.
If you follow the logic, system keys (including HKEY_LOCAL_MACHINE) will not be disposed except for HKEY_PERFORMANCE_DATA.
[System.Security.SecuritySafeCritical] // auto-generated
private void Dispose(bool disposing)
{
if (hkey != null)
{
if (!IsSystemKey())
{
try
{
hkey.Dispose();
}
catch (IOException)
{
// we don't really care if the handle is invalid at this point
}
finally
{
hkey = null;
}
}
else if (disposing && IsPerfDataKey())
{
// System keys should never be closed. However, we want to call RegCloseKey
// on HKEY_PERFORMANCE_DATA when called from PerformanceCounter.CloseSharedResources
// (i.e. when disposing is true) so that we release the PERFLIB cache and cause it
// to be refreshed (by re-reading the registry) when accessed subsequently.
// This is the only way we can see the just installed perf counter.
// NOTE: since HKEY_PERFORMANCE_DATA is process wide, there is inherent ---- in closing
// the key asynchronously. While Vista is smart enough to rebuild the PERFLIB resources
// in this situation the down level OSes are not. We have a small window of ---- between
// the dispose below and usage elsewhere (other threads). This is By Design.
// This is less of an issue when OS > NT5 (i.e Vista & higher), we can close the perfkey
// (to release & refresh PERFLIB resources) and the OS will rebuild PERFLIB as necessary.
SafeRegistryHandle.RegCloseKey(RegistryKey.HKEY_PERFORMANCE_DATA);
}
}
}
Is there any way to get more detail at runtime about an OutOfMemoryException? Or, can this exception somehow not be caught by the enclosing try/catch and instead a try/catch higher up the call stack? I cannot reproduce using WinDBG so it must be something I can log from the application.
I apologize for the long explanation, but there are a lot of possible causes to eliminate, which I explain.
I have read up on all the possibilities for an OutofMemoryException and basically eliminated all of them. Normally, application runs great, but occasionally on only certain computers, I am getting an OutOfMemoryException. As these reports are in the field on not reproducible locally, I only have logs to go by. But I have a fair amount of detail.
What is strange:
Anything that might logically be allocating memory in the vicinity is in a try/catch, but the exception is treated as unhandled (and caught much higher up the call stack)
There are no StringBuffers in use
The exception happens even after rebooting and restarting the application.
The exception occurs after only a couple minutes, and only about 30MiB of memory allocated, in chunks no more than 1.5MiB.
Verified the application (built for "any" processor) is running as 64 bit.
no shortage of disk space (270Gb free) and pagefile is enabled.
does not appear to be a possible LoH fragmentation issue.
This has happened a couple times in different parts of the application recently. The first time, I concluded there was a corrupt .NET assembly, as the exception was occurring right when it would first load the System.Web.Serialization assembly. I could determine it was happening right during a method call where that assembly was used for the first time. Reimaging the computer (to be identical of original setup) and updating windows resolved this issue.
But, it seems highly unlikely to me that the second case, different client, happening within a few days, is also corruption. This one is happening in a location where no assemblies would be loaded. I'm rethinking the first error now. What I do know:
It's happening in a thread pool thread (System.Timers.Timer, [Statthread])
Small number of threads active (< 5)
It happens around the time a 1MiB file is downloaded. This is read into a MemoryStream, so that could be as big as 2MiB. That is then fed to a System.Drawing.Bitmap constructor, resulting in a Bitmap that would be about 8MiB. However, that is all in a try/catch that catches System.Exception. The only thing not in the try/catch is returning the byte[] reference, which should just be a reference copy, not any memory allocation.
No other significant memory allocations have been done before this time. Reviewing heap in my local version, which should be running identically, shows just the app icon and a couple dozen objects that would be on Small Object Heap.
it is repeatable on a specific system with specific input. However, these systems are cloned from one another. Only obvious variation would be the order of windows updates.
The assembly I'm running is signed. Isn't there a checksum that ensures it isn't corrupted? Same for all the system assemblies? I don't see how this instance could be explained by corrupted dlls, or even data.
Viewing the call stack at time of exception is surprisingly unhelpful. I indicate in the code below where exception is thrown.
There is some use of COM objects. However, under normal conditions we run the app for weeks without memory problems, and when we get these exceptions, they are almost immediate, after only using around 20 relatively lightweight COM objects (IUPnPDevice)
// Stack Trace indicates this method is throwing the OutOfMemoryException
// It isn't CAUGHT here, though, so not in the try/catch.
//
internal void Render(int w, int h)
{
if (bitmap != null)
{
bitmap.Dispose();
bitmap = null;
}
if (!String.IsNullOrEmpty(url))
{
// this information is printed successfully to log, with correct url
// exception occurs sometime AFTER this somehow.
Logger.Default.LogInfo("Loading {0}", url);
// when file contents changed (to go from 1MiB to 500MiB, the error went away)
byte[] data = DownloadBinaryFile(url);
if (data != null)
{
try
{
Bitmap bmp;
using (var ms = new MemoryStream(data))
{
bmp = new Bitmap(ms);
}
bitmap = bmp;
}
catch (Exception)
{
// We do not catch anything here.
Logger.Default.LogWarning("WARNING: Exception loading image {0}", url);
}
}
//
// if we had any errors, just skip this slide
//
if (bitmap == null)
{
return;
}
// QUESTION EDIT:
// in the problematic version, there was actually an unnecessary
// call here that turns out to be where the exception was raised:
using( Graphics g = Graphics.FromImage(bitmap)) {
}
}
}
// calling this would trigger loading of the System.Web assembly, except
// similar method has been called earlier that read everything. Only
// class being used first time is the BinaryReader, which is in System.IO
// and already loaded.
internal static byte[] DownloadBinaryFile(String strURL, int timeout = 30000)
{
try
{
HttpWebRequest myWebRequest = HttpWebRequest.Create(strURL) as HttpWebRequest;
myWebRequest.KeepAlive = true;
myWebRequest.Timeout = timeout;
myWebRequest.ReadWriteTimeout = timeout;
myWebRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)";
Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
using (HttpWebResponse myWebResponse = myWebRequest.GetResponse() as HttpWebResponse)
{
if (myWebResponse.StatusCode != HttpStatusCode.OK)
{
Logger.Default.LogWarning("WARNING: Response {0} loading {1}", myWebResponse.StatusCode, strURL);
return null;
}
using (Stream receiveStream = myWebResponse.GetResponseStream())
{
using (BinaryReader readStream = new BinaryReader(receiveStream))
{
// this extension method uses MemoryStream, but seems irrelevant since we don't catch anything here.
return readStream.ReadAllBytes();
}
}
}
}
catch (Exception e)
{
// we do not catch anything here.
Logger.Default.LogError("ERROR: Exception {0} loading {1}", e.Message, strURL);
}
return null;
}
So, after all of that, I return to my opening question. Are there any known properties on the OutOfMemoryException object I can inspect, or calls I can make after the exception is thrown, to narrow this down?
And..is there any reason an OutOfMemoryException would not be caught by the first try/catch, but would be caught further up the call stack?
Thank you all. The answer is somewhat curious and I had some details wrong which made it hard to figure out. The error is here:
Bitmap bmp;
using (var ms = new MemoryStream(data))
{
bmp = new Bitmap(ms);
}
bitmap = bmp;
In the remarks in documentation on the Bitmap constructor, I found this:
You must keep the stream open for the lifetime of the Bitmap.
Obviously, closing the MemoryStream immediately after constructing was violating this. A garbage collection between this and when I actually used the Bitmap was apparently creating the error. (EDIT: actually, it seems that a boundary exists around 1MiB where the FromStream function will decompress only so much of a JPEG file initially. For JPEG < 1MiB, the entire image is decompressed and it doesn't actually use the stream after the initialization. For larger JPEG, it will not read beyond the first 1MiB until those pixels are needed)
It's hard for me to imagine why Microsoft did it this way. I wouldn't want to keep the original stream open, either (which is an http connection) so only solution I see is to clone the bitmap:
// Create a Bitmap object from a file.
using (var ms = new MemoryStream(data))
{
bmp = new Bitmap(ms);
Rectangle cloneRect = new Rectangle(0, 0, bmp.Width, bmp.Height);
System.Drawing.Imaging.PixelFormat format = bmp.PixelFormat;
this.bitmap = bmp.Clone(cloneRect, bmp.PixelFormat);
}
What led to my long frustrating search and the exclusion of a key piece of information was that the code executing on a client machine was a slightly older version, with only a subtle change. Graphics.FromImage() was being called on the bitmap in the previous version, but that had been removed. Still, that version functioned very well the vast majority of the time.
I implemented a C# application that recevies frame RGB at framerate of 30fps.
The event of frame arrive is managed with this code:
void client_ColorFrameReady(object sender, ColorFrameReadyEventArgs e)
{
mycounter++;
Console.WriteLine("new frame received: " + mycounter);
if (writer != null)
{
count++;
if (count % 2== 0)
{
using (var frame = BitmapImage2Bitmap(e.ColorFrame.BitmapImage))
using (var thumb = ResizeBitmap(frame, 320, 240))
{
writer.WriteVideoFrame(thumb);
}
}
}
else
{
writer.Close();
}
}
with the if condition I manage only one of two frames.
When my code call BitmapImage2Bitmap I obtain this exception:
The exception in english should be:
A first chance exception of type 'System.NotSupportedException' occurred in `PresentationCore.dll`
Additional information: BitmapMetadata is not available on BitmapImage.
The strange thing is that my application works "well" because the frames are correctly inserted in the output file.
I've read this, so the problem seems a bug in WPF framework.
This is by design. A first-chance exception notification doesn't mean that there's a problem. The relevant code inside the Create() method looks like this:
try
{
metadata = source.Metadata as BitmapMetadata;
}
catch (NotSupportedException)
{
}
In other words, the exception is expected and simply swallowed. Which is certainly very annoying since these exceptions do make the debugger stop when you have the Thrown checkbox checked in the Debug + Exception dialog. But it certainly is not a bug, this was intentionally written this way. Sometimes it is a lot cheaper to just let an exception be thrown and swallowing it instead of writing the code that prevents the exception. Especially when it gets unpractical to avoid the exception, the case with bitmaps since there are so many different kind of bitmap types. Some of which don't support metadata. Wherever this is done inside the framework code, it is almost always done to make the code faster. Speed is also an important aspect of code.
Feature, not a bug. Untick the Thrown checkbox to avoid seeing these exceptions.
I hope my answer help you,
I had using same code, but BitmapFrame.cs (at PresetationCore.dll) occur Exception when we are using BitmapFrame.Create(source).
So, I just Using other create function below one, which is Inner function of BitmpaFrame.Create,
BitmapFrame.cs
public static BitmapFrame Create(
BitmapSource source,
BitmapSource thumbnail,
BitmapMetadata metadata,
ReadOnlyCollection<colorcontext> colorContexts
)
we can get same result BitmapFrame.Create(source, null, null, null).
in your case,
enc.Frames.Add(BitmapImage.Create(bitmap, null, null, null));
thanks.
Running with .NET Framework 4.5, I had to change the similar line in the Microsoft SDK WPF Photo Viewer sample from
_image = BitmapFrame.Create(_source);
to
_image = BitmapFrame.Create(_source, BitmapCreateOptions.None, BitmapCacheOption.None);
to avoid the ConfigurationErrorsException. Things seem to be drifting under the hood...
I've come across this issue lately when dealing with images included in projects as Resources (BuildType=Resource in file properties). It seems to be some build related issue which makes the resources corrupt and causes what seems like random issues as WPF are loading them. Simply performing a clean/rebuild makes the error(s) go away. They may reappear when adding new images though but the same fix obviously applies.
I'm using the nVLC dll's for using the VLC Media Player within my application. It works like a charm except for one thing. I have a DataGridView with a list of movies. When I select a movie from that DataGridView it starts playing the movie within the panel that is handled by nVLC. I also use filters to filter the movies within the DataGridView. When I do this a couple of times I get an error from the nVLC DLL:
CallbackOnCollectedDelegate occurred
Managed Debugging Assistant 'CallbackOnCollectedDelegate' has detected a problem in 'C:\Users\User\Documents\Visual Studio 2013\Projects\Soft.UltimateMovieManager\Soft.UltimateMovieManager\bin\Release\Soft.UltimateMovieManager.vshost.exe'.
Additional information: A callback was made on a garbage collected
delegate of type
'nVLC.Implementation!Implementation.VlcEventHandlerDelegate::Invoke'.
This may cause application crashes, corruption and data loss. When
passing delegates to unmanaged code, they must be kept alive by the
managed application until it is guaranteed that they will never be
called.
The problem is that I can't catch that exeption. Even when I set a try/catch on the application itself, it still can't be handled.
Is this something I can resolve myself or is this a problem of the nVLC dll I use?
if (!string.IsNullOrEmpty(video_url))
{
if (pnlStartVideo != null)
{
pnlStartVideo.Dispose();
}
pnlStartVideo = new System.Windows.Forms.Panel();
pnlStartVideo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
pnlStartVideo.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
pnlStartVideo.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
pnlStartVideo.Location = new System.Drawing.Point(pnlStartInfo.Location.X, (pnlStartInfo.Location.Y + (pnlStartInfo.Height - 1)));
pnlStartVideo.Name = "pnlStartVideo";
pnlStartVideo.Size = new System.Drawing.Size(275, 153);
pnlStartVideo.TabIndex = 3;
tpStart.Controls.Add(pnlStartVideo);
m_factory = new MediaPlayerFactory(true);
m_player = m_factory.CreatePlayer<IDiskPlayer>();
m_player.WindowHandle = pnlStartVideo.Handle;
m_player.Events.PlayerStopped += Events_PlayerStopped;
UISync ui = new UISync();
ui.Init(this);
m_media = m_factory.CreateMedia<IMedia>(video_url);
m_player.Open(m_media);
m_media.Parse(true);
m_media.Events.StateChanged += Events_StateChanged;
m_player.Play();
}
Managed Debugging Assistant 'CallbackOnCollectedDelegate' ...
It is not a catchable exception since it is not an exception at all. A managed debugging assistant is helper code added to the debugger that can detect various mishaps at runtime. This one steps in when it sees the VLC player trying to use a disposed delegate object. Without the debugger your program will keel over and die in a much worse way, an AccessViolationException, not catchable either since it is native code that fails.
Looking at the VLC wrapper source code, you must create the m_player instance only once to avoid this failure mode. When you create it over and over again like you do now, the previous IDiskPlayer instances are not reference anywhere anymore. The garbage collector will collect them, big kaboom when the native VLC code makes the callback to fire an event. The wrapper also doesn't implement proper cleanup that I can see, ensuring that the native code cannot fire events anymore when the object is disposed.
Making the m_player variable static is strongly recommended. Assign it just once.
Fixing the wrapper would require writing the equivalent of initializeEventsEngine() but setting all the callbacks back to null. This is not necessarily straight-forward, there are probably threading races involved. Taking a dependency on this code is a liability, you might want to keep shopping.
I am using DirectShow's SampleGrabber to capture an image from a webcam video. Codes are writing in C# and use .NET wrappers of DirectShow's interfaces to do COM communication. The following BufferCB, first, copies image data to a local array variable, disables SampleGrabber callback, processes a received image data, and uses MessageBox to shows a result.
public int BufferCB(double sampleTime, IntPtr pBuffer, int bufferLen)
{
if (Monitor.TryEnter(lockSync))
{
try
{
if ((pBuffer != IntPtr.Zero))
{
this.ImageData = new byte[bufferLen];
Marshal.Copy(pBuffer, this.ImageData, 0, bufferLen);
// Disable callback
sampleGrabber.SetCallback(null, 1);
// Process image data
var result = this.Decode(new Bitmap(this.ImageData));
if (result != null)
{
MessageBox.Show(result.ToString());
}
// Enable callback
sampleGrabber.SetCallback(this,1);
}
}
finally
{
Monitor.Exit(this.parent.lockSync);
}
}
return 0;
}
Now, if the result = null, hence the MessageBox.Show never runs, both clamping calls sampleGrabber.SetCallback() will run without any issue. Once the result != null, and the MessageBox shows up, the call sampleGrabber.SetCallback(this,1) will throw the InvalidCastException as below:
Unable to cast COM object of type 'System.__ComObject' to interface type 'DirectShowInterfaces.ISampleGrabber'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{6B652FFF-11FE-4FCE-92AD-0266B5D7C78F}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
If I stop in a VS debugger and add a watch of ((ISampleGrabber)sampleGrabber).SetCallback(sampleGrabber, 1), I will get the ArgumentException with the message of "Cannot find the method on the object instance." instead.
May someone experience the same issue can give me some advise. Thank you.
BufferCB and SampleCB calls take place on worker threads, which typically belong to MTA. Your graph initialization on the other hand typically takes place on STA thread. DirectShow API and filters volantarily ignore COM threading rules while .NET enforces thread checks an raises exception on attempts to use COM interface pointer on a wrong thread. You are hitting exactly this issue.
You don't need to reset callback and then set it back. Use SampleCB callback instead and it happens as a blocking call. Before you complete the processing the rest of the streaming is on hold.