您现在的位置是:网站首页> C/C++
VC相关信息
- C/C++
- 2024-10-10
- 606人已阅读
VS2013 编译VC6.0等比较老版本的MFC工程字符集错误问题的解决方法
Windows API(IXMLHTTPRequest)获取XML
特别注意new char[10] 与 new char(10) 区别
FFMPEG学习-版本为4.2.2 使用opencv播放 opencv版本为4.2.0
VS2022设置VC项目的SDK版本
项目右键属性
VC结构体调整字节对齐
在有的编译器中,sizeof得到的结构体内存长度可能比理论值大。例如VC环境下,下面两个结构体类型
struct A {
int a;//4字节
char b;//1字节
short c; //2字节
}
struct B {
char b; //1字节
int a;//4字节
short c; //2字节
}
成员相同 (仅顺序不同) ,理论上它们的内存长度应是4+1+2=7。但实际上sizeof(struct A)的结果为8,sizeof(struct B)的结果为12。
为了加快数据存取的速度,编译器默认情况下会对结构体成员和结构体本身(实际上其他数据对象也是如此) 存储位置进行处理,使其存放的起始地址是一定字节数的倍数,而不是顺序存放,称为字节对齐。
VC默认的字节对齐数为8
更改为1后,sizeof()结果正常。
#include <stdio.h>
#pragma pack(push)
#pragma pack(1)
struct A {
int a;
char b;
short c;
};
struct B {
char b;
int a;
short c;
};
#pragma pack(pop)
int main()
{
printf("A:%llu ", sizeof(A));
printf("B:%llu", sizeof(B));
return 0;
}
执行结果为:A:7 B:7
拦截Console输出
库代码位于:F:\2019LastCode\VC\2020客户端应用\Console2App
典型使用例子是:F:\2019LastCode\VC\2020客户端应用\自动控制模块
库典型代码如下:
#ifndef CONSOLE_H
#define CONSOLE_H
typedef void (*ConsoleOutPtr)(LPVOID pClass,HANDLE hProcess,CString sOut,bool bExit);
struct ConsoleST
{
CString sAppPath;
CString args;
bool bHide;
ConsoleOutPtr m_ConsoleOut;
LPVOID pClass;
HANDLE hProcess;
HANDLE hThread;
bool bExit;
};
extern CString RunConsole(CString sAppPath,CString args,bool bHide);
extern void RunConsoleSrv(CString sAppPath,CString args,bool bHide, ConsoleOutPtr m_ConsoleOut,LPVOID pClass,bool bAsync=false);
#endif
UINT LookProcess(LPVOID p)
{
ConsoleST *pConsoleST=(ConsoleST *)p;
WaitForSingleObject(pConsoleST->hProcess,INFINITE);
if(pConsoleST->m_ConsoleOut!=NULL && !pConsoleST->bExit)
{
//CDC *pDC=CWnd::GetDesktopWindow()->GetWindowDC();
//pDC->TextOut(0,100,"exit111...");
pConsoleST->m_ConsoleOut(pConsoleST->pClass,pConsoleST->hProcess,"",true);
::TerminateThread(pConsoleST->hThread,0);
}
delete pConsoleST;
return 1;
}
void RealRunConsoleSrv(ConsoleST *pConsoleST)
{
CString strCmd = pConsoleST->sAppPath+" "+pConsoleST->args;
SECURITY_ATTRIBUTES sa;
/*
HANDLE hStdInRead,hStdInWrite;
HANDLE hStdOutRead,hStdOutWrite;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL; //使用系统默认的安全描述符
sa.bInheritHandle = TRUE; //创建的进程继承句柄
if (!CreatePipe(&hStdInRead,&hStdInWrite,&sa,0)) //创建读匿名管道
{
if(pConsoleST->m_ConsoleOut!=NULL)
pConsoleST->m_ConsoleOut(pConsoleST->pClass,0,"",true);
delete pConsoleST;
return;
}
if (!CreatePipe(&hStdOutRead,&hStdOutWrite,&sa,0)) //创建读匿名管道
{
if(pConsoleST->m_ConsoleOut!=NULL)
pConsoleST->m_ConsoleOut(pConsoleST->pClass,0,"",true);
delete pConsoleST;
return;
}
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si,sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
si.hStdInput=hStdInRead;
si.hStdError = hStdOutWrite;
si.hStdOutput = hStdOutWrite; //新创建进程的标准输出连在写管道一端
if(pConsoleST->bHide)
si.wShowWindow = SW_HIDE; //隐藏窗口
else
{
si.wShowWindow = SW_SHOW;
}
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
char cmdline[255];
sprintf(cmdline,"%s",(char *)(const char *)strCmd);
*/
HANDLE hStdOutRead,hStdOutWrite;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL; //使用系统默认的安全描述符
sa.bInheritHandle = TRUE; //创建的进程继承句柄
if (!CreatePipe(&hStdOutRead,&hStdOutWrite,&sa,0)) //创建匿名管道
{
if(pConsoleST->m_ConsoleOut!=NULL)
pConsoleST->m_ConsoleOut(pConsoleST->pClass,0,"",true);
delete pConsoleST;
return;
}
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si,sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
si.hStdError = hStdOutWrite;
si.hStdOutput = hStdOutWrite; //新创建进程的标准输出连在写管道一端
if(pConsoleST->bHide)
si.wShowWindow = SW_HIDE; //隐藏窗口
else
{
si.wShowWindow=SW_SHOW;
}
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
char cmdline[255];
sprintf(cmdline,"%s",(char *)(const char *)strCmd);
if (!CreateProcess(NULL,cmdline,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi)) //创建子进程
{
//MessageBox("CreateProcess Failed!","提示",MB_OK | MB_ICONWARNING);
if(pConsoleST->m_ConsoleOut!=NULL)
pConsoleST->m_ConsoleOut(pConsoleST->pClass,0,"",true);
delete pConsoleST;
return;
}
pConsoleST->hProcess=pi.hProcess;
//CloseHandle(hStdInWrite); //关闭管道句柄
//CloseHandle(hStdOutWrite); //关闭管道句柄
CloseHandle(hStdOutWrite); //关闭管道句柄
pConsoleST->bExit=false;
pConsoleST->hThread=GetCurrentThread();
AfxBeginThread(LookProcess,pConsoleST);
char buffer[4096] = {0};
CString strOutput;
DWORD bytesRead;
while (true)
{
if (ReadFile(hStdOutRead,buffer,4095,&bytesRead,NULL) == NULL) //读取管道
{
//AfxMessageBox("read exit");
pConsoleST->bExit=true;
break;
}
if(bytesRead>=0)
{
buffer[bytesRead]=0;
strOutput.Format("%s",buffer);
if(pConsoleST->m_ConsoleOut!=NULL)
{
pConsoleST->m_ConsoleOut(pConsoleST->pClass,pi.hProcess,strOutput,false);
}
}
Sleep(50);
}
CloseHandle(hStdOutRead);
pConsoleST->m_ConsoleOut(pConsoleST->pClass,pi.hProcess,"",true);
}
UINT ConsoleThread(LPVOID p)
{
ConsoleST *pConsoleST=(ConsoleST *)p;
if(pConsoleST!=NULL)
{
RealRunConsoleSrv(pConsoleST);
}
return 1;
}
extern void RunConsoleSrv(CString sAppPath,CString args, bool bHide,ConsoleOutPtr m_ConsoleOut,LPVOID pClass,bool bAsync)
{
ConsoleST *pConsoleST=new ConsoleST();
pConsoleST->args=args;
pConsoleST->sAppPath=sAppPath;
pConsoleST->m_ConsoleOut=m_ConsoleOut;
pConsoleST->pClass=pClass;
pConsoleST->bHide=bHide;
if(bAsync)
{
AfxBeginThread(ConsoleThread,pConsoleST);
}
else
{
RealRunConsoleSrv(pConsoleST);
}
}
extern CString RunConsole(CString sAppPath,CString args,bool bHide)
{
CString strCmd = sAppPath+" "+args;
SECURITY_ATTRIBUTES sa;
HANDLE hStdOutRead,hStdOutWrite;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL; //使用系统默认的安全描述符
sa.bInheritHandle = TRUE; //创建的进程继承句柄
if (!CreatePipe(&hStdOutRead,&hStdOutWrite,&sa,0)) //创建匿名管道
{
return "";
}
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si,sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
si.hStdError = hStdOutWrite;
si.hStdOutput = hStdOutWrite; //新创建进程的标准输出连在写管道一端
if(bHide)
si.wShowWindow = SW_HIDE; //隐藏窗口
else
{
si.wShowWindow=SW_SHOW;
}
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
char cmdline[255];
sprintf(cmdline,"%s",(char *)(const char *)strCmd);
if (!CreateProcess(NULL,cmdline,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi)) //创建子进程
{
//MessageBox("CreateProcess Failed!","提示",MB_OK | MB_ICONWARNING);
return "";
}
CloseHandle(hStdOutWrite); //关闭管道句柄
char buffer[4096] = {0};
CString strOutput="";
DWORD bytesRead;
while (true)
{
if (ReadFile(hStdOutRead,buffer,4095,&bytesRead,NULL) == NULL) //读取管道
break;
strOutput += buffer;
memset(buffer,0,bytesRead);
Sleep(100);
}
CloseHandle(hStdOutRead);
return strOutput;
}
VC客户端应用
配置文件Frame.ini
[软件]
运行一个=1
网络地址=http://www.1xn1.com
包含网络模块=0 #是否包含网路模块 0未不包含 1为包含
[界面]
是否最大化=1
是否花样启动=0
隐藏主菜单栏=0
隐藏主工具栏=0
隐藏广告栏=0
广告栏高度=170
是否框架FACE=0
是否加载FACE=0
标题图片=Caption.bmp
状态栏图片=状态栏.bmp
选栏=选栏.bmp
选栏压=选栏压.bmp
选栏背景色=0xcadedc
子工具栏底图=子工具背景.bmp
BAR背景色=0xffffff
广告框颜色=0xffffff
工具栏背景图=工具背景.bmp
介绍背景图=background.bmp
公司标徽=LOGO.bmp
广告FALSH=
启动画面=splash.bmp
视窗背景图=bei.bmp
退出图片=guan.ico
热退出图片=guan.ico
全屏图片=quan.ico
热全屏图片=quan.ico
配置图片=peizhi.ico
热配置图片=peizhi.ico
帮助图片=hlp.ico
热帮助图片=hlp.ico
模块图片=Mode.ico
热模块图片=Mode.ico
软件名称=Windows客户端框架
软件名称颜色=0xffff00
[本地模块]
nActiveMode=1
ModeCount=3
[MODE_7]
ModeName=智慧农业
ModeFile=智慧农业.dll
ModeWriter=
JiTuanID=
[MODE_2]
ModeName=浏览器
ModeFile=XNChrome.dll
ModeWriter=
JiTuanID=
[MODE_6]
ModeName=巧手在线
ModeFile=巧手在线.dll
ModeWriter=
JiTuanID=
[MODE_1]
ModeName=自动化
ModeFile=AutoCTL.dll
ModeWriter=
JiTuanID=
[MODE_5]
ModeName=增强仪
ModeFile=zqy.dll
ModeWriter=
JiTuanID=
[MODE_4]
ModeName=公有模块
ModeFile=ShareMode.dll
ModeWriter=
JiTuanID=
[MODE_3]
ModeName=高版本VC
ModeFile=SuperVC.dll
ModeWriter=
JiTuanID=
模块编译后位置:
编写模版为dll
包含的Frame.h头文件内容
#ifndef FRAM_H
#define FRAM_H
#define WM_SETSTATUSTEXT WM_USER+1
#define WM_OWNSIZE WM_USER+2000
#define WM_SPKEYDOWN WM_USER+55555
#define WM_MODELOADOVER WM_USER+2001
#define WM_ADDMAINMENU WM_USER+1001
#define WM_SHOWMODE WM_USER+3000
#define WM_EXITAPP WM_USER+2999
#define BaseCommandID WM_USER+50
struct MenuST
{
HWND RehWnd;
UINT nCommandID;
char nCommandName[20];
int nSubWei;
bool bCha;
char strModeName[20];
};
struct ModuleST//模块记录结构
{
HWND hWnd;//模块窗口
char ModuleName[50];//模块名
int nLeftData[5];//保留
};
typedef LPVOID (*RUN_FUNC)(LPVOID PTR,int Length,int &ReturnLength);
struct FuncInfo
{
char FuncName[50];//函数名
RUN_FUNC Func;
int InDataLength;
char InST[400];//输入描述
char OutST[400];//输出描述
};
typedef LPVOID (*EVENT_FUNC)(LPVOID pClass,LPVOID PTR,int Length);
struct OneEventAttach
{
char ToModeName[50];
EVENT_FUNC pFunc;
LPVOID pClass;
};
struct EventAttach
{
char sEventName[50];
char InST[400];//输入描述
CPtrList m_EventPtr;//
};
class AFX_EXT_CLASS COwnMode
{
public:
//用户需要函数
BOOL KillBindEvent(char * sModeName, char * sEventName, EVENT_FUNC pFunc);
BOOL BindEvent(char * sModeName, char * sEventName, EVENT_FUNC pFunc, LPVOID pClass);
void FireEvent(char * sEventName,LPVOID pInData,int L);
bool DetachOutEvent(char * sEventName,char * sFromMode,EVENT_FUNC pFunc);
struct EventAttach * FindOutEventAttach(char * sEventName);
CPtrList m_AllEventLink;
bool AttachOutEvent(char * sEventName,char * sFromMode,EVENT_FUNC pFunc,LPVOID pClass);
void AddOneEvent(char * sEventName,char * sInST);
bool GetChanST(char * FuncName,char * InST,char *OutST);
char ModeName[50];
void TestMode();
void RemoveAllFunc();
RUN_FUNC GetFunc(char * Name,int InDataLength);
bool AddFunc(char * Name,RUN_FUNC MyFunc,char * InST,char * OutST,int InDataLength );
CPtrList FuncList;//保存函数明和它地址的对列
HWND hViewWnd;
COwnMode();
virtual ~COwnMode();
};
class AFX_EXT_CLASS FrameCodeLib
{
public:
FrameCodeLib();
virtual ~FrameCodeLib();
static char * UTF_8ToGB2312(char *pText, int pLen);
static char * GB2312ToUTF_8(char *pText, int pLen);
// Unicode 转换成UTF-8
static void UnicodeToUTF_8(char* pOut,WCHAR* pText);
// GB2312 转换成 Unicode
static void Gb2312ToUnicode(WCHAR* pOut,char *gbBuffer);
// 把Unicode 转换成 GB2312
static void UnicodeToGB2312(char* pOut,unsigned short uData);
// 把UTF-8转换成Unicode
static void UTF_8ToUnicode(WCHAR* pOut,char* pText);
};
extern bool SendDataToOtherModule(char *SourceModuleName,char *ToModuleName,BYTE *Data,int DataLength);//提供给各小模块发送数据
extern void SendSyncDataToOtherModule(char *SourceModuleName,char *ToModuleName,BYTE *Data,int DataLength,int nWait=0);
extern bool ExitFrame();//退出框架
extern void SetUpAllModule(CWnd *ParentWnd,CPtrList &ModelePtr,bool bNET);//安装所有模块
extern LPVOID RunOtherModeFun(char* ModeName,char *FuncName,LPVOID InPtr,int Length,int &ReturnLength);//运行别的模块函数
extern void SetBarText(int nIndex,char *Text);
extern bool AddModeFunc(COwnMode *Mode,char *Name,RUN_FUNC Func,char *InST,char *OutST,int InDataLength=-1);//InDataLength=-1不检查输入长度
extern bool SetModeState(char* ModeName,bool bActive);//设置模块状态
extern bool AddMainMenu(struct MenuST &ST);
extern void ShowModeView(char *sModeName);
extern bool HaveLoadMode(char* ModeName);
extern void GetNameAndIp();
#endif
模块典型代码
#include "stdafx.h"
#include <afxdllx.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#ifdef _DEBUG
#pragma comment(lib,"..\\libD\\Frame.lib")
#else
#pragma comment(lib,"..\\lib\\Frame.lib")
#endif
#include "..\Include\Frame.h"
#include "FrameView.h"
HINSTANCE hDLL=NULL;
static AFX_EXTENSION_MODULE AutoCTLDLL = { NULL, NULL };
CString DllPath;
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
// Remove this if you use lpReserved
UNREFERENCED_PARAMETER(lpReserved);
if (dwReason == DLL_PROCESS_ATTACH)
{
TRACE0("AUTOCTL.DLL Initializing!\n");
// Extension DLL one-time initialization
if (!AfxInitExtensionModule(AutoCTLDLL, hInstance))
return 0;
// Insert this DLL into the resource chain
// NOTE: If this Extension DLL is being implicitly linked to by
// an MFC Regular DLL (such as an ActiveX Control)
// instead of an MFC application, then you will want to
// remove this line from DllMain and put it in a separate
// function exported from this Extension DLL. The Regular DLL
// that uses this Extension DLL should then explicitly call that
// function to initialize this Extension DLL. Otherwise,
// the CDynLinkLibrary object will not be attached to the
// Regular DLL's resource chain, and serious problems will
// result.
char szDllPath[MAX_PATH] = { 0 };
GetModuleFileNameA(AutoCTLDLL.hModule, szDllPath, MAX_PATH);//输出dll所在路径
DllPath.Format("%s",szDllPath);
int nPos=DllPath.ReverseFind('\\');
if(nPos!=-1)
{
DllPath=DllPath.Mid(0,nPos+1);
}
new CDynLinkLibrary(AutoCTLDLL);
hDLL=AutoCTLDLL.hModule;
}
else if (dwReason == DLL_PROCESS_DETACH)
{
TRACE0("AUTOCTL.DLL Terminating!\n");
// Terminate the library before destructors are called
AfxTermExtensionModule(AutoCTLDLL);
}
return 1; // ok
}
class COwnMode MyMode;
CFrameView *pDlg;
HMODULE WINAPI ModuleFromAddress(PVOID pv)
{
MEMORY_BASIC_INFORMATION mbi;
if(::VirtualQuery(pv, &mbi, sizeof(mbi)) != 0)
{
return (HMODULE)mbi.AllocationBase;
}
else
{
return NULL;
}
}
extern HWND SetupMode(HWND hWnd,char *ModuleName)
{
//get_DLL_resource();
//AFX_MANAGE_STATE(AfxGetStaticModuleState());
//GetNameAndIp();
HINSTANCE m_hInst = AfxGetResourceHandle();
AfxSetResourceHandle(AutoCTLDLL.hResource);
hDLL=ModuleFromAddress((PVOID)DllMain);//GetModuleHandle("QiaoMode.dll");
pDlg=new CFrameView();
if(pDlg->Create(IDD_VIEWFRAME,CWnd::FromHandle(hWnd)))
{
AfxSetResourceHandle(m_hInst);
sprintf(MyMode.ModeName,"%s",ModuleName);
//AddModeFunc(&MyMode,"测试过程1",Func1,"char *","char *");
return pDlg->m_hWnd;
}
else
{
AfxSetResourceHandle(m_hInst);
delete pDlg;
pDlg=NULL;
return NULL;
}
}
extern void GetOtherModuleData(char *ModuleName,BYTE *Data,int DataLength)
{
CString Str;
Str.Format("Name:%s Data:%s",ModuleName,Data);
AfxMessageBox(Str);
}
extern bool ExitModule()
{
pDlg->Exit();
return true;
}
extern LPVOID GetFuncClass()
{
return &MyMode;
}
extern void GetMyModeState(bool bActive)
{
}
extern void ShowFloatWnd(bool bShow)
{
if(pDlg==NULL)
return;
if(bShow)
{
//if(bActiveMode)
if(::IsWindow(pDlg->m_hWnd))
{
pDlg->ShowWindow(SW_SHOW);
}
}
else
{
//if(::IsWindowVisible(pDlg->m_hWnd))
if(::IsWindow(pDlg->m_hWnd))
{
pDlg->ShowWindow(SW_HIDE);
}
}
}
模块主窗口改变大小
LRESULT CFrameView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
if(message==WM_OWNSIZE)
{
int CX=wParam,CY=lParam;
SetWindowPos(0,0,0,CX,CY,SWP_NOMOVE|SWP_NOZORDER);
GetDlgItem(IDC_CTRLFRAME)->SetWindowPos(0,0,nMenuHeight+2,CX,CY-nMenuHeight,SWP_NOMOVE|SWP_NOZORDER);
m_DFVCtrl1.SetWindowPos(0,0,nMenuHeight+2,CX,CY-nMenuHeight-2,SWP_NOZORDER);
if(m_wndReBar)
m_wndReBar.SetWindowPos(0,0,0,CX,nMenuHeight,SWP_NOZORDER|SWP_NOMOVE);
}
switch(message)
{
case WM_COMMAND:
{
int nID=LOWORD(wParam);
switch(nID)
{
case ID_LOADFILE:
{
//AfxMessageBox("载入脚本");
CSampleView *pView=(CSampleView *)m_DFVCtrl1.GetView();
if(pView!=NULL)
{
pView->m_ViewRong.LoadFile();
}
}
break;
case ID_CONSOLE:
{
//AfxMessageBox("ok");
pMainFrame->ShowConsole();
}
break;
case 101:
{
AfxMessageBox("打开");
}
break;
}
}
break;
}
return CDialog::WindowProc(message, wParam, lParam);
}
VC++ 任务计划自启动
#include "stdafx.h"
#include <windows.h>
#include <initguid.h>
#include <ole2.h>
#include <mstask.h>
#include <msterr.h>
#include <wchar.h>
#include <stdio.h>
#pragma comment(lib, "Mstask.lib")
#pragma comment(lib, "ole32.lib")
int main(int argc, char **argv)
{
HRESULT hr = S_OK;
ITaskScheduler *pITS;
hr = CoInitialize(NULL);
if (SUCCEEDED(hr))
{
hr = CoCreateInstance(CLSID_CTaskScheduler,
NULL,
CLSCTX_INPROC_SERVER,
IID_ITaskScheduler,
(void **) &pITS);
if (FAILED(hr))
{
CoUninitialize();
return 1;
}
}
else
{
return 1;
}
LPCWSTR pwszTaskName;
ITask *pITask;
pwszTaskName = L"我要启动";
hr = pITS->NewWorkItem(pwszTaskName,
CLSID_CTask,
IID_ITask,
(IUnknown**)&pITask);
if (FAILED(hr))
{
wprintf(L"Failed calling ITaskScheduler::NewWorkItem: ");
wprintf(L"error = 0x%x\n",hr);
CoUninitialize();
return 1;
}
LPCWSTR pwszApplicationName = L"C:\\Users\\Administrator\\Desktop\\ddw\\Debug\\ddw.exe";
hr = pITask->SetApplicationName(pwszApplicationName);
if (FAILED(hr))
{
wprintf(L"Failed calling ITask::SetApplicationName: ");
wprintf(L"error = 0x%x\n",hr);
pITS->Release();
pITask->Release();
CoUninitialize();
return 1;
}
pITask->SetAccountInformation(L"ADMINISTRATOR", NULL);
pITask->SetFlags(TASK_FLAG_RUN_ONLY_IF_LOGGED_ON);
pITask->SetWorkingDirectory(L"C:\\Users\\Administrator\\Desktop\\ddw\\Debug");
pITask->SetParameters(L"");
pITS->AddWorkItem(pwszTaskName, pITask);
pITS->Release();
hr = pITask->Run();
if (FAILED(hr))
{
wprintf(L"Failed calling ITask::Run, error = 0x%x\n",hr);
pITask->Release();
CoUninitialize();
return 1;
}
pITask->Release();
CoUninitialize();
return 0;
}
VS2013 编译VC6.0等比较老版本的MFC工程字符集错误问题的解决方法
用VS2013编译网络上一些用比较老版本的VS写的MFC程序总会出现字符集错误问题,原因是2013取消了对 (MBCS) 库的多字节字符集的默认支持,直接改成Unicode字符集又需要修改很多代码,还很有可能改不好。所以比较直接的解决方法是安装多字节字符串的支持库,官网地址。装上之后再编译就不会有这种问题了。
问题1:
Building an MFC project for a non-Unicode character set is deprecated
解决方法:
用于多字节字符编码 (MBCS) 的 MFC 库 (DLL) 不再包含于 Visual Studio 中,但是可用作插件,您可以在任何装有 Visual Studio Professional、Visual Studio Premium 或 Visual Studio Ultimate 的计算机上下载和安装。(在 Visual Studio 中,必须启用 MFC。)安装需要大约 440 MB 磁盘空间,包括英语(美国)和 DLL 的本地化版本。
在安装 MBCS DLL 后,如果卸载或修复 Visual Studio,则还会卸载或修复。 但是,如果只禁用 MFC,MBCS DLL 仍会保留在系统上。 如果仅卸载或修复 MBCS DLL,将不会修改 Visual Studio。
总结下就是安装 Multibyte MFC Library for Visual Studio 2013
详细信息:http://blogs.msdn.com/b/vcblog/archive/2013/07/08/mfc-support-for-mbcs-deprecated-in-visual-studio-2013.aspx
下载地址:http://www.microsoft.com/zh-cn/download/details.aspx?id=40770
问题2:
warning C4996: 'MBCS_Support_Deprecated_In_MFC': MBCS support in MFC is deprecated and may be removed in a future version of MFC.
解决方法:
这个链接http://go.microsoft.com/fwlink/p/?LinkId=279048文中提到可以通过将 NO_WARN_MBCS_MFC_DEPRECATION 预处理器定义添加到您的项目生成定义消除此警告。在项目stdafx.h文件中的#pragma once下面添加
[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
#define NO_WARN_MBCS_MFC_DEPRECATION
问题3:
error C1189: #error : MFC does not support WINVER less than 0x0501. Please change the definition of WINVER in your project properties or precompiled header.
解决方法:
将stdafx.h文件中的
[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
#define WINVER 0x0400
#define WINVER 0x0501
#define _WIN32_WINNT 0x0400
改为
#define _WIN32_WINNT 0x0501
问题4:
_WIN32_WINNT not defined. Defaulting to _WIN32_WINNT_MAXVER (see WinSDKVer.h)
解决方法:
在StdAfx.h头文件里面加上#include <SDKDDKVer.h>有关于平台的定义
问题5:
warning C4996: 'CWinApp::Enable3dControlsStatic': CWinApp::Enable3dControlsStatic is no longer needed. You should remove this call.
解决方法:
直接注释掉 代码如下
[cpp] view plain copy 在CODE上查看代码片 派生到我的代码片
#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
//Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif
问题6:
LNK4075: ignoring '/EDITANDCONTINUE' due to '/SAFESEH' specification
解决方法:
VS 解决办法:
属性,链接器,常规,启动增量链接 选择 是(INCREMENTAL)
或者
选择项目 属性->配置属性->c/c++
修改 “调试信息格式” 为 程序数据库(/zi)
通过vcpkg安装ffmpeg
vcpkg是微软提供的 C/C++ 库管理工具,音视频开发中常用的库几乎都已经支持了,比如ffmpeg、X264、X265、librtmp等,目前还在不断的新增中。
1.1 安装vcpkg
直接从github上下载 Release 版本并按照文档安装即可
https://github.com/microsoft/vcpkg
//vcpkg安装过程中可能会遇到的问题
① 下载某些源码库失败; (可能是因为网络的原因, 目前还没找到 vcpkg 可以修改镜像地址的地方)
采用的解决方案:直接复制下载报错信息中的地址到 Google 下载,再拷贝到 /downloads 目录中,有些库的名称需要根据vcpkg中的信息进行修改
② boost库校验信息失败;
如:Downloading https://raw.githubusercontent.com/boostorg/boost/boost-1.73.0/LICENSE_1_0.txt... Failed. Status: 6;"Couldn't resolve host name"
采用的解决方案:直接该地址下载对应的LICENSE文件: https://github.com/microsoft/vcpkg/issues/13348)
③ 其他样式的错误;
采用的解决方案: 将VS2019升级到最新
安装
打开clone 下来的vcpkg目录(或解压的目录
shift+鼠标右键打开powershell(或cmd)
输入如下命令:
.\bootstrap-vcpkg.bat
完成后输入
./vcpkg.exe --help
在此分享一个安装好 vcpkg 后如何使用它来安装 C/C++库的博客, 包括如何与VS2019集成等。
https://blog.csdn.net/cjmqas/article/details/79282847
在此向该博客作者表示真挚的感谢
1.2 安装 ffmpeg
动态库方式安装:
.\vcpkg.exe install ffmpeg:x64-windows
或者以静态库的方式安装
.\vcpkg.exe install ffmpeg:x64-windows-static
安装完成后就可以在 vcpkg\installed\x64-windows\bin 中看到ffmpeg相关的库和PDB啦
VC的多字节编程和Unicode编程注意
字符串的处理
char * 变 wchar_t *
CString str=L"你好";
CString str2=L"世界";
str.Format(L"你好%s",str2);
str.Format(L"你好%s",(wchar_t *)(const wchar_t *)str2);
编译器已经把CString视为宽字符处理了,就不能再自动转为char *了
AfxMessageBox(_T("编码类型不正确!"));
在Unicode字符集下写文件的时候,对于长度操作要注意,一个宽字符是要写两个长度的:
CFile fileSave;
CString strGetData(_T("写入测试"));
CString strPath(_T("test.txt"));
if (!fileSave.Open(strPath, CFile::modeCreate |CFile::modeNoTruncate | CFile::modeWrite))
{
return;
}
wchar_t wch = 0xFEFF;
fileSave.Write(&wch, sizeof(wchar_t));
fileSave.Write(strGetData.LockBuffer(), wcslen(strGetData)*2);
strGetData.UnlockBuffer();
fileSave.Close();
使用Unicode字符集还有一大问题,就是CString与char之间的相互转换,以下函数就我总结的转换函数,char转CString函数:
CString Char2CString(char *pChar)
{
int charLen = strlen(pChar); // 计算pChar所指向的字符串大小
int len = MultiByteToWideChar(CP_ACP, 0, pChar, charLen, NULL, 0); // 计算多字节字符的大小
wchar_t *pWChar = new wchar_t[len + 1]; // 为宽字节字符数申请空间
MultiByteToWideChar(CP_ACP, 0, pChar, charLen, pWChar, len); // 多字节编码转换成宽字节编码
pWChar[len] = '\0';
// 将wchar_t数组转换为CString
CString str;
str.Append(pWChar);
delete[] pWChar;
return str;
}
CString转char*函数:
char* CString2Char(CString str)
{
DWORD dwCount = str.GetLength();
int len = WideCharToMultiByte(CP_ACP, 0, str, dwCount, NULL, 0, NULL, NULL); // 获取宽字节字符的大小
char *pChar = new char[len + 1];
WideCharToMultiByte(CP_ACP, 0, str, dwCount, (char *)pChar, len, NULL, NULL); // 宽字节编码转换成多字节编码
pChar[len] = '\0'; // 注意以'\0'结束
return pChar;
}
从代码可以看出,这里CString转char*需要new一个内存空间,使用后得记得delete掉才行。如果不习惯释放空间,那CString转char时最好不要开辟空间,万一忘记delete就造成内存泄露了,可以写一个改进版的转换函数:
tatic int CStrintToCharWithoutNew(CString str, char *buf)
{
int len = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
if (len > 0)
WideCharToMultiByte(CP_ACP, 0, str, -1, buf, len, NULL, NULL);
buf [len] = '\0'; // 注意以'\0'结束
return len;
}
这样使用后就不需要再记得delete了,前提是数组得定义的足够大:
char recvData[200];
CString testdata = _T("测试转换");
len = CStrintToCharWithoutNew(testdata, recvData);
上面的方法虽然基础,但显得麻烦了些,char*转CString只需要使用A2T()或A2W()宏即可:
char cBuf[] = "hello 世界";
CString str = _T("");
USES_CONVERSION;
str = A2T(cBuf);
// str = A2W(cBuf);
如果项目没包含头文件#include <atlconv.h>需要自己加上,USES_CONVERSION宏一定要放在使用前,否则会报错:
类似的CString转char只需使用T2A或W2A宏即可。
C++第三方库管理工具vcpkg使用教程
vcpkg介绍
在使用C/C++编写项目时, 引用第三方库是很麻烦的事, 需要手动下载源码然后编译最后再添加到项目里,配置头文件、lib、dll,如果是一个简单点的库,编译加配置起来也不麻烦,可能半个小时或一个上午就能解决;如果是一个复杂点的库,那可能是一天、乃至一周可能都无法编译成功,例如ffmpeg, openssl,gRPC等等,这些库在windows上的的编译极其麻烦,如果是新手,可能更痛苦。相比 java有maven,python有pip,go有go mod, C#有NuGet,Rust有cargo,这些语言在导入第三方库时都很方便,修改版本也方便,但是对于C++项目则很痛苦,vcpkg的出现解决了C/C++编译第三库困难的问题,vcpkg跨平台, 在windows、linux、MacOS都可以使用。安装vcpkg,想要使用哪个库,vcpkg只要一条命令, 直接用安装编译,无需配置头文件、lib、dll, 直接写代码即可,十分的方便。
官网:https://vcpkg.io/en/index.html
点击Get started可以查看如何安装vcpkg
点击Browse Packages可以查找想要的库
安装如果需要PowerShell审计可下载安装,点击进入下载地址
安装:
clone vcpkg
打开git bash,开始clone vcpkg, 命令:
git clone https://github.com/Microsoft/vcpkg.git
如果网络不好,可能无法clone, 需要有合理良好的网络环境。vcpkag clone ok后,cd到vcpkg目录,执行脚本bootstrap-vcpkg.bat下载vcpkg.exe
vcpkg具体使用
1、演示安装jsoncpp库
将vcpkg.exe目录添加到系统path, 以后在任意目录都可以执行vcpkg.exe命令了,但是安装的文件依然是在vcpkg目录,安装第三方库的命令:
vcpkg install [name]
比如安装jsoncpp库,输入以下命令进行安装
.\vcpkg install jsoncpp
默认安装的是32位的
首次安装时会比较慢,耐心等待。
库的安装位置
指定位数安装
指定版本安装前,先查找是否存在对应的版本,命令
.\vcpkg search 库的名字
如果需要指定版本安装,比如安装64位jsoncpp的,命令如下:
./vcpkg install jsoncpp:x64-windows
查看已经安装了哪些库
命令
./vcpkg list
miniblink最小的基于chromium开发库
windows下注册ocx控件
VC编程经常要用到一些第三方xxx.ocx控件(具体到各个控件的名称),在用之前需要注册,总结了两种方法。
方法一:
1,对于32位系统将xxx.ocx拷贝到C:\Windows\System32,对于64位系统将xxx.ocx拷贝到C:\Windows\System32和C:\windows\SysWOW64下。
2,以管理员身份打开cmd,输入regsvr32 xxx.ocx 回车,OK了。
方法二:
1,对于32位系统将xxx.ocx拷贝到C:\Windows\System32,对于64位系统将xxx.ocx拷贝到C:\windows\SysWOW64下。
2,32位系统,管理员身份打开cmd,输入 regsvr32 C:\Windows\System32\xxx.ocx xxx.ocx就是要注册的的控件的名称
64位系统,管理员身份打开cmd,输入 regsvr32 C:\windows\SysWOW64\xxx.ocx
如果注册成功的话,会弹出DllRegisterServer xxxxxxxx succeeded字样。
Windows API(IXMLHTTPRequest)获取XML
网上大多如微软示例使用的是
#import “msxml6.dll”
using namespace MSXML2;
如下示例并不多见,故查找艰难,以记于此,示于人。
#include <iostream>
#include <atlbase.h>
#include <comdef.h>
#include <msxml6.h>
#pragma comment(lib,"msxml6.lib")
using namespace std;
int main()
{
CoInitialize(NULL);
HRESULT hr;
CComPtr<IXMLHTTPRequest> request;
hr = request.CoCreateInstance(CLSID_XMLHTTP60);
hr = request->open(
_bstr_t("GET"),
_bstr_t("http://192.168.1.77:49152/TxMediaRenderer_desc.xml"),
_variant_t(VARIANT_FALSE),
_variant_t(),
_variant_t());
hr = request->send(_variant_t());
long status;
hr = request->get_status(&status);
BSTR bstrText;
request->get_responseText(&bstrText);
cout << _com_util::ConvertBSTRToString(bstrText) << endl;
SysFreeString(bstrText);
request.Detach();
CoUninitialize();
system("pause");
return 0;
}
// load image data (if url points to an image)
//VARIANT responseVariant;
//hr = request->get_responseStream(&responseVariant);
//IStream* stream = (IStream*)responseVariant.punkVal;
//CImage image = new CImage();
//image->Load(stream);
//stream->Release();
VC6 实现
#include <comdef.h>
#include <atlbase.h>
/*
#include <Mshtml.h>
#import <msxml.dll> named_guids
using namespace MSXML;
*/
#import <msxml6.dll> named_guids //raw_interfaces_only
using namespace MSXML2;
class RunXML
{
public:
bool RemoteRun2(CString Url,CString NameKong,CString Method, CString SoapBody, IXMLDOMDocument **pCOM);
bool RunGetUrl(CString Url, CString &sReturn,CString &sHead);
bool RunForm(CString Url,CString sCan,CString &sReturn,CString &sHead);
bool RemoteRun(CString Url,CString NameKong,CString Method, CString SoapBody,IXMLDOMDocument **pCOM);
CString RemoteRun(CString Url,CString Method,CString SoapBody);
bool RunAction(CString Url,CString sCan,IXMLDOMDocument **pCOM);
//CComPtr<IXMLHTTPRequest> xmlHttpReq;
CComPtr<MSXML2::IXMLHTTPRequest> xmlHttpReq;
//CComPtr<MSXML2::IServerXMLHTTPRequest> xmlHttpReq;
//IXMLDOMDocument *m_pXMLDoc;
RunXML();
virtual ~RunXML();
};
RunXML::RunXML()
{
::CoInitialize(NULL);
/*
HRESULT hr=xmlHttpReq.CoCreateInstance(__uuidof(XMLHTTPRequest), NULL,
CLSCTX_INPROC_SERVER);
*/
//HRESULT hr=xmlHttpReq.CoCreateInstance(__uuidof(ServerXMLHTTP), NULL,
HRESULT hr=xmlHttpReq.CoCreateInstance(__uuidof(XMLHTTP), NULL,
CLSCTX_INPROC_SERVER);
if(!SUCCEEDED(hr))
{
AfxMessageBox("無法創建XMLHTTP對象,請檢查是否安裝了MS XML運行庫!");
}
//m_phttpResCreateInstance(
}
RunXML::~RunXML()
{
xmlHttpReq.Release();
::CoUninitialize();
}
/*
m_XML.RunAction("http://localhost/test3.asp","<用户资料><姓名>谢柠檬</姓名><性别>女</性别></用户资料>");
*/
bool RunXML::RunAction(CString Url, CString sCan,IXMLDOMDocument **pCOM)
{
CString ReturnStr;
HRESULT hRet;
hRet=xmlHttpReq->open("POST",(LPCSTR)Url,false,"");
if(hRet!=0)
return false;
try
{
xmlHttpReq->send((LPCSTR)sCan);
}
catch(_com_error &e)
{
return false;
}
long nState;
CComPtr<IXMLDOMDocument> m_Doc;
/*CComQIPtr<IXMLDOMDocument> m_DocEx;
CComPtr<IXMLDOMElement> m_Ement;
CComPtr<IXMLDOMNodeList>m_NodeList;
*/
xmlHttpReq->get_status(&nState);
if(nState== 200)
{
/*
BSTR sReturn;
xmlHttpReq->get_responseText(&sReturn);
ReturnStr=static_cast<CString>(sReturn);
AfxMessageBox("返回数据为:"+ReturnStr);
*/
xmlHttpReq->get_responseXML((IDispatch **)&m_Doc);
m_Doc.CopyTo(pCOM);
/*
m_Doc->get_documentElement(&m_Ement);
m_Ement->get_baseName(&sReturn);
ReturnStr=static_cast<CString>(sReturn);
SysFreeString(sReturn);
AfxMessageBox("基础键名:"+ReturnStr);
m_Ement->get_childNodes(&m_NodeList);
long nCount;
m_NodeList->get_length(&nCount);
long i;
for(i=0;i<nCount;i++)
{
CComPtr<IXMLDOMNode>m_Node;
m_NodeList->get_item(i,&m_Node);
m_Node->get_baseName(&sReturn);
ReturnStr=static_cast<CString>(sReturn);
SysFreeString(sReturn);
AfxMessageBox(":"+ReturnStr);
m_Node->get_text(&sReturn);
ReturnStr=static_cast<CString>(sReturn);
SysFreeString(sReturn);
AfxMessageBox("值:"+ReturnStr);
}
*/
}
else
{
return false;
}
return true;
}
/*
var SoapBoad="<NO>"+Num +"</NO>"+
"<PWD>"+PassWord+"</PWD>"+
"<nState>"+State+"</nState>"+
"<UserName>"+UserName+"</UserName>"+
"<UserSchool>"+SchoolName+"</UserSchool>";
SoapBoad=RemoteRun(Url,"SetMenJinData",SoapBoad);
*/
/*
CString Data="";
Data+="<NO>Hello My Friends 96500</NO>";
Data+="<PWD>2</PWD>";
Data+="<nState>2</nState>";
Data+="<UserName>2</UserName>";
Data+="<UserSchool>2</UserSchool>";
m_XML.RemoteRun("http://61.128.100.18/JsService/MyService1.asmx","SetMenJinData",Data);
*/
/*
m_XML.RemoteRun("http://61.128.100.18/JsService/MyService1.asmx","GetMenJinDataNO","");
*/
CString RunXML::RemoteRun(CString Url, CString Method, CString SoapBody)
{
CString ReturnStr="";
CString urlStr=Url+"?methodname="+Method;
CString SoapHead ,SoapTail,SoapRequest,TStr,TStr0;
SoapHead = "<?xml version='1.0' encoding='utf-8'?>";
SoapHead+="<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'><soap:Body><";
SoapHead+=Method+" xmlns='http://tempuri.org/'>";
SoapTail = "</"+ Method+"></soap:Body></soap:Envelope>";
SoapRequest = SoapHead + SoapBody + SoapTail;
TRACE("\n");
TRACE(SoapRequest);
COleVariant VQuest(SoapRequest);
BSTR sUrl;
sUrl=urlStr.AllocSysString();
xmlHttpReq->open("POST",sUrl,false);
xmlHttpReq->setRequestHeader("Content-Type", "text/xml;charset=utf-8");
TStr="http://tempuri.org/"+Method;
xmlHttpReq->setRequestHeader("SOAPAction",TStr.AllocSysString());
//一定要与WEBSERVICE的命名空间相同,否则服务会拒绝
TStr0.Format("%d",SoapRequest.GetLength());
xmlHttpReq->setRequestHeader("Content-Length",TStr0.AllocSysString());
xmlHttpReq->send(VQuest);
long nStatus;
xmlHttpReq->get_status(&nStatus);
CComPtr<IXMLDOMDocument> m_Doc;
CComPtr<IXMLDOMNodeList>m_NodeList;
if(nStatus==200)
{
xmlHttpReq->get_responseXML((IDispatch **)&m_Doc);
CString Name;
Name=Method + "Result";
m_NodeList=m_Doc->getElementsByTagName(Name.AllocSysString());
CComPtr<IXMLDOMNode>m_Node;
m_NodeList->get_item(0,&m_Node);
BSTR sReturn;
m_Node->get_text(&sReturn);
ReturnStr=static_cast<CString>(sReturn);
AfxMessageBox(ReturnStr);
SysFreeString(sReturn);
}
return ReturnStr;
}
bool RunXML::RemoteRun(CString Url,CString NameKong,CString Method, CString SoapBody, IXMLDOMDocument **pCOM)
{
return RemoteRun2( Url, NameKong, Method, SoapBody, pCOM);
CString ReturnStr="";
CString urlStr=Url+"?methodname="+Method;
CString SoapHead ,SoapTail,SoapRequest,TStr,TStr0;
SoapHead = "<?xml version='1.0' encoding='utf-8'?>";
SoapHead+="<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'><soap:Body><";
SoapHead+=Method+" xmlns='"+NameKong+"'>";
SoapTail = "</"+ Method+"></soap:Body></soap:Envelope>";
SoapRequest = SoapHead + SoapBody + SoapTail;
TRACE("\n");
BSTR sUrl;
sUrl=urlStr.AllocSysString();
xmlHttpReq->open("POST",sUrl,false);
xmlHttpReq->setRequestHeader("Content-Type", "text/xml;charset=utf-8");
if(NameKong.Mid(NameKong.GetLength()-1)=="/")
TStr=NameKong+Method;
else
TStr=NameKong+"/"+Method;
BSTR bStr0=TStr.AllocSysString();
// xmlHttpReq->setRequestHeader("SOAPAction",TStr.AllocSysString());
xmlHttpReq->setRequestHeader("SOAPAction",bStr0);
//一定要与WEBSERVICE的命名空间相同,否则服务会拒绝
TStr0.Format("%d",SoapRequest.GetLength());
BSTR bStr1=TStr.AllocSysString();
//xmlHttpReq->setRequestHeader("Content-Length",TStr0.AllocSysString());
xmlHttpReq->setRequestHeader("Content-Length",bStr1);
BSTR bStr2=SoapRequest.AllocSysString();
try
{
//xmlHttpReq->send(VQuest);
xmlHttpReq->send(bStr2);
}
catch(_com_error &e)
{
// AfxMessageBox("调用失败");
::SysFreeString(bStr0);
::SysFreeString(bStr1);
::SysFreeString(bStr2);
CString m_strErrorString;
m_strErrorString.Format("%s:%s",e.ErrorMessage(),(LPCTSTR)e.Description());
AfxMessageBox(m_strErrorString);
return false;
}
//CString tStr = (char* )(_bstr_t)VQuest;
// AfxMessageBox(tStr);
::SysFreeString(bStr0);
::SysFreeString(bStr1);
::SysFreeString(bStr2);
long nStatus;
xmlHttpReq->get_status(&nStatus);
CComPtr<IXMLDOMDocument> m_Doc;
CComPtr<IXMLDOMNodeList>m_NodeList;
if(nStatus==200)
{
xmlHttpReq->get_responseXML((IDispatch **)&m_Doc);
m_Doc.CopyTo(pCOM);
return true;
}
else
{
CString m_strErrorString;
m_strErrorString.Format("nStatus 错误:%d",nStatus);
AfxMessageBox(m_strErrorString);
return false;
}
}
bool RunXML::RunForm(CString Url, CString sCan, CString &sReturn,CString &sHead)
{
CString ReturnStr;
HRESULT hRet;
hRet=xmlHttpReq->open("POST",(LPCSTR)Url,false,"");
if(hRet!=0)
return false;
try
{
xmlHttpReq->setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xmlHttpReq->send((LPCSTR)sCan);
}
catch(_com_error &e)
{
return false;
}
long nState;
xmlHttpReq->get_status(&nState);
if(nState== 200)
{
BSTR sbReturn;
//xmlHttpReq->get_responseText(&sbReturn);
HRESULT hr;
IStream *pIStream = NULL;
VARIANT varValue;
BSTR bStr;
bStr=xmlHttpReq->getAllResponseHeaders();
// hr = xmlHttpReq->get_responseStream(&varValue);
sHead=static_cast<CString>(bStr);
::SysFreeString(bStr);
try
{
// Create XMLHttpRequest object and initialize pIXMLHttpRequest.
hr = xmlHttpReq->get_responseStream(&varValue);
if(SUCCEEDED(hr))
{
pIStream = (IStream*)varValue.punkVal;
if(pIStream)
{
HGLOBAL h;
GetHGlobalFromStream(pIStream,&h);
DWORD size = GlobalSize(h);//大小
char *pStr=new char[size+1];
memset(pStr,0,size+1);
unsigned long nSize;
pIStream->Read(pStr,size,&nSize);
sReturn.Format("%s",pStr);
pIStream->Release();
pIStream = NULL;
delete[] pStr;
}
}
}
catch(...)
{
if(pIStream)
pIStream->Release();
return false;
}
/*
BSTR sbReturn;
CComPtr<IHTMLDocument2> m_Doc;
xmlHttpReq->get_responseStream((IDispatch **)&m_Doc);
// sReturn=CString((BSTR)m_Doc->xml);
CComPtr<IHTMLElement>m_AllElement ;
m_Doc->get_body(&m_AllElement);
m_AllElement->get_innerHTML(&sbReturn);
sReturn=static_cast<CString>(sbReturn);
*/
return true;
}
return false;
}
bool RunXML::RunGetUrl(CString Url, CString &sReturn,CString &sHead)
{
CString ReturnStr;
HRESULT hRet;
hRet=xmlHttpReq->open("GET",(LPCSTR)Url,false,"");
if(hRet!=0)
return false;
try
{
// xmlHttpReq->setRequestHeader("Content-Type","application/x-www-form-urlencoded");
if(sHead!="")
xmlHttpReq->setRequestHeader("Cookie",(LPCSTR)sHead);
xmlHttpReq->send("");
}
catch(_com_error &e)
{
return false;
}
long nState;
xmlHttpReq->get_status(&nState);
if(nState== 200)
{
BSTR sbReturn;
//xmlHttpReq->get_responseText(&sbReturn);
HRESULT hr;
IStream *pIStream = NULL;
VARIANT varValue;
BSTR bStr;
bStr=xmlHttpReq->getResponseHeader((LPCSTR)"Set-Cookie");
sHead=static_cast<CString>(bStr);
::SysFreeString(bStr);
try
{
// Create XMLHttpRequest object and initialize pIXMLHttpRequest.
hr = xmlHttpReq->get_responseStream(&varValue);
//xmlHttpReq->getResponseHeader("Set-Cookie");
if(SUCCEEDED(hr))
{
pIStream = (IStream*)varValue.punkVal;
if(pIStream)
{
HGLOBAL h;
GetHGlobalFromStream(pIStream,&h);
DWORD size = GlobalSize(h);//大小
char *pStr=new char[size+1];
memset(pStr,0,size+1);
unsigned long nSize;
pIStream->Read(pStr,size,&nSize);
sReturn.Format("%s",pStr);
pIStream->Release();
pIStream = NULL;
delete[] pStr;
}
}
}
catch(...)
{
if(pIStream)
pIStream->Release();
return false;
}
/*
BSTR sbReturn;
CComPtr<IHTMLDocument2> m_Doc;
xmlHttpReq->get_responseStream((IDispatch **)&m_Doc);
// sReturn=CString((BSTR)m_Doc->xml);
CComPtr<IHTMLElement>m_AllElement ;
m_Doc->get_body(&m_AllElement);
m_AllElement->get_innerHTML(&sbReturn);
sReturn=static_cast<CString>(sbReturn);
*/
return true;
}
return false;
}
bool RunXML::RemoteRun2(CString Url, CString NameKong, CString Method, CString SoapBody, IXMLDOMDocument **pCOM)
{
CString ReturnStr="";
CString urlStr=Url+"?methodname="+Method;
CString SoapHead ,SoapTail,SoapRequest,TStr,TStr0;
SoapHead = "<?xml version='1.0' encoding='utf-8'?>";
SoapHead+="<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'><soap:Body><";
SoapHead+=Method+" xmlns='"+NameKong+"'>";
SoapTail = "</"+ Method+"></soap:Body></soap:Envelope>";
SoapRequest = SoapHead + SoapBody + SoapTail;
TRACE("\n");
BSTR sUrl;
sUrl=urlStr.AllocSysString();
xmlHttpReq->open("POST",sUrl,false);
xmlHttpReq->setRequestHeader("Content-Type", "text/xml;charset=utf-8");
if(NameKong.Mid(NameKong.GetLength()-1)=="/")
TStr=NameKong+Method;
else
TStr=NameKong+"/"+Method;
BSTR bStr0=TStr.AllocSysString();
// xmlHttpReq->setRequestHeader("SOAPAction",TStr.AllocSysString());
xmlHttpReq->setRequestHeader("SOAPAction",bStr0);
//一定要与WEBSERVICE的命名空间相同,否则服务会拒绝
TStr0.Format("%d",SoapRequest.GetLength());
BSTR bStr1=TStr0.AllocSysString();
//xmlHttpReq->setRequestHeader("Content-Length",TStr0.AllocSysString());
xmlHttpReq->setRequestHeader("Content-Length",bStr1);
BSTR bStr2=SoapRequest.AllocSysString();
try
{
//xmlHttpReq->send(VQuest);
xmlHttpReq->send(bStr2);
}
catch(_com_error &e)
{
// AfxMessageBox("调用失败");
::SysFreeString(bStr0);
::SysFreeString(bStr1);
::SysFreeString(bStr2);
CString m_strErrorString;
m_strErrorString.Format("%s:%s",e.ErrorMessage(),(LPCTSTR)e.Description());
AfxMessageBox(m_strErrorString);
return false;
}
//CString tStr = (char* )(_bstr_t)VQuest;
// AfxMessageBox(tStr);
::SysFreeString(bStr0);
::SysFreeString(bStr1);
::SysFreeString(bStr2);
long nStatus;
xmlHttpReq->get_status(&nStatus);
CComPtr<IXMLDOMDocument> m_Doc;
CComPtr<IXMLDOMNodeList>m_NodeList;
if(nStatus==200)
{
xmlHttpReq->get_responseXML((IDispatch **)&m_Doc);
m_Doc.CopyTo(pCOM);
return true;
}
else
{
CString m_strErrorString;
m_strErrorString.Format("nStatus 错误:%d",nStatus);
AfxMessageBox(m_strErrorString);
return false;
}
}
win11如何运行vc++6.0
如果运行,就会提示下图的程序兼容,点在线获取帮助,还是运行程序而不获取帮助,程序一闪而过,怎么也运行不起来。
想到程序兼容,我去属性设置程序兼容,这个错误提示依旧弹出来。
后来研究了很久,才找到解决办法。
可以进入安装目录,把Microsoft Visual Studio\Common\MSDev98\Bin\MSDEV.exe。
复制一个MSDEV.exe副本,然后把副本改名为MSDEV1.exe。
点击MSDEV1.exe,然后右键属性,点击兼容性,勾选兼容模式windows 7,最后勾选管理员。
然后点击MSDEV1.exe发送到桌面快捷方式。直接运行程序即可。
但是在运行代码的时候,还是会弹出程序兼容性提示。
不用管他,直接点关闭,程序结果就运行出来了。
VC使用miniblink
弹出窗口
#include "..\include\wke.h"
#include "odeLib.h"
wkeSetWkeDllPath(L"node.dll");
wkeInitialize();
//for(int i=0;i<50;i++)
{
wkeWebView window=wkeCreateWebWindow(WKE_WINDOW_TYPE_POPUP,NULL, 0, 0, 1080, 680);
wkeLoadURL(window,"qq.com");
wkeShowWindow(window,TRUE);
}
//非弹出窗口
wkeWebView m_web;
// 页面标题更改时调用此回调
void _cdecl wkeOnTitleChangedCallBack(wkeWebView webView, void* param, const wkeString title)
{
CMFCMiniWebDlg *pDlg = (CMFCMiniWebDlg*)param;
if (NULL != pDlg)
{
const char *pUTF8Str=wkeGetString(title);
char *pGBStr=CodeLib::UTF_8ToGB2312((char *)pUTF8Str,strlen(pUTF8Str));
pDlg->SetWindowText(pGBStr);
delete[]pGBStr;
}
}
void _cdecl wkeOnDocumentReady2CallBack(wkeWebView webView, void* param,wkeWebFrameHandle frameId)
{
//AfxMessageBox("ok");
}
//中转函数
jsValue JS_CALL js_msgBox(jsExecState es)
{
const char *jsonString= jsToString(es, jsArg(es, 0));
//转编码格式
char *pStr=CodeLib::UTF_8ToGB2312((char *)jsonString,strlen(jsonString));
delete[]pStr;
//返回对象
jsValue jv = jsEmptyObject(es);
CString sText="xuneng汉语";
pStr=CodeLib::GB2312ToUTF_8((char *)(const char *)sText,sText.GetLength());
jsValue jOv1 = jsString(es, pStr);
delete[]pStr;
jsValue jOv2 = jsInt(2);
jsSet(es, jv, "name", jOv1);
jsSet(es, jv, "age", jOv2);
return jv;
}
BOOL CMFCMiniWebDlg::OnInitDialog()
{
CDialog::OnInitDialog();
wkeInitialize();
CRect rt;
m_RongWnd.GetClientRect(&rt);
jsBindFunction("msgBox", js_msgBox, 1);//JS调用C++
m_web=wkeCreateWebWindow(WKE_WINDOW_TYPE_CONTROL,m_RongWnd.m_hWnd, 0, 0, rt.Width(),rt.Height());
wkeOnTitleChanged(m_web, wkeOnTitleChangedCallBack, this);
wkeOnDocumentReady2(m_web, wkeOnDocumentReady2CallBack, this);
wkeLoadURL(m_web,"https://u.jd.com/5MJw57k");//"http://www.1xn1.com");
wkeShowWindow(m_web,TRUE);
}
//执行js
void CMFCMiniWebDlg::OnButton1()
{
// TODO: Add your control notification handler code here
CString TStr;
TStr="alert('你哈');var obj=window.msgBox('3333成都');alert(obj.name); return '123';";
//TStr="var str=document.documentElement.outerHTML;alert(str); return str;";
char *pStr=CodeLib::GB2312ToUTF_8((char *)(const char *)TStr, TStr.GetLength());
jsValue jsRet =wkeRunJS(m_web,pStr);
char *pUTF8String=(char *)jsToString(wkeGlobalExec(m_web), jsRet);
char *ss=CodeLib::UTF_8ToGB2312(pUTF8String, strlen(pUTF8String));
//AfxMessageBox(ss);
CFile MyFile("f:\\1.txt",CFile::modeCreate |CFile::modeReadWrite);
MyFile.WriteHuge(ss,strlen(ss));
MyFile.Close();
delete[]ss;
delete[] pStr;
}
void CMFCMiniWebDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
if(m_RongWnd)
{
m_RongWnd.SetWindowPos(NULL,0,0,cx-10,cy-80,SWP_NOMOVE|SWP_NOZORDER|SWP_SHOWWINDOW);
wkeResize(m_web,cx-10,cy-80);
}
// TODO: Add your message handler code here
}
class CodeLib
{
public:
static char * UTF_8ToGB2312(char *pText, int pLen);
static char * GB2312ToUTF_8(char *pText, int pLen);
// Unicode 转换成UTF-8
static void UnicodeToUTF_8(char* pOut,WCHAR* pText);
// GB2312 转换成 Unicode
static void Gb2312ToUnicode(WCHAR* pOut,char *gbBuffer);
// 把Unicode 转换成 GB2312
static void UnicodeToGB2312(char* pOut,unsigned short uData);
// 把UTF-8转换成Unicode
static void UTF_8ToUnicode(WCHAR* pOut,char* pText);
CodeLib();
virtual ~CodeLib();
};
CodeLib::CodeLib()
{
}
CodeLib::~CodeLib()
{
}
void CodeLib::UTF_8ToUnicode(WCHAR* pOut,char *pText)
{
char* uchar = (char *)pOut;
uchar[1] = ((pText[0] & 0x0F) << 4) + ((pText[1] >> 2) & 0x0F);
uchar[0] = ((pText[1] & 0x03) << 6) + (pText[2] & 0x3F);
return;
}
void CodeLib::UnicodeToGB2312(char* pOut,unsigned short uData)
{
WideCharToMultiByte(CP_ACP,NULL,&uData,1,pOut,sizeof(WCHAR),NULL,NULL);
return;
}
void CodeLib::Gb2312ToUnicode(WCHAR* pOut,char *gbBuffer)
{
::MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,gbBuffer,2,pOut,1);
return;
}
void CodeLib::UnicodeToUTF_8(char* pOut,WCHAR* pText)
{
// 注意 WCHAR高低字的顺序,低字节在前,高字节在后
char* pchar = (char *)pText;
pOut[0] = (0xE0 | ((pchar[1] & 0xF0) >> 4));
pOut[1] = (0x80 | ((pchar[1] & 0x0F) << 2)) + ((pchar[0] & 0xC0) >> 6);
pOut[2] = (0x80 | (pchar[0] & 0x3F));
return;
}
char * CodeLib::GB2312ToUTF_8(char *pText, int pLen)
{
char buf[4];
char* rst = new char[pLen + (pLen >> 2) + 2];
memset(buf,0,4);
memset(rst,0,pLen + (pLen >> 2) + 2);
int i = 0;
int j = 0;
while(i < pLen)
{
//如果是英文直接复制就可以
if( *(pText + i) >= 0)
{
rst[j++] = pText[i++];
}
else
{
WCHAR pbuffer;
Gb2312ToUnicode(&pbuffer,pText+i);
UnicodeToUTF_8(buf,&pbuffer);
unsigned short int tmp = 0;
tmp = rst[j] = buf[0];
tmp = rst[j+1] = buf[1];
tmp = rst[j+2] = buf[2];
j += 3;
i += 2;
}
}
rst[j] = '\0';
//返回结果
/*
pOut = rst;
delete []rst;
*/
return rst;
}
char * CodeLib::UTF_8ToGB2312( char *pText, int pLen)
{
char * newBuf = new char[pLen*2];
char Ctemp[4];
memset(Ctemp,0,4);
int i =0;
int j = 0;
while(i < pLen)
{
if(pText[i] > 0)
{
newBuf[j++] = pText[i++];
}
else
{
WCHAR Wtemp;
UTF_8ToUnicode(&Wtemp,pText + i);
UnicodeToGB2312(Ctemp,Wtemp);
newBuf[j] = Ctemp[0];
newBuf[j + 1] = Ctemp[1];
i += 3;
j += 2;
}
}
newBuf[j] = '\0';
/*
pOut = newBuf;
delete []newBuf;
*/
return newBuf;
}
Windows应用程序如何访问GPIO引脚?
在Linux中,使用访问/ dev / gpio *文件或使用inb()/ outb()访问GPIO引脚等方式访问GPIO引脚似乎非常容易。有没有这么简单的方法在Windows中访问应用程序中的GPIO引脚,而不是驱动程序级别?
注册自己的URL
拿javascript执行后的页面内容
jameshooo,你纯粹在误人子弟,我都已经拿到了内容了
IHTMLElement *body;
pHTMLDocument->get_body(&body);
CString sHtml;
if (body)
{
BSTR bs;
HRESULT h = body->get_innerHTML(&bs);
if (h != S_OK)
{
MessageBox(L"Error");
}
else
{
//sHtml = _com_util::ConvertBSTRToString( bs );
}
}
这样拿到的就是javascript执行之后的页面内容。
这个垃圾坛子他妈的越来越多滥竽充数,还振振有词的假牛,从不回复技术帖子,实在是觉得误人子弟
C++ string类(C++字符串)完全攻略
string 类是 STL 中 basic_string 模板实例化得到的模板类。其定义如下:
typedef basic_string <char> string;
basic_string 此处可以不必深究。
string 类的成员函数有很多,同一个名字的函数也常会有五六个重载的版本。篇幅所限,不能将这些原型一一列出并加以解释。这里仅对常用成员函数按功能进行分类,并直接给出应用的例子,通过例子,读者可以基本掌握这些成员函数的用法。
要想更深入地了解 string 类,还要阅读 C++ 的参考手册或编译器自带的联机资料。对于前面介绍过的字符串处理的内容,这里不再重复说明。
1. 构造函数
string 类有多个构造函数,用法示例如下:
string s1(); // si = ""
string s2("Hello"); // s2 = "Hello"
string s3(4, 'K'); // s3 = "KKKK"
string s4("12345", 1, 3); //s4 = "234",即 "12345" 的从下标 1 开始,长度为 3 的子串
为称呼方便,本教程后文将从字符串下标 n 开始、长度为 m 的字符串称为“子串(n, m)”。
string 类没有接收一个整型参数或一个字符型参数的构造函数。下面的两种写法是错误的:
string s1('K');
string s2(123);
2. 对 string 对象赋值
可以用 char* 类型的变量、常量,以及 char 类型的变量、常量对 string 对象进行赋值。例如:
string s1;
s1 = "Hello"; // s1 = "Hello"
s2 = 'K'; // s2 = "K”
string 类还有 assign 成员函数,可以用来对 string 对象赋值。assign 成员函数返回对象自身的引用。例如:
string s1("12345"), s2;
s3.assign(s1); // s3 = s1
s2.assign(s1, 1, 2); // s2 = "23",即 s1 的子串(1, 2)
s2.assign(4, 'K'); // s2 = "KKKK"
s2.assign("abcde", 2, 3); // s2 = "cde",即 "abcde" 的子串(2, 3)
3. 求字符串的长度
length 成员函数返回字符串的长度。size 成员函数可以实现同样的功能。
4. string对象中字符串的连接
除了可以使用+和+=运算符对 string 对象执行字符串的连接操作外,string 类还有 append 成员函数,可以用来向字符串后面添加内容。append 成员函数返回对象自身的引用。例如:
string s1("123"), s2("abc");
s1.append(s2); // s1 = "123abc"
s1.append(s2, 1, 2); // s1 = "123abcbc"
s1.append(3, 'K'); // s1 = "123abcbcKKK"
s1.append("ABCDE", 2, 3); // s1 = "123abcbcKKKCDE",添加 "ABCDE" 的子串(2, 3)
5. string对象的比较
除了可以用 <、<=、==、!=、>=、> 运算符比较 string 对象外,string 类还有 compare 成员函数,可用于比较字符串。compare 成员函数有以下返回值:
小于 0 表示当前的字符串小;
等于 0 表示两个字符串相等;
大于 0 表示另一个字符串小。
例如:
string s1("hello"), s2("hello, world");
int n = s1.compare(s2);
n = s1.compare(1, 2, s2, 0, 3); //比较s1的子串 (1,2) 和s2的子串 (0,3)
n = s1.compare(0, 2, s2); // 比较s1的子串 (0,2) 和 s2
n = s1.compare("Hello");
n = s1.compare(1, 2, "Hello"); //比较 s1 的子串(1,2)和"Hello”
n = s1.compare(1, 2, "Hello", 1, 2); //比较 s1 的子串(1,2)和 "Hello" 的子串(1,2)
6. 求 string 对象的子串
substr 成员函数可以用于求子串 (n, m),原型如下:
string substr(int n = 0, int m = string::npos) const;
调用时,如果省略 m 或 m 超过了字符串的长度,则求出来的子串就是从下标 n 开始一直到字符串结束的部分。例如:
string s1 = "this is ok";
string s2 = s1.substr(2, 4); // s2 = "is i"
s2 = s1.substr(2); // s2 = "is is ok"
7. 交换两个string对象的内容
swap 成员函数可以交换两个 string 对象的内容。例如:
string s1("West”), s2("East");
s1.swap(s2); // s1 = "East",s2 = "West"
8. 查找子串和字符
string 类有一些查找子串和字符的成员函数,它们的返回值都是子串或字符在 string 对象字符串中的位置(即下标)。如果查不到,则返回 string::npos。string: :npos 是在 string 类中定义的一个静态常量。这些函数如下:
find:从前往后查找子串或字符出现的位置。
rfind:从后往前查找子串或字符出现的位置。
find_first_of:从前往后查找何处出现另一个字符串中包含的字符。例如:
s1.find_first_of("abc"); //查找s1中第一次出现"abc"中任一字符的位置
find_last_of:从后往前查找何处出现另一个字符串中包含的字符。
find_first_not_of:从前往后查找何处出现另一个字符串中没有包含的字符。
find_last_not_of:从后往前查找何处出现另一个字符串中没有包含的字符。
下面是 string 类的查找成员函数的示例程序。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1("Source Code");
int n;
if ((n = s1.find('u')) != string::npos) //查找 u 出现的位置
cout << "1) " << n << "," << s1.substr(n) << endl;
//输出 l)2,urce Code
if ((n = s1.find("Source", 3)) == string::npos)
//从下标3开始查找"Source",找不到
cout << "2) " << "Not Found" << endl; //输出 2) Not Found
if ((n = s1.find("Co")) != string::npos)
//查找子串"Co"。能找到,返回"Co"的位置
cout << "3) " << n << ", " << s1.substr(n) << endl;
//输出 3) 7, Code
if ((n = s1.find_first_of("ceo")) != string::npos)
//查找第一次出现或 'c'、'e'或'o'的位置
cout << "4) " << n << ", " << s1.substr(n) << endl;
//输出 4) l, ource Code
if ((n = s1.find_last_of('e')) != string::npos)
//查找最后一个 'e' 的位置
cout << "5) " << n << ", " << s1.substr(n) << endl; //输出 5) 10, e
if ((n = s1.find_first_not_of("eou", 1)) != string::npos)
//从下标1开始查找第一次出现非 'e'、'o' 或 'u' 字符的位置
cout << "6) " << n << ", " << s1.substr(n) << endl;
//输出 6) 3, rce Code
return 0;
}
9. 替换子串
replace 成员函数可以对 string 对象中的子串进行替换,返回值为对象自身的引用。例如:
string s1("Real Steel");
s1.replace(1, 3, "123456", 2, 4); //用 "123456" 的子串(2,4) 替换 s1 的子串(1,3)
cout << s1 << endl; //输出 R3456 Steel
string s2("Harry Potter");
s2.replace(2, 3, 5, '0'); //用 5 个 '0' 替换子串(2,3)
cout << s2 << endl; //输出 HaOOOOO Potter
int n = s2.find("OOOOO"); //查找子串 "00000" 的位置,n=2
s2.replace(n, 5, "XXX"); //将子串(n,5)替换为"XXX"
cout << s2 < < endl; //输出 HaXXX Potter
10. 删除子串
erase 成员函数可以删除 string 对象中的子串,返回值为对象自身的引用。例如:
string s1("Real Steel");
s1.erase(1, 3); //删除子串(1, 3),此后 s1 = "R Steel"
s1.erase(5); //删除下标5及其后面的所有字符,此后 s1 = "R Ste"
11. 插入字符串
insert 成员函数可以在 string 对象中插入另一个字符串,返回值为对象自身的引用。例如:
string s1("Limitless"), s2("00");
s1.insert(2, "123"); //在下标 2 处插入字符串"123",s1 = "Li123mitless"
s1.insert(3, s2); //在下标 2 处插入 s2 , s1 = "Li10023mitless"
s1.insert(3, 5, 'X'); //在下标 3 处插入 5 个 'X',s1 = "Li1XXXXX0023mitless"
12. 将 string 对象作为流处理
使用流对象 istringstream 和 ostringstream,可以将 string 对象当作一个流进行输入输出。使用这两个类需要包含头文件 sstream。
示例程序如下:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main()
{
string src("Avatar 123 5.2 Titanic K");
istringstream istrStream(src); //建立src到istrStream的联系
string s1, s2;
int n; double d; char c;
istrStream >> s1 >> n >> d >> s2 >> c; //把src的内容当做输入流进行读取
ostringstream ostrStream;
ostrStream << s1 << endl << s2 << endl << n << endl << d << endl << c <<endl;
cout << ostrStream.str();
return 0;
}
程序的输出结果是:
Avatar
Titanic
123
5.2
K
第 11 行,从输入流 istrStream 进行读取,过程和从 cin 读取一样,只不过输入的来源由键盘变成了 string 对象 src。因此,"Avatar" 被读取到 s1,123 被读取到 n,5.2 被读取到 d,"Titanic" 被读取到s2,'K' 被读取到 c。
第 12 行,将变量的值输出到流 ostrStream。输出结果不会出现在屏幕上,而是被保存在 ostrStream 对象管理的某处。用 ostringstream 类的 str 成员函数能将输出到 ostringstream 对象中的内容提取出来。
dll的搜索顺序
我们可以使用LoadLibrary()或LoadLibraryEx()来显式地加载某个dll,在我们未提供dll全路径或调用SetDefaultDllDirectories和 AddDllDirectory两个API对DLL路径进行设置时,系统依然会尝试着在某些目录下寻找我们想要的DLL文件,在寻找DLL时,Windows系统会按一定的顺序在不同的目录下查找.
Windows查找DLL的顺序
在以前的Windows版本(Windows xp sp2之前),系统在寻找某个DLL时,会按照以下顺序搜索:
应用程序EXE所在的路径。
当前目录(可通过SetCurrentDirectory设置,GetCurrentDirectory获取)
系统目录(通常是C:\Windows\System32,WOW64程序也会重定向到C:\Windows\SysWOW64目录,可以通过GetSystemDirectory获取)
16位系统目录(通常是,C:\Windows\System)
Windows目录(通常是,C:\Windows,可以通过GetWindowsDirectory获取)
PATH环境变量指定的目录
VC命令行通过dll生成lib文件
dumpbin /exports Qt5Qmqttd.dll > Qt5Qmqttd.def
lib /def:Qt5Qmqttd.def /machine:i386 /out:libQt5Qmqttd.lib
特别注意new char[10] 与 new char(10) 区别
特别注意new char[10] 与 new char(10) 区别
char *pData=new char[10];
delete []pData;
new char(10) 这个用10来初始化你定义的指针所指向的那个char
char *lpc = new char('a'); //开辟一个内存单元,并用括号里的初始化
VS下使用多字符集编码和Unicode字符集编码的总结
● A2W、W2A、T2A、T2W 宏的使用以及注意事项:
- 使用 alloca() 函数进行空间的申请,宏返回的地址空间是从栈上面申请的,那么以后就不必释放,这样就涉及到了一个作用域的问题,具体见MSDN,大家可以简单的理解为“向下兼容”!
- 不要在一个函数的循环体中使用 A2W 等字符转换宏,可能引起栈溢出。
例子在unicode里面
CString A = _T("程序");
USES_CONVERSION;
char* colA = T2A(A.GetBuffer(0));
int L = strlen(colA);
wchar_t *colW = A2W(colA);
CString B(colW);
AfxMessageBox(B);
编写MFC程序的时候,总遇到字符集转换的问题,这里总结一下,方便大家使用。
在多字节字符集编码下,设置如下环境:
这时CString与char数组是可以互相转换的,而如果改成“使用Unicode字符集”,设置如下:
原来的代码就会报很多错误,诸如:
error C2664: “Cxxxxx::ConvertStringtoBtye”: 不能将参数 1 从“wchar_t *”转换为“char *”
这是因为使用Unicode编码,编译器已经把CString视为宽字符处理了,就不能再自动转为char *了。那么代码中用到的地方都得处理下,简单的如使用字符串常量,加上_T宏就可以解决问题,如:
AfxMessageBox("编码类型不正确!");改为 AfxMessageBox(_T("编码类型不正确!"));
strTest.Replace(" ", "");改为strTest.Replace(_T(" "), _T(""));
而对于一些函数,MFC为了兼容老版本,定义了两种类型,一种以W结尾的宽字符函数,另一种以A结尾的多字符函数。例如SQLGetInstalledDrivers函数,如果是多字符集就调用SQLGetInstalledDriversA,如果是Unicode字符集,就调用SQLGetInstalledDriversW:
对于这种函数,使用时我们也得进行区分,为了兼容性,也使用UNICODE分别处理:
WORD cbBufMax = 2000;
WORD cbBufOut;
#ifdef UNICODE
char szBuf[2001];
char *pszBuf = szBuf;
// Get the names of the installed drivers ("odbcinst.h" has to be included )
if(!SQLGetInstalledDrivers(szBuf, cbBufMax, & cbBufOut))
{
m_sExcelDriver = "";
}
#else
wchar_t szBuf[2001];
wchar_t *pszBuf = szBuf;
// Get the names of the installed drivers ("odbcinst.h" has to be included )
if (!SQLGetInstalledDrivers(szBuf, cbBufMax, &cbBufOut))
{
m_sExcelDriver = _T("");
}
#endif
对于一些操作字符和字符串的库函数,也是有区别的:
#ifdef UNICODE
// Search for the driver...
do
{
if (wcsstr(pszBuf, _T("Excel")) != 0)
{
// Found !
m_sExcelDriver = CString(pszBuf);
break;
}
pszBuf = wcschr(pszBuf, '\0') + 1;
} while (pszBuf[1] != '\0');
#else
// Search for the driver...
do
{
if( strstr( pszBuf, "Excel" ) != 0 )
{
// Found !
m_sExcelDriver = CString( pszBuf );
break;
}
pszBuf = strchr( pszBuf, '\0' ) + 1;
}
while( pszBuf[1] != '\0' );
为了有更好的兼容性,应该选择两个版本通用的函数,比如字符串转长整形,最好使用_tcstol函数来代替使用跟字符集相关的strtol或wcstol函数,类似的还有_ttoi、_ttof之类的转换函数。
在Unicode字符集下写文件的时候,对于长度操作要注意,一个宽字符是要写两个长度的:
CFile fileSave;
CString strGetData(_T("写入测试"));
CString strPath(_T("test.txt"));
if (!fileSave.Open(strPath, CFile::modeCreate |CFile::modeNoTruncate | CFile::modeWrite))
{
return;
}
wchar_t wch = 0xFEFF;
fileSave.Write(&wch, sizeof(wchar_t));
fileSave.Write(strGetData.LockBuffer(), wcslen(strGetData)*2);
strGetData.UnlockBuffer();
fileSave.Close();
使用Unicode字符集还有一大问题,就是CString与char之间的相互转换,以下函数就我总结的转换函数,char转CString函数:
CString Char2CString(char *pChar)
{
int charLen = strlen(pChar); // 计算pChar所指向的字符串大小
int len = MultiByteToWideChar(CP_ACP, 0, pChar, charLen, NULL, 0); // 计算多字节字符的大小
wchar_t *pWChar = new wchar_t[len + 1]; // 为宽字节字符数申请空间
MultiByteToWideChar(CP_ACP, 0, pChar, charLen, pWChar, len); // 多字节编码转换成宽字节编码
pWChar[len] = '\0';
// 将wchar_t数组转换为CString
CString str;
str.Append(pWChar);
delete[] pWChar;
return str;
}
CString转char*函数:
char* CString2Char(CString str)
{
DWORD dwCount = str.GetLength();
int len = WideCharToMultiByte(CP_ACP, 0, str, dwCount, NULL, 0, NULL, NULL); // 获取宽字节字符的大小
char *pChar = new char[len + 1];
WideCharToMultiByte(CP_ACP, 0, str, dwCount, (char *)pChar, len, NULL, NULL); // 宽字节编码转换成多字节编码
pChar[len] = '\0'; // 注意以'\0'结束
return pChar;
}
从代码可以看出,这里CString转char*需要new一个内存空间,使用后得记得delete掉才行。如果不习惯释放空间,那CString转char时最好不要开辟空间,万一忘记delete就造成内存泄露了,可以写一个改进版的转换函数:
static int CStrintToCharWithoutNew(CString str, char *buf)
{
int len = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
if (len > 0)
WideCharToMultiByte(CP_ACP, 0, str, -1, buf, len, NULL, NULL);
buf [len] = '\0'; // 注意以'\0'结束
return len;
}
这样使用后就不需要再记得delete了,前提是数组得定义的足够大:
char recvData[200];
CString testdata = _T("测试转换");
len = CStrintToCharWithoutNew(testdata, recvData);
上面的方法虽然基础,但显得麻烦了些,char*转CString只需要使用A2T()或A2W()宏即可:
char cBuf[] = "hello 世界";
CString str = _T("");
USES_CONVERSION;
str = A2T(cBuf);
// str = A2W(cBuf);
如果项目没包含头文件#include <atlconv.h>需要自己加上,USES_CONVERSION宏一定要放在使用前,否则会报错:
error C2065: “_lpa”: 未声明的标识符
类似的CString转char只需使用T2A或W2A宏即可。对于网上说的char转CString使用Format方法,如下:
char cBuf[] = "hello 世界";
CString str = _T("");
str.Format(_T("%s"), cBuf);
经测试,在Unicode编码下是不行的,cBuf数组就不是宽字符,改为下面写法就可以了:
str.Format(_T("%s"), _T("hello 世界"));
有时函数的参数是指针类型LPTSTR(多字符下是char ,Unicode下实际是wchar_t),那么如何把CString转为LPTSTR呢,下面两种方法都可以:
CString str("hello 世界");
LPTSTR lp = (LPTSTR)(LPCTSTR)str;
// LPTSTR lp = str.GetBuffer();
上面的代码在多字符集和Unicode字符集下都可以使用的,不过使用GetBuffer()时,使用完记得调用ReleaseBuffer()释放内存。这里有个细节,细心的读者可能会发现,CString创建的时候没有加_T宏:
CString str(_T("hello 世界"));
这里CString的构造函数自动为我们处理了,所以不用担心编码问题的。说到这里,您一定对_T宏感兴趣了,这个宏到底做了什么呢?在tchar.h文件中可以看到对它的定义,摘录下来如下:
#define _T(x) __T(x)
#define _TEXT(x) __T(x)
#define __T(x) L ## x // 编码为 Unicode
#define __T(x) x // 编码为 多字符
其实它根据不同的编码环境来转换字符的,在Unicode下,会把字符前面加个L代表宽字符,所以下面的定义只能在Unicode下使用:
wchar_t wBuf[] = _T("hello 世界");
就等同于:
wchar_t wBuf[] = L"hello 世界";
L为宽字符的定义宏,调试时可以发现宽字符变量的值是带L的。而在多字符集下面就报错了,因为转义成了:
wchar_t wBuf[] = "hello 世界;
有时候会见到WCHAR和TCHAR宏,不用慌,其实他们也是wchar_t的变体,类似很多宏定义都可以在WinNT.h文件中找到。说到TCHAR,有必要说明一下,是MFC为了统一字符集操作而定义的类型,它跟_T宏类似,在不同的字符集下有不同的定义:
typedef wchar_t TCHAR; // 编码为 Unicode
typedef char TCHAR; // 编码为 多字符
那么对于刚才的问题就有了解决方案,定义数组时如下定义:
TCHAR tBuf[] = _T("hello 世界");
这样就不会因为编译时选择不同的字符集而造成编译出错了。这下好了,按照这些标准写的代码,无论怎么选字符集都不会报错,本以为万事大吉了,可是世事难料啊,项目要调用两个别人写的库,一个是Unicode字符集的,而另一个是多字符集编译的,怎么选都是报错啊。
比如这里选通用的Unicode字符集,分析一下多字符集库报错的原因,头文件的函数使用了LPCTSTR类型参数,而这个类型也是随不同的字符集而代表不同类型的,在WinNT.h文件有定义:
typedef LPCWSTR PCTSTR, LPCTSTR;
typedef __nullterminated CONST WCHAR *LPCWSTR, *PCWSTR;
分析可见在Unicode下实际上是WCHAR 类型,而那个库原本在多字符集条件下编译时应该转为LPCSTR(实际上是char)类型的:
typedef __nullterminated CONST CHAR *LPCSTR, *PCSTR;
所以对于对外接口来说,写成通用字符集的参数是很不好的,人家编译时选择的字符集不一定和你一样,很容易造成连接错误的,直接写成char*类型才是正道啊。
一般GPIO控制
BOOL WINAPI DeviceIoControl(
_In_ HANDLE hDevice, //CreateFile函数打开的设备句柄
_In_ DWORD dwIoControlCode, //自定义的控制码
_In_opt_ LPVOID lpInBuffer, //输入缓冲区
_In_ DWORD nInBufferSize, //输入缓冲区的大小
_Out_opt_ LPVOID lpOutBuffer, //输出缓冲区
_In_ DWORD nOutBufferSize, //输出缓冲区的大小
_Out_opt_ LPDWORD lpBytesReturned, //实际返回的字节数,对应驱动程序中pIrp->IoStatus.Information。
_Inout_opt_ LPOVERLAPPED lpOverlapped //重叠操作结构指针。同步设为NULL,DeviceIoControl将进行阻塞调用;否则,应在编程时按异步操作设计
);
HANDLE CreateFile(
LPCTSTR lpFileName, //打开的文件名
DWORD dwDesiredAccess, //访问权限
DWORD dwShareMode, //共享模式
LPSECURITY_ATTRIBUTES lpSecurityAttributes, //安全属性
DWORD dwCreationDisposition, //文件存在与不存在时的文件创建模式
DWORD dwFlagsAndAttributes, //文件属性设定(隐藏、只读、压缩、指定为系统文件等)
HANDLE hTemplateFile //文件副本句柄
);
最后总结一下DeviceIoControl的通信流程:
1.驱动程序和应用程序自定义好IO控制码 (CTL_CODE宏 四个参数,32位,4部分,存储设备类型,访问权限,操作功能,缓冲区数据传递方式(四种))
2.驱动程序定义驱动设备名,符号链接名, 将符号链接名与设备对象名称关联 ,等待IO控制码(IoCreateDevice,IoCreateSymbolicLink)
3.应用程序由符号链接名通过CreateFile函数获取到设备句柄DeviceHandle,再用本场的主角,DeviceIoControl通过这个设备句柄发送控制码给派遣函数。
BufferedIO.h
#pragma once
#include <ntifs.h>
#define CTL_SYS \
CTL_CODE(FILE_DEVICE_UNKNOWN,0x830,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define DEVICE_OBJECT_NAME L"\\Device\\BufferedIODeviceObjectName"
//设备与设备之间通信
#define DEVICE_LINK_NAME L"\\DosDevices\\BufferedIODevcieLinkName"
//设备与Ring3之间通信
VOID DriverUnload(PDRIVER_OBJECT DriverObject);
NTSTATUS PassThroughDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS ControlThroughDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp);
BufferedIO.c
#include "BufferedIO.h"
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegisterPath)
{
NTSTATUS Status = STATUS_SUCCESS;
PDEVICE_OBJECT DeviceObject = NULL;
UNICODE_STRING DeviceObjectName;
UNICODE_STRING DeviceLinkName;
ULONG i;
// 栈
// 堆
// 全局(global Static Const)
DriverObject->DriverUnload = DriverUnload;
//创建设备对象名称
RtlInitUnicodeString(&DeviceObjectName,DEVICE_OBJECT_NAME);
//创建设备对象
Status = IoCreateDevice(DriverObject,NULL,
&DeviceObjectName,
FILE_DEVICE_UNKNOWN,
0, FALSE,
&DeviceObject);
if (!NT_SUCCESS(Status))
{
return Status;
}
//创建设备连接名称
RtlInitUnicodeString(&DeviceLinkName, DEVICE_LINK_NAME);
//将设备连接名称与设备名称关联
Status = IoCreateSymbolicLink(&DeviceLinkName,&DeviceObjectName);
if (!NT_SUCCESS(Status))
{
IoDeleteDevice(DeviceObject);
return Status;
}
//设计符合我们代码的派遣历程
for (i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
{
DriverObject->MajorFunction[i] = PassThroughDispatch; //函数指针
}
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ControlThroughDispatch;
return Status;
}
//派遣历程
NTSTATUS PassThroughDispatch(PDEVICE_OBJECT DeviceObject,PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS; //LastError()
Irp->IoStatus.Information = 0; //ReturnLength
IoCompleteRequest(Irp, IO_NO_INCREMENT); //将Irp返回给Io管理器
return STATUS_SUCCESS;
}
NTSTATUS ControlThroughDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS Status;
ULONG_PTR Informaiton = 0;
PVOID InputData = NULL;
ULONG InputDataLength = 0;
PVOID OutputData = NULL;
ULONG OutputDataLength = 0;
ULONG IoControlCode = 0;
PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp); //Irp堆栈
IoControlCode = IoStackLocation->Parameters.DeviceIoControl.IoControlCode;
InputData = Irp->AssociatedIrp.SystemBuffer;
OutputData = Irp->AssociatedIrp.SystemBuffer;
InputDataLength = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
OutputDataLength = IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength;
switch (IoControlCode)
{
case CTL_SYS:
{
if (InputData != NULL&&InputDataLength > 0)
{
DbgPrint( "%s\r\n" , InputData);
}
if (OutputData != NULL&&OutputDataLength >= strlen ( "Ring0->Ring3" ) + 1)
{
memcpy (OutputData, "Ring0->Ring3" , strlen ( "Ring0->Ring3" ) + 1);
Status = STATUS_SUCCESS;
Informaiton = strlen ( "Ring0->Ring3" ) + 1;
}
else
{
Status = STATUS_INSUFFICIENT_RESOURCES; //内存不够
Informaiton = 0;
}
break ;
}
default :
break ;
}
Irp->IoStatus.Status = Status; //Ring3 GetLastError();
Irp->IoStatus.Information = Informaiton;
IoCompleteRequest(Irp, IO_NO_INCREMENT); //将Irp返回给Io管理器
return Status; //Ring3 DeviceIoControl()返回值
}
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING DeviceLinkName;
PDEVICE_OBJECT v1 = NULL;
PDEVICE_OBJECT DeleteDeviceObject = NULL;
RtlInitUnicodeString(&DeviceLinkName, DEVICE_LINK_NAME);
IoDeleteSymbolicLink(&DeviceLinkName);
DeleteDeviceObject = DriverObject->DeviceObject;
while (DeleteDeviceObject != NULL)
{
v1 = DeleteDeviceObject->NextDevice;
IoDeleteDevice(DeleteDeviceObject);
DeleteDeviceObject = v1;
}
}
IO.cpp
// 缓冲区IO.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#define DEVICE_LINK_NAME L"\\\\.\\BufferedIODevcieLinkName"
#define CTL_SYS \
CTL_CODE(FILE_DEVICE_UNKNOWN,0x830,METHOD_BUFFERED,FILE_ANY_ACCESS)
int main()
{
HANDLE DeviceHandle = CreateFile(DEVICE_LINK_NAME,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (DeviceHandle==INVALID_HANDLE_VALUE)
{
return 0;
}
char BufferData = NULL;
DWORD ReturnLength = 0;
BOOL IsOk = DeviceIoControl(DeviceHandle, CTL_SYS,
"Ring3->Ring0" ,
strlen ( "Ring3->Ring0" )+1,
( LPVOID )BufferData,
0,
&ReturnLength,
NULL);
if (IsOk == FALSE)
{
int LastError = GetLastError();
if (LastError == ERROR_NO_SYSTEM_RESOURCES)
{
char BufferData[MAX_PATH] = { 0 };
IsOk = DeviceIoControl(DeviceHandle, CTL_SYS,
"Ring3->Ring0" ,
strlen ( "Ring3->Ring0" ) + 1,
( LPVOID )BufferData,
MAX_PATH,
&ReturnLength,
NULL);
if (IsOk == TRUE)
{
printf ( "%s\r\n" , BufferData);
}
}
}
if (DeviceHandle != NULL)
{
CloseHandle(DeviceHandle);
DeviceHandle = NULL;
}
printf ( "Input AnyKey To Exit\r\n" );
getchar ();
return 0;
}
项目例子:
HANDLE m_hPio;
int PIN_KEYX5_OLD=1;
int IniKEYIO()
{
int ret = 0 ;
PIO_DESC pio_desc[] = { //
{"PIN16", PIN_KEYX0, 1, PIO_PULLUP, PIO_TYPE_OUTPUT}, //RESET信号,与单片机通信
{"PIN17", PIN_KEYX1, 1, PIO_PULLUP, PIO_TYPE_OUTPUT}, //SPI扩展串口中断
{"PIN18", PIN_KEYX2, 1, PIO_PULLUP, PIO_TYPE_INPUT}, //IN1(开关量输入1)
{"PIN19", PIN_KEYX3, 1, PIO_PULLUP, PIO_TYPE_INPUT}, //IN2(开关量输入2)
{"PIN20", PIN_KEYX4, 1, PIO_PULLUP, PIO_TYPE_INPUT}, //IN3(开关量输入3)
{"PIN21", PIN_KEYX5, 1, PIO_PULLUP, PIO_TYPE_OUTPUT}, //与STC直连3(用作看门狗,每10秒改变一次电平)
{"PIN22", PIN_KEYX6, 1, PIO_PULLUP, PIO_TYPE_OUTPUT}, //与STC直连1(用于闪光灯控制X6/Y6电平分别为:0/0-关;
//1/1-开;1/0或0/1-自动)
{"PIN23", PIN_KEYX7, 1, PIO_PULLUP, PIO_TYPE_OUTPUT}, //控制向外的继电器输出K1
{"PIN24", PIN_KEYY0, 1, PIO_PULLUP, PIO_TYPE_OUTPUT}, //控制USB供电通断
{"PIN25", PIN_KEYY1, 1, PIO_PULLUP, PIO_TYPE_OUTPUT}, //控制向内的继电器输出K2
{"PIN26", PIN_KEYY2, 1, PIO_PULLUP, PIO_TYPE_OUTPUT}, //相机锁焦键
{"PIN27", PIN_KEYY3, 1, PIO_PULLUP, PIO_TYPE_OUTPUT}, //相机拍摄键
{"PIN28", PIN_KEYY4, 1, PIO_PULLUP, PIO_TYPE_OUTPUT}, //相机电源输出控制
{"PIN29", PIN_KEYY5, 1, PIO_PULLUP, PIO_TYPE_INPUT}, //IN4(开关量输入4)
{"PIN30", PIN_KEYY6, 1, PIO_PULLUP, PIO_TYPE_OUTPUT}, //与STC直连2(用于闪光灯控制X6/Y6电平分别为:0/0-关;
//1/1-开;1/0或0/1-自动)
{"PIN31", PIN_KEYY7, 1, PIO_PULLUP, PIO_TYPE_INPUT}, //IN5(开关量输入5)
};
m_hPio = CreateFile(L"PIO1:",GENERIC_READ | GENERIC_WRITE, //DWORD dwDesiredAccess,
0, //DWORD dwShareMode,
NULL, //LPSECURITY_ATTRIBUTES lpSecurityAttributes,
OPEN_EXISTING, //DWORD dwCreationDispostion,
FILE_ATTRIBUTE_NORMAL, //DWORD dwFlagsAndAttributes,
NULL);
if (m_hPio == INVALID_HANDLE_VALUE) {
ret = -1;
} else
{
BOOL ret = DeviceIoControl(m_hPio, IOCTL_PIO_CONFIGURE, pio_desc, sizeof(pio_desc), NULL, 0, NULL, NULL);
if (ret == TRUE) {
ret = 1;
}
}
return ret ;
}
WinIo 3.0直接访问IO端口
拦截API Detours
将DLL插入指定进程
bool XNRealInsertIE::StartInsert(CString sUrl)
{
STARTUPINFO sti;
PROCESS_INFORMATION prcin;
bool ret;
ZeroMemory(&sti,sizeof(STARTUPINFO));
sti.cb=sizeof(STARTUPINFO);
CString sIEPath;
GetIEPath(sIEPath);
// AfxMessageBox(sIEPath);
sIEPath.Replace("\"","");
sIEPath.Replace("%1",(char *)(const char *)sUrl);
ret=CreateProcess(NULL, (char *)(const char *)sIEPath,// "http://www.orchidheart.com ",
NULL,NULL,false,0,NULL,NULL,&sti,&prcin);
if(!ret)
{
return false;
}
else
{
CString Path;
Path.Format("%s\InsertIEDLL.dll",GetAppPath());
return DetourContinueProcessWithDll(prcin.hProcess,(char *)(const char *)Path);
//DetourCreateProcessWithDll
//DetourUpdateProcessWithDll
}
}
DLL代码
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
// Remove this if you use lpReserved
UNREFERENCED_PARAMETER(lpReserved);
if (dwReason == DLL_PROCESS_ATTACH)
{
TRACE0("INSERTIEDLL.DLL Initializing!\n");
// Extension DLL one-time initialization
if (!AfxInitExtensionModule(InsertIEDLLDLL, hInstance))
return 0;
// Insert this DLL into the resource chain
// NOTE: If this Extension DLL is being implicitly linked to by
// an MFC Regular DLL (such as an ActiveX Control)
// instead of an MFC application, then you will want to
// remove this line from DllMain and put it in a separate
// function exported from this Extension DLL. The Regular DLL
// that uses this Extension DLL should then explicitly call that
// function to initialize this Extension DLL. Otherwise,
// the CDynLinkLibrary object will not be attached to the
// Regular DLL's resource chain, and serious problems will
// result.
new CDynLinkLibrary(InsertIEDLLDLL);
XNIEHook::StartIE(NULL);
}
else if (dwReason == DLL_PROCESS_DETACH)
{
TRACE0("INSERTIEDLL.DLL Terminating!\n");
// Terminate the library before destructors are called
AfxTermExtensionModule(InsertIEDLLDLL);
}
return 1; // ok
}
跨进程消息
class XNProcessMsg
{
public:
static void PostAppMsg(HWND hWnd, DWORD uMsg,LPVOID p,int nSize);
XNProcessMsg();
virtual ~XNProcessMsg();
};
XNProcessMsg::~XNProcessMsg()
{
}
void XNProcessMsg::PostAppMsg(HWND hWnd,DWORD uMsg, LPVOID p,int nSize)
{
COPYDATASTRUCT MyCDS;
MyCDS.dwData =uMsg; // function identifier
MyCDS.cbData =nSize; // size of data
MyCDS.lpData =p;
SendMessage(hWnd,WM_COPYDATA,NULL, (LPARAM)(LPVOID)&MyCDS);
}
XNIEHook.h文件
// XNIEHook.h: interface for the XNIEHook class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_XNIEHOOK_H__9A5D06BD_14F1_4FC9_B290_571E59B14898__INCLUDED_)
#define AFX_XNIEHOOK_H__9A5D06BD_14F1_4FC9_B290_571E59B14898__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <map>
#include <string>
#include <list>
using namespace std;
// CDlgRequest dialog
#include "WinInet.h"
#pragma comment( lib, "WinInet.lib")
typedef struct _tagInternetConnectInfo
{
CString strHost;
CString strPort;
} tagInternetConnectInfo, *LPInternetConnectInfo;
#pragma pack(1)
struct HttpOpenRequestA_Parame
{
HINTERNET hConnect;
char lpszVerb[1024*10];
char lpszObjectName[1024*10];
char lpszVersion[1024*10];
char lpszReferrer[1024*10];
char lplpszAcceptTypes[1024*10];
DWORD dwFlags;
DWORD dwContext;
struct ReturnHttpOpenRequestA
{
HINTERNET hRequest;
}m_ReturnHttpOpenRequestA;
};
struct InternetConnectA_Parame
{
HINTERNET hInternet;
char lpszServerName[1024*10];
INTERNET_PORT nServerPort;
char lpszUserName[1024*10];
char lpszPassword[1024*10];
DWORD dwService;
DWORD dwFlags;
DWORD dwContext;
struct ReturnInternetConnectA
{
HINTERNET hConnect;
}m_ReturnInternetConnectA;
};
struct InternetCloseHandle_Parame
{
HINTERNET hInternet;
struct ReturnInternetCloseHandle
{
char RET_HTTP_QUERY_RAW_HEADERS_CRLF[1024*10];
char RET_HTTP_QUERY_RAW_HEADERS_CRLF_HTTP_QUERY_FLAG_REQUEST_HEADERS[1024*10];
}m_ReturnInternetCloseHandle;
};
struct HttpSendRequestA_Parame
{
HINTERNET hHttpRequest;
char lpszHeaders[1024*100];
DWORD dwHeadersLength;
char lpOptiona[1024*100];
DWORD dwOptionalLength;
struct ReturnHttpSendRequestA
{
BOOL bOK;
}m_ReturnHttpSendRequestA;
};
struct HttpSendRequestExA_Parame
{
HINTERNET hRequest;
LPINTERNET_BUFFERS lpBuffersIn;
LPINTERNET_BUFFERS lpBuffersOut;
DWORD dwFlags;
DWORD dwContext;
struct ReturnHttpSendRequestExA
{
BOOL bOK;
}m_ReturnHttpSendRequestA;
};
struct IEHookST
{
char HookFName[50];
union
{
struct HttpOpenRequestA_Parame m_HttpOpenRequestA_Parame;
struct InternetConnectA_Parame m_InternetConnectA_Parame;
struct InternetCloseHandle_Parame m_InternetCloseHandle_Parame;
struct HttpSendRequestA_Parame m_HttpSendRequestA_Parame;
}m_Parame;
};
#pragma pack()
typedef map<HINTERNET,tagInternetConnectInfo *>ArrayConnection;
typedef map<HINTERNET,int>ArrayRequest;
class XNIEHook
{
public:
static void RemoveIE();
static ArrayConnection m_mpConnection;
static ArrayRequest m_mpRequestItem;
static void ShowDebug(int x,int y,char *sMsg);
static HWND hMsgWnd;
static BOOL bHOOK;
static void StartIE(HWND hMsg);
XNIEHook();
virtual ~XNIEHook();
};
#endif // !defined(AFX_XNIEHOOK_H__9A5D06BD_14F1_4FC9_B290_571E59B14898__INCLUDED_)
XNIEHook.cpp
// XNIEHook.cpp: implementation of the XNIEHook class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "XNIEHook.h"
#include "XNProcessMsg.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#include "XNIEHook.h"
#include "WinInet.h"
#pragma comment( lib, "WinInet.lib")
#pragma comment(lib,"..\\HookClass\\lib\\detours.lib")
#include "..\HookClass\include\detours.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
DETOUR_TRAMPOLINE(HINTERNET WINAPI Hook_HttpOpenRequestA(IN HINTERNET hConnect,IN LPCSTR lpszVerb, IN LPCSTR lpszObjectName, IN LPCSTR lpszVersion, IN LPCSTR lpszReferrer, IN LPCSTR FAR * lplpszAcceptTypes, IN DWORD dwFlags, IN DWORD dwContext
),
HttpOpenRequestA);
static HINTERNET WINAPI New_HttpOpenRequestA(IN HINTERNET hConnect,IN LPCSTR lpszVerb, IN LPCSTR lpszObjectName, IN LPCSTR lpszVersion, IN LPCSTR lpszReferrer, IN LPCSTR FAR * lplpszAcceptTypes, IN DWORD dwFlags, IN DWORD dwContext)
{
// XNIEHook::ShowDebug((char *)lpszObjectName);
HINTERNET hRequest =Hook_HttpOpenRequestA( hConnect,lpszVerb,lpszObjectName, lpszVersion, lpszReferrer, lplpszAcceptTypes, dwFlags, dwContext);
struct IEHookST m_IEHookST;
sprintf(m_IEHookST.HookFName,"HttpOpenRequestA");
m_IEHookST.m_Parame.m_HttpOpenRequestA_Parame.dwContext=dwContext;
m_IEHookST.m_Parame.m_HttpOpenRequestA_Parame.dwFlags=dwFlags;
m_IEHookST.m_Parame.m_HttpOpenRequestA_Parame.hConnect=hConnect;
m_IEHookST.m_Parame.m_HttpOpenRequestA_Parame.m_ReturnHttpOpenRequestA.hRequest=hRequest;
sprintf(m_IEHookST.m_Parame.m_HttpOpenRequestA_Parame.lplpszAcceptTypes,"%s",lplpszAcceptTypes);
sprintf(m_IEHookST.m_Parame.m_HttpOpenRequestA_Parame.lpszObjectName,"%s",lpszObjectName);
sprintf(m_IEHookST.m_Parame.m_HttpOpenRequestA_Parame.lpszReferrer,"%s",lpszReferrer);
sprintf(m_IEHookST.m_Parame.m_HttpOpenRequestA_Parame.lpszVerb,"%s",lpszVerb);
sprintf(m_IEHookST.m_Parame.m_HttpOpenRequestA_Parame.lpszVersion,"%s",lpszVersion);
if(XNIEHook::hMsgWnd!=NULL)
{
if(::IsWindow(XNIEHook::hMsgWnd))
{
XNProcessMsg::PostAppMsg(XNIEHook::hMsgWnd,0x1234,&m_IEHookST,sizeof(struct IEHookST));
}
}
/*
ArrayConnection::iterator iter;
iter = XNIEHook::m_mpConnection.find(hConnect);
if( iter == XNIEHook::m_mpConnection.end())
{
}
else
{
CString strUrl;
strUrl.Format( "http://%s",(char *)(const char *) iter->second->strHost);
if( iter->second->strPort.Compare("80") != 0 )
strUrl+=":"+iter->second->strPort;
strUrl+=lpszObjectName;
}
*/
return hRequest;
}
DETOUR_TRAMPOLINE(HINTERNET WINAPI Hook_HttpOpenRequestW(IN HINTERNET hConnect,IN LPCWSTR lpszVerb,IN LPCWSTR lpszObjectName,IN LPCWSTR lpszVersion,IN LPCWSTR lpszReferrer,IN LPCWSTR FAR * lplpszAcceptTypes,IN DWORD dwFlags, IN DWORD dwContext
),
HttpOpenRequestW);
static HINTERNET WINAPI New_HttpOpenRequestW(IN HINTERNET hConnect,IN LPCWSTR lpszVerb,IN LPCWSTR lpszObjectName,IN LPCWSTR lpszVersion,IN LPCWSTR lpszReferrer,IN LPCWSTR FAR * lplpszAcceptTypes,IN DWORD dwFlags, IN DWORD dwContext)
{
return Hook_HttpOpenRequestW( hConnect,lpszVerb,lpszObjectName, lpszVersion, lpszReferrer, lplpszAcceptTypes, dwFlags, dwContext);
}
DETOUR_TRAMPOLINE(HINTERNET WINAPI Hook_InternetConnectA(IN HINTERNET hInternet,IN LPCSTR lpszServerName,IN INTERNET_PORT nServerPort,IN LPCSTR lpszUserName,IN LPCSTR lpszPassword,IN DWORD dwService,IN DWORD dwFlags,IN DWORD dwContext
),
InternetConnectA);
static HINTERNET WINAPI New_InternetConnectA(IN HINTERNET hInternet,IN LPCSTR lpszServerName,IN INTERNET_PORT nServerPort,IN LPCSTR lpszUserName,IN LPCSTR lpszPassword,IN DWORD dwService,IN DWORD dwFlags,IN DWORD dwContext)
{
HINTERNET hConnect=Hook_InternetConnectA( hInternet,lpszServerName, nServerPort,lpszUserName,lpszPassword,dwService,dwFlags,dwContext);
if(hConnect!=NULL)
{
/*
tagInternetConnectInfo *pConnectInfo = new tagInternetConnectInfo;
pConnectInfo->strHost = lpszServerName;
pConnectInfo->strPort.Format("%d", nServerPort);
ArrayConnection::iterator iter;
iter = XNIEHook::m_mpConnection.find(hConnect);
if( iter != XNIEHook::m_mpConnection.end())
{
tagInternetConnectInfo *pConnectInfo0=iter->second;
delete pConnectInfo0;
XNIEHook::m_mpConnection.erase(iter);
}
XNIEHook::m_mpConnection.insert(ArrayConnection::value_type( hConnect, pConnectInfo));
*/
IEHookST m_IEHookST;
sprintf(m_IEHookST.HookFName,"InternetConnectA");
m_IEHookST.m_Parame.m_InternetConnectA_Parame.dwContext=dwContext;
m_IEHookST.m_Parame.m_InternetConnectA_Parame.dwFlags=dwFlags;
m_IEHookST.m_Parame.m_InternetConnectA_Parame.dwService=dwService;
m_IEHookST.m_Parame.m_InternetConnectA_Parame.hInternet=hInternet;
m_IEHookST.m_Parame.m_InternetConnectA_Parame.nServerPort=nServerPort;
sprintf(m_IEHookST.m_Parame.m_InternetConnectA_Parame.lpszPassword,"%s",lpszPassword);
sprintf(m_IEHookST.m_Parame.m_InternetConnectA_Parame.lpszServerName,"%s",lpszServerName);
sprintf(m_IEHookST.m_Parame.m_InternetConnectA_Parame.lpszUserName,"%s",lpszUserName);
m_IEHookST.m_Parame.m_InternetConnectA_Parame.m_ReturnInternetConnectA.hConnect=hConnect;
if(XNIEHook::hMsgWnd!=NULL)
{
if(::IsWindow(XNIEHook::hMsgWnd))
{
XNProcessMsg::PostAppMsg(XNIEHook::hMsgWnd,0x1234,&m_IEHookST,sizeof(struct IEHookST));
}
}
}
return hConnect;
}
DETOUR_TRAMPOLINE(HINTERNET WINAPI Hook_InternetConnectW(IN HINTERNET hInternet,IN LPCWSTR lpszServerName,IN INTERNET_PORT nServerPort,IN LPCWSTR lpszUserName,IN LPCWSTR lpszPassword,IN DWORD dwService,IN DWORD dwFlags,IN DWORD dwContext
),
InternetConnectW);
static HINTERNET WINAPI New_InternetConnectW(IN HINTERNET hInternet,IN LPCWSTR lpszServerName,IN INTERNET_PORT nServerPort,IN LPCWSTR lpszUserName,IN LPCWSTR lpszPassword,IN DWORD dwService,IN DWORD dwFlags,IN DWORD dwContext)
{
return Hook_InternetConnectW( hInternet,lpszServerName, nServerPort,lpszUserName,lpszPassword,dwService,dwFlags,dwContext);
}
DETOUR_TRAMPOLINE(HINTERNET WINAPI Hook_InternetCloseHandle(IN HINTERNET hInternet
),
InternetCloseHandle);
static HINTERNET WINAPI New_InternetCloseHandle(IN HINTERNET hInternet)
{
char tszTemp[10240] = {0};
DWORD dwSize=sizeof(tszTemp);;
IEHookST m_IEHookST;
sprintf(m_IEHookST.HookFName,"InternetCloseHandle");
m_IEHookST.m_Parame.m_InternetCloseHandle_Parame.hInternet=hInternet;
if( HttpQueryInfo( hInternet, HTTP_QUERY_RAW_HEADERS_CRLF, tszTemp, &dwSize, 0) )
{
sprintf(m_IEHookST.m_Parame.m_InternetCloseHandle_Parame.m_ReturnInternetCloseHandle.RET_HTTP_QUERY_RAW_HEADERS_CRLF,"%s",tszTemp);
XNIEHook::ShowDebug(0,0,tszTemp);
}
dwSize = sizeof(tszTemp);
ZeroMemory( tszTemp, sizeof(tszTemp));
if( HttpQueryInfo( hInternet, HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLAG_REQUEST_HEADERS , tszTemp, &dwSize, 0) )
{
XNIEHook::ShowDebug(0,50,tszTemp);
/*
if(::IsWindow(XNIEHook::hMsgWnd))
::SetWindowText(XNIEHook::hMsgWnd,tszTemp);
*/
sprintf(m_IEHookST.m_Parame.m_InternetCloseHandle_Parame.m_ReturnInternetCloseHandle.RET_HTTP_QUERY_RAW_HEADERS_CRLF_HTTP_QUERY_FLAG_REQUEST_HEADERS,"%s",tszTemp);
if(XNIEHook::hMsgWnd!=NULL)
{
if(::IsWindow(XNIEHook::hMsgWnd))
{
XNProcessMsg::PostAppMsg(XNIEHook::hMsgWnd,0x1234,&m_IEHookST,sizeof(struct IEHookST));
}
}
}
return Hook_InternetCloseHandle( hInternet);
}
DETOUR_TRAMPOLINE(BOOL WINAPI Hook_HttpSendRequestA(IN HINTERNET hHttpRequest,
IN LPCSTR lpszHeaders,
IN DWORD dwHeadersLength,
IN LPVOID lpOptional,
DWORD dwOptionalLength
),
HttpSendRequestA);
static BOOL WINAPI New_HttpSendRequestA(IN HINTERNET hHttpRequest,
IN LPCSTR lpszHeaders,
IN DWORD dwHeadersLength,
IN LPVOID lpOptional,
DWORD dwOptionalLength)
{
BOOL bRet=Hook_HttpSendRequestA( hHttpRequest,
lpszHeaders,
dwHeadersLength,
lpOptional,
dwOptionalLength);
IEHookST m_IEHookST;
sprintf(m_IEHookST.HookFName,"HttpSendRequestA");
m_IEHookST.m_Parame.m_HttpSendRequestA_Parame.hHttpRequest=hHttpRequest;
m_IEHookST.m_Parame.m_HttpSendRequestA_Parame.dwHeadersLength=dwHeadersLength;
//m_IEHookST.m_Parame.m_HttpSendRequestA_Parame.lpOptiona=lpOptional;
m_IEHookST.m_Parame.m_HttpSendRequestA_Parame.dwOptionalLength=dwOptionalLength;
if(dwOptionalLength>0 && dwOptionalLength<1024*100)
{
memcpy(m_IEHookST.m_Parame.m_HttpSendRequestA_Parame.lpOptiona,(char *)lpOptional,dwOptionalLength);
}
if(dwHeadersLength>0 && dwHeadersLength<1024*100)
memcpy(m_IEHookST.m_Parame.m_HttpSendRequestA_Parame.lpszHeaders,lpszHeaders,dwHeadersLength);
m_IEHookST.m_Parame.m_HttpSendRequestA_Parame.m_ReturnHttpSendRequestA.bOK=bRet;
if(XNIEHook::hMsgWnd!=NULL)
{
if(::IsWindow(XNIEHook::hMsgWnd))
{
XNProcessMsg::PostAppMsg(XNIEHook::hMsgWnd,0x1234,&m_IEHookST,sizeof(struct IEHookST));
}
}
return bRet;
}
DETOUR_TRAMPOLINE(BOOL WINAPI Hook_HttpSendRequestExA(IN HINTERNET hRequest,
IN LPINTERNET_BUFFERS lpBuffersIn,
OUT LPINTERNET_BUFFERS lpBuffersOut,
IN DWORD dwFlags,
IN DWORD dwContext
),
HttpSendRequestExA);
static BOOL WINAPI New_HttpSendRequestExA(IN HINTERNET hRequest,
IN LPINTERNET_BUFFERS lpBuffersIn,
OUT LPINTERNET_BUFFERS lpBuffersOut,
IN DWORD dwFlags,
IN DWORD dwContext)
{
return Hook_HttpSendRequestExA( hRequest,
lpBuffersIn,
lpBuffersOut,
dwFlags,
dwContext);
}
static HINTERNET WINAPI _HttpOpenRequestA(IN HINTERNET hConnect,IN LPCSTR lpszVerb, IN LPCSTR lpszObjectName, IN LPCSTR lpszVersion, IN LPCSTR lpszReferrer, IN LPCSTR FAR * lplpszAcceptTypes, IN DWORD dwFlags, IN DWORD dwContext);
static HINTERNET WINAPI _HttpOpenRequestW(IN HINTERNET hConnect,IN LPCWSTR lpszVerb,IN LPCWSTR lpszObjectName,IN LPCWSTR lpszVersion,IN LPCWSTR lpszReferrer,IN LPCWSTR FAR * lplpszAcceptTypes,IN DWORD dwFlags, IN DWORD dwContext);
static HINTERNET WINAPI _InternetConnectA(IN HINTERNET hInternet,IN LPCSTR lpszServerName,IN INTERNET_PORT nServerPort,IN LPCSTR lpszUserName,IN LPCSTR lpszPassword,IN DWORD dwService,IN DWORD dwFlags,IN DWORD dwContext);
static HINTERNET WINAPI _InternetConnectW(IN HINTERNET hInternet,IN LPCWSTR lpszServerName,IN INTERNET_PORT nServerPort,IN LPCWSTR lpszUserName,IN LPCWSTR lpszPassword,IN DWORD dwService,IN DWORD dwFlags,IN DWORD dwContext);
static BOOL WINAPI _InternetCloseHandle(IN HINTERNET hInternet);
static BOOL WINAPI _InternetReadFile(
IN HINTERNET hFile,
IN LPVOID lpBuffer,
IN DWORD dwNumberOfBytesToRead,
OUT LPDWORD lpNumberOfBytesRead
);
static BOOL WINAPI _HttpSendRequestA(
IN HINTERNET hHttpRequest,
IN LPCSTR lpszHeaders,
IN DWORD dwHeadersLength,
IN LPVOID lpOptional,
DWORD dwOptionalLength
);
static BOOL WINAPI _HttpSendRequestExA(
IN HINTERNET hRequest,
IN LPINTERNET_BUFFERS lpBuffersIn,
OUT LPINTERNET_BUFFERS lpBuffersOut,
IN DWORD dwFlags,
IN DWORD dwContext
);
void ShowText(int x,int y,char *sMsg)
{
CWnd *pDeskWin=CWnd::GetDesktopWindow();
CDC *pDC=pDeskWin->GetWindowDC();
pDC->TextOut(x,y,sMsg);
pDeskWin->ReleaseDC(pDC);
}
DETOUR_TRAMPOLINE(BOOL WINAPI Hook_InternetReadFile(IN HINTERNET hFile,
IN LPVOID lpBuffer,
IN DWORD dwNumberOfBytesToRead,
OUT LPDWORD lpNumberOfBytesRead),
InternetReadFile);
static BOOL WINAPI New_InternetReadFile(IN HINTERNET hFile,
IN LPVOID lpBuffer,
IN DWORD dwNumberOfBytesToRead,
OUT LPDWORD lpNumberOfBytesRead)
{
BOOL bRet=Hook_InternetReadFile(hFile,
lpBuffer,
dwNumberOfBytesToRead,
lpNumberOfBytesRead);
//ShowText(0,0,(char *)lpBuffer);
char tszTemp[10240] = {0};
DWORD dwSize=sizeof(tszTemp);
if( HttpQueryInfo( hFile, HTTP_QUERY_REFERER, tszTemp, &dwSize, 0) )
{
//AfxMessageBox(tszTemp);
}
//AfxMessageBox((char *)lpBuffer);
return bRet;
}
HWND XNIEHook::hMsgWnd=NULL;
BOOL XNIEHook::bHOOK=false;
ArrayConnection XNIEHook::m_mpConnection;
XNIEHook::XNIEHook()
{
}
XNIEHook::~XNIEHook()
{
}
void XNIEHook::StartIE(HWND hMsg)
{
if(hMsg==NULL)
{
hMsgWnd=FindWindow(NULL,"拦截IE数据窗口");
}
if(!bHOOK)
{
//hMsgWnd=hMsg;
DetourFunctionWithTrampoline((PBYTE)Hook_HttpOpenRequestA, (PBYTE)New_HttpOpenRequestA);
DetourFunctionWithTrampoline((PBYTE)Hook_HttpOpenRequestW, (PBYTE)New_HttpOpenRequestW);
DetourFunctionWithTrampoline((PBYTE)Hook_InternetConnectA, (PBYTE)New_InternetConnectA);
DetourFunctionWithTrampoline((PBYTE)Hook_InternetConnectW, (PBYTE)New_InternetConnectW);
DetourFunctionWithTrampoline((PBYTE)Hook_InternetCloseHandle, (PBYTE)New_InternetCloseHandle);
DetourFunctionWithTrampoline((PBYTE)Hook_InternetReadFile, (PBYTE)New_InternetReadFile);
DetourFunctionWithTrampoline((PBYTE)Hook_HttpSendRequestA, (PBYTE)New_HttpSendRequestA);
DetourFunctionWithTrampoline((PBYTE)Hook_HttpSendRequestExA, (PBYTE)New_HttpSendRequestExA);
bHOOK=true;
}
}
void XNIEHook::ShowDebug(int x,int y,char *sMsg)
{
return;
CWnd *pDeskWin=CWnd::GetDesktopWindow();
CDC *pDC=pDeskWin->GetWindowDC();
pDC->TextOut(x,y,sMsg);
pDeskWin->ReleaseDC(pDC);
}
void XNIEHook::RemoveIE()
{
if(bHOOK)
{
DetourRemove((PBYTE)Hook_HttpOpenRequestA, (PBYTE)New_HttpOpenRequestA);
DetourRemove((PBYTE)Hook_HttpOpenRequestW, (PBYTE)New_HttpOpenRequestW);
DetourRemove((PBYTE)Hook_InternetConnectA, (PBYTE)New_InternetConnectA);
DetourRemove((PBYTE)Hook_InternetConnectW, (PBYTE)New_InternetConnectW);
DetourRemove((PBYTE)Hook_InternetCloseHandle, (PBYTE)New_InternetCloseHandle);
bHOOK=false;
}
}
FFMPEG函数调用介绍及顺序
AVFormatContext* fmtctx_ = nullptr;//重要结构
AVInputFormat* fmt_ = nullptr;
AVDictionary* dic_ = nullptr;
avdevice_register_all();//初始化libavformat并且注册所有的封装器,解封装器以及协议
fmt_=av_find_input_format("gdigrab");/
av_dict_set(&dic_, "framerate", "30", 0);//设置参数
//打开
LOCK();
CHECKSTOP();
int ret = 0;
avformat_close_input(&fmtctx_);
fmtctx_ = avformat_alloc_context();
if (fmtctx_ == nullptr)
{
ret = AVERROR(ENOMEM);
av_log(nullptr, AV_LOG_ERROR, "%s %d : %ld\n", __FILE__, __LINE__, ret);
return ret;
}
ret = avformat_open_input(&fmtctx_, input_.c_str(), fmt_, &dic_);
CHECKFFRET(ret);
ret = avformat_find_stream_info(fmtctx_, nullptr);
CHECKFFRET(ret);
av_dump_format(fmtctx_, 0, input_.c_str(), 0);
//循环读数据
int CDemux::demuxthread()
{
int ret = 0;
AVPacket* packet = av_packet_alloc();
const AVBitStreamFilter* bsf = nullptr;
AVBSFContext* bsfctx = nullptr;
AVCodecParameters* codecpar = nullptr;
std::map<unsigned int, AVBSFContext*> bsfctxs;
do
{
if (fmtctx_ == nullptr)
{
ret = AVERROR(EINVAL);
av_log(nullptr, AV_LOG_ERROR, "%s %d : %ld\n", __FILE__, __LINE__, ret);
break;
}
else if (packet == nullptr)
{
ret = AVERROR(ENOMEM);
av_log(nullptr, AV_LOG_ERROR, "%s %d : %ld\n", __FILE__, __LINE__, ret);
break;
}
// 初始化packet
av_init_packet(packet);
// BitStreamFilter
if (bsfs_.size() > 0)
{
for (const auto i : bsfs_)
{
if (i.first >= fmtctx_->nb_streams ||
i.second.empty() ||
(bsf = av_bsf_get_by_name(i.second.c_str())) == nullptr ||
(codecpar = fmtctx_->streams[i.first]->codecpar) == nullptr ||
av_bsf_alloc(bsf, &bsfctx) < 0)
{
continue;
}
if(avcodec_parameters_copy(bsfctx->par_in, codecpar) < 0 ||
av_bsf_init(bsfctx) < 0)
{
av_bsf_free(&bsfctx);
continue;
}
bsfctxs[i.first] = bsfctx;
}
}
// 循环读数据解码数据
while (true)
{
av_usleep(10);
if (status_ != DEMUXING)
{
ret = AVERROR_EOF;
av_log(nullptr, AV_LOG_INFO, "%s %d : %ld\n", __FILE__, __LINE__, ret);
break;
}
// 读数据
ret = av_read_frame(fmtctx_, packet);
if (ret < 0)
{
av_log(nullptr, ret == AVERROR_EOF ? AV_LOG_INFO : AV_LOG_ERROR, "%s %d : %ld\n", __FILE__, __LINE__, ret);
break; //这里认为视频读取完了
}
else if (demuxpacketcb_ != nullptr)
{
if (bsfctxs[packet->stream_index] != nullptr)
{
bsfctx = bsfctxs[packet->stream_index];
ret = av_bsf_send_packet(bsfctx, packet);
if (ret < 0)
{
av_log(nullptr, AV_LOG_ERROR, "%s %d : %ld\n", __FILE__, __LINE__, ret);
break;
}
while (ret >= 0)
{
ret = av_bsf_receive_packet(bsfctx, packet);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
{
// 不完整或者EOF
av_log(nullptr, AV_LOG_DEBUG, "%s %d : %ld\n", __FILE__, __LINE__, ret);
av_usleep(10);
break;
}
else if (ret < 0)
{
// 其他错误
if (demuxstatuscb_ != nullptr)
{
demuxstatuscb_(DEMUXING, ret, demuxstatuscbparam_);
}
break;
}
else
{
demuxpacketcb_(packet, fmtctx_->streams[packet->stream_index]->time_base, demuxpacketcbparam_);
}
}
}
else
{
demuxpacketcb_(packet, fmtctx_->streams[packet->stream_index]->time_base, demuxpacketcbparam_);
}
}
// 不再引用指向的缓冲区
av_packet_unref(packet);
}
break;
} while (true);
// 清理bsf
for (auto& i : bsfctxs)
{
av_bsf_free(&i.second);
}
// 清理packet
av_packet_free(&packet);
status_ = STOP;
if (demuxstatuscb_ != nullptr)
{
demuxstatuscb_(STOP, ret, demuxstatuscbparam_);
}
return true;
}
avformat_close_input(&fmtctx_);
FFMPEG学习-版本为4.2.2 使用opencv播放 opencv版本为4.2.0
ffmpeg当前学习版本为4.2.2
https://www.cnblogs.com/leisure_chn/category/1351812.html 教程主要参考网址
ffmpeg sdk下载地址:https://ffmpeg.zeranoe.com/builds/
ffmpeg官网地址:http://ffmpeg.org/
音视频基础术语介绍:https://www.jianshu.com/p/e9e6484b1f89
Ffmpeg环境搭建 https://blog.csdn.net/qq_41051855/article/details/78665620https://blog.csdn.net/yao_hou/article/details/80553660
ffmpeg命令行工具加入环境变量 https://jingyan.baidu.com/article/a3a3f81124c5e08da2eb8a29.html
ffmpeg命令行入门教程 http://www.ruanyifeng.com/blog/2020/01/ffmpeg.html
国内教程 https://blog.csdn.net/leixiaohua1020/article/details/15811977 雷神教程
网友参考教程https://blog.csdn.net/yao_hou/category_9275800.html
官网教程http://ffmpeg.tv/
Ffmpeg库sdk使用时候的链接问题:https://blog.csdn.net/huyu107/article/details/51980029
将dll库文件放入对应程序目录下面
12. 雷神总结音视频学习方法 https://blog.csdn.net/leixiaohua1020/article/details/18893769
13. ffmpeg sdk中的数据结构和函数总结和记录:
AVFormatContext
描述媒体文件或媒体流构成和基本信息(包含码流参数较多,位于:avformat.h),封装格式上下文结构体,也是统领全局的结构体,保存了视频文件封装格式相关信息
在使用FFMPEG进行开发的时候,AVFormatContext是一个贯穿始终的数据结构,很多函数都要用到它作为参数。它是FFMPEG解封装(flv,mp4,rmvb,avi)功能的结构体。下面看几个主要变量的作用(在这里考虑解码的情况):
主要变量:
struct AVInputFormat *iformat:输入数据的封装格式
AVIOContext *pb:输入数据缓存
unsigned int nb_streams:音视频流个数(输入视频的AVStream 个数)
AVStream **streams:音视频流(输入视频的AVStream []数组)
char filename[1024]:文件名
int64_t duration:时长(单位:us)(输入视频的时长(以微秒为单位))
int bit_rate:比特率(输入视频的码率)
AVDictionary *metadata:元数据
参考地址:https://blog.csdn.net/leixiaohua1020/article/details/14214705
AVInputFormat
每种封装格式(例如FLV, MKV, MP4, AVI)对应一个该结构体。
long_name:封装格式的长名称
extensions:封装格式的扩展名
id:封装格式ID
一些封装格式处理的接口函数
AVCodecContext:
描述编解码器上下文的数据结构,包含编解码器需要的参数信息(位于:avcodec.h),编码器上下文结构体,保存了视频(音频)编解码相关信息,AVCodecContext中很多的参数是编码的时候使用的,而不是解码的时候使用的。
说明:
codec:编解码器的AVCodec
width, height:图像的宽高(只针对视频)
pix_fmt:像素格式(只针对视频)
sample_rate:采样率(只针对音频)
channels:声道数(只针对音频)
sample_fmt:采样格式(只针对音频)
参考网址:https://blog.csdn.net/leixiaohua1020/article/details/14214859
AVCodecContext函数的空间开辟和释放空间函数如下:
AVCodecContext * avcode_alloc_context3(const AVCodec *codec)
初始化解码器上下文
void avcodec_free_context(AVCodecContext ** avcodecContext)
释放解码器上下文
参考网址 https://blog.csdn.net/king1425/article/details/70622258 ffmpeg源码简析(四)avcodec_find_encoder(),avcodec_open2(),avcodec_close()
AVStream
描述一个媒体流(存储视频/音频流信息的结构体,位于:avformat.h),视频文件中每个视频(音频)流对应一个该结构体
主要变量:
AVCodecContext *codec// 已过时,使用另一个 codecpar 结构体代替。
AVRational time_base // 时间基数。
int64_t duration // 总时长。流的总时长,该参数不可靠。
AVRational avg_frame_rate // 帧率。
AVCodecParameters *codecpar;// 包含音视频参数的结构体。很重要,可以用来获取音视频参数中的宽度、高度、采样率、编码格式等信息。
//事实上codecpar包含了大部分解码器相关的信息,这里是直接从AVCodecParameters复制到AVCodecContext
avcodec_parameters_to_context(codec_ctx, stream->codecpar);
AVStream结构体中 用AVCodecParameters代替AVCodecContext
参考网址:https://blog.csdn.net/luotuo44/article/details/54981809
https://blog.51cto.com/fengyuzaitu/2059121
AVCodecParameters
enum AVMediaType codec_type;// 编码类型。说明这段流数据究竟是音频还是视频。
enum AVCodecID codec_id;/ 编码格式。说明这段流的编码格式,h264,MPEG4, MJPEG,etc...
uint32_t codecTag; // 一般不用
int format;//格式。对于视频来说指的就是像素格式(YUV420,YUV422...),对于音频来说,指的就是音频的采样格式。
int width, int height;// 视频的宽高,只有视频有
uint64_t channel_layout;// 取默认值即可
int channels;// 声道数
int sample_rate;// 样本率
int frame_size;// 只针对音频,一帧音频的大小
AVCodec
每种视频(音频)编解码器(例如H.264解码器)对应一个该结构体。
name:编解码器名称
long_name:编解码器长名称
type:编解码器类型
id:编解码器ID
一些编解码的接口函数
AVFrame
存储一帧解码后像素(采样)数据。
data:解码后的图像像素数据(音频采样数据)。
linesize:对视频来说是图像中一行像素的大小;对音频来说是整个音频帧的大小。
width, height:图像的宽高(只针对视频)。
key_frame:是否为关键帧(只针对视频) 。
pict_type:帧类型(只针对视频) 。例如I,P,B。
https://www.cnblogs.com/leisure_chn/p/10404502.html 参考地址
Avframe内存分配方式 https://blog.csdn.net/xionglifei2014/article/details/90693048
常用的API接口
1、avformat_open_input
int avformat_open_input(AVFormatContext **ic_ptr,const char *filename,AVInputFormat *fmt,AVDictionary **options);
作用:打开文件或URL,并使基于字节流的底层输入模块得到初始化;解析多媒体文件或多媒体流的头信息,创建AVFormatContext结构并填充其中的关键字段,依次为各个原始流建立AVStream结构。
参数:
ic_ptr:用于返回avformat_open_input内部构造的一个AVFormatContext结构体。
filename:指定文件名。
fmt:用于显式指定输入文件的格式,如果设为空则自动判断其输入格式。
options:传入的附加参数。
说明:这个函数通过解析多媒体文件或流的头信息及其他辅助数据,能够获取足够多的关于文件、流和编解码器的信息,但任何一种多媒体格式提供的信息都是有限的,而且不同的多媒体软件制作对头信息的设置各有不同,另外这些软件在产生多媒体内容时难免引入错误,这种情况下并不能保证获取到所有需要的信息,这是就要考虑另一个函数:avformat_find_stream_info。
2、avformat_find_stream_info
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);
作用:用于获取必要的编解码器参数。需要得到各媒体流对应编解码器的类型和id,这是两个定义在avutils.h和avcodec.h中的枚举:
enum AVMediaType {
AVMEDIA_TYPE_UNKNOWN = -1,
AVMEDIA_TYPE_VIDEO,
AVMEDIA_TYPE_AUDIO,
AVMEDIA_TYPE_DATA,
AVMEDIA_TYPE_SUBTITLE,
AVMEDIA_TYPE_ATTACHMENT,
AVMEDIA_TYPE_NB
};
enum CodecID {
CODEC_ID_NONE,
CODEC_ID_MPEG1VIDEO,
CODEC_ID_MPEG2VIDEO,
CODEC_ID_MPEG2VIDEO_XVMC,
CODEC_ID_H261,
CODEC_ID_H263,
CODEC_ID_H264,
...
};
若媒体格式的数据流具有完整头信息,可以通过avformat_open_input得到编解码器的类型和id;否则,需要通过avformat_find_stream_info函数获取。此外,对于音频编解码器,时间基准、采样率、声道数、位宽、帧长度与视频编解码器图像大小、色彩空间等也需要从avformat_find_stream_info函数得到。
3、av_read_frame
int av_read_frame(AVFormatContext *s, AVPacket *pkt);
作用:用于从多媒体文件或多媒体流中读取媒体数据,数据由AVPacket结构pkt来存放。对于音频数据,若是固定比特率,则pkt中装载一个或多个音频帧;若为可变比特率,则pkt中装载一个音频帧。对于视频数据,pkt中装载有一个视频帧。注:当再次调用本函数之前,需使用av_free_packet释放pkt所占用的资源。
4、av_seek_frame
int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags);
作用:通过改变媒体文件的读写指针来实现对媒体文件的随机访问,大多源于媒体播放器的快进、快退等功能。
参数:
s:AVFormatContext指针;
avformat_open_input返回得到。
stream_index:指定媒体流。
timestamp:时间标签。
flags:定位方式。
5、av_close_input_file
void av_close_input_file(AVFormatContext *s);
作用:关闭媒体文件,释放资源,关闭物理IO。
6、avcodec_find_decoder
AVCodec *avcodec_find_decoder(enum CodecID id);
AVCodec *avcodec_find_decoder_by_name(const char *name);
作用:根据指定解码器ID或者解码器名称查找相应的解码器并返回AVCodec 。
7、avcodec_open
int avcodec_open(AVCodecContext *avctx, AVCodec *codec);
作用:根据输入的AVCodec指针具体化AVCodecContext结构。在调用该函数之前,首先调用avcodec_alloc_context分配一个AVCodecContext结构,或调用avformat_open_input获取媒体文件中对应媒体流的AVCodecContext结构;
此外,通过avcodec_find_decoder获取AVCodec结构。
8、avcodec_decode_video2
int avcodec_decode_video2(AVCodecContext *avctx,AVFrame *picture,int *got_picture_ptr,AVPacket *avpkt);
作用:解码视频帧。
参数:
avctx:解码器上下文。
picture:输出数据。
got_picture_ptr:指示是否有解码数据输出。
avpkt:输入数据。
9、avcodec_decode_audio4
int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt);
作用:解码音频帧。输入数据在AVPacket结构中,输出数据在frame中,got_frame_ptr表示是否有数据输出。
参数:
avctx:解码器上下文。
frame:输出数据。
got_frame_ptr:指示是否有解码数据输出。
avpkt:输入数据。
10、avcodec_close
int avcodec_close(AVCodecContext *avctx);作用:关闭解码器,释放avcodec_open中分配的资源。
FFMPEG开发中遇到的问题①avpicture_fill和AVFrame::data的内存管理
https://blog.csdn.net/maybeall/article/details/78921144
https://blog.csdn.net/u013539952/article/details/80002434 Mat构造函数
https://blog.csdn.net/slj2017/article/details/80819753 Mat的行数和列数理解
视频解码 并使用opencv播放的代码如下:
/*****************************************************************
A simple ffmpeg player.
*
* refrence:
* 1. https://blog.csdn.net/leixiaohua1020/article/details/38868499
* 2. http://dranger.com/ffmpeg/ffmpegtutorial_all.html#tutorial01.html
* 3. http://dranger.com/ffmpeg/ffmpegtutorial_all.html#tutorial02.html
******************************************************************/
#if 1
#include <stdio.h>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
extern "C"
{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libavcodec\avcodec.h>
#include <libavformat\avformat.h>
#include <libswscale\swscale.h>
#include <libavutil\pixfmt.h>
#include <libavutil\imgutils.h>
};
int main(int argc, char *argv[])
{
// Initalizing these to NULL prevents segfaults!
//描述媒体文件或媒体流构成和基本信息, 封装格式上下文结构体,也是统领全局的结构体,保存了视频文件封装格式相关信息
AVFormatContext* p_fmt_ctx = NULL;
//描述编解码器上下文的数据结构,包含编解码器需要的参数信息,编码器上下文结构体,保存了视频(音频)编解码相关信息
AVCodecContext* p_codec_ctx = NULL;
//该参数用来获取 AVCodecContext
AVCodecParameters* p_codec_par = NULL;
//每种视频(音频)编解码器(例如H.264解码器)对应一个该结构体
AVCodec* p_codec = NULL;
AVFrame* p_frm_raw = NULL; // 帧,由包解码得到原始帧
AVFrame* p_frm_rgb = NULL; // 帧,由原始帧色彩转换得到
AVPacket* p_packet = NULL;// 包,从流中读出的一段数据
//主要用于视频图像的转换,比如格式转换
struct SwsContext* sws_ctx = NULL;
int buf_size;
uint8_t* buffer = NULL;
int width;// / 4
int height;// / 4
int i;
int v_idx;
int ret;
// 初始化libavformat(所有格式),注册所有复用器/解复用器
// av_register_all();// 已被申明为过时的,直接不再使用即可
// A1. 打开视频文件:读取文件头,将文件格式信息存储在p_fmt_ctx中
ret = avformat_open_input(&p_fmt_ctx, "test.mp4", NULL, NULL);
if (ret != 0)
{
printf("avformat_open_input() failed\n");
return -1;
}
// A2. 搜索流信息:读取一段视频文件数据,尝试解码,将取到的流信息填入pFormatCtx->streams
//p_fmt_ctx->streams是一个指针数组,数组大小是pFormatCtx->nb_streams
ret = avformat_find_stream_info(p_fmt_ctx, NULL);
if (ret < 0)
{
printf("avformat_find_stream_info() failed\n");
return -1;
}
// 将文件相关信息打印在标准错误设备上
//av_dump_format()是一个手工调试的函数,能使我们看到pFormatCtx->streams里面有什么内容。
//一般接下来我们使用av_find_stream_info()函数,它的作用是为pFormatCtx->streams填充上正确的信息。
av_dump_format(p_fmt_ctx, 0, "test.mp4", 0);
// A3. 查找第一个视频流
v_idx = -1;
for (i = 0; i < p_fmt_ctx->nb_streams; i++)
{
if (p_fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
v_idx = i;
printf("Find a video stream, index %d\n", v_idx);
break;
}
}
if (v_idx == -1)
{
printf("Cann't find a video stream\n");
return -1;
}
// A5. 为视频流构建解码器AVCodecContext
// A5.1 获取解码器参数AVCodecParameters
p_codec_par = p_fmt_ctx->streams[v_idx]->codecpar;
// A5.2 获取解码器
p_codec = avcodec_find_decoder(p_codec_par->codec_id);
if (p_codec == NULL)
{
printf("Cann't find codec!\n");
return -1;
}
// A5.3 构建解码器AVCodecContext
// A5.3.1 p_codec_ctx初始化:分配结构体,使用p_codec初始化相应成员为默认值
p_codec_ctx = avcodec_alloc_context3(p_codec);
// A5.3.2 p_codec_ctx初始化:p_codec_par ==> p_codec_ctx,初始化相应成员
ret = avcodec_parameters_to_context(p_codec_ctx, p_codec_par);
if (ret < 0)
{
printf("avcodec_parameters_to_context() failed %d\n", ret);
return -1;
}
// A5.3.3 p_codec_ctx初始化:使用p_codec初始化p_codec_ctx,初始化完成
//p_codec_ctx进行解码的时候 需要avcodec_parameters_to_context和avcodec_open2两步进行解码
ret = avcodec_open2(p_codec_ctx, p_codec, NULL);
if (ret < 0)
{
printf("avcodec_open2() failed %d\n", ret);
return -1;
}
// A6. 分配AVFrame
// A6.1 分配AVFrame结构,注意并不分配data buffer(即AVFrame.*data[])
p_frm_raw = av_frame_alloc();
p_frm_rgb = av_frame_alloc();
if (!p_frm_raw || !p_frm_rgb)
{
goto FreeAssets;
}
//pVideoCodecCtx->pix_fmt == AV_PIX_FMT_NONE的时候如果调用sws_getContext函数会出现错误,需要提前避过
if (p_codec_ctx->pix_fmt == AV_PIX_FMT_NONE)
{
goto FreeAssets;
}
width = p_codec_ctx->width;// / 4
height = p_codec_ctx->height;// / 4
// A6.2 为AVFrame.*data[]手工分配缓冲区,用于存储sws_scale()中目的帧视频数据
//p_frm_raw的data_buffer由av_read_frame()分配,因此不需手工分配
//p_frm_yuv的data_buffer无处分配,因此在此处手工分配
buf_size = av_image_get_buffer_size(AV_PIX_FMT_BGRA,
width,
height,
1
);
// buffer将作为p_frm_yuv的视频数据缓冲区
buffer = (uint8_t *)av_malloc(buf_size);
// 使用给定参数设定p_frm_rgb->data和p_frm_rgb->linesize
av_image_fill_arrays(p_frm_rgb->data,// dst data[]
p_frm_rgb->linesize, // dst linesize[]
buffer, // src buffer
AV_PIX_FMT_BGRA, // pixel format
width, // width
height, // height
1 // align
);
//A7. 初始化SWS context,用于后续图像转换
//此处第6个参数使用的是FFmpeg中的像素格式,对比参考注释B4
// FFmpeg中的像素格式AV_PIX_FMT_YUV420P对应SDL中的像素格式SDL_PIXELFORMAT_IYUV
//如果解码后得到图像的不被SDL支持,不进行图像转换的话,SDL是无法正常显示图像的
//如果解码后得到图像的能被SDL支持,则不必进行图像转换
//这里为了编码简便,统一转换为SDL支持的格式AV_PIX_FMT_YUV420P==>SDL_PIXELFORMAT_IYUV
sws_ctx = sws_getContext(p_codec_ctx->width, // src width
p_codec_ctx->height, // src height
p_codec_ctx->pix_fmt, // src format
width, // dst width
height, // dst height
AV_PIX_FMT_BGRA,// dst format
SWS_BICUBIC,// flags
NULL, // src filter
NULL,// dst filter
NULL// param
);
p_packet = (AVPacket *)av_malloc(sizeof(AVPacket));
// A8. 从视频文件中读取一个packet
//packet可能是视频帧、音频帧或其他数据,解码器只会解码视频帧或音频帧,非音视频数据并不会被
//扔掉、从而能向解码器提供尽可能多的信息
//对于视频来说,一个packet只包含一个frame
//对于音频来说,若是帧长固定的格式则一个packet可包含整数个frame,
//若是帧长可变的格式则一个packet只包含一个frame
cv::namedWindow("bgra", cv::WINDOW_NORMAL);
while (av_read_frame(p_fmt_ctx, p_packet) == 0)
{
if (p_packet->stream_index == v_idx) // 仅处理视频帧
{
// A9. 视频解码:packet ==> frame
// A9.1 向解码器喂数据,一个packet可能是一个视频帧或多个音频帧,此处音频帧已被上一句滤掉
ret = avcodec_send_packet(p_codec_ctx, p_packet);
if (ret != 0)
{
printf("avcodec_send_packet() failed %d\n", ret);
return -1;
}
// A9.2 接收解码器输出的数据,此处只处理视频帧,每次接收一个packet,将之解码得到一个frame
ret = avcodec_receive_frame(p_codec_ctx, p_frm_raw);
if (ret != 0)
{
printf("avcodec_receive_frame() failed %d\n", ret);
return -1;
}
// A10. 图像转换:p_frm_raw->data ==> p_frm_rgb->data
// 将源图像中一片连续的区域经过处理后更新到目标图像对应区域,处理的图像区域必须逐行连续
// plane: 如YUV有Y、U、V三个plane,RGB有R、G、B三个plane
// slice: 图像中一片连续的行,必须是连续的,顺序由顶部到底部或由底部到顶部
// stride/pitch: 一行图像所占的字节数,Stride=BytesPerPixel*Width+Padding,注意对齐
// AVFrame.*data[]: 每个数组元素指向对应plane
// AVFrame.linesize[]: 每个数组元素表示对应plane中一行图像所占的字节数
sws_scale(sws_ctx, // sws context
(const uint8_t *const *)p_frm_raw->data, // src slice
p_frm_raw->linesize,// src stride
0, // src slice y
height, // src slice height
p_frm_rgb->data, // dst planes
p_frm_rgb->linesize // dst strides
);
//rows 是行数 , 即图像的高度
//cols 是列数 , 即图像的宽度
cv::Mat BGR24_IMG(height, width, CV_8UC4, p_frm_rgb->data[0]);
cv::imshow("bgra", BGR24_IMG);
cv::waitKey(33);
}
av_packet_unref(p_packet);
}
FreeAssets:
if (sws_ctx != NULL)
sws_freeContext(sws_ctx);
if (buffer != NULL)
av_free(buffer);
if (p_frm_rgb != NULL)
av_frame_free(&p_frm_rgb);
if (p_frm_raw != NULL)
av_frame_free(&p_frm_raw);
if(p_codec_ctx!=NULL)
avcodec_free_context(&p_codec_ctx);
if (p_fmt_ctx != NULL)
avformat_close_input(&p_fmt_ctx);
return 0;
}
#endif
MQTT使用
eclipse-paho-mqtt-c-win32-1.3.9.rar
头文件
// MQTTFrame.h: interface for the MQTTFrame class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_MQTTFRAME_H__8CE5D444_AA37_47DF_B98D_F567D8ACAE5F__INCLUDED_)
#define AFX_MQTTFRAME_H__8CE5D444_AA37_47DF_B98D_F567D8ACAE5F__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "..\include\XNFrameNETCall.h"
#include "..\eclipse-paho-mqtt-c-win32-1.3.9\include\MQTTClient.h"
#include ".\AES\AES.h"
#include "XTiShiDlg.h"
struct Config
{
CString m_MQTTAddress;
CString m_ClientID;
CStringArray m_SubTopicArray;
CStringArray m_PubTopicArray;
CByteArray m_SubQOSArray;
CByteArray m_PubQOSArray;
CString Url;
};
struct AuthFile
{
char head[10];
char appname[50];
char apptype[50];
char reguser[50];
char sys_companys_nodeuuid[50];
char deviceid[50];
char uid[50];
char limittype[50];
char limitdata[50];
char outmark[50];
};
struct JsonReturn
{
HANDLE hOutParameJson;
};
struct RowReturn
{
int total;
int pageSize;
CDWordArray m_RowJsonArray;
};
struct OneHttp
{
char ClassName[50];
char FuncName[50];
char Msg[1000];
HANDLE hParameJson;
HANDLE hOverEvent;
BOOL isRow;
BOOL isOver;
BOOL isOK;
struct JsonReturn m_JsonReturn;
struct RowReturn m_RowReturn;
};
class NETFrame
{
public:
//AuthFile m_AuthFile;
void ReturnMQTT(CString msgno,HANDLE hData);
void ActionMQTTMessage(CString TPName,CString MsgString);
static UINT StartSVRThread(LPVOID p);
void AddMsg(CString sMsg);
CWnd *pWnd;
static UINT NETDownThread(LPVOID p);
void NETDown();
BOOL bAuthError;
BOOL ChkPWD(CString pwd,CString outMark);
CString getRandPWD(CString outMark);
void Init();
BOOL StartSVR(CString &sError);
BOOL ReadKey(AuthFile *pAuthFile);
static CString AuthMark;
BOOL SubMessages(CStringArray &m_TopicArray,CByteArray &m_QOSArray,CString &sError);
XTiShiDlg m_XTiShiDlg;
BOOL AddOneHttp(OneHttp *pOneHttp);
BOOL RunHttpFunction(CString ClassName, CString FunctionName, HANDLE hParameJson, CString &sMsg, int &total, int &pageSize,CDWordArray &m_RowJsonArray,bool bInThread=false);
BOOL RunHttpFunction(CString ClassName,CString FuncName,HANDLE hParameJson,CString &sMsg,HANDLE &hOutParameJson,bool bInThread=false);
void ClearWorkPtr();
CPtrList m_WorkPtr;
void ActionOneHttp(OneHttp *pOneHttp);
CRITICAL_SECTION CS;
HANDLE hStart,hExit;
void ActionHttp();
static UINT HttpThread(LPVOID p);
static void Wait(int nWait);
static CString GetPCName();
static BOOL SaveKey(CString appName,CString appType,CString userName,CString sys_companys_nodeuuid,CString deviceID,CString uidNET,CString limittypeNET,CString limitdataNET,CString outmarkNET);
BOOL ActiveApp(CString deviceid,CString username);
static CString DecryAES(CString str, CString key, CString iv="1234567890abcdef");
static CString EncryAES(CString str,CString key,CString iv="1234567890abcdef");
static void Base64String2Byte(CString str,BYTE *pOutData,int &outSize);
static CString Byte2Base64String(BYTE *pData,int nDataL);
static CString StringMD5(CString str);
static void ConverToUTF8(CString &strXml);
static void ConvertUtf8ToGBK(CString &strUtf8);
static BOOL KillExe(LPCSTR lpProcessName);
static CString GetPath();
BOOL GetNewAppVer(CString &Ver,CString &DownUrl,CString &AppExe);
void InitNET();
bool SubMessage(CString Topic,int Qos,CString &sError);
volatile MQTTClient_deliveryToken deliveredtoken;
MQTTClient client;
bool bInitMQTT;
void PubMessage();
bool InitMQTT(CString &sMsg);
bool ConnectMQTT(CString address,CString clientid,CString username,CString password,CString &sError);
NETFrame();
virtual ~NETFrame();
private:
Config m_Config;
CString myClientID;
void GetConfig();
};
#endif // !defined(AFX_MQTTFRAME_H__8CE5D444_AA37_47DF_B98D_F567D8ACAE5F__INCLUDED_)
cpp文件
// MQTTFrame.cpp: implementation of the MQTTFrame class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "NETFrame.h"
#include "MainForm.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#include "..\单核CEF封装\include\MiniJson.h"
#include "tlhelp32.h"
#include ".\MD5\md5.h"
#include ".\AES\Base64.h"
#include ".\Lock\DES.h"
#define ADDRESS "tcp://154.83.13.144:1883"
#define CLIENTID "MQTTApplication"
//#define TOPIC "MQTT Examples"
#define TOPIC "/dev/upAeaa"
#define PAYLOAD "Hello World!"
#define QOS 1
#define TIMEOUT 10000L
#pragma comment(lib,"..\\eclipse-paho-mqtt-c-win32-1.3.9\\lib\\paho-mqtt3c.lib")
#ifdef _DEBUG
#pragma comment(lib,"..\\lib\\FrameNETCalld.lib")
#pragma comment(lib,"..\\单核CEF封装\\lib\\MiniJsond.lib")
#else
#pragma comment(lib,"..\\lib\\FrameNETCall.lib")
#pragma comment(lib,"..\\单核CEF封装\\lib\\MiniJson.lib")
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
extern CString DllPath;
CString NETFrame::AuthMark="XNXZT";
void delivered(void *context, MQTTClient_deliveryToken dt)
{
NETFrame *pNETFrame=(NETFrame *)context;
printf("Message with token value %d delivery confirmed\n", dt);
pNETFrame->deliveredtoken = dt;
}
int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
NETFrame *pNETFrame=(NETFrame *)context;
printf("Message arrived\n");
printf(" topic: %s\n", topicName);
printf(" message: %.*s\n", message->payloadlen, (char*)message->payload);
CString TStr="接收到 topicname:";
TStr+=topicName;
CString TMsg;
TMsg.Format(",message: %.*s", message->payloadlen, (char*)message->payload);
TStr+=TMsg;
//AfxMessageBox(TStr);
CString TPName,MsgString;
TPName.Format("%s",topicName);
MsgString.Format("%s",(char*)message->payload);
NETFrame::ConvertUtf8ToGBK(TPName);
NETFrame::ConvertUtf8ToGBK(MsgString);
int nPos=MsgString.ReverseFind('}');
if(nPos!=-1)
{
MsgString=MsgString.Mid(0,nPos+1);
}
pNETFrame->ActionMQTTMessage(TPName,MsgString);
MQTTClient_freeMessage(&message);
MQTTClient_free(topicName);
return 1;
}
void connlost(void *context, char *cause)
{
NETFrame *pNETFrame=(NETFrame *)context;
printf("\nConnection lost\n");
printf(" cause: %s\n", cause);
if(!pNETFrame->bAuthError)
{
pNETFrame->NETDown();
}
}
NETFrame::NETFrame()
{
bAuthError=false;
srand(GetTickCount());
bInitMQTT=false;
::InitializeCriticalSection(&CS);
hStart=::CreateEvent(NULL,true,false,NULL);
hExit=CreateEvent(NULL,true,false,NULL);
}
NETFrame::~NETFrame()
{
::DeleteCriticalSection(&CS);
CloseHandle(hStart);
CloseHandle(hExit);
}
bool NETFrame::ConnectMQTT(CString address,CString clientid,CString username,CString password,CString &sError)
{
sError="";
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_message pubmsg = MQTTClient_message_initializer;
MQTTClient_deliveryToken token;
int rc;
bAuthError=false;
//if ((rc = MQTTClient_create(&client, ADDRESS, CLIENTID,
// MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTCLIENT_SUCCESS)
if ((rc = MQTTClient_create(&client, address, clientid,
MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to create client, return code %d\n", rc);
//exit(EXIT_FAILURE);
bInitMQTT=false;
sError.Format("Failed to create client, return code %d", rc);
}
else
{
if ((rc = MQTTClient_setCallbacks(client, this, connlost, msgarrvd, delivered)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to set callbacks, return code %d\n", rc);
//rc = EXIT_FAILURE;
//goto destroy_exit;
bInitMQTT=false;
//AfxMessageBox("Failed to set callbacks, return code");
sError.Format("Failed to set callbacks, return code %d", rc);
}
else
{
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
//conn_opts.username="xn";
//conn_opts.password="123456";
conn_opts.username=(char *)(const char *)username;
conn_opts.password=(char *)(const char *)password;
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
//exit(EXIT_FAILURE);
CString TStr;
TStr.Format("Failed to connect, return code %d", rc);
//AfxMessageBox(TStr);
sError.Format("Failed to connect, return code %d", rc);
if(rc==5)
{
bAuthError=true;
}
else
{
AfxBeginThread(StartSVRThread,this);
}
}
else
{
myClientID=clientid;
bInitMQTT=true;
}
}
}
return bInitMQTT;
}
void NETFrame::GetConfig()
{
CString TStr=DllPath,Path;
Path=DllPath+"Aeaa.ini";
char tt[MAX_PATH];
char Xiang[20];
sprintf(Xiang,"地址");
GetPrivateProfileString("配置",Xiang,"",tt,200,Path);
m_Config.Url.Format("%s",tt);
}
bool NETFrame::InitMQTT(CString &sMsg)
{
bool bOK=false;
HANDLE hParameJson=CreateJson();
HANDLE hOutParameJson;
m_Config.m_PubQOSArray.RemoveAll();
m_Config.m_PubTopicArray.RemoveAll();
m_Config.m_SubQOSArray.RemoveAll();
m_Config.m_SubTopicArray.RemoveAll();
//if(XNFrameNETCall::RunFunction("Aeaa","getMQTT", hParameJson,sMsg,hOutParameJson))
CString sTMsg;
if(RunHttpFunction("Aeaa","getMQTT", hParameJson,sMsg,hOutParameJson))
{
CString sValue,sType;
CString IP,Port,WSPort,WSPath;
if(!GetMFCJsonVar(hOutParameJson,"ip",sValue,sType))
{
//MessageBox("缺少ip参数","获得MQTT信息失败",MB_OK|MB_ICONERROR);
sMsg="缺少ip参数";
}
else
{
IP=sValue;
if(!GetMFCJsonVar(hOutParameJson,"port",sValue,sType))
{
//MessageBox("缺少port参数","获得MQTT信息失败",MB_OK|MB_ICONERROR);
sMsg="缺少port参数";
}
else
{
Port=sValue;
if(!GetMFCJsonVar(hOutParameJson,"wsport",sValue,sType))
{
//MessageBox("缺少wsport参数","获得MQTT信息失败",MB_OK|MB_ICONERROR);
sMsg="缺少wsport参数";
}
else
{
WSPort=sValue;
if(!GetMFCJsonVar(hOutParameJson,"wspath",sValue,sType))
{
//MessageBox("缺少wspath参数","获得MQTT信息失败",MB_OK|MB_ICONERROR);
sMsg="缺少wspath参数";
}
else
{
WSPath=sValue;
int nSize=GetJsonArraySize(hOutParameJson,"subs");
{
for(int k=0;k<nSize;k++)
{
CString KeyName;
KeyName.Format("subs[%d]",k);
GetMFCJsonVar(hOutParameJson,KeyName,sValue,sType);
HANDLE hOutJson=TextToJson((char *)(const char *)sValue);
if(GetMFCJsonVar(hOutJson,"topic",sValue,sType))
{
CString topic=sValue;
if(GetMFCJsonVar(hOutJson,"qos",sValue,sType))
{
CString qos=sValue;
m_Config.m_SubTopicArray.Add(topic);
m_Config.m_SubQOSArray.Add(atoi(qos));
}
}
CloseJson(hOutJson);
}
}
nSize=GetJsonArraySize(hOutParameJson,"pubs");
{
for(int k=0;k<nSize;k++)
{
CString KeyName;
KeyName.Format("pubs[%d]",k);
GetMFCJsonVar(hOutParameJson,KeyName,sValue,sType);
HANDLE hOutJson=TextToJson((char *)(const char *)sValue);
if(GetMFCJsonVar(hOutJson,"topic",sValue,sType))
{
CString topic=sValue;
if(GetMFCJsonVar(hOutJson,"qos",sValue,sType))
{
CString qos=sValue;
m_Config.m_PubTopicArray.Add(topic);
m_Config.m_PubQOSArray.Add(atoi(qos));
}
}
CloseJson(hOutJson);
}
}
if(m_Config.m_SubTopicArray.GetSize()==0 && m_Config.m_PubTopicArray.GetSize()==0)
{
//MessageBox("缺少消息信息","获得MQTT信息失败",MB_OK|MB_ICONERROR);
sMsg="缺少消息信息";
}
else
{
bOK=true;
m_Config.m_MQTTAddress.Format("tcp://%s:%s",(char *)(const char *)IP,(char *)(const char *)Port);
AddMsg(m_Config.m_MQTTAddress);
}
}
}
}
}
CloseJson(hOutParameJson);
}
else
{
//AfxMessageBox("11");
//MessageBox(sMsg,"获得MQTT信息失败",MB_OK|MB_ICONERROR );
}
//CloseJson(hParameJson);
return bOK;
}
void NETFrame::PubMessage()
{
MQTTClient_message pubmsg = MQTTClient_message_initializer;
pubmsg.payload = PAYLOAD;
pubmsg.payloadlen = (int)strlen(PAYLOAD);
pubmsg.qos = QOS;
pubmsg.retained = 0;
int rc;
MQTTClient_deliveryToken token;
if ((rc = MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to publish message, return code %d\n", rc);
//exit(EXIT_FAILURE);
AfxMessageBox("发送失败");
return;
}
printf("Waiting for up to %d seconds for publication of %s\n"
"on topic %s for client with ClientID: %s\n",
(int)(TIMEOUT/1000), PAYLOAD, TOPIC, CLIENTID);
rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);
printf("Message with delivery token %d delivered\n", token);
}
bool NETFrame::SubMessage(CString Topic,int Qos,CString &sError)
{
int rc;
//if ((rc = MQTTClient_subscribe(client, TOPIC, QOS)) != MQTTCLIENT_SUCCESS)
if ((rc = MQTTClient_subscribe(client, (char *)(const char *)Topic, Qos)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to subscribe, return code %d\n", rc);
//rc = EXIT_FAILURE;
//AfxMessageBox("Failed to subscribe, return code");
sError.Format("Failed to subscribe, return code %d",rc);
return false;
}
else
{
//AfxMessageBox("subscribe OK");
return true;
}
}
void NETFrame::InitNET()
{
m_XTiShiDlg.Create(IDD_TISHI);
m_XTiShiDlg.CenterWindow();
GetConfig();
XNFrameNETCall::SetUTF8();
// TODO: Add extra initialization here
AddMsg("Url:"+m_Config.Url);
XNFrameNETCall::SetUrl((char *)(const char *)m_Config.Url);
CWinThread *pThread=AfxBeginThread(HttpThread,this);
pThread->m_bAutoDelete=true;
}
BOOL NETFrame::GetNewAppVer(CString &Ver,CString &DownUrl,CString &AppExe)
{
bool bOK=false;
HANDLE hParameJson=CreateJson();
HANDLE hOutParameJson;
AddOneStr(hParameJson,"appname","Aeaa");
AddOneStr(hParameJson,"apptype","windows");
AddOneStr(hParameJson,"ver",(char *)(const char *)Ver);
CString sMsg="获得新版本";
if(RunHttpFunction("CoreSYS.SYS","GetNewAppVer", hParameJson,sMsg,hOutParameJson))
{
//CString sText=MFCJsonToText(hOutParameJson);
CString sValue,sType;
if(!GetMFCJsonVar(hOutParameJson,"NewVer",sValue,sType))
{
return false;
}
else
{
sValue.MakeUpper();
sValue.TrimLeft();
sValue.TrimRight();
if(sValue=="TRUE")
{
if(!GetMFCJsonVar(hOutParameJson,"appexe",sValue,sType))
{
return false;
}
else
{
AppExe=sValue;
if(!GetMFCJsonVar(hOutParameJson,"ver",sValue,sType))
{
return false;
}
else
{
Ver=sValue;
if(!GetMFCJsonVar(hOutParameJson,"DownUrl",sValue,sType))
{
return false;
}
else
{
DownUrl=m_Config.Url+sValue;
return true;
}
}
}
}
else
{
return false;
}
}
}
else
{
return false;
}
}
CString NETFrame::GetPath()
{
CString TStr,Path;
char tt[300];
GetModuleFileName(NULL,tt,200);
TStr.Format("%s",tt);
int nWei=TStr.ReverseFind('\\');
TStr=TStr.Mid(0,nWei);
return TStr;
}
BOOL NETFrame::KillExe(LPCSTR lpProcessName)
{
CString sEXE;
sEXE.Format("%s",lpProcessName);
sEXE.MakeLower();
sEXE.TrimLeft();
sEXE.TrimRight();
HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe;
pe.dwSize = sizeof(PROCESSENTRY32);
if(!Process32First(hSnapShot,&pe))
{
return FALSE;
}
CString strProcessName = lpProcessName;
strProcessName.MakeLower();
while (Process32Next(hSnapShot,&pe))
{
CString scTmp = pe.szExeFile;
scTmp.MakeLower();
//if(!scTmp.Compare(strProcessName))
if(scTmp.Find(sEXE)!=-1)
{
DWORD dwProcessID = pe.th32ProcessID;
HANDLE hProcess = ::OpenProcess(PROCESS_TERMINATE,FALSE,dwProcessID);
::TerminateProcess(hProcess,0);
CloseHandle(hProcess);
return TRUE;
}
scTmp.ReleaseBuffer();
}
strProcessName.ReleaseBuffer();
return FALSE;
}
void NETFrame::ConvertUtf8ToGBK(CString &strUtf8)
{
int len=MultiByteToWideChar(CP_UTF8, 0, (LPCTSTR)strUtf8, -1, NULL,0);
unsigned short * wszGBK = new unsigned short[len+1];
memset(wszGBK, 0, len * 2 + 2);
MultiByteToWideChar(CP_UTF8, 0, (LPCTSTR)strUtf8, -1, wszGBK, len);
len = WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, NULL, 0, NULL, NULL);
char *szGBK=new char[len + 1];
memset(szGBK, 0, len + 1);
WideCharToMultiByte (CP_ACP, 0, wszGBK, -1, szGBK, len, NULL,NULL);
strUtf8 = szGBK;
delete[] szGBK;
delete[] wszGBK;
}
void NETFrame::ConverToUTF8(CString &strXml)
{
WCHAR *chBuf;
char * p;
int iLen;
iLen = MultiByteToWideChar(CP_ACP, 0, strXml,-1 , NULL, 0);
chBuf = new WCHAR[iLen+1];
ZeroMemory(chBuf, iLen * sizeof(WCHAR));
iLen =MultiByteToWideChar(CP_ACP, 0, strXml, -1, chBuf, iLen+1);
iLen = WideCharToMultiByte(CP_UTF8, 0, chBuf,-1 , NULL, 0,NULL,NULL);
p = new CHAR[iLen+1];
ZeroMemory(p, iLen * sizeof(CHAR));
iLen =WideCharToMultiByte(CP_UTF8, 0, chBuf, -1, p, iLen+1,NULL,NULL);
delete []chBuf;
CString re(p);
strXml=re;
}
CString NETFrame::StringMD5(CString str)
{
return MD5String((char *)(const char *)str);
}
CString NETFrame::Byte2Base64String(BYTE *pData, int nDataL)
{
return Base64::MFCEncodeBase64(pData,nDataL);
}
void NETFrame::Base64String2Byte(CString str, BYTE *pOutData, int &outSize)
{
BYTE *pData=Base64::MFCDecodeBase64(str,outSize);
memcpy(pOutData,pData,outSize);
}
CString NETFrame::EncryAES(CString str, CString key, CString iv)
{
if(iv.GetLength()!=16)
{
return "";
}
int L=16-key.GetLength();
if(L<0)
{
key=key.Mid(0,16);
}
for(int i=0;i<L;i++)
{
key+=" ";
}
return AES::EncryptionAES(str,key,iv);
}
CString NETFrame::DecryAES(CString str, CString key, CString iv)
{
if(iv.GetLength()!=16)
{
return "";
}
int L=16-key.GetLength();
if(L<0)
{
key=key.Mid(0,16);
}
for(int i=0;i<L;i++)
{
key+=" ";
}
return AES::DecryptionAES(str,key,iv);
}
BOOL NETFrame::ActiveApp(CString deviceid,CString username)
{
bool bOK=false;
CString apptype;
apptype="windows";
CString outmark="";
HANDLE hParameJson=CreateJson();
HANDLE hOutParameJson;
CString appname;
appname="Aeaa";
AuthFile m_AuthFile;
if(ReadKey(&m_AuthFile))
{
outmark.Format("%s",m_AuthFile.outmark);
}
AddOneStr(hParameJson,"appname",(char *)(const char *)appname);
/*
AddOneStr(hParameJson,"apptype","windows");
AddOneStr(hParameJson,"deviceid","54RIHswGhDFuU_0d16");
AddOneStr(hParameJson,"reguser","xzt");
AddOneStr(hParameJson,"outmark","4f9af392bc5b426d9c01a791f940682f");
*/
/*
AddOneStr(hParameJson,"apptype","diy");
AddOneStr(hParameJson,"deviceid","54Sy6BmYOdLrW_f8c3");
AddOneStr(hParameJson,"reguser","xzt");
AddOneStr(hParameJson,"outmark","98e158c96119449f8916147d9673e95f");
*/
AddOneStr(hParameJson,"apptype",(char *)(const char *)apptype);
AddOneStr(hParameJson,"deviceid",(char *)(const char *)deviceid);
AddOneStr(hParameJson,"reguser",(char *)(const char *)username);
AddOneStr(hParameJson,"outmark",(char *)(const char *)outmark);
CString sMsg="激活终端";
if(RunHttpFunction("CoreSYS.SYS","appregOffline", hParameJson,sMsg,hOutParameJson))
{
CString ActivationCode,code,sys_companys_nodeuuid="",company,expression,limitdate,limitnum,limittype,logo;
CString sValue,sType;
if(!GetMFCJsonVar(hOutParameJson,"ActivationCode",sValue,sType))
{
}
else
{
ActivationCode=sValue;
}
if(!GetMFCJsonVar(hOutParameJson,"code",sValue,sType))
{
}
else
{
code=sValue;
}
if(!GetMFCJsonVar(hOutParameJson,"company",sValue,sType))
{
}
else
{
company=sValue;
}
if(!GetMFCJsonVar(hOutParameJson,"expression",sValue,sType))
{
}
else
{
expression=sValue;
}
if(!GetMFCJsonVar(hOutParameJson,"limittype",sValue,sType))
{
}
else
{
limittype=sValue;
}
if(!GetMFCJsonVar(hOutParameJson,"limitdate",sValue,sType))
{
}
else
{
limitdate=sValue;
}
if(!GetMFCJsonVar(hOutParameJson,"limitnum",sValue,sType))
{
}
else
{
limitnum=sValue;
}
if(!GetMFCJsonVar(hOutParameJson,"logo",sValue,sType))
{
}
else
{
logo=sValue;
}
if(!GetMFCJsonVar(hOutParameJson,"sys_companys_nodeuuid",sValue,sType))
{
}
else
{
sys_companys_nodeuuid=sValue;
}
CString outCode=NETFrame::DecryAES(code,deviceid);
NETFrame::ConvertUtf8ToGBK(outCode);
//AfxMessageBox(outCode);
HANDLE hCodeJson=TextToJson((char *)(const char *)outCode);
CString outmarkNET,deviceidNET,limittypeNET,uidNET,appnameNET,limitdataNET;
if(hCodeJson!=NULL)
{
if(!GetMFCJsonVar(hCodeJson,"outmark",sValue,sType))
{
}
else
{
outmarkNET=sValue;
}
if(!GetMFCJsonVar(hCodeJson,"deviceid",sValue,sType))
{
}
else
{
deviceidNET=sValue;
}
if(!GetMFCJsonVar(hCodeJson,"limittype",sValue,sType))
{
}
else
{
limittypeNET=sValue;
}
if(!GetMFCJsonVar(hCodeJson,"uid",sValue,sType))
{
}
else
{
uidNET=sValue;
}
if(!GetMFCJsonVar(hCodeJson,"appname",sValue,sType))
{
}
else
{
appnameNET=sValue;
}
if(!GetMFCJsonVar(hCodeJson,"limitdata",sValue,sType))
{
}
else
{
limitdataNET=sValue;
}
CloseJson(hCodeJson);
SaveKey(appname,apptype,username,sys_companys_nodeuuid,deviceid,uidNET,limittypeNET,limitdataNET,outmarkNET);
}
return true;
}
else
{
::MessageBox(NULL,sMsg,"错误提示",MB_OK|MB_ICONHAND);
//CloseJson(hParameJson);
return false;
}
}
BOOL NETFrame::SaveKey(CString appName,CString appType,CString userName,CString sys_companys_nodeuuid,CString deviceID,CString uidNET,CString limittypeNET,CString limitdataNET,CString outmarkNET)
{
CString FName=GetPath()+"\\key.auth";
AuthFile m_AuthFile;
sprintf(m_AuthFile.head,"%s",(char *)(const char *)AuthMark);
sprintf(m_AuthFile.appname,"%s",(char *)(const char *)appName);
sprintf(m_AuthFile.apptype,"%s",(char *)(const char *)appType);
sprintf(m_AuthFile.reguser,"%s",(char *)(const char *)userName);
sprintf(m_AuthFile.sys_companys_nodeuuid,"%s",(char *)(const char *)sys_companys_nodeuuid);
sprintf(m_AuthFile.deviceid,"%s",(char *)(const char *)deviceID);
sprintf(m_AuthFile.uid,"%s",(char *)(const char *)uidNET);
sprintf(m_AuthFile.limittype,"%s",(char *)(const char *)limittypeNET);
sprintf(m_AuthFile.limitdata,"%s",(char *)(const char *)limitdataNET);
sprintf(m_AuthFile.outmark,"%s",(char *)(const char *)outmarkNET);
int nDataL=sizeof(m_AuthFile);
CString sName=GetPCName();
bool bOK=false;
CString sData=Byte2Base64String((BYTE *)&m_AuthFile,sizeof(m_AuthFile));
CString outString=EncryAES(sData,sName);
{
CFile MyFile;
if(MyFile.Open(FName,CFile::modeCreate|CFile::modeReadWrite))
{
MyFile.Write((char *)(const char *)outString,outString.GetLength());
MyFile.Close();
bOK=true;
}
}
return bOK;
}
CString NETFrame::GetPCName()
{
char Name[255];
DWORD L=255;
CString Str;
Str="AuthPC";
if(GetComputerName(Name,&L))
{
Name[L]=0;
Str.Format("%s",Name);
}
int LL=16-Str.GetLength();
if(LL>=0)
{
for(int i=0;i<LL;i++)
{
Str+=" ";
}
}
else
{
Str=Str.Mid(0,16);
}
return Str;
}
void NETFrame::Wait(int nWait)
{
DWORD OldT=GetTickCount();
while(1)
{
MSG Msg;
if(PeekMessage(&Msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
if(GetTickCount()-OldT>nWait)
break;
Sleep(50);
}
}
UINT NETFrame::HttpThread(LPVOID p)
{
NETFrame *pNETFrame=(NETFrame *)p;
pNETFrame->ActionHttp();
return 1;
}
void NETFrame::ActionHttp()
{
HANDLE hEvent[2];
hEvent[0]=hStart;
hEvent[1]=hExit;
while(true)
{
DWORD nWait=WaitForMultipleObjects(2,hEvent,false,INFINITE);
switch(nWait)
{
case WAIT_OBJECT_0:
{
OneHttp *pOneHttp=NULL;
::EnterCriticalSection(&CS);
if(m_WorkPtr.GetCount()>0)
{
pOneHttp=(OneHttp *)m_WorkPtr.GetHead();
m_WorkPtr.RemoveHead();
if(m_WorkPtr.GetCount()==0)
ResetEvent(hStart);
}
::LeaveCriticalSection(&CS);
if(pOneHttp!=NULL)
{
ActionOneHttp(pOneHttp);
}
}
break;
case WAIT_OBJECT_0+1:
{
ClearWorkPtr();
return ;
}
break;
default:
{
}
break;
}
}
}
void NETFrame::ActionOneHttp(OneHttp *pOneHttp)
{
if(pOneHttp!=NULL)
{
if(pOneHttp->isRow)
{
CString sMsg;
if(XNFrameNETCall::RunFunction(pOneHttp->ClassName,pOneHttp->FuncName, pOneHttp->hParameJson, sMsg,pOneHttp->m_RowReturn.total, pOneHttp->m_RowReturn.pageSize,pOneHttp->m_RowReturn.m_RowJsonArray))
{
pOneHttp->Msg[0]=0;
pOneHttp->isOK=true;
pOneHttp->isOver=true;
}
else
{
sprintf(pOneHttp->Msg,"%s",(char *)(const char *)sMsg);
pOneHttp->isOK=false;
pOneHttp->isOver=true;
}
if(pOneHttp->hOverEvent!=NULL)
{
SetEvent(pOneHttp->hOverEvent);
}
}
else
{
CString sMsg;
if(XNFrameNETCall::RunFunction(pOneHttp->ClassName,pOneHttp->FuncName, pOneHttp->hParameJson,sMsg,pOneHttp->m_JsonReturn.hOutParameJson))
{
pOneHttp->Msg[0]=0;
pOneHttp->isOK=true;
pOneHttp->isOver=true;
}
else
{
sprintf(pOneHttp->Msg,"%s",(char *)(const char *)sMsg);
pOneHttp->isOK=false;
pOneHttp->isOver=true;
}
if(pOneHttp->hOverEvent!=NULL)
{
SetEvent(pOneHttp->hOverEvent);
}
}
}
}
void NETFrame::ClearWorkPtr()
{
::EnterCriticalSection(&CS);
for(int i=0;i<m_WorkPtr.GetCount();i++)
{
OneHttp *pOneHttp=(OneHttp *)m_WorkPtr.GetAt(m_WorkPtr.FindIndex(i));
delete pOneHttp;
}
m_WorkPtr.RemoveAll();
::LeaveCriticalSection(&CS);
}
BOOL NETFrame::RunHttpFunction(CString ClassName, CString FuncName, HANDLE hParameJson, CString &sMsg,HANDLE &hOutParameJson, bool bInThread)
{
OneHttp *pOneHttp=new OneHttp();
sprintf(pOneHttp->ClassName,"%s",(char *)(const char *)ClassName);
sprintf(pOneHttp->FuncName,"%s",(char *)(const char *)FuncName);
pOneHttp->hParameJson=hParameJson;
pOneHttp->isOver=false;
pOneHttp->isOK=false;
pOneHttp->isRow=false;
m_XTiShiDlg.Show(sMsg);
Wait(100);
if(bInThread)
{
pOneHttp->hOverEvent=CreateEvent(NULL,true,false,NULL);
}
else
{
pOneHttp->hOverEvent=NULL;
}
AddOneHttp(pOneHttp);
while(true)
{
if(pOneHttp->hOverEvent==NULL)
{
Wait(100);
}
else
{
DWORD nWait=WaitForSingleObject(pOneHttp->hOverEvent,INFINITE);
if(nWait!=WAIT_OBJECT_0)
continue;
else
{
break;
}
}
if(pOneHttp->isOver)
{
break;
}
}
bool isOK=pOneHttp->isOK;
if(!isOK)
{
sMsg.Format("%s",pOneHttp->Msg);
}
else
{
hOutParameJson=pOneHttp->m_JsonReturn.hOutParameJson;
}
if(pOneHttp->hOverEvent!=NULL)
{
CloseHandle(pOneHttp->hOverEvent);
}
delete pOneHttp;
m_XTiShiDlg.Hide();
return isOK;
}
BOOL NETFrame::RunHttpFunction(CString ClassName, CString FunctionName, HANDLE hParameJson, CString &sMsg, int &total, int &pageSize, CDWordArray &m_RowJsonArray,bool bInThread)
{
OneHttp *pOneHttp=new OneHttp();
sprintf(pOneHttp->ClassName,"%s",(char *)(const char *)ClassName);
sprintf(pOneHttp->FuncName,"%s",(char *)(const char *)FunctionName);
pOneHttp->hParameJson=hParameJson;
pOneHttp->isOver=false;
pOneHttp->isOK=false;
pOneHttp->isRow=true;
m_XTiShiDlg.Show(sMsg);
Wait(100);
if(bInThread)
{
pOneHttp->hOverEvent=CreateEvent(NULL,true,false,NULL);
}
else
{
pOneHttp->hOverEvent=NULL;
}
AddOneHttp(pOneHttp);
while(true)
{
if(pOneHttp->hOverEvent==NULL)
{
Wait(100);
}
else
{
DWORD nWait=WaitForSingleObject(pOneHttp->hOverEvent,INFINITE);
if(nWait!=WAIT_OBJECT_0)
continue;
else
{
break;
}
}
if(pOneHttp->isOver)
{
break;
}
}
bool isOK=pOneHttp->isOK;
if(!isOK)
{
sMsg.Format("%s",pOneHttp->Msg);
}
else
{
total=pOneHttp->m_RowReturn.total;
pageSize=pOneHttp->m_RowReturn.pageSize;
m_RowJsonArray.RemoveAll();
for(int i=0;i<pOneHttp->m_RowReturn.m_RowJsonArray.GetSize();i++)
{
m_RowJsonArray.Add(pOneHttp->m_RowReturn.m_RowJsonArray.GetAt(i));
}
}
if(pOneHttp->hOverEvent!=NULL)
{
CloseHandle(pOneHttp->hOverEvent);
}
if(hParameJson!=NULL)
{
CloseJson(hParameJson);
}
delete pOneHttp;
m_XTiShiDlg.Hide();
return isOK;
}
BOOL NETFrame::AddOneHttp(OneHttp *pOneHttp)
{
::EnterCriticalSection(&CS);
m_WorkPtr.AddTail(pOneHttp);
if(m_WorkPtr.GetCount()==1)
{
::SetEvent(hStart);
}
::LeaveCriticalSection(&CS);
return true;
}
BOOL NETFrame::SubMessages(CStringArray &m_TopicArray, CByteArray &m_QOSArray, CString &sError)
{
bool bOK=true;
char **pTopic=new char *[m_TopicArray.GetSize()];
int *pQos=new int[m_TopicArray.GetSize()];
int nSize=m_TopicArray.GetSize();
for(int i=0;i<nSize;i++)
{
pTopic[i]=(char *)(const char *)m_TopicArray.GetAt(i);
pQos[i]=(int)m_QOSArray.GetAt(i);
}
int rc;
//if(MQTTClient_subscribeMany(MQTTClient handle, int count, char* const* topic, int* qos)
if ((rc = MQTTClient_subscribeMany(client, nSize, (char * const char *)pTopic, pQos)) != MQTTCLIENT_SUCCESS)
{
bOK=false;
printf("Failed to subscribe, return code %d\n", rc);
//rc = EXIT_FAILURE;
//AfxMessageBox("Failed to subscribe, return code");
sError.Format("Failed to subscribe, return code %d",rc);
}
delete[] pTopic;
delete[]pQos;
return bOK;
}
BOOL NETFrame::ReadKey(AuthFile *pAuthFile)
{
bool bOK=false;
CString FName=GetPath()+"\\key.auth";
CFile MyFile;
if(!MyFile.Open(FName,CFile::modeReadWrite))
{
return false;
}
int nDataL=MyFile.GetLength();
char *pData=new char[nDataL+1];
MyFile.Read(pData,nDataL);
MyFile.Close();
pData[nDataL]=0;
CString sName=GetPCName();
CString outString=DecryAES(pData,sName);
{
int L=sizeof(struct AuthFile);
Base64String2Byte(outString,(BYTE *)pAuthFile,L);
CString Mark;
Mark.Format("%s",pAuthFile->head);
if(Mark==AuthMark)
{
bOK=true;
}
}
delete[]pData;
return bOK;
}
BOOL NETFrame::StartSVR(CString &sError)
{
AddMsg("开始MQTT连接...");
if(bInitMQTT)
{
return true;
}
AuthFile m_AuthFile;
if(!ReadKey(&m_AuthFile))
{
sError="请先激活后再启动服务";
//MessageBox(NULL,"请先激活后再启动服务","错误提示",MB_OK|MB_ICONHAND);
AddMsg("请先激活后再启动服务");
return false;
}
else
{
//CString sError;
if(!InitMQTT(sError))
{
//MessageBox(NULL,(char *)(const char *)sError,"错误提示",MB_OK|MB_ICONHAND);
AddMsg(sError);
if(sError=="连接错误" || sError=="数据格式错误")
{
AfxBeginThread(StartSVRThread,this);
}
return false;
}
Wait(200);
AddMsg("初始InitMQTT成功正式MQTT连接...");
CString outMark=m_AuthFile.outmark;
CString password=getRandPWD(outMark);
CString TStr;
TStr.Format("deviceid:%s,password:%s",m_AuthFile.deviceid,password);
AddMsg(TStr);
if(ConnectMQTT(m_Config.m_MQTTAddress,m_AuthFile.deviceid,m_AuthFile.deviceid,password,sError))
{
CStringArray m_SubTopicArray;
for(int i=0;i<m_Config.m_SubTopicArray.GetSize();i++)
{
CString Name=m_Config.m_SubTopicArray.GetAt(i);
Name.Replace("+",m_AuthFile.sys_companys_nodeuuid);
m_SubTopicArray.Add(Name);
}
if(SubMessages(m_SubTopicArray,m_Config.m_SubQOSArray,sError))
{
AddMsg("MQTT连接成功");
return true;
}
else
{
MQTTClient_disconnect(client,0);
bInitMQTT=false;
AddMsg(sError);
return false;
}
}
else
{
//MessageBox(NULL,(char *)(const char *)sError,"错误提示",MB_OK|MB_ICONHAND);
AddMsg(sError);
return false;
}
}
}
void NETFrame::Init()
{
InitNET();
}
CString NETFrame::getRandPWD(CString outMark)
{
//return "";
srand(GetTickCount());
int X=0;
int Y=32;
int A =(double)rand()/(RAND_MAX+1)*(Y-X)+X;
int B =(double)rand()/(RAND_MAX+1)*(Y-X)+X;
int C =(double)rand()/(RAND_MAX+1)*(Y-X)+X;
int D =(double)rand()/(RAND_MAX+1)*(Y-X)+X;
int Base=65;
CString WStr,MD5String="";
WStr.Format("%c%c%c%c",A+Base,B+Base,C+Base,D+Base);
MD5String=StringMD5(WStr);
X=0;
Y=32-4-2;//留6位最后两位为位置位与数据位
int nWPos=(double)rand()/(RAND_MAX+1)*(Y-X)+X; //获得位置信息
int nDPos=-1;
int nDataLeftMin=0;
int nDataLeftMax=nWPos-4;
int nLeftDataPos=-1;
if(nDataLeftMax<=0)
{
}
else
{
X=nDataLeftMin;
Y=nDataLeftMax;
nLeftDataPos=(double)rand()/(RAND_MAX+1)*(Y-X)+X;
}
int nRightDataPos=-1;
int nDataRightMin=nWPos+4;
int nDataRightMax=32-4-2;
if(nDataRightMin+4>nDataRightMax)
{
}
else
{
X=nDataRightMin;
Y=nDataRightMax;
nRightDataPos=(double)rand()/(RAND_MAX+1)*(Y-X)+X;
}
X=0;
Y=100;
if(nLeftDataPos==-1 && nRightDataPos==-1)
{
return "";
}
else
{
if(nLeftDataPos!=-1 && nRightDataPos!=-1)
{
int nn=(double)rand()/(RAND_MAX+1)*(Y-X)+X;
if(nn>50)
{
nDPos=nRightDataPos;
}
else
{
nDPos=nLeftDataPos;
}
}
else
{
if(nLeftDataPos!=-1)
{
nDPos=nLeftDataPos;
}
else
{
nDPos=nRightDataPos;
}
}
}
MD5String.SetAt(30,nWPos+Base);
MD5String.SetAt(31,nDPos+Base);
CString LString=MD5String.Mid(0,nWPos);
CString RString=MD5String.Mid(nWPos+4);
MD5String=LString+WStr+RString;
CString sData="1234";
sData.SetAt(0,outMark.GetAt(A));
sData.SetAt(1,outMark.GetAt(B));
sData.SetAt(2,outMark.GetAt(C));
sData.SetAt(3,outMark.GetAt(D));
LString=MD5String.Mid(0,nDPos);
RString=MD5String.Mid(nDPos+4);
MD5String=LString+sData+RString;
return MD5String;
}
BOOL NETFrame::ChkPWD(CString pwd, CString outMark)
{
int Base=65;
int WPos=pwd.GetAt(30)-Base;
int DPos=pwd.GetAt(31)-Base;
CString WStr=pwd.Mid(WPos,4);
CString DStr=pwd.Mid(DPos,4);
int A=WStr.GetAt(0)-Base;
int B=WStr.GetAt(1)-Base;
int C=WStr.GetAt(2)-Base;
int D=WStr.GetAt(3)-Base;
CString RDStr="1234";
RDStr.SetAt(0,outMark.GetAt(A));
RDStr.SetAt(1,outMark.GetAt(B));
RDStr.SetAt(2,outMark.GetAt(C));
RDStr.SetAt(3,outMark.GetAt(D));
if(DStr==RDStr)
return true;
else
{
return false;
}
}
void NETFrame::NETDown()
{
AfxBeginThread(NETDownThread,this);
}
UINT NETFrame::NETDownThread(LPVOID p)
{
NETFrame *pNETFrame=(NETFrame *)p;
Sleep(2000);
CString sError;
pNETFrame->bInitMQTT=false;
pNETFrame->StartSVR(sError);
return 1;
}
void NETFrame::AddMsg(CString sMsg)
{
if(pWnd!=NULL)
{
CMainForm *pCMainForm=(CMainForm *)pWnd;
pCMainForm->AddMsg(sMsg);
}
}
UINT NETFrame::StartSVRThread(LPVOID p)
{
NETFrame *pNETFrame=(NETFrame *)p;
Sleep(2000);
CString sError;
pNETFrame->StartSVR(sError);
return 1;
}
void NETFrame::ActionMQTTMessage(CString TPName, CString MsgString)
{
//AfxMessageBox(MsgString);
HANDLE hJson=NULL;
try
{
AddMsg("收到topic:"+TPName+",消息:"+MsgString);
hJson=TextToJson((char *)(const char *)MsgString);
if(hJson!=NULL)
{
CString sValue,sType;
CString msgno,data="";
if(!GetMFCJsonVar(hJson,"msgno",sValue,sType))
{
}
else
{
msgno=sValue;
}
if(!GetMFCJsonVar(hJson,"data",sValue,sType))
{
}
else
{
data=sValue;
}
HANDLE hDataJson=TextToJson((char *)(const char *)data);
if(hDataJson!=NULL)
{
/*
m_DataHH["com"] = "ask";
m_DataHH["devno"] = devno;
m_DataHH["sno"] = sno;
m_DataHH["stype"] = stype;
m_DataHH["iotype"] = iotype;
m_DataHH["iojsonstring"] = iojsonstring;
*/
CString com="",devno="",sno="",stype="",iotype="",iojsonstring="";
if(!GetMFCJsonVar(hDataJson,"com",sValue,sType))
{
}
else
{
com=sValue;
}
if(!GetMFCJsonVar(hDataJson,"devno",sValue,sType))
{
}
else
{
devno=sValue;
}
if(!GetMFCJsonVar(hDataJson,"sno",sValue,sType))
{
}
else
{
sno=sValue;
}
if(!GetMFCJsonVar(hDataJson,"stype",sValue,sType))
{
}
else
{
stype=sValue;
}
if(!GetMFCJsonVar(hDataJson,"iotype",sValue,sType))
{
}
else
{
iotype=sValue;
}
if(!GetMFCJsonVar(hDataJson,"iojsonstring",sValue,sType))
{
}
else
{
iojsonstring=sValue;
}
HANDLE hIOJson=TextToJson((char *)(const char *)iojsonstring);
CString ioString="",comString="",misoString="",mosiString="",sckString="",nssString="",sdaString="",sclString="";
if(hIOJson!=NULL)
{
if(iotype=="IO")
{
if(!GetMFCJsonVar(hIOJson,"io",sValue,sType))
{
}
else
{
ioString=sValue;
}
}
else
{
if(iotype=="SPI")
{
if(!GetMFCJsonVar(hIOJson,"miso",sValue,sType))
{
}
else
{
misoString=sValue;
}
if(!GetMFCJsonVar(hIOJson,"mosi",sValue,sType))
{
}
else
{
mosiString=sValue;
}
if(!GetMFCJsonVar(hIOJson,"sck",sValue,sType))
{
}
else
{
sckString=sValue;
}
if(!GetMFCJsonVar(hIOJson,"nss",sValue,sType))
{
}
else
{
nssString=sValue;
}
}
else
{
if(iotype=="I2C")
{
if(!GetMFCJsonVar(hIOJson,"sda",sValue,sType))
{
}
else
{
sdaString=sValue;
}
if(!GetMFCJsonVar(hIOJson,"scl",sValue,sType))
{
}
else
{
sclString=sValue;
}
}
else
{
if(iotype=="COM")
{
if(!GetMFCJsonVar(hIOJson,"com",sValue,sType))
{
}
else
{
comString=sValue;
}
}
else
{
}
}
}
}
CloseJson(hIOJson);
}
CloseJson(hDataJson);
HANDLE hReturnHH=CreateJson();
AddOneStr(hReturnHH,"ret","ok");
ReturnMQTT(msgno,hReturnHH);
CloseJson(hReturnHH);
}
}
}
catch(CException* e)
{
}
if(hJson!=NULL)
{
CloseJson(hJson);
}
}
void NETFrame::ReturnMQTT(CString msgno, HANDLE hData)
{
HANDLE hJson=CreateJson();
AddOneStr(hJson,"msgno",(char *)(const char *)msgno);
AddOneJson(hJson,"data",hData);
CString sData=MFCJsonToText(hJson);
CloseJson(hJson);
ConverToUTF8(sData);
MQTTClient_message pubmsg = MQTTClient_message_initializer;
pubmsg.payload = (char *)(const char *)sData;
pubmsg.payloadlen = sData.GetLength();
pubmsg.qos = m_Config.m_PubQOSArray.GetAt(0);//QOS;
pubmsg.retained = 0;
int rc;
CString topic=m_Config.m_PubTopicArray.GetAt(0);
topic.Replace("+",myClientID);
MQTTClient_deliveryToken token;
AddMsg("回馈topic:"+topic+":"+sData);
if ((rc = MQTTClient_publishMessage(client, (char *)(const char *)topic, &pubmsg, &token)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to publish message, return code %d\n", rc);
//exit(EXIT_FAILURE);
AfxMessageBox("发送失败");
return;
}
printf("Waiting for up to %d seconds for publication of %s\n"
"on topic %s for client with ClientID: %s\n",
(int)(TIMEOUT/1000), (char *)(const char *)sData, (char *)(const char *)topic, myClientID);
/*
rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);
printf("Message with delivery token %d delivered\n", token);
*/
}