Search the Community
Showing results for tags 'shared memory'.
Below is a function w/ a working example showing how to access the AIDA64 shared memory. First enable shared memory here: Preferences > Hardware Monitoring > External Applications > Enable Shared Memory The length of the data depends on the number of active sensors and their content. As AIDA64 does not provide a buffer size value, we use _WinAPI_GetSystemInfo() <WinAPISys.au3> to get dwPageSize ($aArray). This value is the used as an address offset, and we continue reading chunks of data until we encounter a 0x00 NUL character. Based on the Delphi example found in the AIDA64 documentation: https://www.aida64.co.uk/user-manual/external-applications Feedback appreciated, especially as all this shared memory stuff is not my ordinary cup of... cake. And regarding this whole ordeal of reading data without knowing the exact length; I'm suspecting my solution to read chunks of data like done below is not by the book, and I'm concerned what might happen if the final chunk is exactly 4096 bytes in length. Will there still be a NUL terminator there? Hmm. #NoTrayIcon #include <WinAPIFiles.au3> #include <WinAPISys.au3> ; #INDEX# =========================================================================================================================== ; Title .........: AIDA64 Shared Memory access for AutoIt3 ; Author(s) .....: demux4555 ; Reference .....: https://www.aida64.co.uk/user-manual/external-applications ; =================================================================================================================================== Global $vSharedmem_data ; The variable used to store the data we read from the shared memory Global $return = ExtApp_SharedMem_ReadBuffer_v2($vSharedmem_data) ; Now, let's see what happens when we run the function... If @error Then _Echo("! ExtApp_SharedMem_ReadBuffer_v2(): @errror = " & @error) If IsBinary($vSharedmem_data) Then ; Convert type Binary to actual human readable text. We also remove the excess of trailing 0x00 characters. $vSharedmem_data = StringStripWS(BinaryToString($vSharedmem_data), $STR_STRIPLEADING+$STR_STRIPTRAILING) EndIf _Echo() _Echo("> return = " & $return) ; The return value. Will be True if everything went ok. _Echo("> length = " & StringLen($vSharedmem_data)) ; The number of characters read from shared memory. _Echo("> data = " & $vSharedmem_data) ; The actual data. _Echo("> data(40) = " & "..." & StringRight($vSharedmem_data, 40)) ; shows the 40 right-most characters, and _should_ show the very end of the data at this point. _Echo() Exit ; #FUNCTION# ==================================================================================================================== ; Name ..........: ExtApp_SharedMem_ReadBuffer_v2 ; Description ...: AIDA64 Shared Memory Example for AutoIt3 ; Syntax ........: ExtApp_SharedMem_ReadBuffer_v2(Byref $_dOutput[, $_sSharedmemName = "AIDA64_SensorValues"]) ; Parameters ....: $_dOutput - [in/out] Variable to store the read data. ; $_sSharedmemName - [optional] Name of the AIDA64 shared memory. Default is "AIDA64_SensorValues". ; Return values .: Success: True. $_dOutput will be type Binary, containing a string of the XML values of the active sensors. ; Failure: False. ; Author ........: demux4555 ; Reference .....: https://www.aida64.co.uk/user-manual/external-applications ; =============================================================================================================================== Func ExtApp_SharedMem_ReadBuffer_v2(ByRef $_dOutput, $_sSharedmemName = "AIDA64_SensorValues") Local $_bReturn = False Local $_aGSI = _WinAPI_GetSystemInfo() ; Retrieves information about the current system... Ref: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsysteminfo Local $_iPageSize = $_aGSI ; ... the page size and the granularity of page protection and commitment. Usually it is 4096, but we read it anyway. Ref: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/ns-sysinfoapi-system_info Local $_hMapping = _WinAPI_OpenFileMapping($_sSharedmemName, $FILE_MAP_READ) ; Opens a named file mapping object. Ref: https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-openfilemappingw If Not IsPtr($_hMapping) Then Return SetError(-2, 0, $_bReturn) Local $_pMappedData = _WinAPI_MapViewOfFile($_hMapping, 0, 0, $FILE_MAP_READ) ; Pointer to the start address. Maps a view of a file mapping into the address space of a calling process. Ref: https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-mapviewoffile If @error Or Not IsPtr($_pMappedData) Then Return SetError(-2, 0, $_bReturn) ; Now we loop until we reach the end of the data. Local $_tData, $_dBuffer While 1 $_tData = DllStructCreate("BYTE[" & $_iPageSize & "]", $_pMappedData) ; Note: we use type BYTE (AutoIt type Binary) instead of CHAR (AutoIt type String). This allows us to look for value 0x00 (NUL termination of the data). If @error Then ExitLoop $_dBuffer = DllStructGetData($_tData, 1) ; The returned value is type Binary. If @error Or ($_dBuffer==0) Or (BinaryLen($_dBuffer)=0) Then ExitLoop ; Pretty sure $_dBuffer==0 can not happen, so just in case. $_dOutput = Binary($_dOutput & $_dBuffer) ; Add the read data to the end of the output variable. If StringRight($_dBuffer, 2)=="00" Then ExitLoop ; Look for NUL termination of the string data. $_pMappedData += $_iPageSize ; We change the address by using the page granularity value (i.e. 4096) as the offset. WEnd ; Quick cleanup $_bReturn = _WinAPI_UnmapViewOfFile($_pMappedData)=1 ; Unmaps a mapped view of a file from the calling process's address space. Ref: https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-unmapviewoffile _WinAPI_CloseHandle($_hMapping) Return $_bReturn EndFunc; Func _Echo($_data = "") ConsoleWrite($_data & @CRLF) EndFunc
IPC_IO.AU3 I am in the need for a simple synchronous Client/Server communication. I found several examples and references to various kinds of Inter-Process Communications such as TCP, Named Pipes, Mail Slots, Shared Memory, Memory Mapped Files, and simple Files. I wanted to see what the best solutions would be. I began developing a library and slowly began adding each of the IPC methods and ended up with a library with a very simple synchronous “ASCII” API where the application can choose which method to use at startup. For the Server side, a Server app must initialize communication by calling: Func InitConnection($cType = $cDefaultType, $ResourceName = "", $bBlock = $cDefaultBlocking, $fSleepFunc = "", $iBufSize = $DEFAULT_BUFSIZE) The optional arguments allow the app to specify the connection type (such as: $cNamedPipe, $cFile, $cTCP, $cSharedMem, $cMailSlot), a value for the resource name (such as the file, named pipe name, TCP port number, etc.), the communication buffer size, and a callback function for when the “read” is waiting for data. A “File Descriptor” is returned and must be used in the future API calls. The Server side must then call: Func StartConnection($iFD) This call waits for a Client to connect. The Server then calls: Func ReadData($iFD, ByRef $sData) To read a Request from the Client and then calls: Func WriteData($iFD, ByRef $sData) To send the reply back to the Client. When communication with the Client is done, the Server app will call: Func StopConnection($iFD) When the Server app is done with the communications it will call: Func EndConnection($iFD) For the Client side, a Client app must open the communication by calling: Func OpenConnection($cType = $cDefaultType, $ResourceName = "", $bBlock = $cDefaultBlocking, $fSleepFunc = "", $iBufSize = $DEFAULT_BUFSIZE) The optional arguments allow the app to specify the connection type (such as: $cNamedPipe, $cFile, $cTCP, $cSharedMem, $cMailSlot), a value for the resource name (such as the file, named pipe name, TCP port number, etc.), the communication buffer size, and a callback function for when the “read” is waiting for data. A “File Descriptor” is returned and must be used in the future API calls. The Client side then send a request to the Server app by calling: Func WriteData($iFD, ByRef $sData) To read a Response from the Server by calling: Func ReadData($iFD, ByRef $sData) To end the connection to the Server by calling: Func CloseConnection($iFD) Within the IPC_IO.AU3 library, each IPC method is ether: · “stream” based where data is read/written by calling _WinAPI_ReadFile/TCPRecv or _WinAPI_WriteFile/ TCPSend · “direct” based for Shared memory where the Client reads the data directly from the Server App’s memory and the Server directly reads the Client App’s memory In processing a request, the “ReadData” process starts by checking if data is ready to be read by calling the routine: “ReadStart”, then it reads in the size of the request by calling “ReadSize”, it then reads in the Ascii Request by calling “ReadBuffer”, then the sequence is completed by calling “ReadEnd”. The Write Process follows the same sequence with “WriteData” calling “WriteStart”, “WriteSize”, “WriteBuffer”, “WriteEnd”. Results My testing showed that the performance of sending and receiving of a 10k file took: · "Shared Memory" was the fastest, at 0.007468 Sec · “Named Pipes” at 0.015954 · “Mail Slots” at 0.016427 · “File Based” at 0.270287 · “TCP” at 0.994884 IPC_IO.au3 Client.au3 Server.au3