mosang 发表于 2019-4-22 17:35:48

求各位鱼友支援一个把exe转化成dll的样例

各位鱼友好,请大家帮帮忙,教我如何把一个exe文件转化成一个dll文件,或者教我如何写一个和exe功能相同的dll,然后导出里面的一个函数给其他的函数调用。

我自己在网上找了一些相关的帖子和博客,但是因为相关知识太匮乏,几乎没有能够看懂的,自己动手瞎改又总是报错,折腾好几天都没有解决问题。

现在我遇到的问题主要在如何去掉exe里面的 main() 函数上,我自己尝试过新建一个dll,然后把exe代码复制过去,然后直接删掉 main() 函数并且导出我想要的函数,但是这样不成功,虽然在编译的时候能通过,但是调用的时候就会像下面的图片一样报错。我搜了一些贴子,好像是空指针的问题,需要调试找到空指针的位置就能解决问题。但因为我是小白,不懂如何调试程序找到问题在哪里。很是烦躁。

我在网上找了好几天,始终没有找到一个合适的解决办法,如果哪位鱼友刚好会这个的话,请不吝赐教,万分感谢!
以下是小程序的代码
/*****************************************************************************
**
** Tool_Assemble_External.cpp
**
** Description:
**    Main file for the application.
**
*****************************************************************************/

/* Include files */
#include <stdarg.h>
    #include <strstream>
    #include <iostream>
    using std::ostrstream;
    using std::endl;   
    using std::ends;
    using std::cerr;
#include <uf.h>
#include <uf_ui.h>
#include <uf_modl.h>
#include <uf_part.h>
#include <uf_cfi.h>
#include <uf_assem.h>

static void ECHO(char *format, ...)
{
    char msg;
    va_list args;
    va_start(args, format);
    vsnprintf_s(msg, sizeof(msg), UF_UI_MAX_STRING_NCHARS, format, args);
    va_end(args);
    printf(msg);
    UF_print_syslog(msg, FALSE);
}

#define UF_CALL(X) (report_error( __FILE__, __LINE__, #X, (X)))

static int report_error( char *file, int line, char *call, int irc)
{
    if (irc)
    {
      char err;

      UF_get_fail_message(irc, err);
      ECHO("*** ERROR code %d at line %d in %s:\n",
                        irc, line, file);
      ECHO("+++ %s\n", err);
      ECHO("%s;\n", call);
    }

    return(irc);
}

/* Main routine */
extern void main( char argc, char *argv[] )
{
    /* Initialize the API environment */
    if( UF_CALL(UF_initialize()) )
    {
      /* Failed to initialize */
      return;
    }
   
    /* TODO: Add your application code here */
        //新建一个一个prt文件
        tag_t PartTAG = NULL_TAG;
        UF_CALL(UF_PART_new("D:\\Program Files\\Siemens\\NX 10.0\\SECONDARY_DEVELOPMENT\\DateBase\\Temp\\Newpart.prt", UF_PART_METRIC, &PartTAG));
        printf("第一步,新建一个prt部件!\n");
       
        //导入刀柄
        UF_import_part_modes_t modes;
        modes.layer_mode = 0;
        modes.group_mode = 0;
        modes.view_mode = 0;
        modes.cam_mode = false;
        double dest_csys0 [ 6 ] = {1.0, 0.0, 0.0, 0.0, 0.0, 1.0};       
        //由三个坐标值确定的X方向和Y方向,笛卡尔坐标系,确定两个就能确定第三个坐标方向
        double dest_point0 [ 3 ] = {0.0, 0.0, 0.0,};        //导入的原点
        double scale0 = 1.0;                //缩放比例
        tag_t group0 = NULL_TAG;
        UF_CALL(UF_PART_import("D:\\Program Files\\Siemens\\NX 10.0\\SECONDARY_DEVELOPMENT\\DateBase\\ToolBase\\刀柄库\\BT40-ER32-100.prt", &modes, dest_csys0, dest_point0, scale0, &group0));       
        printf("第二步,导入刀柄\n");

        //导入夹套
        UF_import_part_modes_t modes1;
        modes1.layer_mode = 0;
        modes1.group_mode = 0;
        modes1.view_mode = 0;
        modes1.cam_mode = false;
        double dest_csys1 [ 6 ] = {1.0, 0.0, 0.0, 0.0, 0.0, 1.0};       
        //由三个坐标值确定的X方向和Y方向,笛卡尔坐标系,确定两个就能确定第三个坐标方向
        double dest_point1 [ 3 ] = {0.0, 0.0, 0.0,};        //导入的原点
        double scale1 = 1.0;                //缩放比例
        tag_t group1 = NULL_TAG;
        UF_CALL(UF_PART_import("D:\\Program Files\\Siemens\\NX 10.0\\SECONDARY_DEVELOPMENT\\DateBase\\ToolBase\\夹套库\\ER32-10.prt", &modes1, dest_csys1, dest_point1, scale1, &group1));
        printf("第三步,导入夹套!");
        //导入刀杆
        UF_import_part_modes_t modes2;
        modes2.layer_mode = 0;
        modes2.group_mode = 0;
        modes2.view_mode = 0;
        modes2.cam_mode = false;
        double dest_csys2 [ 6 ] = {1.0, 0.0, 0.0, 0.0, 0.0, 1.0};       
        //由三个坐标值确定的X方向和Y方向,笛卡尔坐标系,确定两个就能确定第三个坐标方向
        double dest_point2 [ 3 ] = {0.0, -50.0, 0.0,};        //导入的原点
        double scale2 = 1.0;                //缩放比例
        tag_t group2 = NULL_TAG;
        UF_CALL(UF_PART_import("D:\\Program Files\\Siemens\\NX 10.0\\SECONDARY_DEVELOPMENT\\DateBase\\ToolBase\\刀杆库\\266RKF-D10.prt", &modes2, dest_csys2, dest_point2, scale2, &group2));
        printf("第四步,导入刀杆!");
        UF_CALL(UF_PART_save_as("D:\\Program Files\\Siemens\\NX 10.0\\SECONDARY_DEVELOPMENT\\DateBase\\Temp\\ToolNum.prt"));
        UF_CALL(UF_PART_close(PartTAG, 0, 1));
        printf("保存文件!");

    /* Terminate the API environment */
    UF_CALL(UF_terminate());
}
/*****************************************************************************
**Utilities
*****************************************************************************/


ps: 因为我写的小程序是UG二次开发的程序,需要在UG的环境下才能运行,所以各位鱼友如果直接帮我调试的话会不成功,所以如果可以的话,请大家直接教我一个把exe改成dll的样板,谢谢!















人造人 发表于 2019-4-22 17:35:49

好吧,看了这个我明白了,原来只是源码级别的转换,这个太简单了,相对于上面来说^_^
https://fishc.com.cn/thread-134210-1-1.html


你先看看这个例子,如果还有什么不明白就问我
链接:https://pan.baidu.com/s/1KiG0Ja7lF2np2zFLUOWZqw
提取码:qpv8

人造人 发表于 2019-4-25 23:59:55

这个问题有意思,我有兴趣来研究研究

把一个exe文件转换成一个dll文件,如果真的要这么做,那就需要提供好多必要数据,也许你可以考虑一下其他的解决方案,如果 “把一个exe文件转换成一个dll文件”这是唯一的解决方案,那么我们来聊聊吧

首先你要对这个exe文件有足够的了解,例如,这个exe文件中有多少个函数,这些函数的名字分别是什么?其中有多少个函数需要导出给外部调用?
是在有这个exe的源代码的基础上做这件事还是只有这个exe文件没有源代码?这个exe文件现在是debug版本还是release版本?
如果是没有源代码只有一个debug版本的exe,那就不好办了,不过我认为还是可以进行转换的,因为我认为可以通过分析pe结构中的“调试信息”,我认为在这里记录了函数的名字和地址(函数的名字和地址的用途下面再说,要完成转换需要这两个信息),这只是猜测,我并没有研究过“调试信息”,我认为要完成调试,这个exe文件中一定记录了函数的名字,变量的名字,以及其他一些符号
如果是没有源代码只有一个release版本的exe,那就是真的不好办了,因为我认为这时没办法得到函数的名字,这时我们能不能给这个想要导出的函数取一个名字?


dll文件中有好多函数可以给其他程序调用,这是通过dll文件中的导出表来实现的,导出表中需要记录这个函数的名字和这个函数在文件中的位置(你就理解成函数的地址就可以了)
exe文件中一般是没有导出表的,如果只有一个exe文件,没有源代码,地址是可以找到的,名字怎么办?
把exe文件转换成dll文件,我想,应该给exe文件中添加一个导出表就可以了,但是导出表中要记录这些函数的名字和地址
这个名字不太好办

mosang 发表于 2019-4-26 19:29:13

人造人 发表于 2019-4-22 17:35
好吧,看了这个我明白了,原来只是源码级别的转换,这个太简单了,相对于上面来说^_^
https://fishc.com.c ...

您好,感谢您的回答,我验证了一下,您的例子确实可行,不过我还有另外几个问题想要向您请教,希望能够得到您的解答。

一个还是关于源码转换的问题,我写的exe在运行的时候会自动调用另外的dll,但是在把这个exe转换成dll之后如何确保它在被调用的时候还能够自动调用那些dll?

然后这几天我在网上找了一些关于跨目录调用dll的资料(因为我的程序要被别人的程序调用),找到了一种跨目录调用的方法,如下:
typedef int (*ADD)(int a, int b);

int _tmain(int argc, _TCHAR* argv[])
{
        WORD len = 0;
        HMODULE hModule= GetModuleHandle(L"D:\\Visual Studio\\Dynamita_Link_Library\\SOURCE\\Debug\\SOURCE.dll");
       
        if (NULL == hModule)
                hModule= LoadLibrary(L"D:\\Visual Studio\\Dynamita_Link_Library\\SOURCE\\Debug\\SOURCE.dll");
       
        ADD Add = (ADD)GetProcAddress(hModule, "Add");                //Add(int a, int b)是从dll中导出的函数
        printf("%d\n", Add(2, 3));

        FreeLibrary(hModule);
        getchar();
       
       
        return 0;
}


但是我在把这种方法套到我写的程序上的时候会出现调用不成功的问题,错误提示如下:
0x00000000 处的第一机会异常(在 Load_ToolAssemble.exe 中): 0xC0000005: 执行位置 0x00000000 时发生访问冲突。
程序“ Load_ToolAssemble.exe”已退出,返回值为 0 (0x0)。

我在论坛里看了一下关于这种错误的帖子,好像是什么空指针的问题,但是看不太懂,如果可以的话,也希望能够得到您的解答。跪求!

人造人 发表于 2019-4-27 22:27:55

mosang 发表于 2019-4-26 19:29
您好,感谢您的回答,我验证了一下,您的例子确实可行,不过我还有另外几个问题想要向您请教,希望能够得 ...

论坛发代码不方便
qq: 1440332527
页: [1]
查看完整版本: 求各位鱼友支援一个把exe转化成dll的样例