6

I am trying to make a screenshot to the window of a process in Windows 7 64 bit, the problem is that I always get error in the following line:

var bmp = new Bitmap (width, height, PixelFormat.Format32bppArgb);

Saying "invalid parameters", I made a throw to see the errors and width and height are always 0.

Before in 32 bits it worked well, but now in 64 bits it does not work anymore.

The code :

public void CaptureApplication()
{
    string procName = "firefox";

    var proc = Process.GetProcessesByName(procName)[0];
    var rect = new User32.Rect();
    User32.GetWindowRect(proc.MainWindowHandle, ref rect);

    int width = rect.right - rect.left;
    int height = rect.bottom - rect.top;

    var bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
    Graphics graphics = Graphics.FromImage(bmp);
    graphics.CopyFromScreen(rect.left, rect.top, 0, 0, new Size(width, height), CopyPixelOperation.SourceCopy);

    bmp.Save("c:\\tmp\\test.png", ImageFormat.Png);
}

private class User32
{
    [StructLayout(LayoutKind.Sequential)]
    public struct Rect
    {
        public int left;
        public int top;
        public int right;
        public int bottom;
    }

    [DllImport("user32.dll")]
    public static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rect rect);
}

How do I fix this error?

skink
  • 5,133
  • 6
  • 37
  • 58
Chris
  • 111
  • 1
  • 9
  • Maybe because the process name is `firefox.exe`? – Ian H. Oct 26 '17 at 14:31
  • I did it, and it's the same error. – Chris Oct 26 '17 at 14:31
  • 3
    You should also check the return value of the `GetWindowRect` - if it returns `IntPtr.Zero`, something went wrong in that step. – C.Evenhuis Oct 26 '17 at 14:32
  • 1
    I already tried it, it's always zero, I do not understand why, before I was good at 32 bits – Chris Oct 26 '17 at 14:37
  • Does it work with `Handle` instead of `MainWindowHandle`? – NotADeveloper Oct 26 '17 at 14:40
  • No, same error. – Chris Oct 26 '17 at 14:44
  • 2
    How many entries are returned by GetProcessesByName? I don't have FireFox but testing with both GoogleChrome & Internet Explorer the rectangle returned for entry 0 has all 4 bounds as 0, but if I check the next element in the array (var proc = Process.GetProcessesByName(procName)[1]; ) I get sensible values for the rectangle. With internet explorer I have 1 instance & 5 tabs - this results in 5 processes returned. Chrome on the other hand has 6 processes for a single instance with a single tab. – PaulF Oct 26 '17 at 14:49
  • Process.GetProcessesByName(nombre_proceso).Length return 3 – Chris Oct 26 '17 at 14:55
  • I check with Chrome and is the same error. – Chris Oct 26 '17 at 14:57
  • OK - so now you know there are 3 processes - you will need to find which is the correct one. – PaulF Oct 26 '17 at 14:58
  • Process.GetProcessesByName(nombre_proceso)[2] work, but I get a photo of visual studio – Chris Oct 26 '17 at 15:02
  • Is Visual Studio on top of firefox? Your code seems to have been taken from the initial answer to this question - the following answer shows you how to display the application in order to capture the screenshot : https://stackoverflow.com/questions/891345/get-a-screenshot-of-a-specific-application – PaulF Oct 26 '17 at 15:09
  • it's strange with the process `string procName = "notepad";` it works... but with `"chrome"` it doesn't, same error – M. Schena Oct 26 '17 at 15:14
  • yes, when the program worked, it found the firefox window anyway – Chris Oct 26 '17 at 15:15
  • @M.Schena: if you check the task manager you will see that when NotePad starts there is just a single instance - so GetProcessesByName returns an array length 1 so array element 0 is always correct. When other application like Internet Explorer, Google Chrome & FireFox open then multiple processes all with the same name are started - in the case of the OP there are 3 & it is not the first array entry that is the active window. – PaulF Oct 26 '17 at 15:17
  • @PaulF i now installed firefox, and runs several instances, but worked with above code... perhaps i just lucked the right process – M. Schena Oct 26 '17 at 15:18
  • @Chris - I didn't read far enough either - the last answer suggests using PrintWindow & that should work even if the application isn't topmost. – PaulF Oct 26 '17 at 15:18
  • it seems that the problem is firefox, try with sublimetext and I get it working, I'm going to do a for to find the indicated process – Chris Oct 26 '17 at 15:20
  • This explains what is happening with FireFox : https://support.mozilla.org/en-US/questions/1172713 - I haven't found how t find the main process yet. – PaulF Oct 26 '17 at 15:25
  • @PaulF i think i found it out. have a look at my solution and give feedback please. – M. Schena Oct 26 '17 at 15:27

1 Answers1

2

Getting the process of firefox returns an array of processes and you are looking for the one with an rectangle with realistic sizes which is the main process.

Process[] procs = Process.GetProcessesByName(procName);
var rect = new User32.Rect();
int width = 0;
int height = 0:
foreach (Process proc in procs)
{
    User32.GetWindowRect(proc.MainWindowHandle, ref rect);
    width = rect.right - rect.left;
    height = rect.bottom - rect.top;
    // break foreach if an realistic rectangle found => main process found
    if (width != 0 && height != 0)
    {
        break;
    }
}
M. Schena
  • 2,039
  • 1
  • 21
  • 29
  • That seems to work with Internet Explorer (1 instance, 4 tabs) - only 1 process with non-zero rectangle. With Google Chrome (1 instance single tab) though there were 7 process with 3 non-zero sized rectangles (all the same) - so doesn't work for that. I do not have FireFox so can't comment on that. – PaulF Oct 26 '17 at 15:39
  • @PaulF made changes that 0 values are allowed but not in an rectangle what makes more sense. Does it now work also for chrome? By me its working, but i have chrome on a second screen open. – M. Schena Oct 26 '17 at 15:47
  • 1
    Thanks for the help. – Chris Oct 26 '17 at 16:16
  • As I said - I get multiple Chrome process all with the same (non-zero) width & height - but if this works for FireFox then great. The only way I found to locate the correct process for chrome & ie was to check the commandline. – PaulF Oct 26 '17 at 16:16