为 Rainmeter 添加 ipv6 支持

Posted

技术标签:

【中文标题】为 Rainmeter 添加 ipv6 支持【英文标题】:adding ipv6 support to Rainmeter 【发布时间】:2020-06-23 03:54:50 【问题描述】:

我正在尝试从 Rainmeter API 编辑 PluginSysInfo 以包含 IPv6 支持。我已经修改了 SysInfo.cpp 中的代码,据我所知包含的链接具有我对 SysInfo.cpp 所做的编辑。

当我在 Visual Studio 中构建它时,“标识符 GetTcp6Table 未定义”和“标识符 PMIB_IP6TABLE 未定义”即使它们位于包含文件 #include 中。

https://pastebin.com/N30HYRVe

#include <algorithm>
#include <windows.h>
#include <WinSock2.h>
...
MEASURE_IP6_ADDRESS
...
    else if (_wcsicmp(L"IP6_ADDRESS", type) == 0)
    
        defaultData = 0;
        measure->type = MEASURE_IP6_ADDRESS;
    
...
 
case MEASURE_IP6_ADDRESS:
            if (NO_ERROR == GetTcp6Table((PMIB_IP6TABLE)tmpBuffer, &tmpBufferLen, FALSE))
            
                PMIB_IP6TABLE TcpTable = (PMIB_IP6TABLE)tmpBuffer;
                if (measure->useBestInterface)
                
                    for (UINT i = 0; i < TcpTable->dwNumEntries; ++i)
                    
                        if (TcpTable->table[i].dwIndex == measure->data)
                        
                            DWORD ip = TcpTable->table[i].dwAddr;
                            wsprintf(sBuffer, L"%x:%x:%x:%x"/*:%x:%x:%x:%x"*/, ip % 65535, (ip >> 8) % 65535, (ip >> 16) % 65535, (ip >> 24) % 65535);
                            return sBuffer;
                        
                    
                

【问题讨论】:

documentation 表示您需要#include &lt;iphlpapi.h&gt; 我查看了文档,但我似乎没有将 2 和 2 放在一起。 @WhitequillRiclo 函数GetTcp6Tableiphlpapi.h 中声明,而这又需要winsock2.h。如果您打开iphlpapi.h 文件,您会在GetTcp6Table 的声明之前找到注释“以下定义需要Winsock2”。最初,你#include'd 那些标题之前 windows.h,现在你移动它们之后 windows.h,但仍然定义WIN32_LEAN_AND_MEAN 导致我的答案末尾引用中解释的冲突。 【参考方案1】:

Win32 标头 &lt;winsock2.h&gt;&lt;windows.h&gt; 之间存在已知冲突,请参见例如 1、2。

Microsoft documentation 建议使用两个#include 序列之一。

没有&lt;windows.h&gt;:
#include <winsock2.h>
#include <ws2tcpip.h>
&lt;windows.h&gt;:
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>

由于GetTcp6Table 需要&lt;iphlpapi.h&gt; OP 的情况应该使用后一种。

引用同一文档:

如果应用程序使用 IP Helper API,则需要 Iphlpapi.h 头文件。当需要 Iphlpapi.h 头文件时, Winsock2.h 头文件的#include 行应放在 Iphlpapi.h 头文件的#include 行之前。

Winsock2.h 头文件内部包含来自 Windows.h 头文件的核心元素,因此 Winsock 应用程序中的 Windows.h 头文件通常没有#include 行。 如果 Windows.h 头文件需要 #include 行,则应在其前面加上 #define WIN32_LEAN_AND_MEAN 宏。 由于历史原因,Windows.h 头文件默认包括 Windows Sockets 1.1 的 Winsock.h 头文件。 Winsock.h 头文件中的声明将与 Windows Sockets 2.0 所需的 Winsock2.h 头文件中的声明冲突。 WIN32_LEAN_AND_MEAN 宏防止 Winsock.h 包含在 Windows.h 标头中。


[ EDIT ] 跟进评论,下面是正确构建的完整 sn-p。

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#include <winwock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <stdlib.h> // _countof

#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "iphlpapi.lib")

int main()

    BYTE tmpBuffer[7168];
    ULONG tmpBufferLen = _countof(tmpBuffer);

    return NO_ERROR == GetTcp6Table((PMIB_TCP6TABLE)tmpBuffer, &tmpBufferLen, FALSE);

【讨论】:

我已经更新了 pastebin 上的链接代码。我似乎仍然有同样的问题。我是 python3 开发人员。我不习惯 C++。 @WhitequillRiclo 我将完整的代码 sn-p 编辑为答案。注意GetTcp6Table 的第一个参数是PMIB_TCP6TABLE,而不是PMIB_IP6TABLE 有点离题但是; PMIB_TCP6TABLE 读什么?因为我用DWORD ip = TcpTable-&gt;table[measure-&gt;data].dwLocalPort;的时候没有给出单播地址,否则问题就彻底解决了。 IP 不在dwLocalPort 中,详情请参阅MIB_TCP6ROW structure。

以上是关于为 Rainmeter 添加 ipv6 支持的主要内容,如果未能解决你的问题,请参考以下文章

centOS添加ipv6支持(仅限已分配ipv6地址和网关)

为树莓派添加he的ipv6隧道

如何在 ios 中使用带有域的 pjsip 添加对 IPv6 的支持?

怎样在linux中添加ipv6

Rainmeter个人使用的插件

Rainmeter个人使用的插件