1

Based on my question C# IVI VISA (e.g.: NI VISA) TCP Keep Alive I tried to use EasyHook to patch how NI VISA is opening a SOCKET connection. Finally I would like to modify the keep alive settings in the ConnectHook method (not in there yet).

I've the following code:

[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError = true)]
delegate int ConnectDelegate(IntPtr socket, IntPtr sockaddr, int namelen);
[DllImport("ws2_32.dll", SetLastError = true, EntryPoint = "connect")]
static extern int Connect(IntPtr socket, IntPtr sockaddr, int namelen);
static int ConnectHook(IntPtr socket, IntPtr sockaddr, int namelen)
{
 Console.WriteLine("SOCKET Connect");
 int s = Connect(socket, sockaddr, namelen);
 return s;
}

and

static void Main(string[] args)
{
 string rn = "TCPIP::10.0.0.2::hislip0::INSTR";
 //string rn = "TCPIP::10.0.0.2::inst0::INSTR"; // VXI-11
 // Make sure ws2_32.dll is loaded
 var vi = GlobalResourceManager.Open(rn) as IMessageBasedSession;
 vi.Dispose();
 LocalHook hook = LocalHook.Create(LocalHook.GetProcAddress("ws2_32.dll", "connect"),
 new ConnectDelegate(ConnectHook),
 null);
 hook.ThreadACL.SetInclusiveACL(new int[] { 0 });
 // Connect
 vi = GlobalResourceManager.Open(rn) as IMessageBasedSession;
 // IDN query
 vi.RawIO.Write("*IDN?");
 Console.WriteLine(vi.RawIO.ReadString());
 // Sleep to monitor keep alive traffic using Wireshark
 Thread.Sleep(10 * 1000);
 // IDN query
 vi.RawIO.Write("*IDN?");
 Console.WriteLine(vi.RawIO.ReadString());
 // Disconnect
 vi.Dispose();
 hook.Dispose();
}

The above source code is all in the same assembly (Console application). But my ConnectHook method is newer called when GlobalResourceManager.Open(rn) is running.

I'm able to run and hook the MessageBeep example from https://easyhook.github.io/tutorials/createlocalhook.html.

asked Oct 28, 2025 at 9:27
5
  • 1
    The only thing I could image is that NI VISA doesn't use the connect method from ws2_32.dll and instead uses something else. You should be able to check with the process monitor Commented Oct 28, 2025 at 14:59
  • @MindSwipe I can see in the process monitor that ws2_32.dll is loaded. But I don't know how to see which connect method is called. I tried as well for testing replacing all NI VISA stuff with a simple var client = new TcpClient(); client.Connect("10.0.0.2", 80) which loads as well the ws2_32.dll. But as well here my ConnectHook method is never called. Commented Oct 29, 2025 at 7:45
  • Looking into the winsock2 API it might be as simple as hooking the WSAConnect function instead. If that doesn't work you'll probably have to look into hooking into syscalls and seeing which is used. Commented Oct 29, 2025 at 8:00
  • @MindSwipe TcpClient is using WSAConnect and I can hook it. But NI VISA GlobalResourceManager.Open(rn) is not using WSAConnect and not connect. Commented Oct 29, 2025 at 8:47
  • Setting a breakpoint to ws2_32!WSASend I can see that this is been called by NI VISA. Commented Oct 29, 2025 at 9:05

1 Answer 1

0

NI VISA GlobalResourceManager.Open(rn) calls WSASocketW and not connect to establish a TCP connection.

So I was able to hook the WSASocketW method with the following code:

[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)]
delegate IntPtr WSASocketWDelegate(int af, int type, int protocol, IntPtr lpProtocolInfo, uint g, uint dwFlags);
[DllImport("Ws2_32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "WSASocketW")]
static extern IntPtr WSASocketW(int af, int type, int protocol, IntPtr lpProtocolInfo, uint g, uint dwFlags);
static IntPtr WSASocketWHook(int af, int type, int protocol, IntPtr lpProtocolInfo, uint g, uint dwFlags)
{
 Console.WriteLine("SOCKET WSASocketW");
 IntPtr s = WSASocketW(af, type, protocol, lpProtocolInfo, g, dwFlags);
 return s;
}

and now my WSASocketWHook method gets called in the second GlobalResourceManager.Open(rn) call after the hook is activated.

The first call, which is used to make sure that the Ws2_32.dll is loaded, could be replaced with call to WSAStartup with the following code:

[DllImport("ws2_32.dll", SetLastError = true)]
static extern int WSAStartup(ushort wVersionRequested, out WSAData wsaData);
[StructLayout(LayoutKind.Sequential)]
struct WSAData
{
 public short wVersion;
 public short wHighVersion;
 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 257)]
 public string szDescription;
 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 129)]
 public string szSystemStatus;
 public short iMaxSockets;
 public short iMaxUdpDg;
 public IntPtr lpVendorInfo;
}
static void EnsureWs2_32Loaded()
{
 WSAData wsaData;
 int result = WSAStartup(0x202, out wsaData); // Version 2.2
 if (result != 0)
 throw new Exception("WSAStartup failed.");
}

and finally in the main method:

static void Main(string[] args)
{
 //string rn = "TCPIP::10.0.0.2::hislip0::INSTR";
 string rn = "TCPIP::10.0.0.2::inst0::INSTR"; // VXI-11
 EnsureWs2_32Loaded();
 LocalHook hook = LocalHook.Create(LocalHook.GetProcAddress("ws2_32.dll", "WSASocketW"),
 new WSASocketWDelegate(WSASocketWHook),
 null);
 hook.ThreadACL.SetInclusiveACL(new int[] { 0 });
 // Connect
 var vi = GlobalResourceManager.Open(rn) as IMessageBasedSession;
 // ...
 
}
answered Oct 29, 2025 at 15:13
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.