How to detect GDI resource leaks in managed C# screensaver? - c#

Here's my problem ... I suspect a GDI Resource leak in my C# screensaver that uses only managed code. Error: 'Out of memory' after many operations. I compile using VS Prof 2013 Update 4 and run under Windows 7 64bit. I use Dispose and non-static routines wherever possible. Here are my issues:
Being a screensaver, I have not even been able to use the JITdebugger
(the application load process just hangs)
Deleaker is a tool for C++, not C#
Detailed internet links apply to Windows 9x / Windows 2000 (MSDN Magazine from 2001) or Windows 2000 / Windows XP (also MSDN Magazine)
can't download GDIObj (apparently unavailable)
I can display 'GDO Objects' in Task Manager but the screensaver uses the whole screen and overlays it while running
... also with GDIview from NirSoft (Explorer.exe strangely has the highest count of GDI objects)
Thus my questions are ...
do developers no longer have GDI resource leaks using Visual Studio C#?
can GDI+ be used to continually update the screen? (in a simulation app)
do developers no longer use GDI/GDI+ for 2.5D? (= multi-layer 2D)
if so, what technology is best suited for a simulation-type application that
runs forever (in theory)
regularly updates parts within the whole screen (text & graphics)
runs in real-time (100 msec difference is tolerable but it must keep pace with a radio clock).
high resolution graphics (to the pixel in 1920x1080 format), i.e. no low-res gaming use of DirectX; no use of single-precision GPU arithmetic
C# almost worked!
In appreciation of your creative responses...
UPDATE 1
I implemented GetGuiResources() in C# as follows (code extract):
using System.Diagnostics;
using System.Runtime.InteropServices;
static class FreeMem
{
[DllImport("user32.dll")]
static extern uint GetGuiResources(IntPtr hProcess, uint uiFlags);
public static int GetGuiResourcesGDICount()
{
return (int)GetGuiResources(Process.GetCurrentProcess().Handle, 0);
}
public static int GetGuiResourcesUserCount()
{
return (int)GetGuiResources(Process.GetCurrentProcess().Handle, 1);
}
}
and my application showed
a stable GCIcount between 38 and 42
a stable UserCount between 18 and 19
until the intentionally (user-) provoked crash after which it showed
GCIcount = 62
UserCount = 35
i.e. nothing dramatic.
Please note that I regularly execute the following on a 1920 x 1080 pixel bitmap:
Graphics grTemp = Graphics.FromImage(HighlightedTZ.p_bmpC);
grTemp.DrawImage(DayNight.p_bmp, new Rectangle(0, 0, DayNight.p_bmp.Width, DayNight.p_bmp.Height));
grTemp.Dispose();

You can use a second system to remotely debug your C# code.
If you only have one machine available, you can create a second system using a virtual machine system, such as Oracle's free Virtual Box (I recommend this), or some other VM software. You will need a valid Windows license, because even though your VM software is emulating a computer, the new OS will count it as a real computer. If you have an MSDN subscription, then you can get extra OS license keys for debugging and development purposes.
Put your product on that VM, install the Visual Studio remote bugger on the VM, start it up and make sure you can access it from your host machine's Visual Studio (by using attach to process from your host machine's Visual Studio). Now you are ready to remotely debug.
Let your screen saver start on the VM. Once it starts, start up your host VS debugging by attaching to the screen saver using the remote debugger. Now set your breakpoints and watchpoints and debug as normal.
If you have a second windows box available, then you don't need the Virtual Machine software. Just install your product (screen saver) on the second windows machine, install the Visual Studio remote debugging toolset on it, start remote debugger, set it to allow you to access it, start up your preferred machine's Visual Studio, wait for the screen saver to start on second machine, attach from your Visual Studio, set break points, watch items, and debug as normal.

Related

Console application window and buffer sizes in Windows 11

Okay so I have a console application in Windows 11 using .Net-7.0 and not targeting any particular platform
When I go to set the console's window and buffer sizes it does absolutely nothing, and without checking if the operating system is Windows using OperatingSystem.IsWindows() before calling either Console.SetWindowSize([w], [w]) or Console.SetBufferSize([w], [h]) the IDE throws a warning of CA1416 as it isn't a platform specific call.
I have no problem using the IsWindows() check as this is just a test application, but I am trying to output the data in a fixed width and height (such as a REPL application would, but without redrawing the screen). Since I cannot set either the window width OR the buffer width through the System.Console API I would have to implement my own buffer code to accomplish what I am trying to do.
Is this an issue with Windows Terminal vs CMD? How do I accomplish what I am trying to do without bringing in a third party library? Am I stuck having to do some P/Invoke magic to do this?
EDIT: I am unable to change the framework I am targeting at all as the code this program tests requires .Net-7.0
EDIT 2: Upon further diagnosis I have found that a fresh console app targeting .Net Core 3.1 WILL allow me to set the buffer width/height in the following way, however it does NOT modify the window's size at all and does NOT work in .Net-7.0. Only the buffer is actually adjusted, and the call to Console.Clear() is required to make it actually stick.
Console.SetWindowSize(5,5);
Console.SetBufferSize(5,5);
Console.Clear();
According to Classic Console APIs versus Virtual Terminal Sequences:
Our recommendation is to replace the classic Windows Console API with
virtual terminal sequences. This article will outline the difference
between the two and discuss the reasons for our recommendation.
Definitions The classic Windows Console API surface is defined as the
series of C language functional interfaces on kernel32.dll with
"Console" in the name.
...
Cross-Platform Support
Virtual terminal sequences are natively
supported across platforms, making terminal applications and
command-line utilities easily portable between versions and variations
of operating systems, with the exception of Windows.
By contrast, Windows Console APIs are only supported on Windows. An
extensive adapter or translation library must be written between
Windows and virtual terminal, or vice-versa, when attempting to port
command-line utilities from one platform or another.
In the OP you've specified Windows Console APIs
Console.SetWindowSize
Console.SetBufferSize
but stated that you're not targeting any particular platform which is why you've received the following message:
CA1416: This call site is reachable on all platforms. 'Console.SetBufferSize(int, int)' is only supported on: 'windows'.
and
CA1416: This call site is reachable on all platforms. 'Console.SetWindowSize(int, int)' is only supported on: 'windows'.
Both messages state: only supported on: 'windows', which means that if you want to use them, you need to target Windows.
To Target Windows (VS 2022):
In VS menu, click Project
Select <project name> Properties
Under Target OS, select Windows
Clean and rebuild.
Also see: Target frameworks in SDK-style projects
The following code is adapted from here and has been tested. It works with .NET 7 after setting the Target OS to Windows.
static void Main(string[] args)
{
int width = 80;
int height = 10;
if (Console.WindowLeft + Console.WindowWidth < width && Console.WindowTop + Console.WindowHeight < height)
System.Console.SetBufferSize(width, height);
System.Console.SetWindowSize(width, height);
for (int i = 0; i < height; i++)
{
Console.WriteLine($"line {i + 1}");
}
}
Additional Resources:
Windows Console and Terminal Ecosystem Roadmap
Console Virtual Terminal Sequences
Console Functions
VB.NET Console: Use ANSI Sequences (Console Virtual Terminal Sequences)

Internal Speaker Beep in Windows 8 Embedded Standard

I've got an industrial panel which running a 32-bit version of Windows Embedded 8 Standard. It is required to use the internal speaker to make beep sounds. Connecting external speakers is not an option.
Previously this was running XP based Windows Embedded Standard and using Console.Beep in C# will use the internal speaker. However in Windows 8 Embedded Standard this seems to use the external speakers instead, despite not being connected up.
The internal speaker is still operational - the touchscreen driver (eGalaxTouch) still uses the internal speaker when tapping the screen, however I cannot replicate this in my own application.
I've tried the following from a C# application with no effect;
Console.Beep()
MessageBeep() (user32.dll)
Beep() (kernel32.dll)
SystemSounds.Beep.Play()
I understand this is not possible from Windows 7 64-bit onwards, but I'm using 32-bit OS here and it still works with the touchscreen?
While a solution in C#/.NET would be ideal, I'd be up for other solutions (C/C++/whatever).
Typically shortly after posting the question, I find an answer...
Basically, using the 'Beep.sys' file from the Windows (XP) Embedded Standard in place of the Windows 8 Embedded version allows Console.Beep to work as expected.
harrymc's answer to a similar question https://superuser.com/a/230167/83606 below. Note that there is no 'Beep' device in the device manager in Windows 8 (Embedded), but the procedure is otherwise similar.
From Default Beep PC Speaker changed in windows 7 – How to get back to old style :
The default beep is controlled by a
driver under,
c:\windows\system32\drivers\beep.sys.
Maybe if you switched it out with a
driver from XP/Vista it would increase
the volume.
To see this driver you have to open
device manager then click on View >
Show hidden devices. Then under
Non-Plug and Play Drivers you’ll see
“Beep.” This is the driver that runs
your beep. Right click on it then
choose properties and go to the driver
tab, then click on Driver Details…
This shows the file version which
looks like it’s been change with
Windows 7. So replace it with an
older version and see what happens.
Procedure to follow :
Boot from an UBCD4WIN disc (or BartPE if you don’t have an SATA hard
drive)
Take ownership of the “C:\Windows\System32\Drivers\Beep.sys”
file and give the local
“Administrators” Group “Full Control”
permissions.
Rename “Beep.sys” to “Beep.old” (just in case)
Copy “Beep.sys” from an XP machine to this location.

XNA 4.0 game doesn't do anything when ran on another PC

This issue is getting real tiresome and I've been spending atleast 2 days looking around for an answer. Basically, I want to publish a game, and I've hired a friend of mine to test it out before I officially release it. Whenever he runs it, reports as "nothing happends".
These conditions are met:
He has installed the .NET Framework 4.0 and the XNA Redistributable 4.0 (he most likely also has installed other .NET Frameworks and XNA Frameworks as well, because nothing worked).
The game is compiled onto a Release build.
GamerService referenced is removed.
A possible issue could be that he's using Win8, but as my searching experience goes, XNA DEVELOPMENT is only restricted on Windows 8, right?
So, what's going on? I'm clueless.. I even put a MessageBox.Show(); after the execution of my game in my Program.cs file via try/catch, and no results.
Are there any extreme conditions in my code that I need to meet?
Any site describing 100% of all requirements to run an XNA game and the most proper way to build it?
Any issues when using non-distributable "developer tools" in XNA coding? If so, what includes in these "developer tools", and what do I need to modify? (I noticed that on another thread).
An answer to this issue would more than make my day...
Ah, and also, I tried running it on a virtual machine ( Windows 7 ) but then it spat out a messagebox saying Index outside the bounds of the array on a perfectly valid code execution, and various other random errors such as missing files when they clearly are there.
Thank you greatly!
In summary I think your app wont run on Windows 8, let me explain:
Windows 8
A possible issue could be that he's using Win8, but as my searching experience goes, XNA DEVELOPMENT is only restricted on Windows 8, right?
Officially, desktop games using unmodified Microsoft XNA 4/is not supported on Windows 8 in any form:
Microsoft officials have said the XNA tools/runtime environment used primarily by game developers isn't supported on Windows 8. - Read more...
Redistributables
Any issues when using non-distributable "developer tools" in XNA coding?
That depends on whether they are required at runtime on the target machine. That might sound like an oxymoron but in Windows c/c++, I can have an app that depends on Microsoft DLLs but we are not allowed to deploy the DLLs, one must depend on it being present in the OS; service pack or some other form. Is there something you are missing?
Windows 7
Ah, and also, I tried running it on a virtual machine ( Windows 7 ) but then it spat out a messagebox saying Index outside the bounds of the array on a perfectly valid code execution
This is more interesting and I suspect is one of the more testable aspects of your application (also that it is not Windows 8). I suggest you setup a remote-debug session to your Win7 VM or if that is not possible, use Debug.WriteLine() or equivalent displaying critical state contents.

No suitable graphics card is found error in Visual Studio 2010 debug mode

When i try to run my program i get this error:
"No suitable graphics card is found. Could not find a Direct3D device
that supports the XNA Framework Hi-Def profile. Verify that a suitable
graphics device is installed. Make sure your desktop isn't locked, and
that no other application is running in full screen mode. Avoid
running under Remote Desktop or as a Windows service. Check the
display properties to make sure hardware acceleration is set to Full."
I tryied to search: i can't set Rearch profile because i have to use Hi-Def libraries. I tryied to uninstall and install XNA 4.0 and .NET 4.5 but it doesn't work.
What i should do?
My laptop:
Pentium (R) Dual-Core CPU 2.2GHz
RAM: 4GB
Windows 7 Ultimate 32 bit
DirectX 11
Mobile Intel(R) 4 Series Express Chipset Family
Intel Graphics Media Accelerator (GMA) 4500MHD
Your graphics card does not meet the XNA requirements. Why do you have to use Hi-Def? Your DirectX sounds up to date, but those are still very low end cards. Read the exact specifications on Shawn Hargreaves blog for more information.
You can set your XNA project settings in the corresponding tab to target Reach profile, not the HD one. This will probably let you run the app, but beware the performance may be very low.
You may still be able to reference the HD libs and call their methods. Try to solve specific problems you have with that approach instead.
But really get a discrete graphics card if you want high performance and less problems.

SetWindowLong is not working on some computers

Edit: More Information
I've narrowed it down to certain applications on certain computers. I am trying to launch chrome in a full screen mode on a certain monitor. This works perfectly on most systems I have tested however we have run into a set of computers running Windows 7 Pro 32bit which are being moved and resized correctly, but their border and buttons are still intact.
I realize that chrome windows all spawn under a single chrome process and that their lifecycle is volatile, but we have been able to work around this using a separate data directory which keeps each chrome instance launched that way in it's own parent process. Chrome seems to be the only application we have problems launching full screen and only on one set of computers. When running calc.exe for instance it maximizes and removes the borders without any problems on all systems we have tested. I have confirmed that the version of chrome running on each system is the same. I would really appreciate it if anyone had more insight into either this problem, or ways of further troubleshooting the issue.
I'm trying to run an application in a full screen mode using SetWindowLong and it's worked great up until the latest computer I tried it on. I am basically using the code referenced in this question: Removing window border?
This works fine on both of my laptops (Windows 7 Ultimate) and a couple work boxes that I have tested it on (Windows 7 POS Embedded) but it's not working on another computer at work (Windows 7 Professional). The SetWindowLong call is returning the expected value which indicates to me that it should be working, and the call to SetWindowPos works fine as it's resizing the window correctly, but the border and buttons are still there! It's functioning as if there was no call to SetWindowLong at all. I would greatly appreciate some help as I'm out of ideas at this point.
Edit: Here is the code in all it's 1AM red eyed glory. Pretty much a direct copy of the linked question.
int lStyle = GetWindowLong(process.MainWindowHandle, GWL_STYLE);
lStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU);
_logger.Debug(String.Format("Style: {0}", lStyle)); // 369295360
var swlResult = SetWindowLong(process.MainWindowHandle, GWL_STYLE, lStyle);
_logger.Debug(String.Format("SetWindowLong: {0}", swlResult)); // 382664704
int lExStyle = GetWindowLong(process.MainWindowHandle, GWL_EXSTYLE);
lExStyle &= ~(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);
SetWindowLong(process.MainWindowHandle, GWL_EXSTYLE, lExStyle);
Screen screen = GetDisplay(display);
return SetWindowPos(
process.MainWindowHandle,
HWND_TOPMOST,
screen.WorkingArea.Left,
screen.WorkingArea.Top,
screen.WorkingArea.Width,
screen.WorkingArea.Height,
SetWindowPosFlags.SWP_FRAMECHANGED);
Found the problem. We are using LogMeIn for remote computer management, and it seems like their video mirror driver is causing problems on certain machines. Uninstalling their mirror driver, and restarting causes everything to work as expected.
It is also the case that this fails with out-of-date copies of XP (even SP3, and perhaps others). I have confirmed on over a dozen workstations that installing recommended updates resolves this issue. There were an average of updates needed on each, so it's hard to say which one did the trick, but apparently one of them did. Yet another reason to keep updates enabled.
Is the Windows 7 Professional system 64 bit? According to the documentation for SetWindowLong
This function has been superseded by the SetWindowLongPtr function. To write code that is compatible with both 32-bit and 64-bit versions of Windows, use the SetWindowLongPtr function.
Try modifying your code to call the SetWindowLongPtr function on 64 bit systems and see what happens.

Categories

Resources