Start process on specific screen - c#

I'm writing a small tool that opens programs on specific screens, so that I can set our monitoring screens (1 machine has 2 screens) to reboot overnight and have it restore the monitoring webpages on boot to the correct screens. I had in mind to accomplish this by using .NET's System.Diagnostics.Process class.
I already saw it's possible to open a process and THEN move it somewhere using P/Invokes ( Open notepad to specific location on the screen, and to desired size? ),
however I want to set the target screen BEFORE the application opens, so that for example Chrome in Kiosk mode starts properly with this setup.
Does anyone know how to do this?

We created a similar solution not to long ago using the user32.dll's SetWindowPos. While it does not open the program on the desired window, it takes a couple of milliseconds to do so, so not really an issue for your requirement!
You can have a look at the following gist:
https://gist.github.com/reinhardholl/013a7c3fa319beeaf534#file-display-cs
Pay specific attention to the Display class:
private void ShowAppOnDisplay(App app)
{
SetWindowPos(app.Process.MainWindowHandle, 0, _screen.WorkingArea.Left, _screen.WorkingArea.Top, _screen.WorkingArea.Width, _screen.WorkingArea.Height, SWP_SHOWWINDOW);
}
Let me know if you require some more help!

Related

Is there any way to detect if an external process is running on exclusive fullscreen mode?

spent the whole day looking up for a solution, but I couldn't find it
I'm not talking about borderless windowed fullscreen, but those exclusive fullscreen mode that usually games use
is this possible?
I think you can get list of the process independently from your mode using System.Diagnostics.Process. Than you can just find any process by name or other properties.
UPDATED
So I have tried some solutions, but for now found one that works if process if full-screen right now, not minimized. Pretty much that:
Is there a way to check to see if another program is running full screen
My code Snippet (Runs in loop and checks if the process with specific name is fullsreen)
https://pastebin.com/qwE7ZXVt
Another possible solution based on window into style flags
https://www.reddit.com/r/AutoHotkey/comments/6maqdd/detecting_if_window_in_the_foreground_is/
But I was unable to make it work. You can try to PM folks there.
Also this site was very handy
https://www.pinvoke.net/index.aspx

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.

How can a screensaver continue to draw over the desktop in Windows 8?

I’m developing a screen saver in C# .NET4.0 on VS2010 which needs to do a fair bit of processing before it actually shows screens (fairly complex database access). This is fine because the user is unaware that this processing is going on and then the full screen forms kick in when everything is ready. That is, unless we are running on Windows 8.
Searching on the Microsoft Community (http://answers.microsoft.com/en-us/windows/forum/windows_8-desktop/bubbles-screensaver-has-black-background/e0807324-5ca6-4abe-b6ba-716848b41ff5?page=4) reveals that a design change was made in Windows 8 that prevents screensavers from drawing over an image of the desktop. Any screensaver that previously drew over the desktop will instead draw over a plain background using your chosen “metro” background colour. Experimenting reveals that this background kicks in immediately the .scr file launches i.e. before any forms can be displayed. Hence tricks like displaying forms minimised or with 0% opacity don’t work because this simply reveals the plain background underneath.
The best I’ve been able to come up with is to display full screen plain black forms as first action when my code starts i.e. before any database processing or other screen construction takes place. Why try to replace a plain screen with another plain screen? Well, because the default Windows background colour seems to be blue. That’s blue as in BSOD blue which looks kind of alarming when it kicks in. So the best I can do for a Windows 8 user experience is a quick flicker of blue followed by 3-4 seconds of plain black before screens are populated with something meaningful.
This new behaviour from Microsoft is apparently “by design”. The fact that it doesn’t manifest itself in Preview mode is apparently an error which one supposes MS will tidy up later.
So my question is does anyone know any way around this so that I can continue to have the desktop showing until screensaver forms are ready to kick in?
I struggled quite a lot with a similar problem regarding this awkward design decision in win8.
I the end had to compromise but my search continues for a a bullet proof solution, when I have time.
Now what I ended up with is running a batch file after the monitoring system starts and have thread detect idle time and run that batch again.
#start /wait Bubbles.scr /s & rundll32 user32.dll,LockWorkStation
What this does is:
starts screensaver preview in fullscreen (this works in win8) and waits
on user action lock screen is show and user prompted for password
As I said it's a compromise until a find something better. Hope it helps
Updated to win10; try to use that cool scr and found same issue;
Try to trick ms restriction and found only one very long solution:
enable logging of screensaver invoked events;
here instruction via gpedit: https://superuser.com/questions/538146/run-a-batch-cmd-upon-screensaver
now you will able to start other comand or app when screensaver starting;
goto C:\Windows\System32
copy Bubbles.scr and rename to Bubbles.exe
then config task to run C:\Windows\System32\Bubbles.exe with argument /s (administration->taskcheduler)
use some windows screensaver and config to use 1 min or more; (or use 'runsarver' with empty options from upper link or create your own empty.exe and rename to .scr and install with right menu, etc)
Found cool app to customize hidden screensaver features: http://winaero.com/download.php?view.8
(work with small bugs but work as needed under win10)
All work fine one cons checkbox to lock PC must be unchecked;
If needed create own app to run Bubbles and on exit lock PC or bat file as above, etc;
hope people will have fun with my solution :)

write code to find the opening windows on desktop

Is there anyway to find what kind of window is opened on the desktop in real time?
It may need C# or C++. What I have found right now is to use C# Process.GetProcesses() method to find the opened windows on desktop.
But the output cannot be changed when the users have opened any new windows. So, is there any method I can use to track the opening windows in real time?
Also, is there any way to track the mouse movement on a specific window by using our web service?
Many many thanks!
I do agree with tnw that this sounds sketchy (possibly an example would be useful to help here). However, you want to look at the windows api calls:
GetForeGroundWindow
GetCursorPos
The first will only give you the current window, and not all open windows, but it sounds like this is what you really want anyway?
Source code to Windows keystroke logger that does this (in C++): http://16s.us/16k/
Edit: It shows the open window the user is typing in (in real time), but not all open Windows, only the active window in use.

C# Select default screen for separate process

Is there a way to designate the start up location of an external process? I am trying to select the screen BEFORE the application launches, NOT move it afterwards.
When start the process and then move the window from one screen to another (programatically or manually) it resizes the window but not the content of that window because they are different resolutions.
I don't have control of the resolution of the screens or selection of which one is primary.
This question is similar to, but not the same as:
Launch an application and send it to second monitor?
Launch an application and send it to second monitor
May be I understand what you mean.
You want that external programm appears immediately in the screen you want, so you will get rid of resolution mananagement bug of the program, cause this is a bug, if content of the window doesn't reflect resolution changes of host window.
There is no way to do that, that I'm aware of. In fact solutions linked by you first load program, find window and finally move where needed.
If this is not what you're actually asking for, please explain better your intentions.
So if I understand correctly, you want to decide location a windows program launches but you don't want to move it after the program starts.
Usually a program remembers its previous position when it closes in registry for next launch. I would control that. For more information, refer to http://www.mywindowsclub.com/resources/3016-Start-up-position-programs-Windows.aspx

Categories

Resources