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