Как я могу установить сетевое соединение с Visual Basic из Microsoft Access? - PullRequest
2 голосов
/ 24 июля 2009

У нас есть приложение Visual Basic внутри Microsoft Access, и нам нужно установить сетевое соединение. В VB6 был небольшой удобный элемент управления, называемый WinSock, который сделал это возможным, но я не могу найти ничего похожего для урезанной версии VB, существующей в Microsoft Access. Есть идеи?

Поскольку я не получаю никаких ответов, я попытаюсь уточнить, для чего мне это нужно.

Мое приложение отправляет электронное письмо, и в настоящее время мы используемвстроенный объект Outlook для создания сообщения и отправки его в фоновом режиме. Недостатком является то, что он предлагает пользователю утвердить «внешнюю программу» для отправки электронного письма, что расстраивает наших пользователей и кажется ненужным. Все остальные варианты электронной почты, которые я смог найти в Интернете, требуют от нас либо загрузки, либо покупки элемента управления, который будет слишком трудоемким для развертывания для всех наших пользователей.

Я надеялсяиспользуйте элемент управления сокетом, чтобы вручную подключиться к SMTP-серверу и отправить сообщение (поскольку на других языках это тривиально), но я не могу найти способ установить TCP-соединение в VBA.

Ответы [ 3 ]

1 голос
/ 08 августа 2009

Я только что имел дело с этой самой проблемой в прошлом месяце. По разным причинам CDO было неадекватным, прямое использование MAPI слишком сложным, и Outlook подсказывает, что вы жалуетесь на совершенно неприемлемое.

В итоге я использовал Outlook Redemption . Он широко используется разработчиками Access, хотя я нашел его довольно запутанным и не очень хорошо документированным. Но он хорошо справляется со своей работой.

0 голосов
/ 13 мая 2016

Для конкретной проблемы, упомянутой в ОП, есть лучшее решение. «сохранить» почту в Outlook. Не «отправляйте» это. Он дает пользователю явный контроль над тем, что отправляется, и когда, и не генерирует всплывающие диалоги. Тройной выигрыш.

Но так как вы спрашиваете ....

Option Explicit

Public Const AF_INET = 2 'internetwork: UDP, TCP, etc.
Public Const SOCK_STREAM = 1 'Stream socket
Public Const SOCKET_ERROR = -1

Type sockaddr_in
    sin_family As Integer
    sin_port As Integer
    sin_addr As Long
    sin_zero As String * 8
End Type

#If Win32 Then

'for WSAStartup() function.
Public Const WSADESCRIPTION_LEN = 256
Public Const WSASYS_STATUS_LEN = 128
Public Const WSA_DescriptionSize = WSADESCRIPTION_LEN + 1
Public Const WSA_SysStatusSize = WSASYS_STATUS_LEN + 1

Type wsaData
    wVersion As Integer
    wHighVersion As Integer
    szDescription As String * WSA_DescriptionSize
    szSystemStatus As String * WSA_SysStatusSize
    iMaxSockets As Integer
    iMaxUdpDg As Integer
    lpVendorInfo As String * 200
End Type

#If Not VBA7 Then
'Use this section for Excel 95
Type Hostent
    h_name As Long          '32 bit pointer
    h_aliases As Long       '32 bit pointer
    h_addrtype As Integer   'String * 2 (declared as short)
    h_length As Integer     'String * 2 (declared as short)
    h_addr_list As Long     '32 bit pointer
End Type

Public Declare Function closesocket Lib "ws2_32.dll" (ByVal s As Long) As Long
Public Declare Function connect Lib "ws2_32.dll" (ByVal sID As Long, ByRef name As sockaddr_in, ByVal namelen As Long) As Long
Public Declare Function htons Lib "ws2_32.dll" (ByVal hostshort As Integer) As Integer
Public Declare Function inet_addr Lib "ws2_32.dll" (ByVal cp As String) As Long
Public Declare Function recv Lib "ws2_32.dll" (ByVal s As Long, ByRef buf As Any, ByVal buflen As Long, ByVal flags As Long) As Long
Public Declare Function recvstr Lib "ws2_32.dll" (ByVal s As Long, ByVal buf As Any, ByVal buflen As Long, ByVal flags As Long) As Long
Public Declare Function send Lib "ws2_32.dll" (ByVal s As Long, ByRef buf As Any, ByVal buflen As Long, ByVal flags As Long) As Long
Public Declare Function socket Lib "ws2_32.dll" (ByVal af As Long, ByVal s_type As Long, ByVal Protocol As Long) As Long
Public Declare Function WSAStartup Lib "ws2_32.dll" (wVersionRequested As Integer, lpWSAData As wsaData) As Long
Public Declare Function WSACleanup Lib "ws2_32.dll" () As Long

'Public Declare Function setsockopt Lib "ws2_32.dll" (ByVal s As Long, ByVal level As Long, ByVal optname As Long, optval As Any, ByVal optlen As Long) As Long
Public Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
Public Declare Function gethostbyname Lib "ws2_32.dll" (ByVal host_name As String) As Long

#Else
'on Win64, ws2_32.dll in system32 has the file description "32-bit DLL" and uses 64bit pointers (morons)
'on Win64 as on Win32, 32-bit numbers are called int.
'on VBA7/64, as on VBA6/32, 32 bit numbers are called long.
'delete following duplicate section for Excel 95

Type Hostent
    h_name As LongPtr       '32/64 bit pointer
    h_aliases As LongPtr    '32/64 bit pointer
    h_addrtype As Integer   'String * 2 (declared as short)
    h_length As Integer     'String * 2 (declared as short)
    h_addr_list As LongPtr  '32/64 bit pointer
End Type


Public Declare PtrSafe Function closesocket Lib "ws2_32.dll" (ByVal sID As LongPtr) As Long
Public Declare PtrSafe Function connect Lib "ws2_32.dll" (ByVal sID As LongPtr, ByRef name As sockaddr_in, ByVal namelen As Long) As Long
Public Declare PtrSafe Function htons Lib "ws2_32.dll" (ByVal hostshort As Integer) As Integer
Public Declare PtrSafe Function inet_addr Lib "ws2_32.dll" (ByVal cp As String) As Long
Public Declare PtrSafe Function recv Lib "ws2_32.dll" (ByVal sID As LongPtr, ByRef buf As Any, ByVal buflen As Long, ByVal flags As Long) As Long
Public Declare PtrSafe Function recvstr Lib "ws2_32.dll" (ByVal sID As LongPtr, ByVal buf As Any, ByVal buflen As Long, ByVal flags As Long) As Long
Public Declare PtrSafe Function send Lib "ws2_32.dll" (ByVal sID As LongPtr, ByRef buf As Any, ByVal buflen As Long, ByVal flags As Long) As Long
Public Declare PtrSafe Function socket Lib "ws2_32.dll" (ByVal af As Long, ByVal s_type As Long, ByVal Protocol As Long) As Long
Public Declare PtrSafe Function WSAStartup Lib "ws2_32.dll" (wVersionRequested As Integer, lpWSAData As wsaData) As Long
Public Declare PtrSafe Function WSACleanup Lib "ws2_32.dll" () As Long

'Public Declare PtrSafe Function setsockopt Lib "ws2_32.dll" (ByVal sID As Long, ByVal level As LongPtr, ByVal optname As Long, optval As Any, ByVal optlen As Long) As Long
Public Declare PtrSafe Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As LongPtr)
Public Declare PtrSafe Function gethostbyname Lib "ws2_32.dll" (ByVal host_name As String) As LongPtr


#End If
#Else
'OSX
'delete following duplicate section for Excel 95
'No 64bit version of Excel is available yet for the OSX
Type Hostent
    h_name As Long      '32 bit pointer
    h_aliases As Long   '32 bit pointer
    h_addrtype As Long  '32 bit int (declared as int)
    h_length As Long    '32 bit int (declared as int)
    h_addr_list As Long '32 bit pointer
End Type

'ssize_t is a signed type. signed version of size_t,
'used where a size may instead contain a negative error code
'size_t is the unsigned integer type of the result of the sizeof operator
'size_t is an unsigned integer type of at least 16 bit

'or libsystem.dylib ?
Public Declare Function socket Lib "libc.dylib" (ByVal af As Long, ByVal s_type As Long, ByVal Protocol As Long) As Long
Public Declare Function connect Lib "libc.dylib" (ByVal s As Long, ByRef name As sockaddr_in, ByVal namelen As Long) As Long
' or read ?
Public Declare Function recv Lib "libc.dylib" (ByVal s As Long, buf As   Any, ByVal buflen As Long, ByVal flags As Long) As Long
Public Declare Function send Lib "libc.dylib" (ByVal s As Long, buf As Any, ByVal buflen As Long, ByVal flags As Long) As Long
Public Declare Function htons Lib "libc.dylib" (ByVal Host_Short As Integer) As Integer 'x x x, but seems to work !!!
Public Declare Function inet_addr Lib "libc.dylib" (ByVal cp As String) As Long
Public Declare Function closesocket Lib "libc.dylib" Alias "close" (ByVal s As Long) As Long
Public Declare Function setsockopt Lib "libc.dylib" (ByVal s As Long, ByVal level As Long, ByVal optname As Long, optval As Any, ByVal optlen As Long) As Long
Public Declare Function gethostbyname Lib "libc.dylib" (ByVal host_name As String) As Long
Public Declare Sub CopyMemory Lib "libc.dylib" Alias "memmove" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)

#End If

Private Function MyData(I_SocketAddress As sockaddr_in, Register As Integer, dataword As Long, serr As String) As Long
Dim strSend     As String
Dim count       As Integer
Dim bArray()    As Byte
Dim errCode     As Integer
Dim socketID    As Long

socketID = socket(AF_INET, SOCK_STREAM, 0)
errCode = connect(socketID, I_SocketAddress, Len(I_SocketAddress))

count = send(socketID, ByVal strSend, Len(strSend), 0)

If count <> Len(strSend) Then
    errCode = -1
    serr = "ERROR: network failure on send, " & Err.LastDllError()
Else
    count = RecvB(socketID, bArray, maxLength)

    dodata bArray
End If
    DoEvents
    Call closesocket(socketID)
    MyData = errCode
End Function

Private Function RecvB(socketID As Long, bArray() As Byte, ByVal maxLength As Integer) As Integer
Dim c As String * 1
Dim b           As Byte
Dim buf()       As Byte
Dim Length      As Integer
Dim count       As Long
Dim i           As Integer
Dim dStartTime  As Variant
Dim nErr        As Long

Const iFlags = 0

ReDim bArray(1 To maxLength)
ReDim buf(1 To maxLength)

dStartTime = Time
While (Length < maxLength) And (4 > DateDiff("s", dStartTime, Time))
    DoEvents
    count = recv(socketID, buf(1), maxLength, iFlags)

    If count = SOCKET_ERROR Then '-1
        nErr = Err.LastDllError()
        If nErr = 0 Then
            RecvB = -1
        Else
            RecvB = -nErr
        End If
        'Debug.Print "socket_error in RecvB. lastdllerror:", nErr
        Exit Function '
    End If '
    For i = 1 To count
        bArray(Length + i) = buf(i)
    Next
    Length = Length + count
Wend
RecvB = Length

End Function

Это код TCP, а не код электронной почты. Он также включает в себя код OSX VBA TCP, который я ранее не публиковал.

0 голосов
/ 24 июля 2009

Функция безопасности электронной почты, добавленная Microsoft, разочаровала многих разработчиков. Я не знаю элегантного решения. Я успешно использовал бесплатное приложение ClickYes Express, но, конечно, это не тот ответ, который вы ищете.

...