Сегодня пришло письмо, где человек спрашивал о том, можно ли сделать скриншот средствами PowerShell. Я вообще не очень понял зачем это, но это уже не моё дело. Если я пишу этот пост, значит можно :-)
Для этого существует класс Drawing.Graphics у которого есть замечательный метод CopyFromScreen(). Данный метод принимает в качестве аргументов различные параметры, которые определяют координаты области, которую нужно сфоткать. В принципе можно забивать фиксированные значения (см. конструкторы с Int, как этот — CopyFromScreen(Int32, Int32, Int32, Int32, Size)), а можно эти размеры выставлять динамически, в зависимости от размеров экрана. Для этого лучше воспользоваться самым первым методом: CopyFromScreen(Point, Point, Size).
Как получить размеры экрана? Очень просто, достаточно воспользоваться статическим свойством VirtualScreen класса Windows.Forms.SystemInformation:
[Windows.Forms.SystemInformation]::VirtualScreen
[↓] [vPodans] [Windows.Forms.SystemInformation]::VirtualScreen Location : {X=0,Y=0} Size : {Width=1280, Height=800} X : 0 Y : 0 Width : 1280 Height : 800 Left : 0 Top : 0 Right : 1280 Bottom : 800 IsEmpty : False [↓] [vPodans]
Вот размеры экрана на моём нотебуке. Готично. Теперь нужно создать объект Drawing.Graphics. Однако, этот объект нельзя создать через New-Object, поскольку для этого нет ни одного конструктора. Следовательно объект нужно создавать используя статические методы. Статические методы можно посмотреть на странице Drawing.Graphics Members. И там мы можем найти красивый метод — FromImage. В качестве аргумента этого метода нужно указать картинку — http://msdn.microsoft.com/en-us/library/system.drawing.image.aspx. Это может быть файл или объект класса Drawing.Bitmap. Давайте создадим объект класса Drawing.Bitmap с использованием следующего конструктора — Bitmap Constructor (Int32, Int32):
[↓] [vPodans] [void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") [↓] [vPodans] $size = [Windows.Forms.SystemInformation]::VirtualScreen [↓] [vPodans] $bitmap = new-object Drawing.Bitmap $size.width, $size.height [↓] [vPodans] $bitmap Tag : PhysicalDimension : {Width=1280, Height=800} Size : {Width=1280, Height=800} Width : 1280 Height : 800 HorizontalResolution : 96 VerticalResolution : 96 Flags : 2 RawFormat : [ImageFormat: b96b3caa-0728-11d3-9d7b-0000f81ef32e] PixelFormat : Format32bppArgb Palette : System.Drawing.Imaging.ColorPalette FrameDimensionsList : {7462dc86-6180-4c7e-8e3f-ee7333a7a483} PropertyIdList : {} PropertyItems : {} [↓] [vPodans]
Примечание: WinForms по умолчанию не загружаются вместе с PowerShell, поэтому мы их подгружаем в консоль в ходе работы. Мы создали Bitmap и теперь его можем использовать для создания объекта Drawing.Graphics:
$graphics = [Drawing.Graphics]::FromImage($bitmap)
А дальше уже вызывать метод CopyFromScreen(). При этом указываем первым аргументом начало координат (верхний левый угол или 0,0) и в аргумент правый нижний угол. Т.е. максимум точек по ширине и высоте. Их мы можем получить из свойств Width и Height класса Windows.Forms.SystemInformation. Средний аргумент опускаем и делаем его пустым:
[↓] [vPodans] $graphics = [Drawing.Graphics]::FromImage($bitmap) [↓] [vPodans] $graphics.CopyFromScreen($size.Location,[Drawing.Point]::Empty, $size.size)
Всё, мы сфоткали наш экран и загнали картинку обратно в Bitmap. Теперь нужно выгрузить картинку куда-то в файл. Для этого у Bitmap есть метод Save(), в котором достаточно указать путь к файлу:
[↓] [vPodans] $bitmap.save(".\screenshot.jpg") [↓] [vPodans] gi .\screenshot.jpg Directory: C:\Users\vPodans Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 22.04.2010 22:37 286319 screenshot.jpg [↓] [vPodans]
Всё :-)
Примечание: после сохранения картинка остаётся в памяти, поэтому после работы следует освобождать оперативную память от ненужных пруфпиков используя метод Dispose() без аргументов.
И код:
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") $size = [Windows.Forms.SystemInformation]::VirtualScreen $bitmap = new-object Drawing.Bitmap $size.width, $size.height $graphics = [Drawing.Graphics]::FromImage($bitmap) $graphics.CopyFromScreen($size.location,[Drawing.Point]::Empty, $size.size) $graphics.Dispose() $bitmap.Save(".\screenshot.jpg") $bitmap.Dispose()
Пользуясь тем что начал снова понимать твой код, несколько мелких придирочек: :) >достаточно воспользоваться статическим методом VirtualScreen класса Windows.Forms.SystemInformation Это статическое свойство скорее. >WinForms по умолчанию не загружаются вместе с PowerShell Зависит от. Точно загружаются в ISE, да вроде и в простом v2.0 всегда есть в наличии при старте. >после сохранения картинка остаётся в памяти, поэтому после работы следует освобождать оперативную память от ненужных пруфпиков используя метод Dispose() без аргументов Если совсем придираться к словам - Dispose() помечает объект для удаления из памяти. А память освободится тогда когда кто нибудь будет поджимать, при следующем регулярном вызове Garbage Collector'а, или если вызвать его вручную: [gc]::Collect() >Домашния страница В форме отправки комментария опечатка :)
> Это статическое свойство скорее. угу. Там же скобок нету. > Зависит от. Точно загружаются в ISE, да вроде и в простом v2.0 всегда есть в наличии при старте. а этот код работает и в 1.0 тоже, где WinForms нет по дефолту. >Если совсем придираться к словам - Dispose() помечает объект для удаления из памяти. ну на MSDN написано, что этот метод освобождает ресурсы. Я не в курсе, как там точно происходит. > В форме отправки комментария опечатка :) знаю. И с этим ничего поделать не могу. Разве что убрать русску локализацию интерфейса, что я, наверное, и сделаю.
Приветы. Я бы заменил название переменной $size на, например, $Screen или $ScreenArea. А то, $size.size выглядит как-то не совсем православно и режет глаз ;)
Я не думаю, что это уж очень критично :)
Comments: