-
[RESOLVED]Screenshot, without screen?
Hello,
I have a pc, without a monitor attached to it. I want to make a screenshot once in x minutes, and then upload the image. The problem is, I cannot make a screenshot, because there is no screen?
I tried this code:
Code:
public Image CaptureScreen()
{
System.Windows.Forms.SendKeys.SendWait("{PRTSC}");
return System.Windows.Forms.Clipboard.GetImage();
}
I don't get anything this way.
I also tried this (Also with hardcoded values, 800*600), and don't get anything.
Code:
public Image CaptureScreen()
{
Bitmap bmpScreenshot;
Graphics gfxScreenshot;
// Set the bitmap object to the size of the screen
bmpScreenshot = new Bitmap(System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppArgb);
// Create a graphics object from the bitmap
gfxScreenshot = Graphics.FromImage(bmpScreenshot);
// Take the screenshot from the upper left corner to the right bottom corner
gfxScreenshot.CopyFromScreen(System.Windows.Forms.Screen.PrimaryScreen.Bounds.X, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Y, 0, 0, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy);
return bmpScreenshot;
}
And this (Which gives me a black 800*600 file)
Code:
public Image CaptureScreen()
{
return CaptureWindow(User32.GetDesktopWindow());
}
public Image CaptureWindow(IntPtr handle)
{
// get te hDC of the target window
IntPtr hdcSrc = User32.GetWindowDC(handle);
// get the size
User32.RECT windowRect = new User32.RECT();
User32.GetWindowRect(handle, ref windowRect);
int width = windowRect.right - windowRect.left;
int height = windowRect.bottom - windowRect.top;
// create a device context we can copy to
IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
// create a bitmap we can copy it to,
// using GetDeviceCaps to get the width/height
IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height);
// select the bitmap object
IntPtr hOld = GDI32.SelectObject(hdcDest, hBitmap);
// bitblt over
GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, GDI32.SRCCOPY);
// restore selection
GDI32.SelectObject(hdcDest, hOld);
// clean up
GDI32.DeleteDC(hdcDest);
User32.ReleaseDC(handle, hdcSrc);
// get a .NET image object for it
Image img = Image.FromHbitmap(hBitmap);
// free up the Bitmap object
GDI32.DeleteObject(hBitmap);
return img;
}
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 GetDesktopWindow();
}
Is there any other way to make a screenshot? Is there even a way to do it without having a screen?
With kind regards,
Thomas
-
Re: Screenshot, without screen?
Following is the class I am using. Here is a sample usage. I am not sure if this will work when you don't have a screen. =)
Code:
Image img = ScreenCapture.FullScreen();
string imageFile = applicationPath + @"\Exceptions\ExceptionLog" + DateTime.Now.ToString("MMddyyyy-hhmmss") + ".jpg";
img.Save(imageFile);
ScreenCapture class.
Code:
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Common
{
public class ScreenCapture
{
public static Bitmap FullScreen()
{
return ScreenCapture.ScreenRectangle(SystemInformation.VirtualScreen);
}
public static Bitmap DisplayMonitor(System.Windows.Forms.Screen monitor)
{
Rectangle rect;
try
{
rect = monitor.Bounds;
}
catch (Exception ex)
{
throw new ArgumentException("Invalid parameter.", "monitor", ex);
}
return ScreenCapture.ScreenRectangle(monitor.Bounds);
}
public static Bitmap ActiveWindow()
{
IntPtr hwnd;
Win32.RECT wRect = new Win32.RECT();
hwnd = Win32.GetForegroundWindow();
if (hwnd != IntPtr.Zero)
{
if (Win32.GetWindowRect(hwnd, ref wRect))
{
Rectangle rect = new Rectangle(wRect.Left, wRect.Top, wRect.Right - wRect.Left, wRect.Bottom - wRect.Top);
return ScreenCapture.ScreenRectangle(rect);
}
else
{
throw new System.ComponentModel.Win32Exception();
}
}
else
{
throw new Exception("Could not find any active window.");
}
}
public static Bitmap Window(IntPtr hwnd)
{
Win32.RECT wRect = new Win32.RECT();
if (hwnd != IntPtr.Zero)
{
if (Win32.GetWindowRect(hwnd, ref wRect))
{
Rectangle rect = new Rectangle(wRect.Left, wRect.Top, wRect.Right - wRect.Left, wRect.Bottom - wRect.Top);
return ScreenCapture.ScreenRectangle(rect);
}
else
{
throw new System.ComponentModel.Win32Exception();
}
}
else
{
throw new ArgumentException("Invalid window handle.", "hwnd");
}
}
public static Bitmap Control(Point p)
{
IntPtr hwnd;
Win32.RECT wRect = new Win32.RECT();
hwnd = Win32.WindowFromPoint(p);
if (hwnd != IntPtr.Zero)
{
if (Win32.GetWindowRect(hwnd, ref wRect))
{
Rectangle rect = new Rectangle(wRect.Left, wRect.Top, wRect.Right - wRect.Left, wRect.Bottom - wRect.Top);
return ScreenCapture.ScreenRectangle(rect);
}
else
{
throw new System.ComponentModel.Win32Exception();
}
}
else
{
throw new Exception("Could not find any window at the specified point.");
}
}
public static Bitmap Control(IntPtr hwnd)
{
Win32.RECT wRect = new Win32.RECT();
if (hwnd != IntPtr.Zero)
{
if (Win32.GetWindowRect(hwnd, ref wRect))
{
Rectangle rect = new Rectangle(wRect.Left, wRect.Top, wRect.Right - wRect.Left, wRect.Bottom - wRect.Top);
return ScreenCapture.ScreenRectangle(rect);
}
else
{
throw new System.ComponentModel.Win32Exception();
}
}
else
{
throw new ArgumentException("Invalid control handle.", "hwnd");
}
}
public static Bitmap ScreenRectangle(Rectangle rect)
{
if (!(rect.IsEmpty) && rect.Width != 0 && rect.Height != 0)
{
System.ComponentModel.Win32Exception win32Ex = null;
IntPtr wHdc = Win32.GetDC(IntPtr.Zero);
if (wHdc == IntPtr.Zero)
{
throw new System.ComponentModel.Win32Exception();
}
Graphics g;
Bitmap img = new Bitmap(rect.Width, rect.Height);
img.MakeTransparent();
g = Graphics.FromImage(img);
IntPtr gHdc = g.GetHdc();
if (!(Win32.BitBlt(gHdc, 0, 0, rect.Width, rect.Height, wHdc, rect.X, rect.Y, Win32.SRCCOPY | Win32.CAPTUREBLT)))
{
win32Ex = new System.ComponentModel.Win32Exception();
}
g.ReleaseHdc(gHdc);
g.Dispose();
Win32.ReleaseDC(IntPtr.Zero, wHdc);
if (!(win32Ex == null))
{
throw win32Ex;
}
else
{
return img;
}
}
else
{
throw new ArgumentException("Invalid parameter.", "rect");
}
}
private class Win32
{
public const int CAPTUREBLT = 1073741824;
public const int BLACKNESS = 66;
public const int DSTINVERT = 5570569;
public const int MERGECOPY = 12583114;
public const int MERGEPAINT = 12255782;
public const int NOTSRCCOPY = 3342344;
public const int NOTSRCERASE = 1114278;
public const int PATCOPY = 15728673;
public const int PATINVERT = 5898313;
public const int PATPAINT = 16452105;
public const int SRCAND = 8913094;
public const int SRCCOPY = 13369376;
public const int SRCERASE = 4457256;
public const int SRCINVERT = 6684742;
public const int SRCPAINT = 15597702;
public const int WHITENESS = 16711778;
public const int HORZRES = 8;
public const int VERTRES = 10;
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[DllImport("user32", SetLastError = true)]
public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
[DllImport("user32", SetLastError = true)]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hdc);
[DllImport("user32", SetLastError = true)]
public static extern IntPtr WindowFromPoint(Point pt);
[DllImport("user32", SetLastError = true)]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32", SetLastError = true)]
public static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("gdi32", SetLastError = true)]
public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
[DllImport("gdi32", SetLastError = true)]
public static extern bool BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, uint dwRop);
}
}
}
-
Re: Screenshot, without screen?
Thanks for your reply. It does work when I'm logged in via my Remote Desktop, (Like all the code), but when I'm not logged in, I get an exeption:
Quote:
************** Tekst van uitzondering **************
System.ComponentModel.Win32Exception: Toegang geweigerd
bij Common.ScreenCapture.ScreenRectangle(Rectangle rect)
bij Common.ScreenCapture.FullScreen()
bij WindowsFormsApplication1.Form1.timer1_Tick(Object sender, EventArgs e)
bij System.Windows.Forms.Timer.OnTick(EventArgs e)
bij System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
bij System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
"Acces denied".:(
-
Re: Screenshot, without screen?
I have had this function laying around for a while:
csharp Code:
public static Bitmap CaptureScreen()
{
Bitmap BMP = new Bitmap(System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
System.Drawing.Graphics GFX = System.Drawing.Graphics.FromImage(BMP);
GFX.CopyFromScreen(System.Windows.Forms.Screen.PrimaryScreen.Bounds.X,
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Y,
0, 0,
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Size,
System.Drawing.CopyPixelOperation.SourceCopy);
return BMP;
}
-
Re: Screenshot, without screen?
Too bad, it gives an exception too.
Quote:
************** Tekst van uitzondering **************
System.ComponentModel.Win32Exception: De ingang is ongeldig
bij System.Drawing.Graphics.CopyFromScreen(Int32 sourceX, Int32 sourceY, Int32 destinationX, Int32 destinationY, Size blockRegionSize, CopyPixelOperation copyPixelOperation)
bij WindowsFormsApplication1.Form1.CaptureScreen()
bij WindowsFormsApplication1.Form1.timer1_Tick(Object sender, EventArgs e)
bij System.Windows.Forms.Timer.OnTick(EventArgs e)
bij System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
bij System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
Which means something like "Invalid handle". Hardcoding the screen size give's the same error.
Should there really be no option to do this?
-
Re: Screenshot, without screen?
Note that the function I posted returns a Bitmap and not an Image.
-
Re: Screenshot, without screen?
Saving the image as a BMP gives the same error.:(
-
Re: Screenshot, without screen?
vb Code:
private void button1_Click(object sender, EventArgs e)
{
Bitmap screen = CaptureScreen();
screen.Save(@"C:\myScreen.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
}
-
Re: Screenshot, without screen?
Code:
private void timer1_Tick(object sender, EventArgs e)
{
Bitmap screen = CaptureScreen();
screen.Save(@"C:\" + DateTime.Now.ToLongTimeString().Replace(":",".") + ".bmp", System.Drawing.Imaging.ImageFormat.Bmp);
}
public static Bitmap CaptureScreen()
{
Bitmap BMP = new Bitmap(800, 600, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
System.Drawing.Graphics GFX = System.Drawing.Graphics.FromImage(BMP);
GFX.CopyFromScreen(0, 0, 0, 0, new Size(800,600), System.Drawing.CopyPixelOperation.SourceCopy);
return BMP;
}
Same error ;)
-
Re: Screenshot, without screen?
Quote:
Originally Posted by
Mindstorms
Thanks for your reply. It does work when I'm logged in via my Remote Desktop, (Like all the code), but when I'm not logged in, I get an exeption: "Acces denied".:(
You mean it does not work when no user is logged?
-
Re: Screenshot, without screen?
Exactly. When I'm logged in, it works fine, just like all the other snippets I used. When I'm not logged in, I get a Win32Exception: Acces denied.
-
Re: Screenshot, without screen?
I messed a bit around with all the code. The only snippet that actually makes a screenshot is my third code. It makes a black screenshot, but it does at least something. I also tried another window handle instead of the whole desktop. The size and everything is correct, but it's black when I'm not logged in.
I think that means the screen is not rendered if it hasn't a screen, or an output like RDP?
-
Re: Screenshot, without screen?
I just want to ask, why would you want to take a screenshot of the screen if you are not logged in?
-
Re: Screenshot, without screen?
I can only login with RDP right now. But I'm developing a website with some very basic controls (Start program, shutdown program), so I can watch the system from (for example) my cellphone. It should be nice to have a screenshot, so I can see what's happening.;)
-
Re: Screenshot, without screen?
Quote:
Originally Posted by
Mindstorms
Exactly. When I'm logged in, it works fine, just like all the other snippets I used. When I'm not logged in, I get a Win32Exception: Acces denied.
I've done this a few times already and yes when you're not logged in or locked the workstation, a Win32Exception is generated. I have done a lot of research on this but didnt find any way to resolve it.
However if the monitor is not attached but the user is still logged in, I see no problem why you can't take a snap shot. Taking a snap shot with remote access though has the same effect as locking the computer - a win32 exception is generated.
Jennifer.
-
Re: Screenshot, without screen?
If you're not logged in and there is no screen, there is no reason for rendering everything, so Windows doesn't do it.
I did some research today, but I think I have to build this to make Windows think there is a screen attached, and so render everything. That should do the trink I think.
-
Re: Screenshot, without screen?
Quote:
Originally Posted by
Mindstorms
If you're not logged in and there is no screen, there is no reason for rendering everything, so Windows doesn't do it.
I did some research today, but I think I have to build
this to make Windows
think there is a screen attached, and so render everything. That should do the trink I think.
come on, there's got to be another way to do this. I'm not saying this method won't work but it seems to me like going after a fly with a bomb.
-
Re: Screenshot, without screen?
Why do you need a screenshot when there is no screen as described? If the form has information you want at specific intervals why not write them to a database table or physical file?
-
Re: Screenshot, without screen?
There are also other programs running, possibly messages to take care of, Windows Update bothering me, etcetera. A screenshot certainly is a lot better than creating a database of all those things.
-
Re: Screenshot, without screen?
Sorry this is not much help to resolve your question but perhaps might assist in why various code is failing.
I am wondering if your wrote the results of the following to a file and then see what the reported width and height is? Since there is no monitor I would guess a) an exception is thrown or b) width and height are 0.
Code:
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height
-
Re: Screenshot, without screen?
It gives the output 800*600, which is the screen resolution I set. The third code in my first post does actually create a bitmap with this size, but it's black.
-
Re: Screenshot, without screen?
You first need to define "logged in", do you mean "Logged in but locked", or never logged in at all.
If your screen is locked then you should be able to accomplish this, unless you are running a full screen OpenGL or DirectX 10 app underneath the lock, in which case you will only ever get a black result without some nasty hooking trickery.
If you have never logged on, then none of "your user" services or your desktop are running, and there is nothing to take a picture of as there is no desktop.
The access denied errors from sending keys and the like could be for a couple of reasons - first sending keys to other apps (im not sure about just out into the ether) isnt allowed any more (post vista) without a manifest and running <requestedExecutionLevel level="requireAdministrator" uiAccess="true" specified - which requires a digital cert. The second is because theres physically no logged on winlogon session running in which to run the program - try running it as a service and see where that gets you.
But it might be a lot easier to grab the events from event viewer to see what your pc is doing in the background.
For example - what if one window was hidden behind another - a screenshot would miss that.....
-
Re: Screenshot, without screen?
Thank you for your reply.
I have no fullscreen apps running.
The pc decodes radiosignals, and my decodingprograms are allways running. TweakUI logs the pc in automatically when I restart.
However, I get exceptions, black files, or no screenshots at all. When I log in with Remote Desktop, I can see what's happening, and if all the programs run correctly. All the snippets work, and do what they should do, as long as I'm logged in with Remote Desktop.
As soon as I close the connection, the computer stays logged in, and the programs keep on running. At this time, the screenshotsnippets don't work anymore.
The computer runs on WinXp SP3 with the latest updates, and both the computer and my Remote Desktop use the user Administrator.
The screenshot would snap the decodingprograms, so I can watch the latest signals and the status of decoding. I can't watch those things in the eventviewer unfortunately.
-
Re: Screenshot, without screen?
Quote:
Originally Posted by
crispin
You first need to define "logged in", do you mean "Logged in but locked", or never logged in at all.
If your screen is locked then you should be able to accomplish this, ......
Could you prove this?
I have tried taking screen shots many times in the past and when the computer was locked I got the Win32Exception and at other times I would get a blank picture. Similar to you I believe it could be done but was unable to find a way to do so.
Also when taking snap shots via the remote administer tool, again sometimes the exception is thrown and other times a blank picture. Again, could you prove this?
Jennifer.
-
Re: Screenshot, without screen?
Are you logged in as a administrator and is the application running as an administrator? Anyways, try this.
Code:
public static Bitmap Bitmap1
{
get
{
System.Windows.Forms.SendKeys.Send("{PRTSC}");
IDataObject data = Clipboard.GetDataObject();
return (Bitmap)data.GetData(DataFormats.Bitmap,true);
}
}
-
Re: Screenshot, without screen?
The application is run as Administrator, yes. But I already tried the sendkeys method, it doesn't work.;)
Nevertheless, I solved the problem today.:) I made a VGA-dummy, and instead of closing the RDP connection with the red X, I use the command
Quote:
%windir%\system32\tscon.exe 0 /dest:console
That insures that the screen isn't locked.
In combination with the last code in my first post, it finally works.:D
Thank you for all your suggestions everyone!
With kind regards,
Thomas
-
Re: Screenshot, without screen?
Remember to mark the thread as resolved! ;)
1) Go to top of page.
2) Click Thread Tools
3) Click Mark Thread as Resolved.