NSIS插件制作

NSIS插件制作

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

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

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

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

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

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

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

如果编译出现:

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

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

如果编译出现:

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

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

以下是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] = ‘\0‘;
    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中传回的值了。

NSIS插件制作

上一篇:hyperf 协程理解和使用


下一篇:第三章 设置界面的模仿以及使用SharePreference来保存设置 3.1