WPF application unable to handle remote desktop resolution change - c#

I'm working on a .NET 4 WPF application, and just the other day, came across a very peculiar bug. I have three Windows 7 Pro machines involved: laptop (1366x768), desktop (1680x1050, multi-monitor), and the remote machine (resolution unknown). Our application is installed on the remote machine.
Consider the following events: I remote desktop into the remote machine from my laptop, start our application, and launch a particular feature (an mdi child) within the application. If I connect to the same remote session from my desktop (thus closing the session on my laptop), this feature within my application becomes completely unusable. By unusable, I mean combo box drop downs are showing in the top/left corner (much like what's described here), other controls aren't laid out correctly, and some controls don't even show at all. Mouse coordinates appear to be off in that clicking certain controls no longer invokes the appropriate actions. It's the strangest thing I've ever seen.
If I close the application and launch a new instance on my desktop, things work great. Also, it only seems to happen when I launch the feature on my laptop, then move to the desktop. Never the other way around.
I wish I could show some code, but I don't really even know where to start or what to show. I can say that it only happens on certain features. Some features handle the resolution change perfectly.
Has anyone else seen these types of symptoms? Or know what could cause them or how they could be fixed?

This is a little embarrassing. After a few hours of "process of elimination", I found that another developer had added some unmanaged code to automatically maximize the window. The approach they followed is documented here. This approach does not work through remote desktop sessions. Lol.

Related

Taking screenshots of partially hidden windows from .NET WPF applications

I am working on a program that starts several other c# WPF applications and checks wether there are errors (using .NET Automation Services / UITesting).
One of the requirements of it is to take a screenshot of the main window and to put it into a word document. I alread got it working quite fine when it´s one application at a time (using code from this site: http://www.developerfusion.com/code/4630/capture-a-screen-shot/) , but as soon as i am using parallelism (say, checking 5 applications in a parallel manner), i am running into the problem that the screenshots of the windows may be overlapped by other windows that just popped up or that are always brought to the front (e.g. splash screens). Bringing the window to the front does not really help.
There was an older similar thread not directly regarding to WPF applications, and sadly, without a clear solution: Taking screenshot of a partially hidden window in a programmatic way
Is there a way to get a "clean" screenshot, may be with the use of the windows AutomationElement instance?

Taking an IE screenshot returns a black image

I'm building a console app which will connect to different computers in the network and take browser screenshots of a webpage.
Using Selenium 2.47.1 to set up server & nodes. The console app runs in the PC which is set up as selenium hub.
The screenshot is fine in firefox,chrome,ie from the hub computer.
The screenshot is also fine in firefox in remote pc.
But with IE it returns a black image.
Both the hub and node computers run on windows 7 64-bit, have IE11. I am using the 64bit IEDriver in both PCs.
The node computer is not locked.
using OpenQA.Selenium;
using OpenQA.Selenium.IE;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium.Support.UI;
static void Main(string[] args)
{
IWebDriver NewDriver = null;
using (NewDriver = new RemoteWebDriver(new Uri("http://172.165.10.111/wd/hub"), DesiredCapabilities.InternetExplorer()))
{
if (NewDriver != null)
{
NewDriver.Navigate().GoToUrl("http://www.google.com");
NewDriver.Manage().Window.Size = new Size(1804, 1096);
Screenshot ss = ((ITakesScreenshot)NewDriver).GetScreenshot();
ICapabilities capabilities = ((RemoteWebDriver)NewDriver).Capabilities;
ss.SaveAsFile(#"C:\Path\123.png", ImageFormat.Png);
NewDriver.Quit();
}
}
}
It's because your screen is locked, or a screensaver is running.
You will need to turn off your screensaver and configure windows to never lock itself when not in use. To turn off your screensaver:
Click the Start button.
Click Control Panel.
In the search box, type screen saver.
Click Turn screen saver on or off.
Then modify your screensaver settings. Make sure you have unchecked "On resume, display logon screen".
While you're in the control panel it's probably worth checking the power options and making sure the machine isn't going to sleep or powering down after a set period of time as well.
You will also want to use VNC or remote assist to access the GUI. If you RDP in it will lock the screen for the local user who is currently logged in and again it will lock the screen when you disconnect.
Finally don't use the 64-bit IE driver, you should be using the 32Bit one. Nobody runs the 64Bit version of IE (even if they have a 64Bit capable machine).
****** Edit
Adding a bit more info from a credible and reputable source ******
Below is a link to a post on the Selenium users forum where Jim Evans (the developer who wrote the IEDriver binaries) explains this:
http://selenium.10932.n7.nabble.com/IE-Screenshots-are-black-when-not-connected-via-Remote-Desktop-to-the-VM-hosting-an-IE-Node-td37004.html
This quote in particular about taking screenshots when you have disconnected from a RDP instance:
It's a known limitation. There is no known workaround. Complain to
Microsoft. They're the ones that make the PrintWindow API (which is
the proper API to use when grabbing screen captures) behave that way.
Either that, or if you discover a way to make it work, you're welcome
to submit a patch.
He explains how the screenshot code works in more detail on his blog here:
http://jimevansmusic.blogspot.co.uk/2014/09/screenshots-sendkeys-and-sixty-four.html
Specifically:
The IE driver takes screenshots using the PrintWindow API function.
PrintWindow can only take a screenshot of the visible portion of any
given window, which means that in order to get a full-page screenshot
(as required by the WebDriver API), the window must be sized large
enough to display the entire page without scroll bars. However,
Windows does not allow the window to be resized larger than the
visible screen resolution. When we ask IE to resize itself, a
WM_GETMINMAXINFO message is sent on a resize event so the IE can
figure how large a window can be. By intercepting that message with a
hook, and modifying the max values, we can trick IE into thinking that
a window can be sized greater than the screen resolution would
otherwise allow.
It looks like this might be a known issue with configuration:
https://code.google.com/p/selenium/issues/detail?id=3536
From what #ShubhasmitGupta mentioned above, it does look like the IE driver hands out black-screen screenshots when the desktop is locked (I'm assuming this has something to do with DWM/Explorer not rendering windows).
There's a workaround involving not locking the targeted computer when connecting to it via RDP. Essentially, you create a disconnect.bat file with the following contents:
tscon rdp-tcp#0 /dest:console
I'm not sure exactly when that's supposed to be run, but the concept is to prevent the test computer from being locked when connecting via Remote Desktop. If that helps, great; I haven't been able to test the workaround myself and figure out how to set it up. Maybe someone else can write a more concise answer.
Open up the Service Control Manager -- You can do WindowsKey+R (run) and type services.msc and hit <ENTER> and it'll start up.
Find the service and right click it and choose properties from the context menu.
Allow Service to Interact With Desktop
Now, select the Log On tab.
You want to make sure the checkbox is selected for "Allow service to interact with the desktop".
You can see it in the image below.
Note: I don't have that service so I just picked another one in the sample picture.
you may want to try removing below line
//NewDriver.Manage().Window.Size = new Size(1804, 1096);
maximize your browser instead.
NewDriver.Manage().Window.Maximize();
I have had a sneaky suspicion that IE has been rendering with DirectX for some time and this article certainly seems to indicate that this is the case... which would explain why you'd have problems as GDI based screen grabs won't work with DirectX surfaces.
I'm saying this is an absolute... just a hunch
I had the same issue a while back, and though I don't completely understand the problem it was basically that the process executing selenium was running under a system account and thus the IE gui was visible only in session 0, whereas session 1 was showing only a black screen.
The solution which worked for me was to create a local user account on the remote host, keep that user permanently signed in and unlocked so that they have an interactive desktop available, then run your selenium app/tests as that user. I know that is not ideal, but as we had dozens of old boxes lying around, it didn't hurt to use one as a dedicated test server. Hope that helps somewhat!
Sorry, not enough rep to add this as a comment.
Perhaps an interesting hint...
...working with Selenium 2.47.x and 2.52.0 Jenkins, RDP and IE 11 in mode IE 7 (setting by website) on the server Win 2008. Additional to this, I have to screens connected to my PC.
If I am disconnected from the Win Server (not logged off) I have two situations:
The JAVA prog on the Server produces black boxes or real screenshoots. The difference is just one marker in RDP options in the display part on the local RDP configuration of my client (Win 7).
I have not an english spoken display so I hope the translation may ok.
The configuration detail is: "using all monitors by remote session"
If this marker is set, I get real screen shoots. If this one is not set I have black boxes. I can't explain why, but it works in this way...
Windows would sometimes cause black screens because the machine/desktop was not in use.

remote desktop application with wrongly displayed buttons

I have a winform within a remote desktop application that is built dynamically with a container panel for a toolbar with large (regular) buttons. The application is writen in C# and .NET 4.0. The application is viewed as it should only if I do not maximize the window (meaning restored view is fine).
Now, after RDP login - within most client computers - the application looks fine (even when we maximize and restoring). Within low resolution client computers (800x600), the buttons on the toolbar are not displayed in the right position (such as in the 1024x768 clients).
I used double buffering and it didn't help... the problem may or may not be depended on the screen resolution (it can be memory issue or something). It is not a problem of localization layout.
The following image shows the Fine and Bad states: http://imgur.com/gO4UJ,v7O9K
What can I do to resolve this issue?
OK, so in case anybody gets to this kind of case, this is the thing that made the issue:
In the form, there was an empty repaint override. The programmer that created the form was overriding the repaint with an empty method (don't know why, I guess I'll ask my team for the business logic).
How did I reproduce it in the development environment? Following Albin Sunnanbo's note, I ran the RDP application in minimized version during initialization, and I noticed that it occurs with large resolution clients also in this use case... So, I know repaint occurs while performing a window resize - and this made me suspicious about the method...
==> On a side note, I guess this is why inheritance is so bad, and going on to WPF is better. It took me 3 days to understand why this issue occurred.

Detecting raised-event at OS-level (OS Appearance)

I have what seems to be a common problem. I am running Windows 7 Home Premium on one of the most awesomest computers (when it was bought last year) and certain visual effects just automatically turn themselves off.
My average user experience rating is high, so it doesn't explain why this happens. The only feature that ever gets turned off is the 'Show window contents while dragging' option. And it really annoys me.
There are currently no working solutions to this problem online. Other than to "there must be a conflict with another app installed on your machine."
And yes, I do know what app is causing this conflict. It's my bloody Internet Provider's software - you know... that app that you absolutely MUST have open at all times when you're connected to the net.
So, I had a thought. What if I could subscribe to an event so that my app that runs in the background will detect when this 'show window contents while dragging' option is turned off - and then my app will simply turn it back on again.
When I do this manually, it seems to stay in effect for about an hour or two, then it gets switched off again.
Is it possible to handle these types of events, and re-start certain visual effect features? If so, are there any resources on this?
I have not been able to find anything on this sibject yet.
Yes the WM_SETTINGSCHANGE message is sent to all windows when a system setting is changed. Then you can call SystemParametersInfo with SPI_GETDRAGFULLWINDOWS to determine if the "Show window contents while dragging" is disabled and use SPI_SETDRAGFULLWINDOWS to enable it.
So all that you will need to do is create an application with a form (that can even stay hidden) and override the forms WndProc and handle the WM_SETTINGSCHANGE message and call SystemParametersInfo using p/Invoke. The p/Invoke definition for SystemParamtersInfo is available at pinvoke.net
Altough what may be easier is change security on the HKCU\Control Panel\Desktop\DragFullWindows registry value so that it can't be changed.

C# how to run applications on the Desktop?

Is it possible to run applications on the Windows Desktop? I mean... that it can only be seen in the system tray, and it should be able to run alongside the desktop.
I have no idea how to code it, please help me. I'm kind of new to these things, I am supposed to create something like a "Stardock Fence".
I have seen some examples, but they seem buggy, any strong alternative I could use?
Process.Start() can be used to start a windows application/console app from another win application. There are parameters that allow you to optionally hide the UI as well.
You want your application's windows to be always-on-bottom. In other words, your UI will always appear to be beneath any other open window and just above the Desktop's icons.
To accomplish that, see these related questions.
Once you have a window always on the bottom of the z-order, you'll probably want to remove the non-client window chrome (titlebar/min/max/close buttons) so that your UI can look like a more integrated part of the Desktop. There's plenty of examples around; Googling is left as an exercise for the reader.
Not entirely sure what you mean by background. I expect you mean a Windows Service which is a project type in visual studio, or you might (less likely) mean running a background thread.
Actually, if you want it in the system-tray, you don't want it entirely in the background.
If it was to be fully "in the background", then your best bet is to have it as a service.
System tray icons need a window, but you can just make it non-visible and non-taskbar and that's fine.
A common combo is a service that does the actual heavy-lifting, and a hidden-window application with a systray icon that reports on the service's status (possibly making that same window visible when further interaction is needed).
You want to run your application in the background? Is it on a windows machine? If so then you want to look into running your application as a windows service. Here's an msdn link:
Introduction to Windows Services
There's examples in the article I think - if not it's a good starting point. You can configure services to start automatically on startup of the machine etc. Your application will then run in the background.
Basically you craete your application as normal and then host it in a windows service rather than say a console app or a winforms app.

Categories

Resources