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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章