BlackSnoww Posted May 7, 2019 Share Posted May 7, 2019 I stumbled upon the code of @Yashied here at this thread https://www.autoitscript.com/forum/topic/108145-screenshot-over-tcp/?tab=comments#comment-969161 about sending Secreenshots through TCP without saving a physical file to the drive. I tried editing the code and found an error i cant figure it out. can anyone help ? Server expandcollapse popup#Include <APIConstants.au3> #Include <GDIPlus.au3> #Include <Memory.au3> #Include <WinAPIEx.au3> ;Global Const $STM_SETIMAGE = 0x0172 ;Global Const $STM_GETIMAGE = 0x0173 TCPStartup() $Main = TCPListen(@IPAddress4, 33891) If @error Then Exit EndIf GUICreate('MyGUI', 800, 600, @DesktopWidth - 819, @DesktopHeight - 671) $Pic = GUICtrlCreatePic('', 0, 0, 800, 600) GUISetState() Do $Socket = TCPAccept($Main) Until $Socket <> -1 Global $tHeader = DllStructCreate('byte[4]') Global $pHeader = DllStructGetPtr($tHeader) Global $bData = 0, $Count = 0 _GDIPlus_Startup() Do If Not IsBinary($bData) Then $bData = TCPRecv($Socket, 16384, 1) If @error Then ExitLoop EndIf EndIf If IsBinary($bData) Then If Not $Count Then DllStructSetData($tHeader, 1, $bData) $tData = DllStructCreate('dword', $pHeader) $Size = DllStructGetData($tData, 1) $tData = DllStructCreate('byte[' & $Size & ']') $pData = DllStructGetPtr($tData) EndIf $Lenght = BinaryLen($bData) $Sum = $Count + $Lenght If $Sum > $Size Then $dL = $Size - $Count $tPart = DllStructCreate('byte[' & $dL & ']', $pData + $Count) DllStructSetData($tPart, 1, $bData) $tByte = DllStructCreate('byte[' & $Lenght & ']') $tRecv = DllStructCreate('byte[' & ($Lenght - $dL) & ']', DllStructGetPtr($tByte) + $dL) DllStructSetData($tByte, 1, $bData) $bData = DllStructGetData($tRecv, 1) $Sum = $Size Else $tPart = DllStructCreate('byte[' & $Lenght & ']', $pData + $Count) DllStructSetData($tPart, 1, $bData) $Count = $Sum $bData = 0 EndIf If $Sum = $Size Then _SetScreenshot($Pic, $tData) $Count = 0 EndIf EndIf Until GUIGetMsg() = -3 _GDIPlus_Shutdown() TCPCloseSocket($Socket) TCPShutdown() Func _SetScreenshot($CtrlID, ByRef $tData, $fUpdate = 0) Local $hBitmap, $hPrev, $hScreen, $hMemory, $pMemory, $pStream, $pData, $iSize $hWnd = GUICtrlGetHandle($CtrlID) If Not $hWnd Then Return 0 EndIf $pData = DllStructGetPtr($tData) $iSize = DllStructGetData(DllStructCreate('dword', $pData + 4), 1) $hMemory = _MemGlobalAlloc($iSize, $GMEM_MOVEABLE) $pMemory = _MemGlobalLock($hMemory) _MemMoveMemory($pData + 8, $pMemory, $iSize) _MemGlobalUnlock($hMemory) $pStream = _WinAPI_CreateStreamOnHGlobal($hMemory) $hBitmap = _GDIPlus_CreateBitmapFromStream($pStream) $hScreen = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap) _GDIPlus_BitmapDispose($hBitmap) _WinAPI_ReleaseStream($pStream) _WinAPI_DeleteObject(_SendMessage($hWnd, $STM_SETIMAGE, $IMAGE_BITMAP, $hScreen)) $hPrev = _SendMessage($hWnd, $STM_GETIMAGE) If $hPrev <> $hScreen Then _WinAPI_DeleteObject($hScreen) EndIf If $fUpdate Then _WinAPI_UpdateWindow($hWnd) EndIf Return 1 EndFunc ;==>_SetScreenshot Func _GDIPlus_CreateBitmapFromStream($pStream) Local $Ret = DllCall($ghGDIPDll, 'uint', 'GdipCreateBitmapFromStream', 'ptr', $pStream, 'ptr*', 0) If (@error) Or ($Ret[0]) Then Return SetError(@error, @extended, 0) EndIf Return $Ret[2] EndFunc ;==>_GDIPlus_CreateBitmapFromStream Client expandcollapse popup#Include <APIConstants.au3> #Include <GDIPlus.au3> #Include <Memory.au3> #Include <WinAPIEx.au3> TCPStartup() $Socket = TCPConnect(@IPAddress4, 33891) If @error Then Exit EndIf _GDIPlus_Startup() Global $tEncoder = _WinAPI_GUIDFromString(_GDIPlus_EncodersGetCLSID('png')) Global $pEncoder = DllStructGetPtr($tEncoder) Local $iWidth = @DesktopWidth Local $iHeight = @DesktopHeight Local $iX = 0 Local $iY = 0 While 1 TCPSend($Socket, _GetScreenshot($iX, $iY, $iWidth, $iHeight)) If @error Then ExitLoop EndIf Sleep(1000) WEnd _GDIPlus_Shutdown() TCPShutdown() Func _GetScreenshot($iX,$iY, $iWidth, $iHeight) Local $hSrcDC, $hDstDC, $hDstSv, $hBitmap, $hDesktop, $hScreen, $hMemory, $pMemory, $pStream, $tOut, $pOut, $iSize, $pParams=0 $hDesktop = _WinAPI_GetDesktopWindow() $hSrcDC = _WinAPI_GetDC($hDesktop) $hScreen = _WinAPI_CreateCompatibleBitmap($hSrcDC, $iWidth, $iHeight) $hDstDC = _WinAPI_CreateCompatibleDC($hSrcDC) $hDstSv = _WinAPI_SelectObject($hDstDC, $hScreen) _WinAPI_BitBlt($hDstDC, $iX, $iY, $iWidth, $iHeight, $hSrcDC, $iX, $iY, $SRCCOPY) _WinAPI_SelectObject($hDstDC, $hDstSv) _WinAPI_ReleaseDC($hDesktop, $hSrcDC) _WinAPI_DeleteDC($hDstDC) $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hScreen) _WinAPI_DeleteObject($hScreen) $pStream = _WinAPI_CreateStreamOnHGlobal(0) _GDIPlus_SaveImageToStream($hBitmap, $pStream, $pEncoder,$pParams) _GDIPlus_BitmapDispose($hBitmap) $hMemory = _WinAPI_GetHGlobalFromStream($pStream) $pMemory = _MemGlobalLock($hMemory) $iSize = _MemGlobalSize($hMemory) $tOut = DllStructCreate('dword;dword;byte[' & ($iSize - Mod($iSize, 4) + 4) & ']') $pOut = DllStructGetPtr($tOut) DllStructSetData($tOut, 1, DllStructGetSize($tOut)) DllStructSetData($tOut, 2, $iSize) _MemMoveMemory($pMemory, $pOut + 8, $iSize) _WinAPI_ReleaseStream($pStream) Return DllStructGetData(DllStructCreate('byte[' & DllStructGetSize($tOut) & ']', DllStructGetPtr($tOut)), 1) EndFunc Func _GDIPlus_SaveImageToStream($hImage, $pStream, $pEncoder, $pParams) Local $Ret = DllCall($ghGDIPDll, 'uint', 'GdipSaveImageToStream', 'ptr', $hImage, 'ptr', $pStream, 'ptr', $pEncoder, 'ptr', $pParams) If (@error) Or ($Ret[0]) Then Return SetError(@error, @extended, 0) EndIf Return 1 EndFunc ;==>_GDIPlus_SaveImageToStream the error on the attached file Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted May 7, 2019 Moderators Share Posted May 7, 2019 BlackSnoww, The $ghGDIPDll DLL name within the various GDI #include files was renamed a long time ago to $__g_hGDIPDll - try changing that in the calling line and see if it works. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
BlackSnoww Posted May 8, 2019 Author Share Posted May 8, 2019 @Melba23 Thanks for your help i have this fully working on TCP. on the side note i have implemented this using Mailslots UDF as the TCP version made a bottleneck in sending the screenshots lol. I was hoping this would make is faster. So my problem is Running the mailslots on the same PC runs without a problem. Problem arise when its run on the different PC. the mailslot name used on the same PC "Both server and client is using the same name" Global Const $sMailSlotName = "\\.\mailslot\RandomNameForThisTest" On the different PC Name for host Global Const $sMailSlotName = "\\.\mailslot\RandomNameForThisTest" Name for Client where localuser-PC is the computer name of the host Global Const $sMailSlotName = "\\localuser-PC\mailslot\RandomNameForThisTest" Mailslot naming was made to this due to the reading made from this site https://www.codeproject.com/Articles/8527/Using-Mailslots-for-Interprocess-Communication "after the introduction part" my the Client returns a error code of 2 which the UDF documentation states "WriteFile function or call to it failed." and i dont know why. can you help me ? maybe u know whats my problem because in my digging u have been using mailslots alot xD Server expandcollapse popup#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 #include "MailSlot.au3" #Include <APIConstants.au3> #Include <GDIPlus.au3> #Include <Memory.au3> #Include <WinAPIEx.au3> Global Const $sMailSlotName = "\\.\mailslot\RandomNameForThisTest" Global $hMailSlot = _MailSlotCreate($sMailSlotName) If @error Then MsgBox(48 + 262144, "MailSlot", "Failed to create new account!" & @CRLF & "Probably one using that 'address' already exists.") Exit EndIf GUICreate('MyGUI', 800, 600, @DesktopWidth - 819, @DesktopHeight - 671) $Pic = GUICtrlCreatePic('', 0, 0, 800, 600) GUISetState() Global $tHeader = DllStructCreate('byte[4]') Global $pHeader = DllStructGetPtr($tHeader) Global $bData = 0, $Count = 0 Global $sData _GDIPlus_Startup() Do _ReadMessage($hMailSlot) $bData = $sData If IsBinary($bData) Then If Not $Count Then DllStructSetData($tHeader, 1, $bData) $tData = DllStructCreate('dword', $pHeader) $Size = DllStructGetData($tData, 1) $tData = DllStructCreate('byte[' & $Size & ']') $pData = DllStructGetPtr($tData) EndIf $Lenght = BinaryLen($bData) $Sum = $Count + $Lenght If $Sum > $Size Then $dL = $Size - $Count $tPart = DllStructCreate('byte[' & $dL & ']', $pData + $Count) DllStructSetData($tPart, 1, $bData) $tByte = DllStructCreate('byte[' & $Lenght & ']') $tRecv = DllStructCreate('byte[' & ($Lenght - $dL) & ']', DllStructGetPtr($tByte) + $dL) DllStructSetData($tByte, 1, $bData) $bData = DllStructGetData($tRecv, 1) $Sum = $Size Else $tPart = DllStructCreate('byte[' & $Lenght & ']', $pData + $Count) DllStructSetData($tPart, 1, $bData) $Count = $Sum $bData = 0 EndIf If $Sum = $Size Then _SetScreenshot($Pic, $tData) $Count = 0 EndIf EndIf Until GUIGetMsg() = -3 _GDIPlus_Shutdown() Func _SetScreenshot($CtrlID, ByRef $tData, $fUpdate = 0) Local $hBitmap, $hPrev, $hScreen, $hMemory, $pMemory, $pStream, $pData, $iSize $hWnd = GUICtrlGetHandle($CtrlID) If Not $hWnd Then Return 0 EndIf $pData = DllStructGetPtr($tData) $iSize = DllStructGetData(DllStructCreate('dword', $pData + 4), 1) $hMemory = _MemGlobalAlloc($iSize, $GMEM_MOVEABLE) $pMemory = _MemGlobalLock($hMemory) _MemMoveMemory($pData + 8, $pMemory, $iSize) _MemGlobalUnlock($hMemory) $pStream = _WinAPI_CreateStreamOnHGlobal($hMemory) $hBitmap = _GDIPlus_CreateBitmapFromStream($pStream) $hScreen = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap) _GDIPlus_BitmapDispose($hBitmap) _WinAPI_ReleaseStream($pStream) _WinAPI_DeleteObject(_SendMessage($hWnd, $STM_SETIMAGE, $IMAGE_BITMAP, $hScreen)) $hPrev = _SendMessage($hWnd, $STM_GETIMAGE) If $hPrev <> $hScreen Then _WinAPI_DeleteObject($hScreen) EndIf If $fUpdate Then _WinAPI_UpdateWindow($hWnd) EndIf Return 1 EndFunc ;==>_SetScreenshot Func _GDIPlus_CreateBitmapFromStream($pStream) Local $Ret = DllCall($__g_hGDIPDll, 'uint', 'GdipCreateBitmapFromStream', 'ptr', $pStream, 'ptr*', 0) If (@error) Or ($Ret[0]) Then Return SetError(@error, @extended, 0) EndIf Return $Ret[2] EndFunc ;==>_GDIPlus_CreateBitmapFromStream Func _ReadMessage($hHandle) Local $iSize = _MailSlotCheckForNextMessage($hHandle) If $iSize Then $sData = _MailSlotRead($hMailSlot, $iSize, 0) ; $iNumberOfMessagesOverall += 1 ; GUICtrlSetData($hEdit, "Message No" & $iNumberOfMessagesOverall & " , Size = " & $iSize & " :" & @CRLF & @CRLF & $sData) Else ; MsgBox(64, "Nothing read", "MailSlot is empty", 0, $hGUI) EndIf EndFunc ;==>_ReadMessage Client expandcollapse popup#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 #Include <APIConstants.au3> #Include <GDIPlus.au3> #Include <Memory.au3> #Include <WinAPIEx.au3> #include <File.au3> #include <MsgBoxConstants.au3> #include "MailSlot.au3" _GDIPlus_Startup() Global Const $sMailSlotName = "\\localuser-PC\mailslot\RandomNameForThisTest" Global $tEncoder = _WinAPI_GUIDFromString(_GDIPlus_EncodersGetCLSID('png')) Global $pEncoder = DllStructGetPtr($tEncoder) Local $iWidth = @DesktopWidth Local $iHeight = @DesktopHeight Local $iX = 0 Local $iY = 0 Global $time = 0 Global $Loops = 10 Global $begin = TimerInit() While 1 $ret = _GetScreenshot($iX, $iY, $iWidth, $iHeight) _MailSlotWrite($sMailSlotName, $ret,0) Switch @error Case 1 MsgBox(48, "MailSlot demo error", "Account that you try to send to likely doesn't exist!") Exit Case 2 MsgBox(48, "MailSlot demo error", "Message is blocked!") Case 3 MsgBox(48, "MailSlot demo error", "Message is send but there is an open handle left." & @CRLF & "That could lead to possible errors in future") Case 4 MsgBox(48, "MailSlot demo error", "All is fucked up!" & @CRLF & "Try debugging MailSlot.au3 functions. Thanks.") Case Else ; MsgBox(64, "MailSlot demo", "Sucessfully sent!") EndSwitch WEnd _GDIPlus_Shutdown() Func _GetScreenshot($iX,$iY, $iWidth, $iHeight) Local $hSrcDC, $hDstDC, $hDstSv, $hBitmap, $hDesktop, $hScreen, $hMemory, $pMemory, $pStream, $tOut, $pOut, $iSize, $pParams=0 $hDesktop = _WinAPI_GetDesktopWindow() $hSrcDC = _WinAPI_GetDC($hDesktop) $hScreen = _WinAPI_CreateCompatibleBitmap($hSrcDC, $iWidth, $iHeight) $hDstDC = _WinAPI_CreateCompatibleDC($hSrcDC) $hDstSv = _WinAPI_SelectObject($hDstDC, $hScreen) _WinAPI_BitBlt($hDstDC, $iX, $iY, $iWidth, $iHeight, $hSrcDC, $iX, $iY, $SRCCOPY) _WinAPI_SelectObject($hDstDC, $hDstSv) _WinAPI_ReleaseDC($hDesktop, $hSrcDC) _WinAPI_DeleteDC($hDstDC) $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hScreen) _WinAPI_DeleteObject($hScreen) $pStream = _WinAPI_CreateStreamOnHGlobal(0) _GDIPlus_SaveImageToStream($hBitmap, $pStream, $pEncoder,$pParams) _GDIPlus_BitmapDispose($hBitmap) $hMemory = _WinAPI_GetHGlobalFromStream($pStream) $pMemory = _MemGlobalLock($hMemory) $iSize = _MemGlobalSize($hMemory) $tOut = DllStructCreate('dword;dword;byte[' & ($iSize - Mod($iSize, 4) + 4) & ']') $pOut = DllStructGetPtr($tOut) DllStructSetData($tOut, 1, DllStructGetSize($tOut)) DllStructSetData($tOut, 2, $iSize) _MemMoveMemory($pMemory, $pOut + 8, $iSize) _WinAPI_ReleaseStream($pStream) Return DllStructGetData(DllStructCreate('byte[' & DllStructGetSize($tOut) & ']', DllStructGetPtr($tOut)), 1) EndFunc Func _GDIPlus_SaveImageToStream($hImage, $pStream, $pEncoder, $pParams) Local $Ret = DllCall($__g_hGDIPDll, 'uint', 'GdipSaveImageToStream', 'ptr', $hImage, 'ptr', $pStream, 'ptr', $pEncoder, 'ptr', $pParams) If (@error) Or ($Ret[0]) Then Return SetError(@error, @extended, 0) EndIf Return 1 EndFunc ;==>_GDIPlus_SaveImageToStream Func _FileSend($sBuff) While BinaryLen($sBuff) $iSendReturn = TCPSend($Socket, $sBuff) If @error Then Return SetError(4, 0, -1) $sBuff = BinaryMid ($sBuff, $iSendReturn + 1, BinaryLen ($sBuff) - $iSendReturn) WEnd Return 1 EndFunc Link to comment Share on other sites More sharing options...
RTFC Posted May 8, 2019 Share Posted May 8, 2019 MailSlot MTU is limited to 65,507 bytes on localhost, and 412 bytes (datagram - 12 bytes header) on LAN. See my Pool environment (link in sig) for more info and some examples how to transfer larger data chunks on LANs. My Contributions and Wrappers Spoiler BitMaskSudokuSolver BuildPartitionTable CodeCrypter CodeScanner DigitalDisplay Eigen4AutoIt FAT Suite HighMem MetaCodeFileLibrary OSgrid Pool RdRand SecondDesktop SimulatedAnnealing Xbase I/O Link to comment Share on other sites More sharing options...
BlackSnoww Posted May 8, 2019 Author Share Posted May 8, 2019 Now thats a lot of code lol Link to comment Share on other sites More sharing options...
BlackSnoww Posted May 22, 2019 Author Share Posted May 22, 2019 @RTFC "by sending larger chunks of data on Lan" what do u mean by this? is it through TCP or MailSlots? Link to comment Share on other sites More sharing options...
RTFC Posted May 22, 2019 Share Posted May 22, 2019 through TCP or UDP My Contributions and Wrappers Spoiler BitMaskSudokuSolver BuildPartitionTable CodeCrypter CodeScanner DigitalDisplay Eigen4AutoIt FAT Suite HighMem MetaCodeFileLibrary OSgrid Pool RdRand SecondDesktop SimulatedAnnealing Xbase I/O Link to comment Share on other sites More sharing options...
BlackSnoww Posted May 22, 2019 Author Share Posted May 22, 2019 oh i figured that one out by making use of a buffer but the sending of data is much slower compared to Mailslots i tried comparing the FPS and the mailslots gave much more smoother results. Link to comment Share on other sites More sharing options...
RTFC Posted May 22, 2019 Share Posted May 22, 2019 You could test UDP; should be faster than TCP because there's no triple handshake, but there's no resend upon packet-loss, so you'd have to check the file integrity at the other end yourself. My Contributions and Wrappers Spoiler BitMaskSudokuSolver BuildPartitionTable CodeCrypter CodeScanner DigitalDisplay Eigen4AutoIt FAT Suite HighMem MetaCodeFileLibrary OSgrid Pool RdRand SecondDesktop SimulatedAnnealing Xbase I/O Link to comment Share on other sites More sharing options...
BlackSnoww Posted May 22, 2019 Author Share Posted May 22, 2019 ill try thanks Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now