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中传回的值了。