Windows Office 2010中的VBA套接字连接
简短问题Windows Office 2010中的VBA套接字连接,windows,sockets,vba,windows-7,visio,Windows,Sockets,Vba,Windows 7,Visio,简短问题 是否有一个库可以取代用于在VBA应用程序中创建和维护套接字连接的mswinsoc.osx 背景 我正在尝试在Visio 2010 Professional文档中创建套接字连接。我找到了一种在Windows 7上注册mswinsoc.osx的方法,但这似乎很奇怪,因为微软放弃了一个用于建立套接字连接的库,而没有(更好的)替换它。让我更担心的是,使用Office 2010的Winsoc库的例子很少甚至没有。我不支持旧文档,所以Winsoc不是一个要求;这只是我知道会有用的秘密 其他想法 我
是否有一个库可以取代用于在VBA应用程序中创建和维护套接字连接的mswinsoc.osx 背景
我正在尝试在Visio 2010 Professional文档中创建套接字连接。我找到了一种在Windows 7上注册mswinsoc.osx的方法,但这似乎很奇怪,因为微软放弃了一个用于建立套接字连接的库,而没有(更好的)替换它。让我更担心的是,使用Office 2010的Winsoc库的例子很少甚至没有。我不支持旧文档,所以Winsoc不是一个要求;这只是我知道会有用的秘密 其他想法
我为Visio找到了一些非常有用的VBA内容,使我相信应该有一个新的解决方案
任何Office 2010的套接字连接示例或了解mswinsoc.osx发生了什么都会有很大帮助 简短回答
附加信息
我在C和VB中找到了一些使用此DLL的详细示例。
到目前为止,由于我的项目范围发生了变化,我还没有机会在VBA中运行任何示例。相反,我使用Python通过连接控制Visio,取得了巨大成功 我制作了vba登录客户端(ws2_32.dll)示例 它可能工作得很好(我测试过) ServerMain.c
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "16001"
static char LoginCheck(char * recvbuf);
int main(void)
{
WSADATA wsaData;
int iResult;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int iSendResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
char sendbuf[DEFAULT_BUFLEN];
int sendbuflen = DEFAULT_BUFLEN;
printf("Excel Login Server Start..\n");
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
// Setup the TCP listening socket
iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
printf("Server Is running at port %s\n", DEFAULT_PORT);
while(1) {
// Accept a client socket
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
//closesocket(ListenSocket);
//WSACleanup();
//return 1;
}
// recieve data from client
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
recvbuf[iResult] = '\0';
printf("Recieved string : %s\n", recvbuf);
// id, pw check
sendbuf[0] = LoginCheck(recvbuf); //success code
sendbuf[1] = '\0';
// Echo the buffer back to the sender
iSendResult = send(ClientSocket, sendbuf, 1, 0);
if (iSendResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
//closesocket(ClientSocket);
//WSACleanup();
//return 1;
}
printf("Bytes sent: %d\n", iSendResult);
}
else if (iResult == 0)
printf("Connection closing...\n");
else {
printf("recv failed with error: %d\n", WSAGetLastError());
//closesocket(ClientSocket);
//WSACleanup();
//return 1;
}
Sleep(10);
}
// No longer need server socket
closesocket(ListenSocket);
// shutdown the connection since we're done
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
// cleanup
closesocket(ClientSocket);
WSACleanup();
return 0;
}
// check if login info correct (input : "id"|"pw")
static char LoginCheck(char * recvbuf)
{
char *id, *pw;
if (!recvbuf | !recvbuf[0])
return 0;
// temp id, pw info (later, may use db info)
id = strtok(recvbuf, "|");
if (!id)
return 0;
if (strcmp(id, "testid"))
return 0;
pw = strtok(NULL, "|");
if (!pw)
return 0;
if (strcmp(pw, "testpw"))
return 0;
return 's'; //success
}
#未定义UNICODE
#定义WIN32_精益_和_平均值
#包括
#包括
#包括
#包括
#包括
//需要链接到Ws2_32.lib
#pragma注释(lib,“Ws2_32.lib”)
#定义默认值\u BUFLEN 512
#定义默认_端口“16001”
静态字符登录检查(char*recvbuf);
内部主(空)
{
WSADATA WSADATA;
国际结果;
套接字ListenSocket=无效的\u套接字;
套接字ClientSocket=无效的\u套接字;
struct addrinfo*result=NULL;
结构addrinfo提示;
int iSendResult;
char recvbuf[默认值];
int recvbuflen=默认值;
char sendbuf[默认值];
int sendbuflen=默认值;
printf(“Excel登录服务器启动..\n”);
//初始化Winsock
iResult=WSAStartup(MAKEWORD(2,2)和wsaData);
如果(iResult!=0){
printf(“WSAStartup失败,错误:%d\n”,iResult);
返回1;
}
零内存(&提示,sizeof(提示));
hits.ai_family=AF_INET;
hits.ai_socktype=SOCK_流;
hits.ai_protocol=IPPROTO_TCP;
hits.ai_flags=ai_被动;
//解析服务器地址和端口
iResult=getaddrinfo(NULL、默认端口、提示和结果);
如果(iResult!=0){
printf(“getaddrinfo失败,错误:%d\n”,iResult);
WSACleanup();
返回1;
}
//创建用于连接到服务器的套接字
ListenSocket=socket(结果->ai_族,结果->ai_socktype,结果->ai_协议);
if(ListenSocket==无效的_套接字){
printf(“套接字失败,错误:%ld\n”,WSAGetLastError());
freeaddrinfo(结果);
WSACleanup();
返回1;
}
//设置TCP侦听套接字
iResult=bind(ListenSocket,result->ai_addr,(int)result->ai_addrlen);
if(iResult==SOCKET\u错误){
printf(“绑定失败,错误:%d\n”,WSAGetLastError());
freeaddrinfo(结果);
闭合插座(ListenSocket);
WSACleanup();
返回1;
}
freeaddrinfo(结果);
iResult=侦听(ListenSocket,SOMAXCONN);
if(iResult==SOCKET\u错误){
printf(“侦听失败,错误为:%d\n”,WSAGetLastError());
闭合插座(ListenSocket);
WSACleanup();
返回1;
}
printf(“服务器正在端口%s\n上运行”,默认为\u端口);
而(1){
//接受客户端套接字
ClientSocket=accept(ListenSocket,NULL,NULL);
if(ClientSocket==无效的_SOCKET){
printf(“接受失败,错误:%d\n”,WSAGetLastError());
//闭合插座(ListenSocket);
//WSACleanup();
//返回1;
}
//从客户端接收数据
iResult=recv(ClientSocket,recvbuf,recvbuflen,0);
如果(iResult>0){
printf(“收到的字节数:%d\n”,iResult);
recvbuf[iResult]='\0';
printf(“收到的字符串:%s\n”,recvbuf);
//id,pw检查
sendbuf[0]=登录检查(recvbuf);//成功代码
sendbuf[1]='\0';
//将缓冲区回显给发送方
iSendResult=send(ClientSocket,sendbuf,1,0);
if(iSendResult==套接字错误){
printf(“发送失败,错误:%d\n”,WSAGetLastError());
//闭合插座(ClientSocket);
//WSACleanup();
//返回1;
}
printf(“发送的字节数:%d\n”,iSendResult);
}
else if(iResult==0)
printf(“连接关闭…\n”);
否则{
printf(“recv失败,错误:%d\n”,WSAGetLastError());
//闭合插座(ClientSocket);
//WSACleanup();
//返回1;
}
睡眠(10);
}
//不再需要服务器套接字
闭合插座(ListenSocket);
//完成后关闭连接
iResult=关机(客户端套接字,SD\U发送);
if(iResult==SOCKET\u错误){
printf(“关闭失败,错误:%d\n”,WSAGetLastError());
闭合插座(ClientSocket);
WSACleanup();
返回1;
}
//清理
闭合插座(ClientSocket);
WSACleanup();
返回0;
}
//检查登录信息是否正确(输入:“id”|“pw”)
静态字符登录检查(char*recvbuf)
{
字符*id,*pw;
如果(!recvbuf |!recvbuf[0])
返回0;
//临时id,pw信息(稍后可能使用db信息)
id=strtok(recvbuf,“|”);
如果(!id)
返回0;
if(strcmp(id,“testid”))
返回0;
pw=strtok(空,“|”);
'
' reference site https://stackoverflow.com/questions/49028281/vba-with-winsock2-send-sends-wrong-data
' edited by robotmanya (2018.10.28) (https://blog.naver.com/monkey5255/221386590654)
' Constants ----------------------------------------------------------
Const ip = "127.0.0.1"
Const port = "16001"
Const INVALID_SOCKET = -1
Const WSADESCRIPTION_LEN = 256
Const SOCKET_ERROR = -1
Const SD_SEND = 1
' Typ definitions ----------------------------------------------------
Private Type WSADATA
wVersion As Integer
wHighVersion As Integer
szDescription(0 To WSADESCRIPTION_LEN) As Byte
szSystemStatus(0 To WSADESCRIPTION_LEN) As Byte
iMaxSockets As Integer
iMaxUdpDg As Integer
lpVendorInfo As Long
End Type
Private Type ADDRINFO
ai_flags As Long
ai_family As Long
ai_socktype As Long
ai_protocol As Long
ai_addrlen As Long
ai_canonName As LongPtr 'strptr
ai_addr As LongPtr 'p sockaddr
ai_next As LongPtr 'p addrinfo
End Type
' Enums ---------------------------------------------------------------
Enum AF
AF_UNSPEC = 0
AF_INET = 2
AF_IPX = 6
AF_APPLETALK = 16
AF_NETBIOS = 17
AF_INET6 = 23
AF_IRDA = 26
AF_BTH = 32
End Enum
Enum sock_type
SOCK_STREAM = 1
SOCK_DGRAM = 2
SOCK_RAW = 3
SOCK_RDM = 4
SOCK_SEQPACKET = 5
End Enum
' External functions --------------------------------------------------
Public Declare Function WSAStartup Lib "ws2_32.dll" (ByVal wVersionRequested As Integer, ByRef data As WSADATA) As Long
Public Declare Function connect Lib "ws2_32.dll" (ByVal socket As Long, ByVal SOCKADDR As Long, ByVal namelen As Long) As Long
Public Declare Sub WSACleanup Lib "ws2_32.dll" ()
Private Declare PtrSafe Function GetAddrInfo Lib "ws2_32.dll" Alias "getaddrinfo" (ByVal NodeName As String, ByVal ServName As String, ByVal lpHints As LongPtr, lpResult As LongPtr) As Long
Public Declare Function ws_socket Lib "ws2_32.dll" Alias "socket" (ByVal AF As Long, ByVal stype As Long, ByVal Protocol As Long) As Long
Public Declare Function closesocket Lib "ws2_32.dll" (ByVal socket As Long) As Long
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal length As Long)
Public Declare Function Send Lib "ws2_32.dll" Alias "send" (ByVal s As Long, ByVal buf As String, ByVal buflen As Long, ByVal flags As Long) As Long
Public Declare Function Recv Lib "ws2_32.dll" Alias "recv" (ByVal s As Long, ByRef buf As Byte, ByVal buflen As Long, ByVal flags As Long) As Long
Public Declare Function SendWithPtr Lib "ws2_32.dll" Alias "send" (ByVal s As Long, ByVal bufPtr As Long, ByVal buflen As Long, ByVal flags As Long) As Long
Public Declare Function shutdown Lib "ws2_32.dll" (ByVal s As Long, ByVal how As Long) As Long
Private Declare PtrSafe Function WSAGetLastError Lib "ws2_32.dll" () As Long
Private Declare Function VarPtrArray Lib "VBE7" Alias "VarPtr" (var() As Any) As Long
'Login Button Click Event
Function Login(ID As String, pw As String)
Dim m_wsaData As WSADATA
Dim m_RetVal As Integer
Dim m_Hints As ADDRINFO
Dim m_ConnSocket As Long: m_ConnSocket = INVALID_SOCKET
Dim pAddrInfo As LongPtr
Dim RetVal As Long
Dim lastError As Long
Dim iRC As Long
Dim MAX_BUF_SIZE As Integer: MAX_BUF_SIZE = 512
Login = 0
'Socket Settings
RetVal = WSAStartup(MAKEWORD(2, 2), m_wsaData)
If (RetVal <> 0) Then
LogError "WSAStartup failed with error " & RetVal, WSAGetLastError()
Call WSACleanup
Exit Function
End If
m_Hints.ai_family = AF.AF_UNSPEC
m_Hints.ai_socktype = sock_type.SOCK_STREAM
RetVal = GetAddrInfo(ip, port, VarPtr(m_Hints), pAddrInfo)
If (RetVal <> 0) Then
LogError "Cannot resolve address " & ip & " and port " & port & ", error " & RetVal, WSAGetLastError()
Call WSACleanup
Exit Function
End If
m_Hints.ai_next = pAddrInfo
Dim connected As Boolean: connected = False
Do While m_Hints.ai_next > 0
CopyMemory m_Hints, ByVal m_Hints.ai_next, LenB(m_Hints)
m_ConnSocket = ws_socket(m_Hints.ai_family, m_Hints.ai_socktype, m_Hints.ai_protocol)
If (m_ConnSocket = INVALID_SOCKET) Then
LogError "Error opening socket, error " & RetVal
Else
Dim connectionResult As Long
connectionResult = connect(m_ConnSocket, m_Hints.ai_addr, m_Hints.ai_addrlen)
If connectionResult <> SOCKET_ERROR Then
connected = True
Exit Do
End If
LogError "connect() to socket failed"
closesocket (m_ConnSocket)
End If
Loop
If Not connected Then
LogError "Fatal error: unable to connect to the server", WSAGetLastError()
RetVal = closesocket(m_ConnSocket)
Call WSACleanup
Exit Function
End If
'After Socket Connected
Dim SendBuf As String
SendBuf = ID + "|" + pw
'Send Login Data
RetVal = Send(m_ConnSocket, SendBuf, Len(SendBuf), 0)
If RetVal = SOCKET_ERROR Then
LogError "send() failed", WSAGetLastError()
RetVal = closesocket(m_ConnSocket)
Call WSACleanup
Exit Function
Else
Debug.Print "sent " & RetVal & " bytes"
End If
' shutdown the connection since no more data will be sent
RetVal = shutdown(m_ConnSocket, SD_SEND)
If RetVal <> 0 Then
LogError "send socket close failed", WSAGetLastError()
RetVal = closesocket(m_ConnSocket)
Call WSACleanup
Else
Debug.Print "send socket closed"
End If
'Recieve From Server (Login Success : 1, Fail : 0)
Dim RecvBuf As Byte
RetVal = Recv(m_ConnSocket, RecvBuf, MAX_BUF_SIZE, 0)
If RetVal = SOCKET_ERROR Then
LogError "recv() failed", WSAGetLastError()
RetVal = closesocket(m_ConnSocket)
Call WSACleanup
Exit Function
Else
Debug.Print "recieved " & RetVal & " bytes"
End If
'Login Check (s : success(id,pw correspond, f : fail)
If Left(Chr(RecvBuf), 1) = "s" Then
Login = 1
Else
Login = 0
End If
RetVal = closesocket(m_ConnSocket)
If RetVal <> 0 Then
LogError "closesocket() failed", WSAGetLastError()
Call WSACleanup
Else
Debug.Print "closed socket"
End If
End Function
Public Function MAKEWORD(Lo As Byte, Hi As Byte) As Integer
MAKEWORD = Lo + Hi * 256& Or 32768 * (Hi > 127)
End Function
Private Sub LogError(msg As String, Optional ErrorCode As Long = -1)
If ErrorCode > -1 Then
msg = msg & " (error code " & ErrorCode & ")"
End If
Debug.Print msg
End Sub