Что нового

[Автоматизация] Получаем изображение экрана удаленного компьютера (через screenshot)

zlo-kazan

Скриптер
Сообщения
374
Репутация
100
AutoIt: 3.3.6.1
Версия:

Категория: Администратирование, Автоматизация, Окна и диалоги, Файловая система, Элементы GUI

Описание:
Требовалась программа которая не требует установки и прав администратора. Работает в скрытом режиме, без установки. Не создает дополнительных TCP/UDP подключений и при этом передает текущее изображение экрана на другой компьютер. Реализованно через создание скриншота и сохранение его в общую папку (ScreenShot). И также 2-я часть которая это изображение у себя динамически обновляет (ScreenView). Функция создания скриншота взята у Yashied.

Код/Пример:
Код:
#Include <ClipBoard.au3>
#Include <GDIPlus.au3>
#include <array.au3>
#NoTrayIcon
$k=0
$pList=ProcessList()
For $i=1 to UBound($pList)-1
	if $pList[$i][0]="ScreenShot.exe" then $k+=1
Next

If $k>1 then
	msgbox(0,"","ScreenShot.exe уже запущен",2)
	exit
EndIf


Global $setingINI="настройки.ini"
Global $IP=IniRead($setingINI,"","$IP","127.0.0.1")  ;IP по которому проверять есть связь или нет. (указываешь IP главного компа)
Global $File=IniRead($setingINI,"","$File",@ScriptDir & "\" & "Screenshot.jpg") ;Куда сохранять скриншот
Global $chek=IniRead($setingINI,"","$chek",10) ;Частота обновления в сек.

While 1
if ping($IP, 4000) Then
_ScreenCapture($File)
$chek=IniRead($setingINI,"","$chek",10)
sleep($chek*1000)
Else
sleep(100)
EndIf
WEnd


Func _ScreenCapture($sFile)
    Local $Result, $Timer, $hImage, $hBitmap = 0
	$temp=ClipGet()
    ClipPut('')
    Send('{PRINTSCREEN}')
    $Timer = TimerInit()
    While TimerDiff($Timer) < 1000
        _ClipBoard_Open(0)
        $hBitmap = _ClipBoard_GetDataEx($CF_BITMAP)
        _ClipBoard_Close()
        If $hBitmap Then
            ExitLoop
        EndIf
        Sleep(10)
    WEnd
    If Not $hBitmap Then
        Return 0
    EndIf
    _GDIPlus_Startup()
    $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
    $Result = _GDIPlus_ImageSaveToFile($hImage, $sFile)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_Shutdown()
	ClipPut($temp)
    Return $Result
EndFunc   ;==>_ScreenCapture
Код:
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
;Указываем какую функцию выполнять при выключении скрипта разными способами.
OnAutoItExitRegister("ExitMsg")

;Подгрузка настроек при запуске. если настроек нет, то вбивает настройки по умолчанию. и после выкл. создаст ini-файлик.
Global $setingINI="настройки.ini"
Global $File=IniRead($setingINI,"","$File",@ScriptDir & "\" & "Screenshot.jpg")	; Файл скриншота
Global $chek=IniRead($setingINI,"","$chek",5)									;Частота обновления в сек.
Global $old_size[3]=[IniRead($setingINI,"","$old_size[0]",2),IniRead($setingINI,"","$old_size[1]",1280),IniRead($setingINI,"","$old_size[2]",720)] ;размер скрина в пикселях
Global $IP=IniRead($setingINI,"","$IP","127.0.0.1")								;IP главного компа. :-)
Global $IP1=IniRead($setingINI,"","$IP1","127.0.0.1")							;IP адрес / доменное имя / имя NetBIOS первого компьютера
Global $IP2=IniRead($setingINI,"","$IP2","127.0.0.2")							;IP адрес / доменное имя / имя NetBIOS второго компьютера
Global $delay=IniRead($setingINI,"","$delay",200)								;Делей... при проверки пинга... влияет на обновление GUI...
Global $size=$old_size

; меню в трее.
Opt("TrayMenuMode", 1+2)
Global $MenuItem1t = TrayCreateItem("Развернуть")
Global $MenuItem2t = TrayCreateItem("Выход")
GUI_create()

$timer=TimerInit()+10000
While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
		Case $GUI_exit
			Exit
		Case $GUI_path
			$path=FileOpenDialog("выбор скриншота", -1, "Images (*.jpg;*.bmp)", 3)
			GUictrlsetdata($GUI_input, $path)
		Case $com
			_GUI_update()
		Case $GUI_chek
			IniWrite($setingINI, "","$chek",GUICtrlRead($GUI_chek,0))
	EndSwitch
	_UPdate()
	$msg = TrayGetMsg()
    Switch $msg
        Case $MenuItem1t
;~ 			TrayItemSetState($MenuItem1t,$TRAY_UNCHECKED)
            GUISetState(@SW_SHOW)
			WinActivate("ScreenView")
        Case $MenuItem2t
			_iniwrite()
            Exit
    EndSwitch
WEnd

Func GUI_create()
	Global $Form = GUICreate("ScreenView", $size[1]+10, $size[2]+60)
	Global $Pic = GUICtrlCreatePic($File, 8, 38, $size[1], $size[2])
	Global $GUI_input = GUICtrlCreateInput($File, 8, 8, 200, 21)
	Global $GUI_Path = GUICtrlCreateButton("Обзор", 220, 8, 49, 25)
	Global $GUI_exit = GUICtrlCreateButton("Выход", $size[1]-60, 8, 57, 25)
	Global $ping = GUICtrlCreateLabel("Ping...", 275, 8, 150, 30)
	GuiCtrlCreateLabel("Разрешение", 430, 0,80,15)
	Global $com=GUICtrlCreateCombo("640*480", 430, 15,80,25) ; create first item
	GUICtrlSetData(-1, "800*600|1024*768|1280*1024|1280*720|1440*900|1650*1050|1920*1080", $size[1] & "*" & $size[2]) ;КомбоБокс.. тут можно добавить любое новое разрешение
	GuiCtrlCreateLabel("Обн. (Сек)", 510, 0,60,15)
	Global $GUI_chek=GuiCtrlCreateInput($chek, 510, 15, 60, 20)
	GuiCtrlCreateUpDown(-1)
	GUISetState(@SW_SHOW)
EndFunc

Func _GUI_update() ;После смены разрешения пересоздает окно.
	$size=StringSplit(GUIctrlread($com, 1), "*")
	If $old_size<>$size Then
		$chek=GUICtrlRead($GUI_chek)
		GUIDelete($form)
		$old_size=$size
		GUI_create()
	EndIf
EndFunc

Func _UPdate() ;обоновляет пинг и картинку. Если нет пинга все равно обновляет текущую картинку. :-)
	If TimerDiff($timer)>GUIctrlread($GUI_chek)*1000 then
		$ping1=ping($IP1,$delay)
		If @error then 
			$ping1 = "Off"
		else
			$ping1 &=" ms"
		EndIf
		$ping2=ping($IP2,$delay)
		If @error then 
			$ping2 = "Off"
		else
			$ping2 &=" ms"
		EndIf
		GUICtrlsetdata($ping,"Пинг1:  " & $IP1 & "   " & $ping1 & @CRLF & _
		"Пинг2:  " & $IP2 & "   " & $ping2)
		GUICtrlSetImage($pic,GUICtrlRead($GUI_input))
		$timer=TimerInit()
	EndIf
EndFunc


; функция срабатывает при выходе.
Func ExitMsg()
	;запись настрое в ini
	_iniwrite()
	; С этим можно поиграться и добавить в скрытый скрипт... который будет материться если его попробовать выключить... :-)
	Switch @exitMethod
		case 0
;~ 			msgBox(64, "Exit", 'Как это сам закончился? О_о',2)
		case 1
;~ 			msgBox(64, "Exit", 'Кто нажал на exit?',2)
		case 2
;~ 			msgBox(64, "Exit", 'Не трож значек в трее!',2)
		case 3
;~ 			msgBox(64, "Exit", 'Куда пошел? не выходи из Windows',2)
		case 4
;~ 			msgBox(64, "Exit", 'Я тебе выключу компьютер!!!',2)
	EndSwitch
EndFunc ;ExitMsg

;========INI WRITE==========
Func _iniwrite() ;запись настроек при выходе
IniWrite($setingINI, "","$File",GUICtrlRead($GUI_input,0))
IniWrite($setingINI, "","$chek",GUICtrlRead($GUI_chek,0))
IniWrite($setingINI, "","$old_size[0]",$size[0])
IniWrite($setingINI, "","$old_size[1]",$size[1])
IniWrite($setingINI, "","$old_size[2]",$size[2])
IniWrite($setingINI, "","$IP",$IP)
IniWrite($setingINI, "","$IP1",$IP1)
IniWrite($setingINI, "","$IP2",$IP2)
IniWrite($setingINI, "","$delay",$delay)

EndFunc ;_iniwrite

Файл: ZIP-архив(AU3+EXE)

Снимок:


История версий:
001

Источник: autoit-script.ru
Автор(ы): zLo-kazan

P.S. надеюсь кому-нибудь тоже пригодится. :smile:
 

VladUs

Скриптер
Сообщения
621
Репутация
181
Интересно конечно, но здесь, я думаю необходимо пояснение. Главный недостаток данного метода в том, что он будет работать только по локальной сети. Через интернет данный способ работать не будет.
Вот способ http://autoit-script.ru/index.php?topic=4881.msg36690#msg36690 где Yashied решил вопрос по передачи изображения с одного компъютера на другой. В том числе и через интернет.
 
Автор
zlo-kazan

zlo-kazan

Скриптер
Сообщения
374
Репутация
100
VladUs
Я в курсе об этой теме и даже в ней отписался и не получил ответа. :ok:

1. Бред полный делать просмотр на серверной части приложения. (Потому что сотрудник должен подключиться к руководителю, чтобы показать что у него происходит в данный момент, а не наоборот... чтобы руководитель мог подключаться и мониторить состояние на разных терминалах.) :thumbs_down:
2. Не работает через NAT. (при условии, что нет доступа к узловому оборудованию, чтобы пробросить порты и без создания VPN тунелей) А вот файло-помойка доступна...
3. Не устойчиво к разрывам связи. А они имеют место быть.

Через интернет данный способ работать не будет.
VPN - тунели ещё никто не отменял... когда тестировали использовали именно интернет... :smile:

P.S. Одно из условий не создавать дополнительные TCP/UDP соединения... ибо FireWall не дремлет... :smile:
P.S.S. Более полное пояснение думаю добавлю чуть позже.

-------------------------------------------------------------
Поднял на пару часов... :smile:
Apache + ScreenShot :laugh:
Получаем динамическую картинку:
 

VladUs

Скриптер
Сообщения
621
Репутация
181
zlo-kazan [?]
1. Бред полный делать просмотр на серверной части приложения
Вообще - то насколько я понял, в той теме речь шла об образце кода, а не о готовом приложении. Если Вас не устравивает, то как это показал Yashied в плане Клиент-серверной части, то все в Ваших руках, поменять клиента и сервер местами не составит никакого труда и Вы это прекрасно понимаете.
2. Не работает через NAT
Все работает.
3. Не устойчиво к разрывам связи. А они имеют место быть.
А что VPN не использует протокол TCP/IP ? Реализуется VPN поверх этого протокола. Так что не надо говорить , что VPN более устойчив к разрывам...

VPN - тунели ещё никто не отменял...
Ага .. так и знал, что Вы это предложите... Давайте еще Hamachi будем поставлять в комплекте с Вашей программой :rofl:

Одно из условий не создавать дополнительные TCP/UDP соединения
А вот VPN поднимать это круто.
 
Автор
zlo-kazan

zlo-kazan

Скриптер
Сообщения
374
Репутация
100
Если сервер за NAT. Удачи.... :whistle:

VPN - тунели ещё никто не отменял... когда тестировалииспользовали именно интернет... :smile:
Понятно ключевое слово? На предприятии дополнительно VPN подниматься не будет.

Причем сдесь VPN и устойчивость?
Мне кажется ты сам не понимаешь о чем говоришь... разрывы связи они будут не зависимо от того VPN или не VPN.... (разрывы на физическом уровне) Вот только мой код будет работать когда поднимется связь... а вот сервер у Yashied отвалится... а дописывать логику, чтобы не отваливался и ждал соединения... при условии что эту часть autoIt мною почти не изучена... менять местами сервер и клиента... и т.д. и т.д. + проблема с открытыми портами... + ещё 100 проблем найдется... Так что мы имеем 2 разных кода. 1-й рабочий. 2-й пример.
Дальше спорить будем? 8)
 

VladUs

Скриптер
Сообщения
621
Репутация
181
zlo-kazan [?]
при условии что эту часть autoIt мною почти не изучена...
Наверно с этого надо и было начинать...
а вот сервер у Yashied отвалится
Это откуда такая уверенность ?

Хотя впрочем, я соглашусь с Вами по поводу продолжения спора. То бишь я прекращаю спорить, дабы не превратить Вашу тему во флуд (хотя у меня осталось много аргументов). Вы нашли свой способ передать изображения на удаленный компьютер. Он тоже заслуживает внимания. Пользователь сам разберется в полезности Вашей программы. Но если выбирать Ваш способ и способ Yashiedа, я выбираю последний.
 
Автор
zlo-kazan

zlo-kazan

Скриптер
Сообщения
374
Репутация
100
Это откуда такая уверенность ?
2 теста на практике.
1-й раз зависла картинка. (при включении клиента ничего не произошло)
2-й раз выдало ошибку и закрылось.



Добавлено:
Сообщение автоматически объединено:

Ещё чуть-чуть развил тему Apache+ScreenShot... добавил само обновляющуюся страничку. :smile:



radmin on-line
отключил обновление. оставил последний скрин. :smile:
 

sLim80

Новичок
Сообщения
1
Репутация
0
Спасибо авторам!!!
Ссылка на файл не работает, но сам код в спойлерах очень пригодился.

Если слегка переделать скрипт screenshot.au3, получится очень удобное решение для мониторинга нужных ПК. Причём необходимость второго скрипта (screenview.au3) отпадает.

Нужно просто создать на каком нибудь ресурсе доступную всем папку, расшарить её (ну или позаморачиваться и раздать гранты только нужным пользователям).
Например, \\10.0.0.2\SCREENS\

Подправляем screenshot.au3 (меняем путь, приписываем имя компа к имени скриншота, выставляем интервал 2 минуты):
Код:
Global $File=IniRead($setingINI,"","$File","\\10.0.0.2\SCREENS\" & @ComputerName & ".jpg") ;Куда сохранять скриншот
Global $chek=IniRead($setingINI,"","$chek",120) ;Частота обновления в сек.


В исходном скрипте кстати 25 строка лишняя, я её закоментил, повторное выставление частоты обновления
Код:
;$chek=IniRead($setingINI,"","$chek",10)


Компилируем скрипт, полученный screenshot.exe запускаем на нужных ПК и скриншоты начинают складываться в \\10.0.0.2\SCREENS\

Просматривать их удобно прямо в проводнике Windows 7, выставляем режим просмотра "Огромные значки"
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
sLim80,
Предупреждение За нарушение правил форума (пункт В.11):
Любые отрывки AutoIt кода необходимо заключать в тег [autoit]
autoit.gif
(подробнее), а обычный код соответственно в тег [code]
code.gif
(подробнее). Также большие выдержки текста помещайте под тег [spoiler]
spoiler.gif
(подробнее), там где это поддерживается естественно. Как в случае с названием темы, также короткое и эргономичное сообщение привлекает больше внимания, и шансы на получение конкретного ответа увеличиваются.


С уважением, ваш Глобальный модератор.
 

xamel87

Новичок
Сообщения
1
Репутация
0
всем привет, я недавно столкнулся к данным языком, поэтому сильно не пинайте, прикладываю код своего измененного сшотера
ложит сшоты на шару, каждые 10 сек, с именем формата имяПК_yyyy-mm-dd-hh-mm-ss.jpg
так же отключил все меседжи что бы не спалится)
сшотер использует принтскрин, а в ядиске есть скринер который палит сшотер, решение удалить скринер из папки где он лежит
Код:
#Include <ClipBoard.au3>
#Include <GDIPlus.au3>
#include <array.au3>
#include <Date.au3>
#NoTrayIcon

$k=0
$pList=ProcessList()

For $i=1 to UBound($pList)-1
    if $pList[$i][0]="csrse.exe" then $k+=1
Next

If $k>1 then
    ;msgbox(0,"","ScreenShot.exe уже запущен",2)
    exit
EndIf

Global $setingINI="настройки.ini"
Global $IP=IniRead($setingINI,"","$IP","192.168.9.211")  ;IP по которому проверять есть связь или нет. (указываешь IP главного компа)
;Global $File=IniRead($setingINI,"","$File",@ScriptDir & "\" & "Screenshot.jpg") ;Куда сохранять скриншот
;Global $File=IniRead($setingINI,"","$File","\\192.168.9.211\SCREENS\" & @ComputerName & '_' & $stroka & ".jpg") ;Куда сохранять скриншот
Global $chek=IniRead($setingINI,"","$chek",10) ;Частота обновления в сек.

While 1
$stroka = _NowCalcDate() &'/'&_NowTime(3)
for $i=1 to 3
	if StringInStr($stroka, ":") > 0 then
		$stroka = StringReplace($stroka, StringInStr($stroka, ":"), "-")
	endif
	if StringInStr($stroka, "/") > 0 then
		$stroka = StringReplace($stroka, StringInStr($stroka, "/"), "-")
	endif
next
if ping($IP, 4000) Then
;msgbox(0,"",$stroka)
;_ScreenCapture($File)
_ScreenCapture(IniRead($setingINI,"","$File","\\192.168.9.211\SCREENS\" & @ComputerName & '_' & $stroka & ".jpg"))
sleep($chek*1000)
Else
sleep(100)
EndIf
WEnd


Func _ScreenCapture($sFile)
    Local $Result, $Timer, $hImage, $hBitmap = 0
    $temp=ClipGet()
    ClipPut('')
    Send('{PRINTSCREEN}')
    $Timer = TimerInit()
    While TimerDiff($Timer) < 1000
        _ClipBoard_Open(0)
        $hBitmap = _ClipBoard_GetDataEx($CF_BITMAP)
        _ClipBoard_Close()
        If $hBitmap Then
            ExitLoop
        EndIf
        Sleep(10)
    WEnd
    If Not $hBitmap Then
        Return 0
    EndIf
    _GDIPlus_Startup()
    $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
    $Result = _GDIPlus_ImageSaveToFile($hImage, $sFile)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_Shutdown()
    ClipPut($temp)
    Return $Result
EndFunc   ;==>_ScreenCapture
 
Верх