Besserer Aufbau einer Funktion mit DllCalls

Post a reply


In an effort to prevent automatic submissions, we require that you complete the following challenge.
Smilies
:D :) ;) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :!: :?: :idea: :| :mrgreen: :geek: :ugeek: :arrow: :angel: :clap: :crazy: :eh: :lolno: :problem: :shh: :shifty: :sick: :silent: :think: :thumbup: :thumbdown: :salute: :wave: :wtf: :yawn: :facepalm: :bravo: :dance: :beard: :morebeard: :xmas: :HeHe: :trollface: :cookie: :rainbow: :monkeysee: :monkeysay: :happybday: :headwall: :offtopic: :superhappy: :terms: :beer:
View more smilies

BBCode is ON
[img] is OFF
[flash] is OFF
[url] is ON
Smilies are ON

Topic review
   

Expand view Topic review: Besserer Aufbau einer Funktion mit DllCalls

Re: Besserer Aufbau einer Funktion mit DllCalls

Post by nnnik » 22 Oct 2013, 06:29

Du könntest anstatt eine PID zu übergeben eine Funktion machen bei der du ein hProcess übergeben musst.
Dies müsstest du dann nur 1 mal Öffnen und 1 mal schließen.
Das würde das OpenProcess und CloseProcess umgehen.

Re: Besserer Aufbau einer Funktion mit DllCalls

Post by jNizM » 22 Oct 2013, 05:06

relativ oft ;)
Immer her mit Verbesserung =)

edit: http://ahkscript.org/boards/viewtopic.php?f=6&t=254

Re: Besserer Aufbau einer Funktion mit DllCalls

Post by nnnik » 22 Oct 2013, 04:46

Nur so als Frage rufst du die Funktion sehr oft auf?

Re: Besserer Aufbau einer Funktion mit DllCalls

Post by jNizM » 22 Oct 2013, 01:56

Hab das jetzt so gelöst:
Für Win 7 x64 / x86 & XP brauch ich beide Funktionen

Code: Select all

BuildVersion := DllCall("GetVersion") >> 16 & 0xffff

if (BuildVersion >= "7600") {
   GPMI := GetProcessMemoryInfo_PMCEX(ownPID)
   PUsage := Round(GPMI[10] / 1024, 0)
} else {
   GPMI := GetProcessMemoryInfo_PMC(ownPID)
   PUsage := Round(GPMI[8] / 1024, 0)
}

GetProcessMemoryInfo_PMCEX(PID) {
    pu := ""
    hProcess := DllCall(Kernel32.OpenProcess, "UInt", 0x001F0FFF, "UInt", 0, "UInt", PID)
    if (hProcess) {
        static PMCEX, size := (A_PtrSize = "8" ? "80" : "44"), init := VarSetCapacity(PMCEX, size, 0) && NumPut(size, PMCEX)
        if (DllCall(Kernel32.K32GetProcessMemoryInfo, "Ptr", hProcess, "UInt", &PMCEX, "UInt", size))
            pu := { 10 : NumGet(PMCEX, (A_PtrSize = "8" ? "72" : "40"), "Ptr") }
        DllCall(Kernel32.CloseHandle, "Ptr", hProcess)
    }
    return, % pu
}
GetProcessMemoryInfo_PMC(PID) {
    pu := ""
    hProcess := DllCall(Kernel32.OpenProcess, "UInt", 0x001F0FFF, "UInt", 0, "UInt", PID)
    if (hProcess) {
        static PMC, size := (A_PtrSize = "8" ? "72" : "40"), init := VarSetCapacity(PMC, size, 0) && NumPut(size, PMC)
        if (DllCall("psapi.dll\GetProcessMemoryInfo", "Ptr", hProcess, "UInt", &PMC, "UInt", size))
            pu := { 8 : NumGet(PMC, (A_PtrSize = "8" ? "56" : "32"), "Ptr") }
        DllCall(Kernel32.CloseHandle, "Ptr", hProcess)
    }
    return, % pu
}

Re: Besserer Aufbau einer Funktion mit DllCalls

Post by just me » 19 Oct 2013, 02:36

Statische wie lokale Variablen existieren nur innerhalb der umgebenden Funktion. Du kannst deshalb dieselben Namen in unterschiedlichen Funktionen wiederverwenden und brauchst Dir auch keine Gedanken darüber zu machen, ob der Name im "globalen" Teil des Skripts (d.h. außerhalb von Funktionen) verwendet wird.

Bei mir (Win 7 x64 - AHK U64) liefern übrigens beide API-Funktionen (K32GetProcessMemoryInfo und GetProcessMemoryInfo) identische Ergebnisse. Laut MSDN ist die Struktur PROCESS_MEMORY_COUNTERS_EX seit XP SP2 definiert. Vielleicht machst Du Dir mit der Unterscheidung zu viel Mühe.

Re: Besserer Aufbau einer Funktion mit DllCalls

Post by jNizM » 19 Oct 2013, 01:04

Ok. Das gilt aber nur innerhalb einer Funktion?
Oder muss ich dass über das ganze Script so ziehen?

Re: Besserer Aufbau einer Funktion mit DllCalls

Post by HotKeyIt » 18 Oct 2013, 19:05

Um Fehler zu vermeiden darf die Variable nur 1 mal deklariert werden.

Code: Select all

GetProcessMemoryInfo(PID){
static PMCEx,PMCExsize := (A_PtrSize = "8" ? "80" : "44"), init := VarSetCapacity(PMCEx, PMCExsize, 0) && NumPut(PMCExsize, PMCEx)
static PMC, PMCsize := (A_PtrSize = "8" ? "72" : "40"), init2 := VarSetCapacity(PMC, PMCsize, 0) && NumPut(PMCsize, PMC)

Re: Besserer Aufbau einer Funktion mit DllCalls

Post by jNizM » 18 Oct 2013, 15:03

Und woran liegt es genau?

Code: Select all

GetVersionEx()
static OSVerEX, init := VarSetCapacity(OSVerEX, 284, 0) && Numput(284, OSVerEX, "UInt")

GetProcessMemoryInfo(PID)
static PMCEx, size := (A_PtrSize = "8" ? "80" : "44"), init := VarSetCapacity(PMCEx, size, 0) && NumPut(size, PMCEx)
static PMC, size := (A_PtrSize = "8" ? "72" : "40"), init := VarSetCapacity(PMC, size, 0) && NumPut(size, PMC)
wenn ich die static PMC auskommeniter gehts obwohl ja da auch 2x static + 2x init dabei ist
Oder darf ich nur nicht in einer Function das doppelt aufrufen mit static init

Re: Besserer Aufbau einer Funktion mit DllCalls

Post by just me » 18 Oct 2013, 14:57

Klassen machen manchmal durchaus Sinn, aber nicht immer!

Re: Besserer Aufbau einer Funktion mit DllCalls

Post by nnnik » 18 Oct 2013, 14:37

static Variablen werden auch vor Scriptstart ausgelesen.
Die Definition ist deshalb doppelt weil die statics nicht von der If-Abfrage abhängig sind.

Re: Besserer Aufbau einer Funktion mit DllCalls

Post by jNizM » 18 Oct 2013, 14:10

Warum bekomm ich hier die Meldung: Error: Duplicate declaration? (bei static PMC size & init)
Durch if else wird doch eh nur eins zutreffen?

Code: Select all

ownPID := DllCall("GetCurrentProcessId")
MsgBox, % "BUILD: " GetVersionEx() " | PID: " ownPID " | " Round(GetProcessMemoryInfo(ownPID) / 1024, 0) " K"

GetVersionEx() {
    static OSVerEX, init := VarSetCapacity(OSVerEX, 284, 0) && Numput(284, OSVerEX, "UInt")
    DllCall("GetVersionEx", "Ptr", &OSVerEX)
    return, NumGet(OSVerEX, 12, "UInt")
}


GetProcessMemoryInfo(PID) {
    pu := ""
    hProcess := DllCall("OpenProcess", "UInt", 0x001F0FFF, "Int", 0, "UInt", PID)
    if (hProcess)
    {
        if (GetVersionEx() >= "7600")
        {
            static PMCEx, size := (A_PtrSize = "8" ? "80" : "44"), init := VarSetCapacity(PMCEx, size, 0) && NumPut(size, PMCEx)
            if (DllCall("Kernel32.dll\K32GetProcessMemoryInfo", "Ptr", hProcess, "UInt", &PMCEx, "UInt", size))
                pu := NumGet(PMCEx, (A_PtrSize = "8" ? "72" : 40), (A_PtrSize = 8 ? "Int64" : "Int"))
            DllCall("Kernel32.dll\CloseHandle", "Int", hProcess)
        }
        else
        {
            static PMC, size := (A_PtrSize = "8" ? "72" : "40"), init := VarSetCapacity(PMC, size, 0) && NumPut(size, PMC)
            if (DllCall("psapi.dll\GetProcessMemoryInfo", "Ptr", hProcess, "UInt", &PMC, "UInt", size))
                pu := NumGet(PMC, (A_PtrSize = 8 ? 56 : 32), (A_PtrSize = 8 ? "Int64" : "Int"))
            DllCall("psapi.dll\CloseHandle", "Ptr", hProcess)
        }
    }
    return, % pu
}

Re: Besserer Aufbau einer Funktion mit DllCalls

Post by nnnik » 18 Oct 2013, 11:53

Wegen dem zweiten:
Da fragst du per If-Abfrage ab ob das OS system gleich oder größer als 7600 ist.
Du könntest diese If abfrage 1 mal ausführen und daraufhin per Func objekt eine andere Funktion definieren, die dann immer aufgerufen wird:

Code: Select all

Class GetOwnMemory{
__new()
{
this.ownPID := DllCall("GetCurrentProcessId")
VarSetCapacity(OSVerEX, 284, 0)
Numput(284, OSVerEX,0, "UInt")
DllCall("GetVersionEx", "Ptr", &OSVerEX)
NumGet(OSVerEX, 12, "UInt")
If this.hProcess := DllCall("OpenProcess", "UInt", 0x001F0FFF, "Int", 0, "UInt", this.ownPID)
{
if (NumGet(OSVerEX, 12, "UInt")>= "7600")
this.fnc:=func("GetProcessMemoryInfo1")
Else
this.fnc:=func("GetProcessMemoryInfo2")
}
Else
this.fnc:=func("Error")
}
Info()
{
return this.fnc.(this)
}
}

GetProcessMemoryInfo1(this) {
        static PCMEX:="",size := (A_PtrSize = "8" ? "80" : "44"),init:=VarSetCapacity(PMCEX, size, 0)&& NumPut(size, PMCEX)
            if (DllCall("K32GetProcessMemoryInfo", "Ptr", this.hProcess, "UInt", &PMCEX, "UInt", size))
                return NumGet(PMCEX, (A_PtrSize = "8" ? "72" : 40), (A_PtrSize = 8 ? "Int64" : "Int"))
}
 GetProcessMemoryInfo2(this)
    {
       static PCM:="",size := (A_PtrSize = "8" ? "72" : "40"), init:=VarSetCapacity(PMC, size, 0)&& NumPut(size, PMC) 
            if (DllCall("psapi.dll\GetProcessMemoryInfo", "Ptr", this.hProcess, "UInt", &PMC, "UInt", size))
              return, NumGet(PMC, (A_PtrSize = 8 ? 56 : 32), "ptr")
    }

Error(this)
{
return "Error"
}

Re: Besserer Aufbau einer Funktion mit DllCalls

Post by jNizM » 18 Oct 2013, 11:20

Re: Besserer Aufbau einer Funktion mit DllCalls

Post by nnnik » 18 Oct 2013, 11:14

Ähm mem.refresh() ?

Re: Besserer Aufbau einer Funktion mit DllCalls

Post by HotKeyIt » 18 Oct 2013, 09:38

Für die Klasse brauchst du einen weg die werte zu aktualisieren, andernfalls wirst du nicht die aktuellen werte bekommen.
Werte bei jedem get zu aktualisieren macht auch kein Sinn, also bleibt nur A_TickCount zu überprüfen und je nach dem wie alt der letzte Aufruf ist zu aktualisieren.

Das verlangsamt leider alles und ist eher nicht empfehlenswert meiner Ansicht nach.

Re: Besserer Aufbau einer Funktion mit DllCalls

Post by nnnik » 18 Oct 2013, 09:20

Oder direkt eine Klasse :D

Code: Select all

Class GlobalMemoryStatusEx{
__new()
{
this.ptr:=DllCall("HeapAlloc","UPtr",DllCall("GetProcessHeap"),"UInt",8,"UPtr",64)	
NumPut(64, this.ptr+0, "UInt")
DllCall("GlobalMemoryStatusEx", "Ptr", this.ptr)
this.offset:={Length:0,MemoryLoad:4,TotalPhys:8,AvailPhys:16,TotalPageFile:24,AvailPageFile:32,TotalVirtual:40,AvailVirtual:48,AvailExtendedVirtual:56}
this.type:={Length:"uint",MemoryLoad:"uint",TotalPhys:"int64",AvailPhys:"int64",TotalPageFile:"int64",AvailPageFile:"int64",TotalVirtual:"int64",AvailVirtual:"int64",AvailExtendedVirtual:"int64"}
}
__get(p)
{
return numget(this.ptr+0,this.offset[p],this.type[p])
}
refresh()
{
DllCall("GlobalMemoryStatusEx", "Ptr", this.ptr)
}
}

Mem:=new GlobalMemoryStatusEx()
Msgbox % mem.length

Re: Besserer Aufbau einer Funktion mit DllCalls

Post by jNizM » 18 Oct 2013, 09:09

Danke an alle =)

Wenn ich daheim bin komme ich nochmal auf dich zu wegen einer weiteren Funktion ;)
Den alten Stand, den ich zusammengeschustert habe, lass ich dir schon mal da.

Code: Select all

ownPID := DllCall("GetCurrentProcessId")
MsgBox, % "BUILD: " GetVersionEx() " | PID: " ownPID " | " Round(GetProcessMemoryInfo(ownPID) / 1024, 0) " K"

GetVersionEx() {
	static OSVerEX, init := VarSetCapacity(OSVerEX, 284, 0) && Numput(284, OSVerEX, "UInt")
    DllCall(Kernel32.GetVersionEx, "Ptr", &OSVerEX)
    return, NumGet(OSVerEX, 12, "UInt")
}

GetProcessMemoryInfo(PID) {
    pu := ""
    if (GetVersionEx() >= "7600")
    {
        size := (A_PtrSize = "8" ? "80" : "44")
        VarSetCapacity(PMCEX, size, 0), NumPut(size, PMCEX)

        hProcess := DllCall("OpenProcess", "UInt", 0x001F0FFF, "Int", 0, "UInt", PID)
        if (hProcess)
        {
            if (DllCall("Kernel32.dll\K32GetProcessMemoryInfo", "Ptr", hProcess, "UInt", &PMCEX, "UInt", size))
                pu := NumGet(PMCEX, (A_PtrSize = "8" ? "72" : 40), (A_PtrSize = 8 ? "Int64" : "Int"))
            DllCall("Kernel32.dll\CloseHandle", "Int", hProcess)
        }
    }
    else
    {
        size := (A_PtrSize = "8" ? "72" : "40")
        VarSetCapacity(PMC, size, 0), NumPut(size, PMC)
        
        hProcess := DllCall("OpenProcess", "UInt", 0x001F0FFF, "Int", 0, "UInt", PID)
        if (hProcess)
        {
            if (DllCall("psapi.dll\GetProcessMemoryInfo", "Ptr", hProcess, "UInt", &PMC, "UInt", size))
                pu := NumGet(PMC, (A_PtrSize = 8 ? 56 : 32), (A_PtrSize = 8 ? "Int64" : "Int"))
            DllCall("psapi.dll\CloseHandle", "Ptr", hProcess)
        }
    }
    return % pu
}

Re: Besserer Aufbau einer Funktion mit DllCalls

Post by jNizM » 18 Oct 2013, 08:13

ergo so?

Code: Select all

GMSEx := GlobalMemoryStatusEx()

MsgBox,, GlobalMemoryStatusEx, % "GlobalMemoryStatusEx function /`n"
        . "MEMORYSTATUSEX structure`n`n"
        . "Lenght:`t`t`t"             GMSEx[0]  "`n`n"
        . "MemoryLoad:`t`t"           GMSEx[1]  " %`n`n"
        . "TotalPhys:`t`t`t"          GMSEx[2]  " bytes`n"
        . "AvailPhys:`t`t`t"          GMSEx[3]  " bytes`n`n"
        . "TotalPageFile:`t`t"        GMSEx[4]  " bytes`n"
        . "AvailPageFile:`t`t"        GMSEx[5]  " bytes`n`n"
        . "TotalVirtual:`t`t"         GMSEx[6]  " bytes`n"
        . "AvailVirtual:`t`t"         GMSEx[7]  " bytes`n`n"
        . "AvailExtendedVirtual:`t`t" GMSEx[8]

GlobalMemoryStatusEx() {
	static MEMORYSTATUSEX, init := VarSetCapacity(MEMORYSTATUSEX, 64, 0) && NumPut(64, MEMORYSTATUSEX, "UInt")
    DllCall("GlobalMemoryStatusEx", "Ptr", &MEMORYSTATUSEX)
    return, { 0 : NumGet(MEMORYSTATUSEX,  0, "UInt"),  1 : NumGet(MEMORYSTATUSEX,  4, "UInt")
            , 2 : NumGet(MEMORYSTATUSEX,  8, "Int64"), 3 : NumGet(MEMORYSTATUSEX, 16, "Int64")
            , 4 : NumGet(MEMORYSTATUSEX, 24, "Int64"), 5 : NumGet(MEMORYSTATUSEX, 32, "Int64")
            , 6 : NumGet(MEMORYSTATUSEX, 40, "Int64"), 7 : NumGet(MEMORYSTATUSEX, 48, "Int64")
            , 8 : NumGet(MEMORYSTATUSEX, 56, "Int64") }
}

Re: Besserer Aufbau einer Funktion mit DllCalls

Post by HotKeyIt » 18 Oct 2013, 08:08

Dann kann ich nur empfehlen die variable als static zu deklarieren und zu initialisieren:

Code: Select all

GlobalMemoryStatusEx(){
 static MEMORYSTATUSEX,init:=VarSetCapacity(MEMORYSTATUSEX, 64, 0) &&  NumPut(64, MEMORYSTATUSEX,"UInt")
...

Top