TR069协议与商业应用5——TR069协议架构设计

article/2025/10/18 21:35:01

声明:原创作品,严禁用于商业目的。 如有任何技术问题,欢迎和我交流:19826269205(微信同号)。

腾讯课堂链接
B站免费视频部分

文章目录

  • 1. TR069(CWMP)程序设计思想
  • 2. 架构分析
  • 3. TR069程序设计
    • 3.1 配置文件解析(libconf)
    • 3.2 日志模块
    • 3.3 XML解析模块
    • 3.4 TASK任务模块
    • 3.5 事件处理模块
    • 3.6 其他线程
  • 4. 数据结构设计
    • 4.1 cwmp_context结构体
    • 4.2 EventType
    • 4.3 设备业务相关
  • 5. 总结

1. TR069(CWMP)程序设计思想

程序架构设计的思想来自于easycwmp官网,看过或者用过easycwmp的工程师应该都知道,该开源代码还有商业版,而且价格不菲。easycwmp官网如是说:DataModel is developped with shell as free solution and with C as commercial solution.。开源代码用来学习还是值得的,若是用于商业产品可能就会显得"力不从心"。具体原因在前面的easycwmp商业源码和免费源码对比中可见,那么如何开发可以商业使用的TR069模块,并且实现DataModel 和CWMP core分离,以便于快速开发业务需求。本篇介绍如何实现这样的系统模块,并且这样的系统模块在主流OEM厂商的研发中非常实用。
TR069设计思想

网管系统目前在一些主流的家用路由、企业网关、语音电话等网络产品中应用广泛。我们可以把TR069部分做一个参考系统名为“TR069平台”,属于远程网管系统的一个子系统。主要功能是通过TR069(CWMP)协议基于可靠链接的TCP协议来远程管理CPE设备。本系统在系统中的位置如图4.1所示。
TR069平台在系统中的位置

2. 架构分析

TR069主体架构协议与设备数据模型层进行分离,达到各产品使用相同的框架,设备相关的编译成一个动态Library或者静态库形式。通过不断的实践,可以使TR069主体框架不断成熟。在国内,可以实现对于同款产品供应给不同的通讯商(电信,移动,联通等),相同的功能,通过可能仅需要改变节点文件XML,基本上不需要改变协议代码。这样,可以快速实现产品的移植开发,更好的维护产品升级。
(1) 对于协议的扩展的分析
对于TR069协议来说,有些功能是可以扩展的。比如事件,可以定义协议规范的上报事件,也可以根据运营商实现私有化或者自定义的事件。比如数据模型的方法,也可以扩展自定义的节点和相应的RPC操作方法等。这些都需要在技术开发实现过程中需要分析清楚。
(2) 对于不同设备,不同产品线差异的分析
需要在相应的XML配置文件中体现出来。
(3) 对于不同TR069客户端之间冲突的分析
在通过TR069改变系统配置的时候,考虑使用进程间互斥来避免发生冲突。
(4) 对于协议开发过程的依赖库分析
对于TR069协议层,主要依赖于网络通信库libcurl和XML文件解析库libexpat,帮助我们简化实现协议层的源码编写工作。,而DataModel数据层,根据自身产品的业务特点,可以使用uci存储、sqlite数据库等实现产品的业务功能开发。
(5) Stun协议支持分析
STUN是RFC3489规定的一种NAT穿透方式,对应于TR111协议,本系统平台采用独立线程运行,支持公网上的网管平台连接,后面会有专门介绍如何实现STUN的CPE侧开发。

3. TR069程序设计

tr069程序的单进程处理流程。大致分为:配置文件解析模块,日志模块,设备xml解析模块,任务模块以及事件处理模块(有关联),多线程模块(可插入模块)等。
原则上,CWMP core的程序代码不需要修改,主要是根据客户的需求修正或者进行"插入式的"新增事件类型和模块化处理。而设备相关的程序,我们封装成了一个动态库(libcwmp.so),便于产品的独立编译和维护开发。
cwmp流程

3.1 配置文件解析(libconf)

根据配置文件的全路径和内容初始化数据结构,使用例子如下:

char      conf_file[PATH_MAX] = {0};
conf_t   *tmp = NULL;
tmp = conf_load(conf_file);
count = conf_get_int(tmp, "global:count", 0);

3.2 日志模块

为了便于和Linux的syslog统一和管理,这里定义的日志等级与syslog一致。 
CWMP_LOG_EMERG ----------------------> EMERG = 0
CWMP_LOG_ALERT ----------------------> ALERT = 1
CWMP_LOG_CRIT ----------------------> CRIT = 2
CWMP_LOG_ERROR ----------------------> ERROR = 3
CWMP_LOG_WARN ---------------------> WARN = 4
CWMP_LOG_NOTICE ---------------------> NOTICE= 5
CWMP_LOG_INFO ---------------------> INFO = 6
CWMP_LOG_DEBUG ---------------------> DEBUG = 7

3.3 XML解析模块

使用libexpat库函数解析设备XML格式文件,以及CWMP和ACS之间交换的SOAP消息。device.xml文件内容如下:

<TR069 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><trf><obj name="InternetGatewayDevice"><param name="DeviceSummary" getval_func="CpeGetDeviceSummary"></param><param name="LANDeviceNumberOfEntries" type="2" getval_func="CpeGetLANDeviceNumberOfEntries"></param><param name="WANDeviceNumberOfEntries" type="2" getval_func="CpeGetWANDeviceNumberOfEntries"></param><obj name="DeviceInfo" noti_rw="1"><param name="SpecVersion" getval_func="CpeGetDeviceInfoSpecVersion"/><param name="HardwareVersion" getval_func="CpeGetDeviceInfoHardwareVersion"></param><param name="SoftwareVersion" getval_func="CpeGetDeviceInfoSoftwareVersion"></param><param name="Manufacturer"      getval_func="CpeGetDeviceInfoManufacturer"></param><param name="SerialNumber"      getval_func="CpeGetDeviceInfoSerialNumber"></param><param name="ManufacturerOUI" getval_func="CpeGetDeviceInfoManufacturerOUI"></param><param name="ProvisioningCode" rw="1" getval_func="CpeGetDeviceInfoProvisioningCode" setval_func="CpeSetDeviceInfoProvisioningCode"></param><param name="ProductClass" getval_func="CpeGetDeviceInfoProductClass"></param><param name="DeviceType" getval_func="CpeGetDeviceInfoDeviceType"></param><param name="ModelName" getval_func="CpeGetDeviceInfoModelName"></param><param name="CpeWANAddress" noti_rw="1" rw="1" getval_func="CpeGetCpeWANAddress" setval_func="CpeSetCpeWANAddress"/></obj><obj name="ManagementServer"><param name="ConnectionRequestURL"                                   getval_func="CpeGetManagementServerConnectionRequestURL"></param><param name="ConnectionRequestUsername"     rw="1"    noti_rw="1"    getval_func="CpeGetManagementServerConnectionRequestUsername" setval_func="CpeSetManagementServerConnectionRequestUsername"></param><param name="ConnectionRequestPassword"     rw="1"    noti_rw="1"    getval_func="CpeGetManagementServerConnectionRequestPassword" setval_func="CpeSetManagementServerConnectionRequestPassword"></param><param name="Username"                      rw="1"    noti_rw="1"    getval_func="CpeGetManagementServerUsername"          setval_func="CpeSetManagementServerUsername"></param><param name="Password"                      rw="1"    noti_rw="1"    getval_func="CpeGetManagementServerPassword"          setval_func="CpeSetManagementServerPassword"></param><param name="ParameterKey"                   getval_func="CpeGetManagementServerParameterKey"      setval_func="CpeSetManagementServerParameterKey"/><param name="URL"                           rw="1"    noti_rw="1"    getval_func="CpeGetManagementServerUrl"               setval_func="CpeSetManagementServerUrl"></param><param name="PeriodicInformEnable"          rw="1"  noti_rw="1"  type="3" getval_func="CpeGetManagementServerPeriodicInformEnable"      setval_func="CpeSetManagementServerPeriodicInformEnable"></param><param name="PeriodicInformInterval"        rw="1"  noti_rw="1"  type="2" getval_func="CpeGetManagementServerPeriodicInformInterval"    setval_func="CpeSetManagementServerPeriodicInformInterval"></param><param name="PeriodicInformTime"            rw="1"          type="4" getval_func="CpeGetManagementServerPeriodicInformTime"        setval_func="CpeSetManagementServerPeriodicInformTime"></param></obj><obj name="Time"><param name="Enable"          rw="1"  type="3"     getval_func="CpeGetTimeEnable"          setval_func="CpeSetTimeEnable"></param><param name="NTPServer1"              rw="1"     getval_func="CpeGetTimeNTPServer1"      setval_func="CpeSetTimeNTPServer1"></param><param name="CurrentLocalTime"       type="4"             getval_func="CpeGetTimeCurrentLocalTime"></param></obj><obj name="X_CT-COM_MonitorCollector"><param name="Enable"      noti_rw="1"     rw="1" type="3"   getval_func="CpeGet_MonitorEnable"                 setval_func="CpeSet_MonitorEnable"></param><obj name="MonitorConfig"  rw="1" addobj_func="TRF_Add_MonitorConfig" delobj_func="TRF_Del_MonitorConfig"  refresh_func="TRF_Refresh_MonitorConfig"><obj name="0"><param name="ParaList"  noti_rw="1"     rw="1"   getval_func="CpeGet_MonitorConfig_ParaList"                 setval_func="CpeSet_MonitorConfig_ParaList"></param><param name="TimeList"   rw="1"  type="2"          getval_func="CpeGet_MonitorConfig_TimeList"      setval_func="CpeSet_MonitorConfig_TimeList"></param></obj></obj></obj><obj name="LANDevice"><obj name="1"><param name="LANEthernetInterfaceNumberOfEntries" type="2" getval_func="CpeGetLANEthernetInterfaceNumberOfEntries"/></obj></obj><obj name="ObjTest"   rw="1"  addobj_func="TRF_Add_ObjTest" delobj_func="TRF_Del_ObjTest" refresh_func="TRF_Refresh_ObjTest"><obj name="0"><param name="TestEnabled" rw="1" type="3" getval_func="CpeGetObjTest_TestEnabled" setval_func="CpeSetObjTest_TestEnabled"/></obj></obj></obj></trf><devlib name="/usr/lib/libcwmp.so"></devlib><auth name="dev_get_auth"></auth><listenport name="dev_get_listenport"></listenport><wanparamname name="dev_get_wanparam_name"></wanparamname><bootstrap name="dev_bootstrap"></bootstrap><init name="dev_init"></init><reboot name="dev_reboot"></reboot><factoryreset name="dev_factoryreset"></factoryreset><download name="dev_download"></download><acsstatus name="dev_set_acs_status"></acsstatus><urldnsresolve name="dev_url_dns_resolve"></urldnsresolve><upload name="dev_upload"></upload><cwmpenable name="dev_cwmp_enable"/><informlist><inform name="InternetGatewayDevice.DeviceInfo.ModelName"/><inform name="InternetGatewayDevice.DeviceInfo.DeviceType"/></informlist><eventlist><event name="X CT-COM BIND"></event></eventlist></TR069>

InternetGatewayDevice是整个参数树的根。obj表示这是一个对象,obj可以读,可以写,当obj的name为0时,表示该obj可以是个模板,为创建后面的实例提供一个模板,当ACS查询时,不会把obj name为0的Obj发送给ACS。Obj的rw=1,表示该obj可以添加子obj,通过addobj_func来添加,通过delobj_func来删除,refresh_func表示刷新该obj下的信息。 Obj的noti_rw =1认为可以设置该obj的属性,譬如notify属性,如果设置了obj的属性,则认为该obj下的所以子树都有该属性。Param表示一个参数项,参数可以读,可以写,通过getval_func来读,通过setval_func来写。noti_rw=1认为可以设置该Param的属性,譬如notify属性。Type的含义如下:

string             ------------------------->         0
int                -------------------------->         1
unsigned int       ----------------------->         2
bool               ------------------------->         3
datetime           ----------------------->         4
base64             ----------------------->         5
long               ------------------------->         6
unsigned long      ---------------------->         7
hex binary         ----------------------->         8
object             ------------------------->         9

3.4 TASK任务模块

根据任务队列中的消息类型进行处理,把需要发送给ACS的事件event消息加入事件队列。

//诊断
#define TASK_DIAG           1
//重启
#define TASK_REBOOT         2
//恢复出厂设置
#define TASK_FACTORY        3
//download
#define TASK_DOWNLOAD       4
//upload
#define TASK_UPLOAD         5
//change ACS URL
#define TASK_CHANGE_ACS_URL 6
#define TASK_SUBDEVICE      7
#define TASK_ADD_EVENT      8
#define TASK_ADD_INFORM     9
#define TASK_CLEAR_EVENT    10#define TASK_VPN_RESTART    20
#define TASK_SYSLOG_RESTART 21
#define TASK_FIREWARE_RESTART 22#define TASK_OTHER          99

3.5 事件处理模块

使用event_handle函数来处理事件,通过信号量来等待是否需要处理的事件,以及从事件队列中获取处理的事件。同理,在其他线程函数中,通过置信号量,将事件加入队列中来通知该模块处理。

    STATUS_IDLE = 0,        /* 空闲状态 */STATUS_INIT,            /* 初始化,获取ACS的URL,以及发送Inform消息*/STATUS_CONN,            /* CPE和ACS处于连接状态,并处理ACS下发的任务 */STATUS_ERROR,         /* 发生错误 */STATUS_FINS,          /* 结束事件处理 */

3.6 其他线程

为了实现"低耦合高内聚"的模块化思想,程序设计采用了多线程来实现。比如:周期上报Inform事件, 根据tr069规范监测参数变化的上报事件,检测WAN口地址变化的事件,STUN线程,DHCP发现ACS地址事件。

4. 数据结构设计

4.1 cwmp_context结构体

cwmp_context结构体是CWMP进程处理的上下文,主要包括初始化设备参数树,Value change,监视参数变化,记录事件等。

struct cwmp_context{file_context_t      file_ctx;           //配置文件trf_param_t         param_root;         //参数树根节点dev_info_t          dev_info;           //设备信息void                *handle_lib;        //设备library的handleint                 acs_port;           //监听ACS的端口int                 acs_retrycount;     //连接ACS重试次数int                 notify_interval;    //监视参数变化的间隔时间pthread_mutex_t     mutex_attr;hash_t              *ht_attr;           //记录参数属性,需要上报的。pthread_mutex_t     mutex_val_change;hash_t              *ht_val_change;     //记录Value Changechar                **inform_array;     //需要上报的参数项数组int                 inform_count;       //需要上报的参数项总数pthread_mutex_t     mutex_inform_tmp;char                **inform_array_tmp; //临时需要上报的参数项数组int                 inform_count_tmp;   //临时需要上报的参数项总数pthread_mutex_t     mutex_evt;int                 evt_count;event_info_t        *evt_array;         //记录事件event_global_t      evt_global_info;    //记录由于重启需要保存的信息sem_t               sem_send_acs;       //发送给acs信息的信号量pthread_mutex_t     mutex_task;         //for task_listlist_t              *task_list;         //task listsem_t               sem_task;pthread_mutex_t     mutex_param;        //对参数进行加锁,防止多线程操作时导致程序不稳定//仅在对参数有操作的线程中加锁trans_t             transfer_info;      //用于Download和Upload
};

4.2 EventType

EventType主要定义了规范中的事件类型:

typedef enum
{EVENT_BOOTSTRAP = 0,EVENT_BOOT,EVENT_PERIODIC,EVENT_SCHEDULED,EVENT_VALUECHANGE,EVENT_KICKED,EVENT_CONNECTIONREQUEST,EVENT_TRANSFERCOMPLETE,EVENT_DIAGNOSTICSCOMPLETE,EVENT_REQUESTDOWNLOAD,EVENT_AUTONOMOUSTRANSFERCOMPLETE,EVENT_MREBOOT,EVENT_MSCHEDULEINFORM,EVENT_MDOWNLOAD,EVENT_MUPLOAD,EVENT_MAXCOUNT
}EventType;

对于自定义的事件类型可以通过xml中如下定义:

   <eventlist><event name="X CT-COM BIND"></event></eventlist>

定义树形结构的节点,每个节点拥有自己的属性和方法。

4.3 设备业务相关

<devlib name="/usr/lib/libcwmp.so"/>                          Libary的位置
<auth name="dev_get_auth"/>                              是否需要开启ACS的认证
<listenport name="dev_get_listenport"/>                          CWMP的监听端口
<wanparamname name="dev_get_wanparam_name"/>                  取得WAN口的参数项名称的全路径
<bootstrap name="dev_bootstrap"/>                          判断是否取得首次连接到ACS的标志
<init name="dev_init"/>                                  初始化设备操作
<reboot name="dev_reboot"/>                              设备的reboot方法
<download name="dev_download"/>                              设备的download的方法,包括下载,升级之类的方法
<upload name="dev_upload"/>                              设备upload的方法,包括生成配置文件,上传日志等方法
<cwmpenable name="dev_cwmp_enable"/>                          判断是否启动CWMP进程
<urldnsresolve name="dev_url_dns_resolve"></urldnsresolve>    ACS的URL解析
...

5. 总结

CWMP core与Datamodel分离,通过不断的调试和实践,并应用于不同的运营商(电信,联通,移动),使得CWMP core的程序不断成熟稳定。
对于相同的功能,我们仅仅需要修改device.xm就可以实现需求,而不用去修改代码;
对于新增的参数项或者节点开发,我们仅需要开发设备相关的库;
对于新增的事件或者ACS下发的任务,修改library的同时我们只需要稍微修改CWMP core的程序就可以达到目的;
对于新增模块,我们采用线程"插入"的思想来实现,而不用修改程序的主体架构。


http://chatgpt.dhexx.cn/article/Mu6N48D3.shtml

相关文章

TR069协议

TR069&#xff08; Technical Report 069&#xff09;全称是“ CPE广域网管理协议&#xff08;CWMP&#xff09;&#xff0c;用于远程终端管理&#xff0c;是 CPE 和 ACS之间沟通的通讯协定。CPE 可以借着这个协定完成服务开通、功能设定、档案上传下载、系统检测 等等初始化及…

TR069浅析

何为TR069&#xff1f; TR069, 全称“Technical Report 069”是由DSL Forum修订的一份技术规范&#xff0c;该规范是应用层的管理协议&#xff0c;命名为“CPE广域网管理协议”。 TR069定义了一套全新的网管体系结构&#xff0c;包括管理模型&#xff0c;交互接口及基本的管理…

TR069

tr069简介 全称是“用户终端设备广域网管理协议&#xff08;CWMP&#xff09; 用于远程终端管理&#xff0c;比如远程的配置阿什么的&#xff08;对远程的设备进行配置等管理&#xff09; 1. TR069协议网络架构 ACS为自动配置服务器&#xff0c;负责对终端设备CPE进行管理…

CWMP协议(TR069协议)学习

文中借鉴了一些大神的整理&#xff0c;后面会贴上链接&#xff0c;如侵删 目录 一、概念&#xff08;来自百度百科&#xff09; 二、网络元素 三、基本功能 四、CWMP协议栈 五、远程调用方法&#xff08;RPC&#xff09;详细的RPC方法定义请参见TR-069 六、inform的事件…

TR069是什么鬼

一&#xff0c;TR069是什么 1&#xff0c;概念 搞嵌入式或通信设备的&#xff0c;或多或少都会听说TR069。那他是什么鬼&#xff1f; TR069&#xff0c;就是CPE广域网管理协议。 它用于ACS和CPE之间的自动协商交互&#xff0c;能够实现终端的自动配置。&#xff08; ACS&#x…

TR069协议详解

一、关于TR069协议 TR069, 全称“Technical Report 069”是由DSL Forum&#xff08;一个非盈利性的全球行业联盟,致力于发展宽带网络范&#xff0c; 其成员包括通讯、设备、计算机、网络和服务提供商等行业的领先厂商&#xff0c;现已更名为“Broadband Forum”&#xff09;修…

TR-069协议介绍

一、概念 关于TR-069 ①协议命名 TR-069, 全称“Technical Report 069”是由DSL Forum&#xff08;一个非盈利性的全球行业联盟,致力于发展宽带网络范&#xff09;。其成员包括通讯、设备、计算机、网络和服务提供商等行业的领先厂商&#xff0c;现已更名为“Broadband Forum…

apache多个php版本fcgi,apache使用mod_proxy_fcgi实现多版本php共存

2019-08-02 apache使用mod_proxy_fcgi实现多版本php共存 首先配置php 安装你想用的php版本&#xff0c;找到你的php-fpm.conf配置文件 将listen换成你想要的端口 比如listen 127.0.0.1:9099 注意&#xff0c;如果你的fpm系变量配置文件在php-fpm.d的www.conf下面&#xff0c;请…

搭建nginx+fcgi并使用Holer实现内外网访问

1、环境搭建 本文使用了ubuntu20.04系统进行搭建。 1.1搭建nginx服务器 到Nginx的官网(http://nginx.org/en/download.html)上去下载最新的源码包&#xff0c;本文使用的是nginx-1.20.0.tar.gz &#xff08;1&#xff09;执行tar -zxvf nginx-1.20.0.tar.gz 命令解压文件到当…

web服务选择lighttpd,采用fcgi组件技术扩展处理业务层

目录 一、简介fcgi&#xff1a;web和web服务器间数据传输的桥梁... 2 二、源码编译配置ARM Lighttpd Fastcgi C.. 3 【1】交叉编译。源文件都从官网下载。 Fcgi lighttpd zlib. 3 【2】配置服务器server.document-root"/www" fastcgi.server "bin-path&quo…

Nginx运行FastCGI程序(ngx_http_fastcgi_module模块、fcgi库、spwan-fcgi进程管理器)

一、什么是CGI 通用网关接口&#xff08;Common Gateway Interface、CGI&#xff09;描述了客户端和服务器程序之间传输数据的一种标准&#xff0c;可以让一个客户端&#xff0c;从网页浏览器向执行在网络服务器上的程序请求数据。 CGI 独立于任何语言的&#xff0c;CGI 程序可…

php运行方式fpm fcgi,php如何从fpm-fcgi切换运行模式到cli

在使用一个php爬虫的时候提示一定要用cli环境 我查看了当前php版本信息如下: 我打印 PHP_SAPI 显示 fpm-fcgi 如何才能变成 cli 服务器环境是linux+nginx 补充:我能不能理解为cli一定是要命令行模式? 刚刚在命令行里测试了PHP_SAPI 输出了cli 问:能不能http模拟调用实现cli…

spwan-fcgi和fcgi 关系

spwan-fcgi: 举个例子&#xff1a; spawn-fcgi -a 127.0.0.1 -p 10000 -f ./login spwan-fcgi.c: main 函数 会执行参数解析过程 获得 ip 端口 和 执行文件的路径。 bind_socket 函数会执行 sockt 的 绑定监听过程&#xff0c; 函数 fcgi_spawn_connection 会通过系统调用d…

nginx+spawn-fcgi+demo+fcgi库函数

由于项目中用到了nginxFastCGI相关内容&#xff0c;所以这段时间学习了一下&#xff0c;顺便记下相关内容。 我是在远程工作机上实验的&#xff0c;有个缺点就是没有root权限&#xff0c;所以有些步骤我就没做了&#xff0c;比如make install&#xff08;nginx&#xff09;、添…

【fcgi-2.4.0】移植fcgi-2.4.0到armv7平台

源码下载链接 Index of /lookaside/extras/fcgi/fcgi-2.4.0.tar.gz/d15060a813b91383a9f3c66faf84867e (fedoraproject.org)https://src.fedoraproject.org/lookaside/extras/fcgi/fcgi-2.4.0.tar.gz/d15060a813b91383a9f3c66faf84867e/下载fcgi-2.4.0.tar.gz 解压源码 tar …

程序异常捕获库 - CrashRpt

CrashRpt.dll用来在应用程序出现异常crash时&#xff0c;捕获到错误&#xff0c;并收集出错信息&#xff1a;MiniDump文件、硬件信息、系统信息、出错信息、进程信息、服务信息、驱动信息、启动信息、软件列表、端口信息、磁盘分区、WinSock LSP、IE插件、网卡信息。 1、使用方…

CrashRpt.dll用来在应用程序出现异常crash

欢迎加入我们的QQ群&#xff0c;无论你是否工作&#xff0c;学生&#xff0c;只要有c / vc / c 编程经验&#xff0c;就来吧&#xff01;158427611 欢迎加入我们的QQ群&#xff0c;无论你是否工作&#xff0c;学生&#xff0c;只要有c / vc / c 编程经验&#xff0c;就来吧&a…

crashRpt使用方法

从官网上下载crashRpt的源码&#xff0c;按说明编译出相应的lib和dll 1 在编译crashRpt的时候&#xff0c;在环境变量中设置 crashrptDirD:\work\AIW\WebMicaps\WebMicapsServer\src\CrashRpt&#xff0c;以简化编译 2 在主程序运行的工作目录下要拷贝crashRpt编译后生成…

CrashRpt使用

CrashRpt 中除了错误处理之外值得学习的地方还是不少的&#xff0c;如屏幕截图、邮件 发送。 这里主要提取屏幕截图的功能。 1. 从 CrashRpt 源码目录中分别复制 minizip 、 zlib 、 libpng 到一个目录作为公 共库使用&#xff0c;并分别编译它们生成 lib &#xff0c;需要设置…

crashRpt用法

从官网上下载crashRpt的源代码&#xff0c;按说明编译出对应的lib和dll 1 在编译crashRpt的时候&#xff0c;在环境变量中设置 crashrptDirD:\work\AIW\WebMicaps\WebMicapsServer\src\CrashRpt&#xff0c;以简化编译 2 在主程序执行的工作文件夹下要拷贝crashRpt编译后生…