Что нового

[Сеть, интернет] Разрастающийся в памяти IE

Vlasssov

Осваивающий
Сообщения
430
Репутация
25
При выполнении в цикле команды
Код:
_IENavigate($oIE,$url)

Почему-то процесс в памяти разрастается до неимоверных размеров :shok:
Правда я несколько раз передаю в подпрограммы объект $oIE в подпрограммы, может там надо в функциях прописать
Код:
func _myfunction(Byref $oIE)

Это что там каждый раз создается копия объекта в памяти?
 

Daymos

Новичок
Сообщения
8
Репутация
1
Какой именно процесс?
Если iexplore.exe, то это обычные утечки памяти (memory leaks) в IE, зачастую из-за java-скриптов. Не могу с уверенностью сказать, но в последней версии их должно быть меньше, т.к. исправляют постоянно.
А если все-таки AutoIt, то не должно быть из-за копии объекта, т.к. все объекты автоматически передаются по ссылке, насколько помню.
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
964
По сути, объект создаётся функцией _IECreate
_IENavigate только использует, уже готовый объект.
Можно взглянуть на ваш код!
 
Автор
Vlasssov

Vlasssov

Осваивающий
Сообщения
430
Репутация
25
Garrett сказал(а):
По сути, объект создаётся функцией _IECreate
_IENavigate только использует, уже готовый объект.
Можно взглянуть на ваш код!
Он дюже здоровый... Сейчас попробую упростить и выложить.Просто навскидку сразу подумалось, что не в объекте IE дело, а в том что я не по byref предавал объект, однако последующие эксперименты доказали обратное. Я там пользователей группы в социальной сети Вконтакте перебираю, чтобы себе базу составить, кого приглашать, кого не приглашать, поэтому там приходится ОЧЕНЬ много раз выполнять команду
_IENavigate
где-то приблизительно 365*40*2, ну вот он на 720 разе и крякается....

Если iexplore.exe, то это обычные утечки памяти (memory leaks) в IE, зачастую из-за java-скриптов.
java-scripts там много... Это да.... Тут уже сталкивался с особенностями отображения страниц
http://autoit-script.ru/index.php?topic=1626.0

Бороться то с этим как? Убивать объект и снова создавать? Пробовал библиотеку, которая работает с Firefox, отказывается понимать, видимо, эта библиотека версию Firefox 3.6, приходится с IE чудить...
 
Автор
Vlasssov

Vlasssov

Осваивающий
Сообщения
430
Репутация
25
Пока просто перевызываю объект IE, смотрел с панели задач - больше 200 мб IE не разрастается.
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
623
Vlasssov
мой тебе совет используй напрямую все методы объекта IEApplication, согласно MSDN. намного лучше будешь понимать механизм работы и контролировать сами объекты включая создание-удаление
 
Автор
Vlasssov

Vlasssov

Осваивающий
Сообщения
430
Репутация
25
Kaster сказал(а):
Vlasssov
мой тебе совет используй напрямую все методы объекта IEApplication, согласно MSDN. намного лучше будешь понимать механизм работы и контролировать сами объекты включая создание-удаление
Это как я их буду "напрямую" использовать? AutoIT предлагает определенный набор команд, для быстроты построения кода. Может мне на другой язык программирования перейти?
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
623
Vlasssov
посредством
Код:
ObjCreate(InternetExplorer.Application)
 
Автор
Vlasssov

Vlasssov

Осваивающий
Сообщения
430
Репутация
25
Kaster сказал(а):
Vlasssov
посредством
Код:
ObjCreate(InternetExplorer.Application)
А я вот грешным делом думал, что IE.au3 уже все нюансы учло... Боже, как я ошибался... :'(
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
964
Vlasssov сказал(а):
Kaster сказал(а):
Vlasssov
посредством
Код:
ObjCreate(InternetExplorer.Application)
А я вот грешным делом думал, что IE.au3 уже все нюансы учло... Боже, как я ошибался... :'(
IE.au3 на том и построена, что использует InternetExplorer.Application
А все нюансы учесть сложно :smile:
По большому счёту для работы с IE.au3 нужны всего лишь знания в JvaScript.

Вот пример:
Код:
#include <IE.au3>
$oIE = _IECreate()
_IEHeadInsertEventScript ($oIE, "document", "onclick", "alert('Привет!');")

При клике в окне IE вы получите диалоговое окно с надписью "Привет!" Не так ли?
[box title=_IEHeadInsertEventScript]Эта функция, позволяет вам вставлять и выполнять код JavaScript, в загруженный документ.[/box]
А вот другой пример:
Код:
#include <IE.au3>
$oIE = _IECreate()
_IEHeadInsertEventScript ($oIE, "document", "onload", "alert('Привет!');")

Как не старайтесь он не будет работать :smile:
[box title=onload Event]Событие происходит при полной загрузки страницы документа.[/box]
Как быть?
Решение занимает пять строчек, и используется всё та же IE.au3
Я напишу решение, но сначала, предлогаю решить задачу вам ;)
 
Автор
Vlasssov

Vlasssov

Осваивающий
Сообщения
430
Репутация
25
Честно - времени пока нет ковырять события в IE, просто приведу вам другой пример. Есть такая функция:
_arraydisplay

Код:
Func _ArrayDisplay(Const ByRef $avArray, $sTitle = "Array: ListView Display", $iItemLimit = -1, $iTranspose = 0, $sSeparator = "", $sReplace = "|", $sHeader = "")
	If Not IsArray($avArray) Then Return SetError(1, 0, 0)
	; Dimension checking
	Local $iDimension = UBound($avArray, 0), $iUBound = UBound($avArray, 1) - 1, $iSubMax = UBound($avArray, 2) - 1
	If $iDimension > 2 Then Return SetError(2, 0, 0)

	; Separator handling
;~     If $sSeparator = "" Then $sSeparator = Chr(1)
	If $sSeparator = "" Then $sSeparator = Chr(124)

	;  Check the separator to make sure it's not used literally in the array
	If _ArraySearch($avArray, $sSeparator, 0, 0, 0, 1) <> -1 Then
		For $x = 1 To 255
			If $x >= 32 And $x <= 127 Then ContinueLoop
			Local $sFind = _ArraySearch($avArray, Chr($x), 0, 0, 0, 1)
			If $sFind = -1 Then
				$sSeparator = Chr($x)
				ExitLoop
			EndIf
		Next
	EndIf

	; Declare variables
	Local $vTmp, $iBuffer = 64
	Local $iColLimit = 250
	Local $iOnEventMode = Opt("GUIOnEventMode", 0), $sDataSeparatorChar = Opt("GUIDataSeparatorChar", $sSeparator)

	; Swap dimensions if transposing
	If $iSubMax < 0 Then $iSubMax = 0
	If $iTranspose Then
		$vTmp = $iUBound
		$iUBound = $iSubMax
		$iSubMax = $vTmp
	EndIf

	; Set limits for dimensions
	If $iSubMax > $iColLimit Then $iSubMax = $iColLimit
	If $iItemLimit < 1 Then $iItemLimit = $iUBound
	If $iUBound > $iItemLimit Then $iUBound = $iItemLimit

	; Set header up
	If $sHeader = "" Then
		$sHeader = "Row  "	; blanks added to adjust column size for big number of rows
		For $i = 0 To $iSubMax
			$sHeader &= $sSeparator & "Col " & $i
		Next
	EndIf

	; Convert array into text for listview
	Local $avArrayText[$iUBound + 1]
	For $i = 0 To $iUBound
		$avArrayText[$i] = "[" & $i & "]"
		For $j = 0 To $iSubMax
			; Get current item
			If $iDimension = 1 Then
				If $iTranspose Then
					$vTmp = $avArray[$j]
				Else
					$vTmp = $avArray[$i]
				EndIf
			Else
				If $iTranspose Then
					$vTmp = $avArray[$j][$i]
				Else
					$vTmp = $avArray[$i][$j]
				EndIf
			EndIf

			; Add to text array
			$vTmp = StringReplace($vTmp, $sSeparator, $sReplace, 0, 1)
			$avArrayText[$i] &= $sSeparator & $vTmp

			; Set max buffer size
			$vTmp = StringLen($vTmp)
			If $vTmp > $iBuffer Then $iBuffer = $vTmp
		Next
	Next
	$iBuffer += 1

	; GUI Constants
	Local Const $_ARRAYCONSTANT_GUI_DOCKBORDERS = 0x66
	Local Const $_ARRAYCONSTANT_GUI_DOCKBOTTOM = 0x40
	Local Const $_ARRAYCONSTANT_GUI_DOCKHEIGHT = 0x0200
	Local Const $_ARRAYCONSTANT_GUI_DOCKLEFT = 0x2
	Local Const $_ARRAYCONSTANT_GUI_DOCKRIGHT = 0x4
	Local Const $_ARRAYCONSTANT_GUI_EVENT_CLOSE = -3
	Local Const $_ARRAYCONSTANT_LVIF_PARAM = 0x4
	Local Const $_ARRAYCONSTANT_LVIF_TEXT = 0x1
	Local Const $_ARRAYCONSTANT_LVM_GETCOLUMNWIDTH = (0x1000 + 29)
	Local Const $_ARRAYCONSTANT_LVM_GETITEMCOUNT = (0x1000 + 4)
	Local Const $_ARRAYCONSTANT_LVM_GETITEMSTATE = (0x1000 + 44)
	Local Const $_ARRAYCONSTANT_LVM_INSERTITEMW = (0x1000 + 77)
	Local Const $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE = (0x1000 + 54)
	Local Const $_ARRAYCONSTANT_LVM_SETITEMW = (0x1000 + 76)
	Local Const $_ARRAYCONSTANT_LVS_EX_FULLROWSELECT = 0x20
	Local Const $_ARRAYCONSTANT_LVS_EX_GRIDLINES = 0x1
	Local Const $_ARRAYCONSTANT_LVS_SHOWSELALWAYS = 0x8
	Local Const $_ARRAYCONSTANT_WS_EX_CLIENTEDGE = 0x0200
	Local Const $_ARRAYCONSTANT_WS_MAXIMIZEBOX = 0x00010000
	Local Const $_ARRAYCONSTANT_WS_MINIMIZEBOX = 0x00020000
	Local Const $_ARRAYCONSTANT_WS_SIZEBOX = 0x00040000
	Local Const $_ARRAYCONSTANT_tagLVITEM = "int Mask;int Item;int SubItem;int State;int StateMask;ptr Text;int TextMax;int Image;int Param;int Indent;int GroupID;int Columns;ptr pColumns"

	Local $iAddMask = BitOR($_ARRAYCONSTANT_LVIF_TEXT, $_ARRAYCONSTANT_LVIF_PARAM)
	Local $tBuffer = DllStructCreate("wchar Text[" & $iBuffer & "]"), $pBuffer = DllStructGetPtr($tBuffer)
	Local $tItem = DllStructCreate($_ARRAYCONSTANT_tagLVITEM), $pItem = DllStructGetPtr($tItem)
	DllStructSetData($tItem, "Param", 0)
	DllStructSetData($tItem, "Text", $pBuffer)
	DllStructSetData($tItem, "TextMax", $iBuffer)

	; Set interface up
	Local $iWidth = 640, $iHeight = 480
	Local $hGUI = GUICreate($sTitle, $iWidth, $iHeight, Default, Default, BitOR($_ARRAYCONSTANT_WS_SIZEBOX, $_ARRAYCONSTANT_WS_MINIMIZEBOX, $_ARRAYCONSTANT_WS_MAXIMIZEBOX))
	Local $aiGUISize = WinGetClientSize($hGUI)
	Local $hListView = GUICtrlCreateListView($sHeader, 0, 0, $aiGUISize[0], $aiGUISize[1] - 26, $_ARRAYCONSTANT_LVS_SHOWSELALWAYS)
	Local $hCopy = GUICtrlCreateButton("Copy Selected", 3, $aiGUISize[1] - 23, $aiGUISize[0] - 6, 20)
	GUICtrlSetResizing($hListView, $_ARRAYCONSTANT_GUI_DOCKBORDERS)
	GUICtrlSetResizing($hCopy, $_ARRAYCONSTANT_GUI_DOCKLEFT + $_ARRAYCONSTANT_GUI_DOCKRIGHT + $_ARRAYCONSTANT_GUI_DOCKBOTTOM + $_ARRAYCONSTANT_GUI_DOCKHEIGHT)
	GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE, $_ARRAYCONSTANT_LVS_EX_GRIDLINES, $_ARRAYCONSTANT_LVS_EX_GRIDLINES)
	GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE, $_ARRAYCONSTANT_LVS_EX_FULLROWSELECT, $_ARRAYCONSTANT_LVS_EX_FULLROWSELECT)
	GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE, $_ARRAYCONSTANT_WS_EX_CLIENTEDGE, $_ARRAYCONSTANT_WS_EX_CLIENTEDGE)

	; Fill listview
	Local $aItem
	For $i = 0 To $iUBound
		If GUICtrlCreateListViewItem($avArrayText[$i], $hListView) = 0 Then
			; use GUICtrlSendMsg() to overcome AutoIt limitation
			$aItem = StringSplit($avArrayText[$i], $sSeparator)
			DllStructSetData($tBuffer, "Text", $aItem[1])

			; Add listview item
			DllStructSetData($tItem, "Item", $i)
			DllStructSetData($tItem, "SubItem", 0)
			DllStructSetData($tItem, "Mask", $iAddMask)
			GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_INSERTITEMW, 0, $pItem)

			; Set listview subitem text
			DllStructSetData($tItem, "Mask", $_ARRAYCONSTANT_LVIF_TEXT)
			For $j = 2 To $aItem[0]
				DllStructSetData($tBuffer, "Text", $aItem[$j])
				DllStructSetData($tItem, "SubItem", $j - 1)
				GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_SETITEMW, 0, $pItem)
			Next
		EndIf
	Next

	; adjust window width
	$iWidth = 0
	For $i = 0 To $iSubMax + 1
		$iWidth += GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_GETCOLUMNWIDTH, $i, 0)
	Next
	If $iWidth < 250 Then $iWidth = 230
	$iWidth += 20
	WinMove($hGUI, "", (@DesktopWidth - $iWidth)/2, Default, $iWidth)

	; Show dialog
	GUISetState(@SW_SHOW, $hGUI)

	While 1
		Switch GUIGetMsg()
			Case $_ARRAYCONSTANT_GUI_EVENT_CLOSE
				ExitLoop

			Case $hCopy
				Local $sClip = ""

				; Get selected indices [ _GUICtrlListView_GetSelectedIndices($hListView, True) ]
				Local $aiCurItems[1] = [0]
				For $i = 0 To GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_GETITEMCOUNT, 0, 0)
					If GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_GETITEMSTATE, $i, 0x2) Then
						$aiCurItems[0] += 1
						ReDim $aiCurItems[$aiCurItems[0] + 1]
						$aiCurItems[$aiCurItems[0]] = $i
					EndIf
				Next

				; Generate clipboard text
				If Not $aiCurItems[0] Then
					For $sItem In $avArrayText
						$sClip &= $sItem & @CRLF
					Next
				Else
					For $i = 1 To UBound($aiCurItems) - 1
						$sClip &= $avArrayText[$aiCurItems[$i]] & @CRLF
					Next
				EndIf
				ClipPut($sClip)
		EndSwitch
	WEnd
	GUIDelete($hGUI)

	Opt("GUIOnEventMode", $iOnEventMode)
	Opt("GUIDataSeparatorChar", $sDataSeparatorChar)

	Return 1
EndFunc   ;==>_ArrayDisplay


Так вот AutoIT от других языков отличается тем - в лучшую сторону, что есть попытка реализовать типрвые задачи программирования в отдельных функциях. Вывести массив на экран можно и без функции _arraydisplay, написав по объему такой же код, обратиться к методам IE можно и без AutoIt. Я поэтому и задаю вопросы именно по AutoIT, потому что новичок, и не знаю всех нюансов реализации той или иной задачи. В принципе Kaster прав, если нет способа реализовать в одну функцию, то надо напрямую обращаться к методам самого объекта...

Что с вашей задачей... Берем напрямую функцию

Код:
Func _IEHeadInsertEventScript(ByRef $o_object, $s_htmlFor, $s_event, $s_script)
	If Not IsObj($o_object) Then
		__IEErrorNotify("Error", "_IEHeadInsertEventScript", "$_IEStatus_InvalidDataType")
		Return SetError($_IEStatus_InvalidDataType, 1, 0)
	EndIf

	Local $o_head = $o_object.document.all.tags("HEAD" ).Item(0)
	Local $o_script = $o_object.document.createElement("script")
	With $o_script
		.defer = True
		.language = "jscript"
		.type = "text/javascript"
		.htmlFor = $s_htmlFor
		.event = $s_event
		.text = $s_script
	EndWith
	$o_head.appendChild($o_script)
	Return SetError($_IEStatus_Success, 0, 1)
EndFunc   ;==>_IEHeadInsertEventScript


Включаем в свою программу и все несуразности правим напрямую...
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
964
Vlasssov [?]
Что с вашей задачей... Берем напрямую функцию. Включаем в свою программу и все несуразности правим напрямую...
Вот что мы получим "Duplicate function name" :smile:

Что касаемо поставленных задач!
Да, несомненно, можно написать функцию _arraydisplay, но зачем? Человек уже написал такую функцию, и поместил её в библиотеку.
Как вы правильно заменили, функции пишутся именно для типовых задач, и когда таких функций становится много, то их логичнее собрать в UDF.
Можно обращаться к COM объектам и напрямую (я только за), но тратить время на написание практически той же самой библиотеки которая уже написана, не вижу смысла. Другое дело если случай не ординарный, и вам нужен функционал, которого нет в UDF, или вы решили написать собственную библиотеку, значительно функциональнее существующей.

Вот решение моей задачи.

Код:
; Средствами только IE.au3
#include <IE.au3>
$oIE = _IECreate()
$oBodys = _IETagNameGetCollection ($oIE, "body")
For $oBody In $oBodys
    $oBodyID = _IEPropertyGet($oBody, "uniqueid")
Next
_IEHeadInsertEventScript ($oIE, $oBodyID, "onload", "alert('Привет!');")

Код:
; Комбинированный вариант, IE.au3 + напрямую
#include <IE.au3>
$oIE = _IECreate()
$oIE.document.body.setAttribute("id", "1")
_IEHeadInsertEventScript ($oIE, "1", "onload", "alert('Привет!');")

Код:
; Напрямую без UDF
$oIE = ObjCreate("InternetExplorer.Application")
$oIE.visible = 1
$oIE.navigate("about:blank")
$oIE.document.body.setAttribute("id", "1")
$oHead = $oIE.document.all.tags("HEAD" ).Item(0)
$oInsert = $oIE.document.createElement("script")
$oInsert.language = "jscript"
$oInsert.type = "text/javascript"
$oInsert.htmlFor = "1"
$oInsert.event = "onload"
$oInsert.text = "alert('Привет!');"
$oHead.appendChild($oInsert)
 
Автор
Vlasssov

Vlasssov

Осваивающий
Сообщения
430
Репутация
25
Вот что мы получим "Duplicate function name"
:rofl: :rofl: :rofl:
Да... Функцию переименовать - не судьба... :shok:
Да, несомненно, можно написать функцию _arraydisplay, но зачем? Человек уже написал такую функцию, и поместил её в библиотеку.
Вот и я об этом же... Если есть задачи не совсем решаемые СТАНДАРТНЫМИ функциями - пишем свою с обращением к com объектам. Временные затраты такие же. Но работать будет более правильно. ИМХО.
 

Gromadina

Новичок
Сообщения
21
Репутация
1
; Напрямую без UDF
$oIE = ObjCreate("InternetExplorer.Application")
$oIE.visible = 1
$oIE.navigate("about:blank")
$oIE.document.body.setAttribute("id", "1")
$oHead = $oIE.document.all.tags("HEAD" ).Item(0)
$oInsert = $oIE.document.createElement("script")
$oInsert.language = "jscript"
$oInsert.type = "text/javascript"
$oInsert.htmlFor = "1"
$oInsert.event = "onload"
$oInsert.text = "alert('Привет!');"
$oHead.appendChild($oInsert)


Как такое на FFoxe сдлать ?
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
623
Gromadina
никак, FF не предоставляет COM-интерфейс. есть какие то плагины, насколько надежно работает я не знаю. но меня больше интересует зачем выбирать браузер для автоматизации? ведь суть автоматизации, это чтобы само делало, а где это само делается, по идее не важно.
и еще, на форуме есть тэги для обрамления кусков кода в количество двух штук - один для AutoIt кодов, другой для всех остальных. найдешь сам? ;)
 
Автор
Vlasssov

Vlasssov

Осваивающий
Сообщения
430
Репутация
25
Кстати, а можно как-то померить объем памяти, который занимает объект Explorer?
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
623
Vlasssov
примерный размер показывает диспетчер задач и Process Explorer, но помоему любая подобная прога может это сделать
 
Автор
Vlasssov

Vlasssov

Осваивающий
Сообщения
430
Репутация
25
Это-т понятно.. А api функций нет?
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
623
Vlasssov
ну дык в чем проблема-то? :smile: если думаешь, что есть такой api, то есть очень высокая вероятность, что Yashied реализовал вызов этой api в своей либе http://autoit-script.ru/index.php/topic,47.0.html. качаешь и видишь что там есть справка. в поиске вбиваешь memory и находишь несколько функций и интуитивно догадываешься что
Код:
_WinAPI_GetProcessMemoryInfo($PID)

возможно то, что тебе нужно. пробуешь, запускаешь и окончательно в этом убеждаешься.
 
Автор
Vlasssov

Vlasssov

Осваивающий
Сообщения
430
Репутация
25
Kaster сказал(а):
Vlasssov
ну дык в чем проблема-то? :smile: если думаешь, что есть такой api, то есть очень высокая вероятность, что Yashied реализовал вызов этой api в своей либе http://autoit-script.ru/index.php/topic,47.0.html. качаешь и видишь что там есть справка. в поиске вбиваешь memory и находишь несколько функций и интуитивно догадываешься что
Код:
_WinAPI_GetProcessMemoryInfo($PID)

возможно то, что тебе нужно. пробуешь, запускаешь и окончательно в этом убеждаешься.
Я просто не первый раз не нахожу функции, потому как английские названия такие забавные.. Помню долго искал функцию, которая задает текущую директорию... :IL_AutoIt_1:
 
Верх