Jump to content

MailSlot


trancexx
 Share

Recommended Posts

"...Mailslot messages can be of around 400 bytes only.", please check this link: http://www.codeproject.com/KB/threads/Win32IPC.aspx

"...cannot be larger than 424 bytes when sent between computers.", and this: http://msdn.microsoft.com/en-us/library/aa365130%28v=vs.85%29.aspx

Aha, between computers. You are right then.

edit: seems Melba23 knows something about that, I haven't used this between computers since initial testings when writing it. Frankly, I don't remember having problems.

Edited by trancexx

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

Aha, between computers. You are right then.

edit: seems Melba23 knows something about that, I haven't used this between computers since initial testings when writing it. Frankly, I don't remember having problems.

Yes! (...)To send messages that are larger than 424 bytes between computers, use named pipes instead.

Could you give me an example of using NamedPipes because the AutoIt help file is not in any instance...

Thank you all for attention.

Edit: Using your example, I can not transmit more than 424 bytes (between escrips, not between computers).

Edited by jscript

http://forum.autoitbrasil.com/ (AutoIt v3 Brazil!!!)

Somewhere Out ThereJames Ingram

somewh10.png

dropbo10.pngDownload Dropbox - Simplify your life!
Your virtual HD wherever you go, anywhere!

Link to comment
Share on other sites

  • Moderators

jscript & trancexx,

Sorry, I too missed the "between computers" bit - I have only ever used mailslots on the same machine. :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png 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 columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

jscript & trancexx,

Sorry, I too missed the "between computers" bit - I have only ever used mailslots on the same machine. :)

M23

OK, but using the example of @trancexx, I can not transmit more than 425 bytes!

Edit: in the same computer...

Edited by jscript

http://forum.autoitbrasil.com/ (AutoIt v3 Brazil!!!)

Somewhere Out ThereJames Ingram

somewh10.png

dropbo10.pngDownload Dropbox - Simplify your life!
Your virtual HD wherever you go, anywhere!

Link to comment
Share on other sites

  • Moderators

jscript,

I sent over 1000 bytes between scripts on the same machine without problem earlier today. I did it to test I could before replying to you. :)

I am using trancexx's UDF with the following script (based on her example). Just compile it and then copy and rename it so you can run several differently named instances:

#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6

#include "MailSlot.au3"

Global $sMailSlotListFile = @AppDataCommonDir & "\MailSlot\MailSlotList.lst"
Global $sMailSlotTitle = StringRegExpReplace(@ScriptName, "\..*$", "")
Global $sRandomMailSlotname = _RandomStr()

ConsoleWrite( $sMailSlotListFile  & @CRLF)

Global Const $sMailSlotName_Receive = "\\.\mailslot\" & $sRandomMailSlotname

; Add MailSlot to list file
IniWrite($sMailSlotListFile, "MailSlots", $sMailSlotTitle, $sRandomMailSlotname)

Global $hMailSlot = _MailSlotCreate($sMailSlotName_Receive)
If @error Then
    MsgBox(48, "MailSlot", "Failed to create new account!" & @CRLF & "Probably one using that 'address' already exists.")
    Exit
EndIf

Global $iNumberOfMessagesOverall
Global $sMailSlotName_Send = ""

Global $hGUI = GUICreate($sMailSlotTitle, 450, 400, 3 * @DesktopWidth / 4 - 225, -1, -1, 8) ; $WS_EX_TOPMOST

GUICtrlCreateLabel("Message To Send To:", 10, 22, 150, 25)
GUICtrlSetColor(-1, 0x0000CC)
GUICtrlSetFont(-1, 11)

Global $hSend_Combo = GUICtrlCreateCombo("", 180, 22, 100, 25)
_UpdateMail()

Global $hEdit_Send = GUICtrlCreateEdit("", 15, 50, 300, 50, 0x0040) ; $ES_AUTOVSCROLL

GUICtrlCreateLabel("Message Received:", 10, 122, 150, 25)
GUICtrlSetColor(-1, 0x0000CC)
GUICtrlSetFont(-1, 11)

Global $hEdit_Read = GUICtrlCreateEdit("", 15, 150, 300, 200, 0x0800) ; $ES_READONLY

Global $hButtonSend = GUICtrlCreateButton("&Send Mail", 330, 100, 100, 25)

Global $hButton_Update = GUICtrlCreateButton("&Update Accounts", 330, 50, 100, 25)

Global $hButtonRead = GUICtrlCreateButton("Read &Mail", 330, 150, 100, 25)

Global $hButtonCheckCount = GUICtrlCreateButton("&Check Mail Count", 330, 200, 100, 25)

Global $hButtonCloseAccount = GUICtrlCreateButton("Close Mail &Account", 330, 250, 100, 25)

Global $hButtonRestoreAccount = GUICtrlCreateButton("&Restore Account", 330, 300, 100, 25)

Global $hButtonCloseApp = GUICtrlCreateButton("&Exit", 330, 350, 100, 25)

GUISetState()

While 1

    Switch GUIGetMsg()
        Case - 3, $hButtonCloseApp
            IniDelete($sMailSlotListFile, "MailSlots", $sMailSlotTitle)
            Exit
        Case $hButtonSend
            If GUICtrlRead($hSend_Combo) = "" Then
                MsgBox(64, "MailSlot demo", "No account selected!", 0, $hGUI)
            Else
                $sMailSlotName_Send = "\\.\mailslot\" & IniRead($sMailSlotListFile, "MailSlots", GUICtrlRead($hSend_Combo), "")
                If $sMailSlotName_Send <> "\\.\mailslot\" Then
                    _SendMail($sMailSlotName_Send)
                Else
                    MsgBox(48, "MailSlot demo", "Not valid account!", 0, $hGUI)
                EndIf
            EndIf
        Case $hButton_Update
            _UpdateMail()
        Case $hButtonRead
            If $hMailSlot Then
                _ReadMessage($hMailSlot)
            Else
                MsgBox(48, "MailSlot demo", "No account is available!", 0, $hGUI)
            EndIf
        Case $hButtonCheckCount
            If $hMailSlot Then
                _CheckCount($hMailSlot)
            Else
                MsgBox(48, "MailSlot demo", "No account is available!", 0, $hGUI)
            EndIf
        Case $hButtonCloseAccount
            If $hMailSlot Then
                _CloseMailAccount($hMailSlot)
            Else
                MsgBox(64, "MailSlot demo", "No account is available!", 0, $hGUI)
            EndIf
        Case $hButtonRestoreAccount
            If $hMailSlot Then
                MsgBox(64, "MailSlot demo", "This account already exists!", 0, $hGUI)
            Else
                _RestoreAccount($sMailSlotName_Receive)
            EndIf
    EndSwitch

WEnd


; Wrapper functions:

Func _UpdateMail()

    Local $aMailSlots = IniReadSection($sMailSlotListFile, "MailSlots")

    If Not IsArray($aMailSlots) Then MsgBox(64, "MailSlot demo", "No accounts available!", 0, $hGUI)

    Local $sMailSlotList = "|"
    For $i = 1 To $aMailSlots[0][0]
        If $aMailSlots[$i][1] <> $sRandomMailSlotname Then $sMailSlotList &= $aMailSlots[$i][0] & "|"
    Next
    GUICtrlSetData($hSend_Combo, $sMailSlotList)

EndFunc

Func _SendMail($sMailSlotName)

    Local $sDataToSend = GUICtrlRead($hEdit_Send)

    If $sDataToSend Then
        _MailSlotWrite($sMailSlotName, $sDataToSend);, 1)
        Switch @error
            Case 1
                MsgBox(48, "MailSlot demo error", "Account that you try to send to likely doesn't exist!", 0, $hGUI)
            Case 2
                MsgBox(48, "MailSlot demo error", "Message is blocked!", 0, $hGUI)
            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", 0, $hGUI)
            Case 4
                MsgBox(48, "MailSlot demo error", "All is fucked up!" & @CRLF & "Try debugging MailSlot.au3 functions. Thanks.", 0, $hGUI)
            Case Else
                MsgBox(64, "MailSlot demo", "Sucessfully sent!", 0, $hGUI)
        EndSwitch
        GUICtrlSetData($hEdit_Send, "")
    Else
        MsgBox(64, "MailSlot demo", "Nothing to send.", 0, $hGUI)
    EndIf

EndFunc   ;==>_SendMail

Func _ReadMessage($hHandle)

    Local $iSize = _MailSlotCheckForNextMessage($hHandle)

    If $iSize Then
        Local $sData = _MailSlotRead($hMailSlot, $iSize, 1)
        $iNumberOfMessagesOverall += 1
        GUICtrlSetData($hEdit_Read, "Message No" & $iNumberOfMessagesOverall & " , Size = " & $iSize & " :" & @CRLF & @CRLF & $sData)
    Else
        MsgBox(64, "Nothing read", "MailSlot is empty", 0, $hGUI)
    EndIf

EndFunc   ;==>_ReadMessage


Func _CheckCount($hHandle)

    Local $iCount = _MailSlotGetMessageCount($hHandle)
    Switch $iCount
        Case 0
            MsgBox(64, "Messages", "No new messages", 0, $hGUI)
        Case 1
            MsgBox(64, "Messages", "There is 1 message waiting to be read.", 0, $hGUI)
        Case Else
            MsgBox(64, "Messages", "There are " & $iCount & " messages waiting to be read.", 0, $hGUI)
    EndSwitch

EndFunc   ;==>_CheckCount


Func _CloseMailAccount(ByRef $hHandle)

    If _MailSlotClose($hHandle) Then
        $hHandle = 0
        MsgBox(64, "MailSlot demo", "Account succesfully closed.", 0, $hGUI)
        IniDelete($sMailSlotListFile, "MailSlots", $sMailSlotTitle)
    Else
        MsgBox(48, "MailSlot demo error", "Account could not be closed!", 0, $hGUI)
    EndIf

EndFunc   ;==>_CloseMailAccount


Func _RestoreAccount($sMailSlotName_Receive)

    Local $hMailSlotHandle = _MailSlotCreate($sMailSlotName_Receive)

    If @error Then
        MsgBox(48, "MailSlot demo error", "Account could not be created!", 0, $hGUI)
    Else
        MsgBox(64, "MailSlot demo", "New account with the same address successfully created!", 2, $hGUI)
        $hMailSlot = $hMailSlotHandle ; global var
        IniWrite($sMailSlotListFile, "MailSlots", $sMailSlotTitle, $sRandomMailSlotname)
    EndIf

EndFunc   ;==>_RestoreAccount

Func _RandomStr()
    Local $sString
    For $i = 1 To 13
        $sString &= Chr(Random(97, 122, 1))
    Next
    Return $sString
EndFunc   ;==>__RandomStr

You need to press the "Update Accounts" button on the earlier instances when you have all of them running so the earlier ones realise the later ones have come along - otherwise your addess list is not complete. The same is true if you close and restore an account. :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png 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 columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

jscript,

I sent over 1000 bytes between scripts on the same machine without problem earlier today. I did it to test I could before replying to you. :)

I am using trancexx's UDF with the following script (based on her example). Just compile it and then copy and rename it so you can run several differently named instances:

(...)

M23

Yes, it works on the same computer. But between computers 425 bytes.

NamedPipes there is no such limit, but do not know how to use it because in the AutoIt help file does not exist examples...

Could you give me an example using NamedPipes?

Because that way I would let the use TCP protocol to a communication program between computers on same network.

Thank you for your attention.

http://forum.autoitbrasil.com/ (AutoIt v3 Brazil!!!)

Somewhere Out ThereJames Ingram

somewh10.png

dropbo10.pngDownload Dropbox - Simplify your life!
Your virtual HD wherever you go, anywhere!

Link to comment
Share on other sites

  • Moderators

jscript,

Could you give me an example using NamedPipes?

Sorry, I have never used them and there is precious little when you search the forum. :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png 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 columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

@Melba23,

No problem...

@trancexx,

Yes, to circumvent this limitation, I'm using the following code below:

Local $iSize = Int(StringLen($sDataToSend) / 420)
For $i = 0 To $iSize
    _MailSlotWrite($sMailSlotName, StringMid($sDataToSend, $i * 420 + 1, 420))
Next
;_MailSlotWrite($sMailSlotName, $sDataToSend);, 1)

But I will try to use NamedPipes because I do not need this modification to transmit more than 425 bytes...

Thank you for your attention.

http://forum.autoitbrasil.com/ (AutoIt v3 Brazil!!!)

Somewhere Out ThereJames Ingram

somewh10.png

dropbo10.pngDownload Dropbox - Simplify your life!
Your virtual HD wherever you go, anywhere!

Link to comment
Share on other sites

  • 1 month later...

Hi trancexx,

I want to know that how can I use the mailslots in multiple sessions ?

I mean, I created a Slot in "System Account" and when my user mode app in "Administrator/Limited Account" try to open the handle of Service Slot, it will give "Access is Denied" (by GetLastErrorMessage ).

Edited by Digisoul

73 108 111 118 101 65 117 116 111 105 116

Link to comment
Share on other sites

Hi trancexx,

I want to know that how can I use the mailslots in multiple sessions ?

I mean, I created a Slot in "System Account" and when my user mode app in "Administrator/Limited Account" try to open the handle of Service Slot, it will give "Access is Denied" (by GetLastErrorMessage ).

Why you run a program in "System Account"? Your intentions are good?

http://forum.autoitbrasil.com/ (AutoIt v3 Brazil!!!)

Somewhere Out ThereJames Ingram

somewh10.png

dropbo10.pngDownload Dropbox - Simplify your life!
Your virtual HD wherever you go, anywhere!

Link to comment
Share on other sites

Why you run a program in "System Account"? Your intentions are good?

Yes! as a service process. I am using service for Service Control notifications and my application is a multi user and a security app (for USB Devices).

I found the problem, why its not working; I need to set the lpSecurityDescriptor but i am unable to understand it.

Edited by Digisoul

73 108 111 118 101 65 117 116 111 105 116

Link to comment
Share on other sites

Hi trancexx,

I want to know that how can I use the mailslots in multiple sessions ?

I mean, I created a Slot in "System Account" and when my user mode app in "Administrator/Limited Account" try to open the handle of Service Slot, it will give "Access is Denied" (by GetLastErrorMessage ).

I found the solution Posted Image

Here is a function; If any body have a same problem (Its already exists in Misc.au3 as _Singleton Posted Image)

; Author ........: Valik
Func GetSecurity(ByRef $structSecurityDescriptor)
    Local Const $ERROR_ALREADY_EXISTS = 183
    Local Const $SECURITY_DESCRIPTOR_REVISION = 1
    Local $handle, $lastError, $pSecurityAttributes = 0

    ; The size of SECURITY_DESCRIPTOR is 20 bytes.  We just
    ; need a block of memory the right size, we aren't going to
    ; access any members directly so it's not important what
    ; the members are, just that the total size is correct.
    $structSecurityDescriptor = DllStructCreate("dword[5]")
    Local $pSecurityDescriptor = DllStructGetPtr($structSecurityDescriptor)
    ; Initialize the security descriptor.
    Local $aRet = DllCall("advapi32.dll", "int", "InitializeSecurityDescriptor", _
            "ptr", $pSecurityDescriptor, "dword", $SECURITY_DESCRIPTOR_REVISION)
    If Not @error And $aRet[0] Then
        ; Add the NULL DACL specifying access to everybody.
        $aRet = DllCall("advapi32.dll", "int", "SetSecurityDescriptorDacl", _
                "ptr", $pSecurityDescriptor, "int", 1, "ptr", 0, "int", 0)
        If Not @error And $aRet[0] Then
            ; Create a SECURITY_ATTRIBUTES structure.
            Local $structSecurityAttributes = DllStructCreate("dword;ptr;int")
            ; Assign the members.
            DllStructSetData($structSecurityAttributes, 1, DllStructGetSize($structSecurityAttributes))
            DllStructSetData($structSecurityAttributes, 2, $pSecurityDescriptor)
            DllStructSetData($structSecurityAttributes, 3, 0)
            ; Everything went okay so update our pointer to point to our structure.
            $pSecurityAttributes = DllStructGetPtr($structSecurityAttributes)
            Return SetError(0, 0, $pSecurityAttributes)
        Else
            Return SetError(2)
        EndIf
    Else
        Return SetError(1)
    EndIf
EndFunc   ;==>GetSecurity

73 108 111 118 101 65 117 116 111 105 116

Link to comment
Share on other sites

  • 3 months later...

I know this is old, but I wanted to say how awesome this UDF is. Thank you. I wrote a script that does a lot of processing of the same rules against data. I am able to 10x the speed simply by spinning off 10 processes, each with their own mailslot. I think scan the slots and simply send a chunk of data when a slot is available. If I want to improve performance further, I simply scale up the processes (takes more memory, sure). Great work on this. If anyone is interested in IPC in AutoIt, this is a great way.

Link to comment
Share on other sites

  • 2 years later...

Will this work between an auto-it script running as a system service, and an auto-it running under the local user?

I am finding that the service is able to create a mail slot, send a message to it, and retrieve messages from it.

However, the auto-it running under the logged in user process is not able to send a message to that mail slot.   It throws an @error "1".

Possibly some kind of permissions issue?   

Is there something I can do, or some other option to allow communication between these two auto-its (service / user)?

Link to comment
Share on other sites

Security attributes parameter for CreateMailslot function needs adjusted for that.

It's rather simple task, so google a bit, it's been explained many times.

 

Um, if you could spare a few moments to point me at something, it would be greatly appreciated - I already did spend some time searching and I cant find anything.

Link to comment
Share on other sites

  • 1 year later...
  • 3 years later...

I know this is pretty old now but i was trying to get comms accross local system, admin and limited users for months in windows 10 and was just not having any luck with anything at all.

ended up finding this solution, CreateFileW kernel32 dll call to create the handle to write the message in mailslot.au3 had to be changed because it still worked between admin and another limited user as it was, but not from local system to any other user.

had to change the file attributes to normal instead of the original flag $SECURITY_ANONYMOUS. see below

only after this would the security attributes pointer used to create the mailslot actually take affect on the system account.

 

Func _MailSlotWrite($sMailSlotName, $vData, $iMode = 0)

    Local $aCall = DllCall("kernel32.dll", "ptr", "CreateFileW", _
            "wstr", $sMailSlotName, _
            "dword", 0x40000000, _ ; GENERIC_WRITE
            "dword", 1, _ ; FILE_SHARE_READ
            "ptr", 0, _  ; lp security attributes (ignored on open existing)
            "dword", 3, _ ; OPEN_EXISTING
            "dword", 128, _ ; 0, _ ; SECURITY_ANONYMOUS  replaced with file attribute normal 128
            "ptr", 0)
            
            
            ; .........

above now works when creating the mailslot with a security pointer which i have used permissions.au3 udf to create, shown below.

#include "MailSlot.au3"

#include <Permissions.au3>

Global Const $sMailSlotName = "\\.\mailslot\SampleCrossSessonMailslot"
Global $ptrSecurityDescriptor = _ConvertStringSecurityDescriptorToSecurityDescriptor("O:BAD:(A;OICI;GRGW;;;AU)(A;OICI;GA;;;BA)(A;OICI;GA;;;SY)")
    If @error Then
        Global $aError = DllCall("kernel32.dll", "dword", "GetLastError")
        if not @Compiled Then ConsoleWrite("err: " & $aError[0] & @CR)
    EndIf
    Global $tSecurityAttributes = DllStructCreate("dword Length;ptr Descriptor;bool InheritHandle")
    DllStructSetData($tSecurityAttributes, 1, DllStructGetSize($tSecurityAttributes))
    DllStructSetData($tSecurityAttributes, 2, DllStructGetPtr($ptrSecurityDescriptor))
    DllStructSetData($tSecurityAttributes, 3, 0) ; InheritHandle = FALSE
Global $hMailSlot = _MailSlotCreate($sMailSlotName,0,0,$tSecurityAttributes)

 

 

hopefully this saves someone else from banging their head against the wall.

 

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...