首页 > 解决方案 > 如何将静态库捆绑到 NSIS 插件中

问题描述

我是 NSIS 和 C++ 的新手。我编写了一个 NSIS 插件来检查带有 VS2010 的 http 请求的许可证。但该插件仅适用于安装了 VS2010 的计算机。我猜原因是像“ws2_32.lib”这样的库没有捆绑在包中。我希望带有此插件的安装包可以在未安装 C++ 的计算机上运行。有什么想法可以解决吗?

非常感谢。这是我的代码。


    // dllmain.cpp : Defines the entry point for the DLL application.
    #include "stdafx.h"
    #include <WinSock2.h>
    #include <iostream>
    #include <stdlib.h>
    using namespace std;
    #include <string.h> 
    #include <stdio.h>
    #include "./../nsis/pluginapi.h"
    #include <windows.h>  
    #include <Wincrypt.h>  
    #pragma comment(lib,"crypt32")  
    #pragma comment(lib,"./../nsis/pluginapi-x86-unicode.lib")
    #pragma comment(lib, "ws2_32.lib")

    void __declspec(dllexport) myFunction(HWND hwndParent, int string_size,
        TCHAR *variables, stack_t **stacktop,
        extra_parameters *extra)
    {
        g_hwndParent = hwndParent;
     
        EXDLL_INIT();
        
        //读取输入参数
        WCHAR szComponent[256];
        popstring(szComponent);
     
        //打印参数
        WCHAR buf[1024];
        //这里能正确打印出来自NSIS的中文信息。
        //wsprintf(buf, L"kagula $0=[%s][szComponent]\n", szComponent);
        //MessageBoxW(g_hwndParent, buf, 0, MB_OK);
    
        WCHAR urlComponent[256];
        popstring(urlComponent);
        //wsprintf(buf, L"kagula $0=[%s][urlComponent]\n", urlComponent);
        //MessageBoxW(g_hwndParent, buf, 0, MB_OK);
    
        WCHAR ipComponent[256];
        popstring(ipComponent);
    
        WCHAR portComponent[256];
        popstring(portComponent);
    
     
        //准备返回参考
    
        int len = (int)wcslen(szComponent);
        int input_len = (int)wcslen(szComponent);
        //printf("%d\n", input_len);
        //char server_id[256];
        //for (int i = 0; i <
        char* server_id = wchar2char(szComponent);
        printf("%d\n", strlen(server_id));
        //char* server_id = new char(256);
        //for (int i = 0; i < input_len; i++) {
        //  server_id[i] = szComponent[i];
        //}
        //to_narrow(szComponent, server_id, 256);
        printf("serid %s", server_id);
        //打印参数
        
    
        
    
        char* ret = ""; // 返回Http Response
        try
        {
            // 开始进行socket初始化
            WSADATA wData;  
            ::WSAStartup(MAKEWORD(2, 2), &wData);  
    
            SOCKET clientSocket = socket(AF_INET, 1, 0);
            struct sockaddr_in ServerAddr = {0};
            char* m_ip = wchar2char(ipComponent);
            int m_port = atoi(wchar2char(portComponent));
    
            char* req = wchar2char(urlComponent);
            WCHAR bufchar[3069];
            //这里能正确打印出来自NSIS的中文信息。
            //wsprintf(bufchar, L"kagula $0=[%s][server_id]\n", char2wchar(server_id));
            //MessageBoxW(g_hwndParent, bufchar, 0, MB_OK);
            printf("req %s", req);
            char* urlSend = (char*) malloc(strlen(req) + strlen(server_id));
            strcpy(urlSend, req);
            strcat(urlSend, server_id);
            //strcat(req, server_id);
            printf("req %s", req);
            ServerAddr.sin_addr.s_addr = inet_addr(m_ip);  
            ServerAddr.sin_port = htons(m_port);
            ServerAddr.sin_family = AF_INET; 
            int errNo = connect(clientSocket, (sockaddr*)&ServerAddr, sizeof(ServerAddr)); 
            printf("errNo connect %d \n", errNo);
            if(errNo == 0)  
            {  
                //  "GET /[req] HTTP/1.1\r\n"  
                //  "Connection:Keep-Alive\r\n"
                //  "Accept-Encoding:gzip, deflate\r\n"  
                //  "Accept-Language:zh-CN,en,*\r\n"
                //  "User-Agent:Mozilla/5.0\r\n\r\n";
                char* cookie = " HTTP/1.1\r\nCookie:16888\r\n\r\n";
                // strSend = "GET " + req + strSend;
                char* gp = "GET ";
    
                char* strSend = (char*) malloc(strlen(gp) + strlen(cookie) + strlen(urlSend));
                strcpy(strSend, gp);
                strcat(strSend, urlSend);
                strcat(strSend, cookie);
    
                // 发送
                errNo = send(clientSocket, strSend, strlen(strSend), 0);
                if(errNo > 0)  
                {  
                    //cout << "发送成功&quot; << endl;
                }
                else
                {
                    //std::cout << "errNo:" << errNo << std::endl;
                    printf("errNo:");
                    // return ret;
                }
    
                // 接收
                char bufRecv[3069] = {0};
                errNo = recv(clientSocket, bufRecv, 3069, 0);
                if(errNo > 0)  
                {  
                    ret = bufRecv;// 如果接收成功,则返回接收的数据内容  
                }
                else
                {
                    // std::cout << "errNo:" << errNo << std::endl;
                    printf("errNo:");
                    // return ret;
                }
            }  
            else  
            {  
                errNo = WSAGetLastError();  
                // std::cout << "errNo:" << errNo << std::endl;
                printf("errNo:");
                printf(errNo + "");
            }  
            // socket环境清理
            ::WSACleanup();  
        }
        catch (...)
        {
            // return "";
        }
        printf(ret);
    
     
        // push back on the stack
    
        TCHAR * tchar;
    
        char* ok_str = "ServerId is OK";
        if(strstr(ret, ok_str) == NULL) {
            tchar = _T("0");
        } else {
            tchar = _T("1");
        }
        
        for (int i = 0; i < len; ++i) {
            printf("%d", i);
            szComponent[i] += 1;
        }
        pushstring(tchar);
        
    }

标签: c++cnsis

解决方案


我猜原因是像“ws2_32.lib”这样的库没有捆绑在包中。

不,那个东西只被 Visual C++ 链接器使用。在运行时,对应的 DLL 取自C:\Windows\System32\ws2_32.dll

最可能的原因是 C 和 C++ 运行时 DLL。默认情况下,Visual Studio C++ 项目使用到这些库的动态链接。对于安装程序插件,修复的一个好方法是切换到静态 C++ 运行时。右键单击项目,配置属性,C/C++,代码生成,将“运行时库”设置更改Multi-threaded Debug (/MTd)为调试配置和Multi-threaded (/MT)发布配置。

PS 我会推荐用于 HTTP 网络的更高级别的库,例如 WinHTTP 或 WinINet。现代互联网已经从http迁移到https。


推荐阅读