Что нового

Расширение стандартной AutoIt библиотеки WinAPI.au3

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Yashied,
Почему Вы не использовали API-функцию GetCurrentProcess в Ваших функциях, которые принимают в качестве аргумента PID процесса и требуют в дальнейшем его handle, в том случае, если аргумент (PID) равен 0, что, обычно, по умолчанию?
 
Автор
Yashied

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Эта функция возвращает не PID, а HANDLE процесса. И почему не использовал?
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Yashied [?]
Эта функция возвращает не PID, а HANDLE процесса.
ИМХО, мы с Вами не поняли друг друга.
Пример 1 (из Справки WinAPIEx):
Код:
#Include <WinAPIEx.au3>

Opt('MustDeclareVars', 1)

Run(@SystemDir & '\taskmgr.exe')

MsgBox(64 + 262144, '', 'Look at the memory used by the "' & _WinAPI_PathStripPath(FileGetLongName(@AutoItExe)) & '" (' & @AutoItPID & ') process.')

; Allocate memory to create an array
Dim $Data[1000000]
For $i = 0 To UBound($Data) - 1
    $Data[$i] = 'AutoIt v3 is a freeware BASIC-like scripting language designed for automating the Windows GUI and general scripting. It uses a combination of simulated keystrokes, mouse movement and window/control manipulation in order to automate tasks in a way not possible or reliable with other languages (e.g. VBScript and SendKeys). AutoIt is also very small, self-contained and will run on all versions of Windows out-of-the-box with no annoying "runtimes" required!'
Next

MsgBox(64 + 262144, '', 'Step 1')

; Empty the working set
_WinAPI_EmptyWorkingSet()

MsgBox(64 + 262144, '', 'Step 2')

; Read data from an array
For $i = 0 To UBound($Data) - 1
    If $Data[$i] Then
        ; Something
    EndIf
Next

MsgBox(64 + 262144, '', 'Step 3')

; Empty the working set
_WinAPI_EmptyWorkingSet()

MsgBox(64 + 262144, '', 'Step 4')
Пример 2 (немного переделанный)
Код:
#include <WinAPIEx.au3>

Opt('MustDeclareVars', 1)

Run(@SystemDir & '\taskmgr.exe')

MsgBox(64 + 262144, '', 'Look at the memory used by the "' & _WinAPI_PathStripPath(FileGetLongName(@AutoItExe)) & '" (' & @AutoItPID & ') process.')

; Allocate memory to create an array
Dim $Data[1000000]
For $i = 0 To UBound($Data) - 1
	$Data[$i] = 'AutoIt v3 is a freeware BASIC-like scripting language designed for automating the Windows GUI and general scripting. It uses a combination of simulated keystrokes, mouse movement and window/control manipulation in order to automate tasks in a way not possible or reliable with other languages (e.g. VBScript and SendKeys). AutoIt is also very small, self-contained and will run on all versions of Windows out-of-the-box with no annoying "runtimes" required!'
Next

MsgBox(64 + 262144, '', 'Step 1')

; Empty the working set
_WinAPI_EmptyWorkingSetSelf()

MsgBox(64 + 262144, '', 'Step 2')

; Read data from an array
For $i = 0 To UBound($Data) - 1
	If $Data[$i] Then
		; Something
	EndIf
Next

MsgBox(64 + 262144, '', 'Step 3')

; Empty the working set
_WinAPI_EmptyWorkingSetSelf()

MsgBox(64 + 262144, '', 'Step 4')

Func _WinAPI_EmptyWorkingSetSelf()
	Local $a_Res

	$a_Res = DllCall('kernel32.dll', 'handle', 'GetCurrentProcess')
	If (@error) Or (Not $a_Res[0]) Then Return 0
	$a_Res = DllCall(@SystemDir & '\psapi.dll', 'int', 'EmptyWorkingSet', 'handle', $a_Res[0])
	If (@error) Or (Not $a_Res[0]) Then Return 0
	Return 1
EndFunc   ;==>_WinAPI_EmptyWorkingSetSelf


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

Навскидку, по первому поиску, функции, принимающие в качестве аргумента PID и использующие HANDLE процесса:
_WinAPI_EnumProcessModules
_WinAPI_GetApplicationRestartSettings
_WinAPI_GetPriorityClass
_WinAPI_GetProcessCommandLine
_WinAPI_GetProcessFileName
_WinAPI_GetProcessHandleCount
_WinAPI_GetProcessIoCounters
_WinAPI_GetProcessMemoryInfo
_WinAPI_GetProcessTimes
_WinAPI_GetProcessUser
_WinAPI_GetProcessWorkingDirectory
_WinAPI_IsWow64Process
_WinAPI_SetPriorityClass
и т.д.
 

Violence

violet lady
Сообщения
8
Репутация
0
Здравствуйте!
Подскажите, пожалуйста, как правильно обратиться и считать QueryThreadCycleTime? msdn
Что именно следует передавать функции в качестве ThreadHandle?
Использую OpenThread, чтобы получить ThreadHandle:
Код:
$handle=DllCall("kernel32.dll","ptr", "OpenThread","dword", "0x0002","int", "0","dword",$TID)
$cTime=DllCall("kernel32.dll","bool","QueryThreadCycleTime","ptr",$handle[0],"dword", $CycleTime)

Во-первых, функция всегда возвращает 0 (получается, я не то ей скармливаю в качестве аргумента?)
Во-вторых, в ней используется ByRef параметр CycleTime, в который выводится необходимое мне значение, а вот как его заполучить через DllCall - не совсем ясно.
 
Автор
Yashied

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Код:
#Include <WinAPI.au3>

$aResult = DllCall('kernel32.dll', 'bool', 'QueryThreadCycleTime', 'handle', _WinAPI_GetCurrentThread(), 'ulong_ptr*', 0)
ConsoleWrite($aResult[2] & @CRLF)
 

asdf8

Скриптер
Сообщения
564
Репутация
152
Yashied, а как пользоваться функцией _WinAPI_GetFinalPathNameByHandle ?
Начало пути все время обрезается до первого слэша :
Код:
$hFile = _WinAPI_CreateFileEx(@ScriptFullPath, 3, 0, 0x03)
If $hFile Then
	$result = _WinAPI_GetFinalPathNameByHandle($hFile)
	_WinAPI_CloseHandle($hFile)
	ConsoleWrite('!>' & $result & @CRLF)
EndIf
 
Автор
Yashied

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
asdf8, да, эта функция возвращает путь без диска. Есть один способ (в сети легко найти) получить полный путь с помощью File Mapping, но у меня нет примера на AutoIt. Вот на PB 4.5 (просто набросок):

Код:
Structure Drives
	Drv.w[1024]
EndStructure

Prototype.l GetMappedFileNameW(Process, Mem, FileName, Size.l)

Path.s = "C:\Windows\explorer.exe"

hFile = CreateFile_(Path, #GENERIC_READ, #FILE_SHARE_READ | #FILE_SHARE_WRITE, #Null, #OPEN_EXISTING, 0, #Null)
 
Global File.s{4096}
Global Name.s{1024}
Global hMap = 0, pMem = 0
Global Drv.Drives
Global Result.s = ""
Global Vol.s

If OpenLibrary(0, "psapi.dll")
	GetMappedFileNameW.GetMappedFileNameW = GetFunction(0, "GetMappedFileNameW")
Else
	; Error
EndIf

hMap = CreateFileMapping_(hFile, #Null, #PAGE_WRITECOPY, 0, 0, #Null)
pMem = MapViewOfFile_(hMap, #FILE_MAP_READ, 0, 0, 1)

If GetMappedFileNameW(GetCurrentProcess_(), pMem, @File, 4096)
	If GetLogicalDriveStrings_(1024 - 1, @Drv)
		Count = 0
		Repeat
			Vol = PeekS(@Drv\Drv[Count], 2)
			If Not Vol
				Break
			EndIf
			If QueryDosDevice_(Vol, @Name, 1024)
				If Not CompareMemoryString(@Name, @File, #PB_String_NoCase, Len(Name))
					Result = Vol + Mid(File, Len(Name) + 1)
					Break
				EndIf
				Count + 4
			Else
				Break
			EndIf
		ForEver
	EndIf
EndIf

UnmapViewOfFile_(pMem)
CloseHandle_(hMap)
CloseLibrary(0)

CloseHandle_(hFile)

MessageRequester("", Result)

Правда это будет работать только для файлов. Что касается _WinAPI_GetFinalPathNameByHandleEx(), то у этой функции есть один известный баг - при попытке получить путь для папки или диска, процесс может зависнуть или вылететь. Так что использовать эту функцию нужно исключительно для файлов.
 

Violence

violet lady
Сообщения
8
Репутация
0
Yashied сказал(а):
Код:
#Include <WinAPI.au3>

$aResult = DllCall('kernel32.dll', 'bool', 'QueryThreadCycleTime', 'handle', _WinAPI_GetCurrentThread(), 'ulong_ptr*', 0)
ConsoleWrite($aResult[2] & @CRLF)

Спасибо, но загвоздка в том, что мне нужно получить загрузку цп определенным потоком, а не текущим. Если конкретнее - есть некая софтина, выполняющаяся в несколько потоков. Один из них грузит ЦП на 12% и при этом никакой значимости не имеет (т.е. я приостанавливаю его вручную через ProcessExplorer, и это ни коим образом не влияет на работоспособность софтины). Как приостановить конкретный поток - понятно, а вот вычислить, какой из потоков данного процесса грузить проц, я не могу.
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
Код:
#Include <WinAPIEx.au3>

Global _
	$ProcId = ProcessExists("opera.exe"), _ ;Target process id
	$aThreads, $aRes, $hThread

$aThreads = _WinAPI_EnumProcessThreads($ProcId)
If Not @Error Then
	For $i = 2 To $aThreads[0] ;Skip main thread
		$aRes = DllCall('kernel32.dll', 'handle', 'OpenThread', 'dword', 0x0800, 'bool', 0, 'dword', $aThreads[$i])
		If Not @Error And $aRes[0] Then
			$hThread = $aRes[0]
			; ---
			$aRes = DllCall('kernel32.dll', 'bool', 'QueryThreadCycleTime', 'handle', $hThread, 'ulong_ptr*', 0)
			If Not @Error And $aRes[0] Then
				ConsoleWrite( 'Thread #' & ( $i - 1 ) & ': ' & $aRes[2] & @CRLF)

			EndIf
			; ---
			_WinAPI_CloseHandle($hThread)
		EndIf
	Next
EndIf
 

Violence

violet lady
Сообщения
8
Репутация
0
Благодарю, сравнила со своим кодом - проблема была в правах при исполнении OpenThread.
Но есть другая загвоздка - возвращает эта функция не то, что ожидалось :stars:
А именно, в ProcessExplorer есть возможность просмотреть данные о потоках, запущенных процессом, среди них есть показатель "Дельта циклов", и он как раз таки наглядно демонстрирует прожорливость необходимого мне потока. А то, что возвращает QueryThreadCycleTime, с этим совсем не сходится... (в данном случае для нужного потока вернула отрицательные значения, а в следующую секунду возвращает уже положительное - для меня это вообще загадка)...
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
Violence
Понятное дело, что исключительно эти цифры вам ничего не дадут. Более того, парочкой WinAPI функций тут не обойтись.

Можете начать изучение с этого примера:
http://www.delphisources.ru/pages/sources/system/2010-year/process-cpu-usage.html

С удовольствием набросал бы вам пример, но как то очень лень ;)
 
Автор
Yashied

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Вот вам пример для вычисления загрузки процесса. Замените функцию GetProcessTimes() на GetThreadTimes() и получите тоже самое, но только для потока.
 

Kasper

Знающий
Сообщения
70
Репутация
8
А можно ли использовать эту библиотеку на версии AutoIt 3.3.12.0 ?
 

Andrey_A

Продвинутый
Сообщения
319
Репутация
68
В функции _WinAPI_SaveHICONToFile() 3-й параметр True ,как я понял, должен сжимать png размером 256х256 для меньшего размера получаемой иконки. Но этого не происходит. Подскажите в чём может быть проблема? Версия Autoit 3.3.15.0


Код:
#include <WinAPIGdi.au3>
#include <WinAPIShellEx.au3>

Local $aIcon[4] = [256,48, 32, 16]

For $i = 0 To UBound($aIcon) - 1
    $aIcon[$i] = _WinAPI_Create32BitHICON(_WinAPI_ShellExtractIcon(@SystemDir & '\imageres.dll', 3, $aIcon[$i], $aIcon[$i]), 1)
Next
_WinAPI_SaveHICONToFile('C:\test.ico', $aIcon,True)
For $i = 0 To UBound($aIcon) - 1
    _WinAPI_DestroyIcon($aIcon[$i])
Next
 
Автор
Yashied

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Я не знаю, что там изменил jpm, но после того, как он куда-либо залезет своими кривыми ручонками, это сразу перестает работать. Andrey_A, замените функцию _WinAPI_CompressBitmapBits() в официальной сборке на функцию из первого поста, впрочем, вот она.

Код:
Func _WinAPI_CompressBitmapBits($hBitmap, ByRef $pBuffer, $iCompression = 0, $iQuality = 100)

	Local $Size[2], $Count, $Format, $Length, $Mime, $Ret, $hDC, $hSv, $hMem, $tBits, $tInfo, $tData, $pData, $Error = 1
	Local $hSource = 0, $hImage = 0, $hToken = 0, $pEncoder = 0, $pStream = 0, $tParam = 0
	Local $tDIB = DllStructCreate($tagDIBSECTION)

	If Not __DLL('gdiplus.dll') Then
		Return SetError(3, 0, 0)
	EndIf

	Do
		Switch $iCompression
			Case 0
				$Mime = 'image/png'
			Case 1
				$Mime = 'image/jpeg'
			Case Else
				ExitLoop
		EndSwitch
		While $hBitmap
			If Not _WinAPI_GetObject($hBitmap, DllStructGetSize($tDIB), DllStructGetPtr($tDIB)) Then
				ExitLoop 2
			EndIf
			If (DllStructGetData($tDIB, 'bmBitsPixel') = 32) And (Not DllStructGetData($tDIB, 'biCompression')) Then
				ExitLoop
			EndIf
			If $hSource Then
				ExitLoop 2
			EndIf
			$hSource = _WinAPI_CreateDIB(DllStructGetData($tDIB, 'bmWidth'), DllStructGetData($tDIB, 'bmHeight'))
			If @error Then
				ExitLoop 2
			EndIf
			$hDC = _WinAPI_CreateCompatibleDC(0)
			$hSv = _WinAPI_SelectObject($hDC, $hSource)
			If _WinAPI_DrawBitmap($hDC, 0, 0, $hBitmap) Then
				$hBitmap = $hSource
			Else
				$hBitmap = 0
			EndIf
			_WinAPI_SelectObject($hDC, $hSv)
			_WinAPI_DeleteDC($hDC)
		WEnd
		If Not $hBitmap Then
			ExitLoop
		EndIf
		For $i = 0 To 1
			$Size[$i] = DllStructGetData($tDIB, $i + 2)
		Next
		$tBits = DllStructCreate('byte[' & ($Size[0] * $Size[1] * 4) & ']')
		If Not _WinAPI_GetBitmapBits($hBitmap, DllStructGetSize($tBits), DllStructGetPtr($tBits)) Then
			ExitLoop
		EndIf
		$tData = DllStructCreate('uint;ptr;int;int')
		DllStructSetData($tData, 1, 1)
		$Ret = DllCall('gdiplus.dll', 'uint', 'GdiplusStartup', 'ptr*', 0, 'ptr', DllStructGetPtr($tData), 'ptr', 0)
		If (@error) Or ($Ret[0]) Then
			ExitLoop
		EndIf
		If _WinAPI_IsAlphaBitmap($hBitmap) Then
			$Format = 0x0026200A
		Else
			$Format = 0x00022009
		EndIf
		$hToken = $Ret[1]
		$Ret = DllCall('gdiplus.dll', 'uint', 'GdipCreateBitmapFromScan0', 'int', $Size[0], 'int', $Size[1], 'uint', $Size[0] * 4, 'uint', $Format, 'ptr', DllStructGetPtr($tBits), 'ptr*', 0)
		If (@error) Or ($Ret[0]) Then
			ExitLoop
		EndIf
		$hImage = $Ret[6]
		$Ret = DllCall('gdiplus.dll', 'uint', 'GdipGetImageEncodersSize', 'uint*', 0, 'uint*', 0)
		If (@error) Or ($Ret[0]) Then
			ExitLoop
		EndIf
		$Count = $Ret[1]
		$tData = DllStructCreate('byte[' & $Ret[2] & ']')
		If @error Then
			ExitLoop
		EndIf
		$pData = DllStructGetPtr($tData)
		$Ret = DllCall('gdiplus.dll', 'uint', 'GdipGetImageEncoders', 'uint', $Count, 'uint', $Ret[2], 'ptr', $pData)
		If (@error) Or ($Ret[0]) Then
			ExitLoop
		EndIf
		For $i = 1 To $Count
			$tInfo = DllStructCreate('byte[16];byte[16];ptr[5];dword[4];ptr[2]', $pData)
			If Not StringInStr(_WinAPI_WideCharToMultiByte(DllStructGetData($tInfo, 3, 5)), $Mime) Then
				$pData += DllStructGetSize($tInfo)
			Else
				$pEncoder = $pData
				ExitLoop
			EndIf
		Next
		If Not $pEncoder Then
			ExitLoop
		EndIf
		Switch $iCompression
			Case 0
				; Nothing
			Case 1
				$tParam = DllStructCreate('dword;byte[16];dword;dword;ptr;ulong')
				DllStructSetData($tParam, 1, 1)
				DllStructSetData($tParam, 3, 1)
				DllStructSetData($tParam, 4, 4)
				DllStructSetData($tParam, 5, DllStructGetPtr($tParam, 6))
				DllStructSetData($tParam, 6, $iQuality)
				$Ret = DllCall('ole32.dll', 'uint', 'CLSIDFromString', 'wstr', '{1D5BE4B5-FA4A-452D-9CDD-5DB35105E7EB}', 'ptr', DllStructGetPtr($tParam, 2))
				If (@error) Or ($Ret[0]) Then
					$tParam = 0
				EndIf
		EndSwitch
		$pStream = _WinAPI_CreateStreamOnHGlobal()
		$Ret = DllCall('gdiplus.dll', 'uint', 'GdipSaveImageToStream', 'ptr', $hImage, 'ptr', $pStream, 'ptr', $pEncoder, 'ptr', DllStructGetPtr($tParam))
		If (@error) Or ($Ret[0]) Then
			ExitLoop
		EndIf
		$hMem = _WinAPI_GetHGlobalFromStream($pStream)
		$Ret = DllCall('kernel32.dll', 'ulong_ptr', 'GlobalSize', 'ptr', $hMem)
		If (@error) Or (Not $Ret[0]) Then
			ExitLoop
		EndIf
		$Length = $Ret[0]
		$Ret = DllCall('kernel32.dll', 'ptr', 'GlobalLock', 'ptr', $hMem)
		If (@error) Or (Not $Ret[0]) Then
			ExitLoop
		EndIf
		$pBuffer = __HeapReAlloc($pBuffer, $Length, 1)
		If Not @error Then
			If _WinAPI_MoveMemory($pBuffer, $Ret[0], $Length) Then
				$Error = 0
			EndIf
		EndIf
	Until 1
	If $pStream Then
		_WinAPI_ReleaseStream($pStream)
	EndIf
	If $hImage Then
		DllCall('gdiplus.dll', 'uint', 'GdipDisposeImage', 'ptr', $hImage)
	EndIf
	If $hToken Then
		DllCall('gdiplus.dll', 'none', 'GdiplusShutdown', 'ptr', $hToken)
	EndIf
	If $hSource Then
		_WinAPI_DeleteObject($hSource)
	EndIf
	If $Error Then
		Return SetError(1, 0, 0)
	EndIf
	Return $Length
EndFunc   ;==>_WinAPI_CompressBitmapBits
 

HFShak

Новичок
Сообщения
2
Репутация
0
Добрый день!
Подскажите, где можно скачать winapiex.au3? Ресурс недоступен
 
A

Alofa

Гость
Вообще-то UDF WinAPIEx.au3 уже присутствует по умолчанию в Autoit
(только это уже видоизмененная и переработанная другими авторами версия).
Если вам нужен именно оригинал, то вот пожалуйста:

Для AutoIt 3.3.6.x: ZIP (архив), EXE (инсталлятор)
Для AutoIt 3.3.8.x: ZIP (архив), EXE (инсталлятор)

Yashied сказал(а):
Так как на форуме выложено огромное количество скриптов, которые используют WinAPIEx UDF разных версий, а полной совместимости между версиями нет, то я добавил в первый пост ссылку на архив всех версий этой библиотеки, начиная с 2.5. В большинстве случаев проще использовать ту версию AutoIt и WinAPIEx UDF, для которых был написан тот или иной скрипт, нежели отслеживать все изменения и адаптировать под них код.

Архив версий v3.0-3.7
 

MRGYV

Новичок
Сообщения
29
Репутация
0
Что-то не могу скачать. Пишет нет файла. Скиньте, пожалуйста, ссылку.
 
Верх