zoukankan      html  css  js  c++  java
  • 制作NSIS命令行窗口输出插件

    在上一篇中,介绍了如何NSIS生成的安装包在静默安装时从命令行窗口输出安装信息,但是产生了很多问题,于是我们想换一个实现方法,毕竟静默安装时的输出信息并不需要那么多,多了反而让人眼花。静默安装时,只要输出生成还是失败,失败了有个失败原因就可以了。所以另一个解决方案就是自己写个插件,向CMD窗口输出一些信息就是了。这篇文章就是要介绍一下如何自己编写这样的一个NSIS插件。

    很奇怪的是,NSIS的官方网站上居然没有介绍如何自己编写Plugin的文章,搜索到在OpenWatcom一篇介绍了NSIS插件要符合的要求。按照它给出的描述——“NSIS plugins are simply DLLs. The functions provided by these functions are exported functions that have a specific array of parameters. That signature is as follows.NSIS插件不过是简单的DLL,只要是符合下面参数列表的函数,就会被认为是合法的NSIS插件。

    __declspec(dllexport) void __cdecl TestFunc(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)

    好啊。那就照葫芦画瓢写个DLL喽。Hello world级的。下面是hello.cpp的源代码。

    #include <windows.h>
    #include 
    <stdio.h>

    #define NSISAPI __declspec(dllexport) void __cdecl

    NSISAPI TestFunc(HWND hwndParent, 
    int string_size, char *variables, stack_t **stacktop)
    {
        printf(
    "Hello");
    }

    很简单吧。用下面的命令编译一下。

    CL /LD Hello.cpp

    编译不过啊!

    error C2061: syntax error : identifier 'stack_t'

    stack_t未定义!这让我去哪里找啊?只当是外面的吧。把代码改成下面的样子。

    #include <windows.h>
    #include 
    <stdio.h>
    #define NSISAPI __declspec(dllexport) void __cdecl

    struct stack_t;

    NSISAPI TestFunc(HWND hwndParent, 
    int string_size, char *variables, stack_t **stacktop)
    {
        printf(
    "Hello");
    }

    这下就过了。把这个DLL放到NSISPlugins文件夹中,写一个最简单的NSIS脚本测试一下。

    OutFile "Test.exe"

    Section

        Hello::TestFunc

    SectionEnd

    结果发现脚本Build不过啊。错误为“Invalid command: Hello::TestFunc

    Command找不到。

    看看MakeNSISW上完整的输出信息。列出了NSIS找到的所有Plugin里的可作为Command的函数。如下

    Processing config:

    Processing plugin dlls: "D:\Program Files\NSIS\Plugins\*.dll"

     - AdvSplash::show

    ……

    - Hello::?TestFunc@@YAXPAUHWND__@@HPADPAPAUstack_t@@@Z

    的确是有我们刚加入的DLL的,不过函数名不对啊。“?TestFunc@@YAXPAUHWND__@@HPADPAPAUstack_t@@@Z”怎么会有这么个恶心的函数名?

    也许有人已经猜到了,由于使用的是C++,而C++是支持函数重载的,但是导出函数表的函数名不能重名啊。所以CL在编译C++的时候,会自动对函数名进行修饰。这个恶心的名字就是修饰过的函数名。有没有办法不让CL修饰呢?一个办法就是告诉CL我们的代码是C代码,不支持重载,CL就不会修饰了。代码再改如下。

    #include <windows.h>
    #include 
    <stdio.h>

    #define NSISAPI extern "C" __declspec(dllexport) void __cdecl

    struct stack_t;

    NSISAPI TestFunc(HWND hwndParent, 
    int string_size, char *variables, stack_t **stacktop)
    {
        printf(
    "Hello");
    }

    再把编译好的DLL复制到插件文件夹,再编译Test.nsi,这次就编译过了。

    双击运行Test.exe,不会看到任何Hello,因为printf是输出到Console的。

    从命令行运行Test.exe,也不会在控制台看到”Hello”,因为这个Test.exe是个GUI程序,是没有ConsoleOutput的。寒。那怎么才能有呢?有三个办法,NSIS也是都可以做到了。三种方法可以参考我的另一篇文章WPF窗体程序支持命令行方式运行的三种方式。方法是通用的。“| more”的方法就不用解释了。让NSIS生成一个CUI程序,可以参考NSIS生成的安装包在静默安装时从命令行窗口输出安装信息,但是这种方法弊端多多,不然也就不会有这篇文章了。最后一种方法就是AttachConsole了,这种方法也有不好的地方,不过比较而言,还是可以的。

    这个DLL的代码很简单,只实现了最基本的功能,大家有需要可以自己添加。


    NSIS Console Plugin

    参考文献:Writing to and read from the console - From a GUI application using the same cout/cin and printf/scanf

  • 相关阅读:
    AngularJS Insert Update Delete Using PHP MySQL
    Simple task manager application using AngularJS PHP MySQL
    AngularJS MySQL and Bootstrap Shopping List Tutorial
    Starting out with Node.js and AngularJS
    AngularJS CRUD Example with PHP, MySQL and Material Design
    How to install KVM on Fedora 22
    Fake_AP模式下的Easy-Creds浅析
    河南公务员写古文辞职信
    AI
    政协委员:最大愿望是让小学生步行上学
  • 原文地址:https://www.cnblogs.com/nankezhishi/p/nsisconsoleplugin.html
Copyright © 2011-2022 走看看