-
2009-06-12
在vs2008中提供对Web Service的访问 - [软件工程]
由于vs2008中不能添加Web 服务的引用.我的解决方法是,首先在VS2003中实现该功能,然后将访问Web service的H文件,添加到VS2008中.
一.利用vs2003建立一个非托管的访问Web Service的程序,得到Web Serices的H文件。该文间包含了Web Services提供的API
1.创建一个Mfc应用程序vs2003E2C,不选择"使用托管扩展"选项。
2.右击项目,弹出在快捷菜单中选则"添加Web引用"菜单项.
3.在添加Web引用的url中输入Web service的url."http://fy.webxml.com.cn/webservices/EnglishChinese.asmx",这是一个提供英语与汉语翻译的Webservice.
4 点击"转到"按钮,然后就找到了这个WEBservice服务.
5.在"Web引用中输入","E2CWebService",再单击"添加引用".编译器就会为我们编译生成"E2CWebService.h"文件.这就是我们访问Web Service的接口文件.
6.在该程序中测试该websercice
///////////////////////////////////////////////////////////
//
//
::CoInitialize(NULL);
using namespace EnglishChinese;CEnglishChineseT<> e2c;
BSTR sKey = L"city";
BSTR* pRet = new BSTR[5];
int nLen = 0;
HRESULT hr = e2c.TranslatorString(sKey, &pRet, &nLen);if (SUCCEEDED(hr))
{
CComBSTR br0(pRet[0]);
CComBSTR br1(pRet[1]);
CComBSTR br2(pRet[2]);
CComBSTR br3(pRet[3]);//"城市"
CComBSTR br4(pRet[4]);}
::CoUninitialize();
//
//
//////////////////////////////////////////////////////////////
二.从http://www.codeplex.com/AtlServer下载ATL的访问Web Servrice的文件,下载解压后为文件夹 ATL_Server_Code
三.将在VS2008中添加ATL_Server_Code文件夹的配置
1.options->Projects and Solutions->VC++ Directories
2.在Show directoried for下拉框中选择"include files"
3.新建一项,输入".\Atl_Server\Code\include".使用现对路径
4.OK四.在VS2008的工程中包含Web Serices的H文件即可.调用的方法同上.
-
2009-06-02
Visual Studio 2008运行时提示找不到msvcr90d.dll的解决办法 - [软件工程]
转载 : http://hi.baidu.com/zgjxwl/blog/item/79b55609b892af87d0581b5b.html
说说微软的bug吧,昨天装Visual Studio 2008,注意:我出现这个bug的缘故是因为将Visual Studio 2008装在了FAT32分区下,当然装在这里也不是说完全有问题,但是这样装的话,就不能将项目同样放在FAT32分区下,装好了以后,随便编了个程序,编译连接,一切OK,是在debug模式下的,但是运行的时候,却出现一些问题,截图上来给大家看看

编译和连接的时候都是正常的,惟独在运行的时候会出现这种错误,当时都无语了,具体有操作有,将MSVCR90D.dll拷到system32\下,结果要出现了另外一个问题,截图上来给大家看看

当时都无语了,总之,以后是不要将库拷来拷去,这样解决不了根本问题,具体解决办法还有,将debug模式改为Release,然后在Release模式下可以正常的编译连接和运行.为什么会这样呢,因为release模式下,程序是不会去链接 *.dll 的库的,所以能正常工作.不过我要说的是,这不是根本原因,根本原因在于微软的bug,下面详细道来:
这个是FAT32文件系统分区的缘故,一般有如下症状;
第一次Build 的时候从不出问题,在以后重新Build 的时候,可能随机地出现问题。可能你Build间隔的时间足够长,也不会出问题。
微软也知道这个bug,但是看来没有打算完全解决它的意向,倒是在项目属性中有个选项,让你在FAT32 下也能正常工作。具体如何解决,是这样做的:
如果是把项目放在FAT32分区,那么这样操作:
英文版:Project Properties -> Manifest Tool-> Use FAT32 Work-around -->Yes
中文版:项目-->项目属性-->配置属性-->清单工具-->使用FAT32解决方法-->是
然后clean下,然后Rebuild即可正常运行,但是这样就会很麻烦,每次建个项目,都要设置它的项目属性
最好的解决办法是,将你的项目放在NTFS分区下,这样才可以正常的工作.
如果可以,提醒用户,直接将Visual Studio 2008装在你的NTFS分区下把,这样就不会有限制了,你可以将你的项目创建在任何地方了,而也不会出现上面所说的错误
在网上搜了下,解决这个问题的自己没搜到,因为微软也没任何有用的提示,所以就把它发表下,让其他的朋友也看看把,别像我一样,弄了一天才弄好,才知道症结所在,微软的这个bug,真让我郁闷,当时真想把电脑给砸了,呵呵...
忘了补充一点:如果你安装的也是NTFS格式的文件系统分区,项目也是建在这样格式的分区里,你还要下载微软的一个补丁,在这里找这样一个补丁,给出下载地方,至此,问题就可以顺利解决了
download.microsoft.com/download/0/d/5/0d5580c0-9d8c-4873-9024-553323ab8589/WindowsXP-KB889016-x86-CHS.exe -
2009-05-12
windows 服务程序 - [软件工程]
http://www.cnblogs.com/wuxilin/archive/2006/06/04/416838.htm
安装服务需要用到sc.exe可执行文件,它是win32Platform sdk中附带的工具.安装服务的DOS命令
sc create 服务名称 binpath= exe的路径
卸载服务的DOS命令
sc delete 服务名称
服务对话框:或在“开始”|“运行”对话框中输入 services.msc /s安装服务需要用到sc.exe可执行文件,它是win32Platform sdk中附带的工具.安装服务的DOS命令
sc create 服务名称 binpath= exe的路径
卸载服务的DOS命令
sc delete 服务名称
服务对话框:或在“开始”|“运行”对话框中输入 services.msc /s
// 启动服务的控制分派机线程
SERVICE_TABLE_ENTRY ServiceTable[2];
ServiceTable[0].lpServiceName = "MemoryStatus";
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
ServiceTable[1].lpServiceName = NULL;
ServiceTable[1].lpServiceProc = NULL;//Connects the main thread of a service process to the service control manager
StartServiceCtrlDispatcher(ServiceTable);// Registers a function to handle service control requests.
RegisterServiceCtrlHandler//Updates the service control manager's status information for the calling service.
SetServiceStatus硬断点
_asm int 3;我的对象是基于“我想让这个对象做什么?”而不是“Windows 用这些 APIs 做什么?”
-
2009-03-05
微软研究院Detour开发包之API拦截技术 - [软件工程]
原文:http://www.cnblogs.com/flying_bat/archive/2008/04/18/1159996.html
我们截获函数执行最直接的目的就是为函数增添功能,修改返回值,或者为调试以及性能测试加入附加的代码,或者截获函数的输入输出作研究,破解使用。通过访 问源代码,我们可以轻而易举的使用重建(Rebuilding)操作系统或者应用程序的方法在它们中间插入新的功能或者做功能扩展。然而,在今天这个商业 化的开发世界里,以及在只有二进制代码发布的系统中,研究人员几乎没有机会可以得到源代码。本文主要讨论Detour在Windows二进制PE文件基础 上的API截获技术。对于Linux平台,作这件事情将会非常的简单,由于最初的操作系统设计者引入了LD_PRELOAD。如果你设置 LD_PRELOAD=mylib.so ,那么应用程序在载入 dll时,会先查看mylib.so的符号表,在relocation 的时候会优先 使用mylib.so 里的 symbol 。假如你在mylib.so里有个printf() ,那么这个printf就会替代libc的 printf。 而在mylib.so里的这个printf可以直接访问 libc.so里的printf函数指针来获得真正的 printf的入口地 址。 这样,所有的dll的API HOOK在loader加载dll的时候就已经完成,非常自然,和平台相关的部分全部交给loader去处理。
一、 Detour开发库:
简介
Detours是一个在x86平台上截获任意Win32函数调用的工具库。中断代码可以在运行时动态加载。Detours使用一个无条件转移指令来替换目 标函数的最初几条指令,将控制流转移到一个用户提供的截获函数。而目标函数中的一些指令被保存在一个被称为“trampoline” (译注:英文意为蹦 床,杂技)的函数中,在这里我觉得翻译成目标函数的部分克隆/拷贝比较贴切。这些指令包括目标函数中被替换的代码以及一个重新跳转到目标函数的无条件分 支。而截获函数可以替换目标函数,或者通过执行“trampoline”函数的时候将目标函数作为子程序来调用的办法来扩展功能。
Detours是执行时被插入的。内存中的目标函数的代码不是在硬盘上被修改的,因而可以在一个很好的粒度上使得截获二进制函数的执行变得更容易。例如, 一个应用程序执行时加载的DLL中的函数过程可以被插入一段截获代码(detoured),与此同时,这个DLL还可以被其他应用程序按正常情况执行(译 注:也就是按照不被截获的方式执行,因为DLL二进制文件没有被修改,所以发生截获时不会影响其他进程空间加载这个DLL)。不同于DLL的重新链接或者 静态重定向,Detours库中使用的这种中断技术确保不会影响到应用程序中的方法或者系统代码对目标函数的定位。
如果其他人为了调试或者在内部使用其他系统检测手段而试图修改二进制代码,Detours将是一个可以普遍使用的开发包。据我所知,Detours是第一 个可以在任意平台上将未修改的目标代码作为一个可以通过“trampoline”调用的子程序来保留的开发包。而以前的系统在逻辑上预先将截获代码放到目 标代码中,而不是将原始的目标代码做为一个普通的子程序来调用。我们独特的“trampoline”设计对于扩展现有的软件的二进制代码是至关重要的。
出于使用基本的函数截获功能的目的,Detours同样提供了编辑任何DLL导入表的功能,达到向存在的二进制代码中添加任意数据节表的目的,向一个新进 程或者一个已经运行着的进程中注入一个DLL。一旦向一个进程注入了DLL,这个动态库就可以截获任何Win32函数,不论它是在应用程序中或者在系统库 中。
基本原理
1. WIN32进程的内存管理
众所周知,WINDOWS NT实现了虚拟存储器,每一WIN32进程拥有4GB的虚存空间, 关于WIN32进程的虚存结构及其操作的具体细节请参阅WIN32 API手册, 以下仅指出与Detours相关的几点:
(1) 进程要执行的指令也放在虚存空间中
(2) 可以使用QueryProtectEx函数把存放指令的页面的权限更改为可读可写可执行,再改写其内容,从而修改正在运行的程序
(3) 可以使用VirtualAllocEx从一个进程为另一正运行的进程分配虚存,再使用 QueryProtectEx函数把页面的权限更改为可读可写可执行,并把要执行的指令以二进制机器码的形式写入,从而为一个正在运行的进程注入任意的代码 。
2. 拦截WIN32 API的原理
Detours定义了三个概念:
(1) Target函数:要拦截的函数,通常为Windows的API。
(2) Trampoline函数:Target函数的部分复制品。因为Detours将会改写Target函数,所以先把Target函数的前5个字节复制保存好,一方面仍然保存Target函数的过程调用语义,另一方面便于以后的恢复。
(3) Detour 函数:用来替代Target函数的函数。
Detours在Target函数的开头加入JMP Address_of_ Detour_ Function指令(共5个字节)把对Target函数 的调用引导到自己的Detour函数, 把Target函数的开头的5个字节加上JMP Address_of_ Target _ Function+ 5共10个字节作为Trampoline函数。请参考下面的图1和图2。
(图1:Detour函数的过程)
(图2: Detour函数的调用过程)
说明:
目标函数:
目标函数的函数体(二进制)至少有5个字节以上。按照微软的说明文档Trampoline函数的函数体是拷贝前5个字节加一个无条件跳转指令的话(如果没 有特殊处理不可分割指令的话),那么前5个字节必须是完整指令,也就是不能第5个字节和第6个字节是一条不可分割的指令,否则会造成Trampoline 函数执行错误,一条完整的指令被硬性分割开来,造成程序崩溃。对于第5字节和第6个字节是不可分割指令需要调整拷贝到杂技函数(Trampoline)的 字节个数,这个值可以查看目标函数的汇编代码得到。此函数是目标函数的修改版本,不能在Detour函数中直接调用,需要通过对Trampoline函数 的调用来达到间接调用。
Trampoline函数:
此函数默认分配了32个字节,函数的内容就是拷贝的目标函数的前5个字节,加上一个JMP Address_of_ Target _ Function+5指令,共10个字节。
此函数仅供您的Detour函数调用,执行完前5个字节的指令后再绝对跳转到目标函数的第6个字节继续执行原功能函数。
Detour函数:
此函数是用户需要的截获API的一个模拟版本,调用方式,参数个数必须和目标函数相一致。如目标函数是__stdcall,则Detour函数声明也必须 是__stdcall,参数个数和类型也必须相同,否则会造成程序崩溃。此函数在程序调用目标函数的第一条指令的时候就会被调用(无条件跳转过来的),如 果在此函数中想继续调用目标函数,必须调用Trampoline函数(Trampoline函数在执行完目标函数的前5个字节的指令后会无条件跳转到目标 函数的5个字节后继续执行),不能再直接调用目标函数,否则将进入无穷递归(目标函数跳转到Detour函数,Detour函数又跳转到目标函数的递归, 因为目标函数在内存中的前5个字节已经被修改成绝对跳转)。通过对Trampoline函数的调用后可以获取目标函数的执行结果,此特性对分析目标函数非 常有用,而且可以将目标函数的输出结果进行修改后再传回给应用程序。
Detour提供了向运行中的应用程序注入Detour函数和在二进制文件基础上注入Detour函数两种方式。本章主要讨论第二种工作方式。通过 Detours提供的开发包可以在二进制EXE文件中添加一个名称为Detour的节表,如下图3所示,主要目的是实现PE加载器加载应用程序的时候会自 动加载您编写的Detours DLL,在Detours Dll中的DLLMain中完成对目标函数的Detour。
(图3)
二、 Detours提供的截获API的相关接口
Detours的提供的API 接口可以作为一个共享DLL给外部程序调用,也可以作为一个静态Lib链接到您的程序内部。
Trampoline函数可以动态或者静态的创建,如果目标函数本身是一个链接符号,使用静态的trampoline函数将非常简单。如果目标函数不能在链接时可见,那么可以使用动态trampoline函数。
要使用静态的trampoline函数来截获目标函数,应用程序生成trampoline的时候必须使用
DETOUR_TRAMPOLINE宏。DETOUR_TRAMPOLINE有两个输入参数:trampoline的原型和目标函数的名字。
注意,对于正确的截获模型,包括目标函数,trampoline函数,以及截获函数都必须是完全一致的调用形式,包括参数格式和调用约定。当通过 trampoline函数调用目标函数的时候拷贝正确参数是截获函数的责任。由于目标函数仅仅是截获函数的一个可调用分支(截获函数可以调用 trampoline函数也可以不调用),这种责任几乎就是一种下意识的行为。
使用相同的调用约定可以确保寄存器中的值被正确的保存,并且保证调用堆栈在截获函数调用目标函数的时候能正确的建立和销毁。
可以使用DetourFunctionWithTrampoline函数来截获目标函数。这个函数有两个参数:trampoline函数以及截获函数的指针。因为目标函数已经被加到trampoline函数中,所有不需要在参数中特别指定。
我们可以使用DetourFunction函数来创建一个动态的trampoline函数,它包括两个参数:一个指向目标函数的指针和一个截获函数的指针。DetourFunction分配一个新的trampoline函数并将适当的截获代码插入到目标函数中去。
当目标函数不是很容易使用的时候,DetourFindFunction函数可以找到那个函数,不管它是DLL中导出的函数,或者是可以通过二进制目标函数的调试符号找到。
DetourFindFunction接受两个参数:库的名字和函数的名字。如果DetourFindFunction函数找到了指定的函数,返回该函数 的指针,否则将返回一个NULL指针。DetourFindFunction会首先使用Win32函数LoadLibrary 和 GetProcAddress来定位函数,如果函数没有在DLL的导出表中找到,DetourFindFunction将使用ImageHlp库来搜索有 效的调试符号(译注:这里的调试符号是指Windows本身提供的调试符号,需要单独安装,具体信息请参考Windows的用户诊断支持信息)。 DetourFindFunction返回的函数指针可以用来传递给DetourFunction以生成一个动态的trampoline函数。
我们可以调用DetourRemoveTrampoline来去掉对一个目标函数的截获。
注意,因为Detours中的函数会修改应用程序的地址空间,请确保当加入截获函数或者去掉截获函数的时候没有其他线程在进程空间中执行,这是程序员的责任。一个简单的方法保证这个时候是单线程执行就是在加载Detours库的时候在DllMain中呼叫函数。
三、 使用Detours实现对API的截获的两种方法
建立一个MFC对话框工程,在对话框的OK按钮的单击事件中加入对MessageBoxA函数的调用,编译后的程序名称MessageBoxApp,效果如图。
(图4)
静态方法
建立一个Dll工程,名称为ApiHook,这里以Visual C++6.0开发环境,以截获ASCII版本的MessageBoxA函数来说明。在Dll的工程加入:
DETOUR_TRAMPOLINE(int WINAPI Real_Messagebox(HWND hWnd ,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType), ::MessageBoxA);
生成一个静态的MessageBoxA的Trampoline函数,在Dll工程中加入目标函数的Detour函数:
int WINAPI MessageBox_Mine( HWND hWnd ,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType)
{
CString tmp= lpText;
tmp+=” 被Detour截获”;
return Real_Messagebox(hWnd,tmp,lpCaption,uType);
// return ::MessageBoxA(hWnd,tmp,lpCaption,uType); //Error
}
在Dll入口函数中的加载Dll事件中加入:
DetourFunctionWithTrampoline((PBYTE)Real_Messagebox, (PBYTE)MessageBox_Mine);
在Dll入口函数中的卸载Dll事件中加入:
DetourRemove((PBYTE)Real_Messagebox, (PBYTE)MessageBox_Mine);
动态方法
建立一个Dll工程,名称为ApiHook,这里以Visual C++6.0开发环境,以截获ASCII版本的MessageBoxA函数来说明。在Dll的工程加入:
//声明MessageBoxA一样的函数原型
typedef int (WINAPI * MessageBoxSys)( HWND hWnd ,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType);
//目标函数指针
MessageBoxSys SystemMessageBox=NULL;
//Trampoline函数指针
MessageBoxSys Real_MessageBox=NULL;
在Dll工程中加入目标函数的Detour函数:
int WINAPI MessageBox_Mine( HWND hWnd ,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType)
{
CString tmp= lpText;
tmp+=” 被Detour截获”;
return Real_Messagebox(hWnd,tmp,lpCaption,uType);
// return ::MessageBoxA(hWnd,tmp,lpCaption,uType); //Error
}
在Dll入口函数中的加载Dll事件中加入:
SystemMessageBox=(MessageBoxSys)DetourFindFunction("user32.dll","MessageBoxA");
if(SystemMessageBox==NULL)
{
return FASLE;
}
Real_MessageBox=(MessageBoxSys)DetourFunction((PBYTE)SystemMessageBox, (PBYTE)MessageBox_Mine);
在Dll入口函数中的卸载Dll事件中加入:
DetourRemove((PBYTE)Real_Messagebox, (PBYTE)MessageBox_Mine);
重写二进制可执行文件
使用Detours自带的SetDll.exe重写二进制可执行文件,可以在需要截获的程序中加入一个新的Detours的PE节表。对于本文就是新建一个批处理文件调用SetDll.exe。
@echo off
if not exist MessageBoxApp.exe (
echo 请将文件解压到MessageBoxApp.exe的安装目录, 然后执行补丁程序
) else (
setdll /d:ApiHook.dll MessageBoxApp.exe
)
Pause
调用后使用depends.exe(微软VC6.0开发包的工具之一)观察MessageBoxApp.exe前后变化, 可以看到Setdll已经重写MessageBoxApp.exe
成功,加入了对ApiHook.dll的依赖关系。
(执行SetDll.exe前) (执行SetDll.exe后)
执行SetDll.exe重写后的MessageBoxApp.exe,点击确定后可以看到结果如下:
至此,MessageBoxApp.exe对MessageBoxA函数的调用已经被截获,弹出的对话框内容已经明显说明这一点。
-
2008-08-15
VS2005 解决"应用程序配置不正确,程序无法启动"问题 - [软件工程]
最近使用VS2005+codejock开发,需要做一个Release版本。当我把必要的mfc库,拷贝到exe目录下时。exe还是不能启动。
经过网上查找,看到一篇文章。“解决"应用程序配置不正确,程序无法启动"”
URL :http://www.cnblogs.com/wuhanhoutao/archive/2008/01/09/1031928.html
于是乎。我按照文章所讲的,将dl和mainfest文件。统统从VS2005的redis文件下,拷贝到exe目录下。
呵呵,居然exe可以运行了。
但是:1.肯定有些dll是当前exe不需要的。还需要将之删除。
2.manifest也许是必须的一个文件。
这篇文章是这样讲的。
在使用 VC++2005环境下生成的程序,放置到未安装VC环境的机器下后,有时候会出现程序无法执行的错误,其提示是:应用程序配置不正确,程序无法启动,重新安装应用程序可能解决问题。
实际上,重装是解决不了问题的,解决的一种方法是查看*exe.intermediate.manifest文件,比如文件的内容是:
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
<dependency>
<dependentAssembly>
<assemblyIdentity type='win32' name='Microsoft.VC80.CRT' version='8.0.50727.762' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly>
<assemblyIdentity type='win32' name='Microsoft.VC80.MFC' version='8.0.50727.762' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly>
<assemblyIdentity type='win32' name='Microsoft.VC80.DebugCRT' version='8.0.50727.762' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
</dependentAssembly>
</dependency>
</assembly>
需要注意这个文件中的3个关键词:Microsoft.VC80.CRT,Microsoft.VC80.MFC和Microsoft.VC80.DebugCRT。寻找到...."Program Files"Microsoft Visual Studio 8"VC"redist文件夹下面,找到这些名称的子文件夹,拷贝它们下面所有的文件到希望发布的EXE文件下面,一起打包。这些文件也就是mfc80.dll,msvcr80.dll,msvcp80.dll和Microsoft.VC80.CRT.manifest等。此错误发生的原因是在目标机器上需要这些文件的支持。
谢谢该文章的作者。







