zoukankan      html  css  js  c++  java
  • NSIS插件制作

    NSIS插件制作

    最近在做串口相关的一个工具,需要在当前系统有多个串口的情况下,有选择串口的界面供用户选择。在网上找了很久都没找到nsis中获取串口的插件或教程,不知道是否是查询的姿势不对,有知道的请告诉我,十分感谢。没找到的情况下就另辟道路,自己做个NSIS的插件。故开始了网上冲浪查找制作NSIS插件,在此记录一下过程。

    首先创建一个TestNSIS的动态库项目

    将在NSIS的ExamplesPlugin目录中有一个示例程序,里面有一个nsis目录,拷贝到TestNSIS项目中,并且包含到TestNSIS项目中

    新建TestNSIS.cpp文件,在该文件中编写实现代码

    属性页C/C++预编译头预编译头---不使用预编译头

    属性页VC++目录库目录---选择当前项目下的nsis目录

    属性页输入附加依赖项--pluginapi.lib

    如果编译出现:

    严重性 代码 说明 项目 文件 行 禁止显示状态
    错误 LNK1104 无法打开文件“LIBC.lib” TestNSIS C:Usersstdiosource eposTestNSISTestNSISLINK 1

    则在TestNSIS.cpp文件中添加代码:#pragma comment(linker, "/NODEFAULTLIB:libc.lib")

    如果编译出现:

    严重性 代码 说明 项目 文件 行 禁止显示状态
    错误 LNK1281 无法生成 SAFESEH 映像。 NSISPort D:Pro_smartclassRG-SCCSNSISPortReleaseNSISPort.dll 1

    则设置属性页链接器命令行其它选项添加 /SAFESEH:No

    还有一个特别需要注意的地方(这里踩过大坑),编译选项使用MT,否则在没有装VCredist的机器上会返回错误的结果并且没有任何提示。
    在配置属性页C/C++代码生成运行库--多线程(/MT)

    以下是TestNSIS.cpp的内容:

    #include<Windows.h>
    #include "nsis/pluginapi.h"
    #include<vector>
    #include<list>
    #include<string>
    #pragma comment(linker, "/NODEFAULTLIB:libc.lib")
    using namespace std;
    HINSTANCE g_hInstance;
    HWND g_hwndParent;
    char* wideCharToMultiByte(wchar_t* pWCStrKey)
    {
        int pSize = ::WideCharToMultiByte(CP_OEMCP, 0, pWCStrKey, ::wcslen(pWCStrKey), nullptr, 0, nullptr, nullptr);
        char* pCStrKey = new char[pSize + 1];
        ::WideCharToMultiByte(CP_OEMCP, 0, pWCStrKey, ::wcslen(pWCStrKey), pCStrKey, pSize, nullptr, nullptr);
        pCStrKey[pSize] = '';
        return pCStrKey;
    
    }
    ::vector<char*> getComPort()
    {
        HKEY hKey;
        wchar_t portName[1024], w_commName[1024];
        std::vector<char*> comName;
        if (ERROR_SUCCESS == ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Hardware\DeviceMap\SerialComm", 0, KEY_READ, &hKey))
        {
            int i = 0;
            int mm = 0;
            DWORD dwLong, dwSize;
            while (TRUE)
            {
                dwLong = dwSize = sizeof(portName);
                if (ERROR_NO_MORE_ITEMS == ::RegEnumValue(hKey, i, portName, &dwLong, nullptr, nullptr, (PUCHAR)w_commName, &dwSize))
                {
                    break;
                }
                char* commName = ::wideCharToMultiByte(w_commName);
                char* ch = new char[100];
                memset(ch, 0, 100);
                strncpy_s(ch, 100, commName, strlen(commName));
                comName.push_back(ch);
                delete[] commName;
                i++;
            }
            ::RegCloseKey(hKey);
        }
        return comName;
    }
    
    char* SerialPort()
    {
        vector<char*> res = ::getComPort();
        if (res.size() > 0)
        {
            char* ch = new char[512];
            strncpy_s(ch, 512, res[0], strlen(res[0]));
            return ch;
        }
        return new char[0];
    }
    extern "C" _declspec(dllexport)  void COMCount(HWND hwndParent, int string_size,
        char* variables, stack_t * *stacktop,
        extra_parameters * extra)
    {
        ::g_hwndParent = hwndParent;
        EXDLL_INIT();
        vector<char*> res = ::getComPort();
        int count = 0;
        if (res.size() > 0)
        {
            count = res.size();
        }
        pushint(count);
    }
    extern "C" _declspec(dllexport)  void COMStr(HWND hwndParent, int string_size,
        char* variables, stack_t * *stacktop,
        extra_parameters * extra)
    {
        ::g_hwndParent = hwndParent;
        EXDLL_INIT();
        vector<char*> res = ::getComPort();
        string data = "";
        if (res.size() > 0)
        {
            for (int i = 0; i < res.size(); i++)
            {
                data = data + string(res[i]) + "|";
            }
        }
        pushstring(data.data());
    }
    extern "C" _declspec(dllexport)  void COMStrFirst(HWND hwndParent, int string_size,
        char* variables, stack_t * *stacktop,
        extra_parameters * extra)
    {
        ::g_hwndParent = hwndParent;
        EXDLL_INIT();
        vector<char*> res = ::getComPort();
        char* ch = new char[0];
        if (res.size() > 0)
        {
            ch = res[0];
        }
        pushstring(ch);
    }
    

    注意这里的导出函数一定要是“C"格式的。

    然后将生成的TestNSIS.dll拷贝到NSIS的Plugins目录下,在nsis脚本中就可以使用了。使用方式如下:

    TestNSIS::COMCount
    pop $2
    

    这里pop $2的$2就是COMCount中传回的值了。

  • 相关阅读:
    Ubuntu安装deepin wine版QQ
    解决anaconda安装cvxpy失败的方法
    1006
    一种不用参数交换两变量值的方法
    输入三位数,翻转输出
    一个简单的问题
    1006ac(转)
    1007(转)
    杭电oj1004 自写成功代码
    1004
  • 原文地址:https://www.cnblogs.com/zzr-stdio/p/15235337.html
Copyright © 2011-2022 走看看