1

Тема: AHK: тонкости с потреблением памяти

Здесь предлагаю делиться ситуациями странного потребления памяти и вариантами их предотвращения.
Сегодня столкнулся с интересной особенностью, что после встраивания своего гуи с WMPlayer.OCX в чужое окно через SetParent и разрушении чужого окна, GPU память продолжала съедаться.
Вылечилось отлавливанием закрытия окна и вызовом метода Controls.stop.
https://docs.microsoft.com/en-us/window … trols-stop
Странно, что такое происходило только с одной конкретной программой.

2

Re: AHK: тонкости с потреблением памяти

Следующий код загружает pdf в gui.

pdfPath := "D:\1064754760.pdf"

VarSetCapacity(GUID, 16)
DllCall("ole32\CLSIDFromString", "wstr", IID_RandomAccessStream := "{905A0FE1-BC53-11DF-8C49-001E4FC686DA}", "ptr", &GUID)
DllCall("ShCore\CreateRandomAccessStreamOnFile", "wstr", pdfPath, "uint", Read := 0, "ptr", &GUID, "ptr*", IRandomAccessStream)
CreateClass("Windows.Data.Pdf.PdfDocument", IPdfDocumentStatics := "{433A0B5F-C007-4788-90F2-08143D922599}", PdfDocumentStatics)
DllCall(NumGet(NumGet(PdfDocumentStatics+0)+8*A_PtrSize), "ptr", PdfDocumentStatics, "ptr", IRandomAccessStream, "ptr*", PdfDocument)   ; LoadFromStreamAsync
WaitForAsync(PdfDocument)
DllCall(NumGet(NumGet(PdfDocument+0)+6*A_PtrSize), "ptr", PdfDocument, "uint", 0, "ptr*", PdfPage)   ; GetPage
DllCall("Ole32\CreateStreamOnHGlobal", "ptr", 0, "uint", true, "ptr*", IStream)
DllCall("ShCore\CreateRandomAccessStreamOverStream", "ptr", IStream, "uint", BSOS_DEFAULT := 0, "ptr", &GUID, "ptr*", IRandomAccessStreamOut)
DllCall(NumGet(NumGet(PdfPage+0)+6*A_PtrSize), "ptr", PdfPage, "ptr", IRandomAccessStreamOut, "ptr*", asyncInfo)   ; RenderToStreamAsync
WaitForAsync(asyncInfo)

DllCall("LoadLibrary", "str", "gdiplus")
VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
DllCall("gdiplus\GdiplusStartup", "ptr*", pToken, "ptr", &si, "ptr", 0)
DllCall("gdiplus\GdipCreateBitmapFromStream", "ptr", IStream, "ptr*", pBitmap)
DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "ptr", pBitmap, "ptr*", hBitmap, "uint", 0xffffffff)
Gui, Add, Picture, , HBITMAP:%hBitmap%
Gui, Show

DllCall("Gdiplus.dll\GdipDisposeImage", "ptr", pBitmap)
Close := ComObjQuery(IRandomAccessStream, IClosable := "{30D5A829-7FA4-4026-83BB-D75BAE4EA99E}")
DllCall(NumGet(NumGet(Close+0)+6*A_PtrSize), "ptr", Close)   ; Close
ObjRelease(Close)
ObjRelease(IRandomAccessStream)
ObjRelease(PdfDocumentStatics)
ObjRelease(PdfDocument)
ObjRelease(PdfPage)
ObjRelease(IStream)
Close := ComObjQuery(IRandomAccessStreamOut, IClosable := "{30D5A829-7FA4-4026-83BB-D75BAE4EA99E}")
DllCall(NumGet(NumGet(Close+0)+6*A_PtrSize), "ptr", Close)   ; Close
ObjRelease(Close)
ObjRelease(IRandomAccessStreamOut)




CreateClass(string, interface, ByRef Class)
{
   CreateHString(string, hString)
   VarSetCapacity(GUID, 16)
   DllCall("ole32\CLSIDFromString", "wstr", interface, "ptr", &GUID)
   result := DllCall("Combase.dll\RoGetActivationFactory", "ptr", hString, "ptr", &GUID, "ptr*", Class, "uint")
   if (result != 0)
   {
      if (result = 0x80004002)
         msgbox No such interface supported
      else if (result = 0x80040154)
         msgbox Class not registered
      else
         msgbox error: %result%
      ExitApp
   }
   DeleteHString(hString)
}

CreateHString(string, ByRef hString)
{
    DllCall("Combase.dll\WindowsCreateString", "wstr", string, "uint", StrLen(string), "ptr*", hString)
}

DeleteHString(hString)
{
   DllCall("Combase.dll\WindowsDeleteString", "ptr", hString)
}

WaitForAsync(ByRef Object)
{
   AsyncInfo := ComObjQuery(Object, IAsyncInfo := "{00000036-0000-0000-C000-000000000046}")
   loop
   {
      DllCall(NumGet(NumGet(AsyncInfo+0)+7*A_PtrSize), "ptr", AsyncInfo, "uint*", status)   ; IAsyncInfo.Status
      if (status != 0)
      {
         if (status != 1)
         {
            DllCall(NumGet(NumGet(AsyncInfo+0)+8*A_PtrSize), "ptr", AsyncInfo, "uint*", ErrorCode)   ; IAsyncInfo.ErrorCode
            msgbox AsyncInfo status error: %ErrorCode%
            ExitApp
         }
         ObjRelease(AsyncInfo)
         break
      }
      sleep 10
   }
   DllCall(NumGet(NumGet(Object+0)+8*A_PtrSize), "ptr", Object, "ptr*", ObjectResult)   ; GetResults
   ObjRelease(Object)
   Object := ObjectResult
}

Если делать это в цикле, то идет утечка памяти, так как не освобождаются ресурсы IRandomAccessStream.
https://docs.microsoft.com/en-us/uwp/ap … inrt-19041
Лечится с помощью:

DllCall("psapi.dll\EmptyWorkingSet", "ptr", -1)

3

Re: AHK: тонкости с потреблением памяти

Malcev пишет:

Следующий код загружает pdf в gui

Ну, всё-таки не pdf, а картинку, сделанную из pdf-страницы.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

4

Re: AHK: тонкости с потреблением памяти

Простой способ открыть pdf в GUI: https://www.autohotkey.com/boards/viewt … 26#p370626

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

5

Re: AHK: тонкости с потреблением памяти

Да, прикольно.
Только в этой теме хотелось бы обсуждать тонкости с потреблением памяти.