Что нового

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

Vlasssov

Осваивающий
Сообщения
428
Репутация
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

Осваивающий
Сообщения
428
Репутация
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

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

kaster

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

Vlasssov

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

kaster

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

Vlasssov

Осваивающий
Сообщения
428
Репутация
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

Осваивающий
Сообщения
428
Репутация
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

Осваивающий
Сообщения
428
Репутация
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
Репутация
622
Gromadina
никак, FF не предоставляет COM-интерфейс. есть какие то плагины, насколько надежно работает я не знаю. но меня больше интересует зачем выбирать браузер для автоматизации? ведь суть автоматизации, это чтобы само делало, а где это само делается, по идее не важно.
и еще, на форуме есть тэги для обрамления кусков кода в количество двух штук - один для AutoIt кодов, другой для всех остальных. найдешь сам? ;)
 
Автор
Vlasssov

Vlasssov

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

kaster

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

Vlasssov

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

kaster

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

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

Vlasssov

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

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