VS 2010编译Gh0st 3.6

 

用Vs编译Gh0st修改的工作量还是挺大的,毕竟从VC6.0移植到VS2010平台,已经是一个很大的跨越了,VS2010相对于VC6.0也改进了不止一点了。Gh0st3.6使用了第三方界面库CJ60Lib,目前这个库只支持到VC6.0,而其后的版本已经商业化,所以使用VS2010编译Gh0st的时候,需要重新编译CJ60Lib。VS2010的自带安装的Windows SDK已经到了7.1版,也不需要像VC6.0那样需要下载Windows SDK,并配置环境了。VC6.0支持的最高版本的Windows SDK 是Windows 2003的,而VS2010自带的7.1版已经到了Windows Server 2008 了,其中发生的变化也是很大的。下面具体来操作一次。

        先列一下几个主要下文件路径。用的是Gh0s3.6原版,硬盘锁代码已经注释。

E:\Programming\VS2010\Gh0st3.6 
E:\Programming\VS2010\Gh0st3.6\gh0st.dsw 
E:\Programming\VS2010\Gh0st3.6\gh0st\CJ60Lib 
E:\Programming\VS2010\Gh0st3.6\gh0st\CJ60Lib\CJ60Lib\CJ60Lib.dsw 
E:\Programming\VS2010\Gh0st3.6\gh0st\CJ60Lib\Lib

一.编译CJ60Lib

        直接用VS2010打开CJ60Lib.dsw进行转换。一共有7个,有4个是已经不存在的项目了,直接删掉。

在灰色的项目上点右键–Remove,或直接按Del键删除。

1.1编译CJ60StaticLib

        直接在CJ60StaticLib项目上点右键— Project Only —- Build Only CJ60StaticLib或者是 Rebuild Only CJ60StaticLib。以后说编译某个项目也是这样,不再重复说明了。

1.1.1

首先修改程序配置,让默认的字符都为ANSI字符,VS2010默认为宽字符Unicode版。

项目—右键—属性—C/C++—Language—WChar_t—No,如图所示:

修改编译后,对照错误,再来一个一个的修改。

1.1.2

1> stdafx.cpp 
1> _WIN32_WINNT not defined. Defaulting to _WIN32_WINNT_MAXVER (see WinSDKVer.h)
1>e:\programming\vs2010\gh0st3.6\gh0st\cj60lib\cj60lib\stdafx.h(51): fatal error C1083: 无法打开包括文件:“..\src\afximpl.h”: No such file or directory

双击这个错误,定位到 stdafx.h 中的

#include <..\src\afximpl.h> 
把这句话改成 
#include <..\src\mfc\afximpl.h>

1.1.3

接着修改warning C4819警告

warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode格式以防止数据丢失

这个警告至需要双击打开该文件,然后保存就可以了。

1.1.4

gh0st3.6\gh0st\cj60lib\cj60lib\subclass.cpp(117): error C2065: “p”: 未声明的标识符

这是因为VS更符号C++标准,临时变量的作用域已经修正了,在Gh0st里,可以看到很多这样的代码。只要把在for或if里面定义的变量,放到for或if之前定义就好了。

这里的代码是:

for (CSubclassWnd* p = theHookMap.Lookup(m_hWnd); p; p=p->m_pNext)

修改为

CSubclassWnd* p = NULL; 
for (p = theHookMap.Lookup(m_hWnd); p; p=p->m_pNext)

后面的i也是一样修改。

gh0st3.6\gh0st\cj60lib\cj60lib\coolmenu.cpp(803): error C2065: “i”: 未声明的标识符

for (i=0; i < nFound; i++) {

这里的i,是在前面的 
for (UINT i=0; i< nItem; i++)

里面定义的,只要把for里面的i放到for之前定义就可以了,修改如下:

UINT i=0; 
for (i=0; i< nItem; i++)

这样的错误修改,以后不再写出,因为实在是太多了,修改方法也很简单。

1.1.5

gh0st3.6\gh0st\cj60lib\cj60lib\coolmenu.cpp(76): error C4430: 缺少类型说明符 –假定为 int。注意: C++ 不支持默认 int

在VC6.0里,用修饰符申明的变量可以不现式的写出变量类型,默认类型为int。如这里的const CXGAP = 1; 等于 const int CXGAP = 1; 但是VS2010必须现式的指出,不能省略。所以修改方法就是现式的写上定义类型。

// constants used for drawing

const CXGAP = 1; // num pixels between button and text

const CXTEXTMARGIN = 2; // num pixels after hilite to start text

const CXBUTTONMARGIN = 2; // num pixels wider button is than bitmap

const CYBUTTONMARGIN = 2; // ditto for height

修改如下:

// constants used for drawing

const int CXGAP = 1; // num pixels between button and text

const int CXTEXTMARGIN = 2; // num pixels after hilite to start text

const int CXBUTTONMARGIN = 2; // num pixels wider button is than bitmap

const int CYBUTTONMARGIN = 2; // ditto for height

这个在Gh0st里有,以后这个错误也不在指出。

1.1.6

接下来要解决的就是一大堆的重定义错误了

1>c:\program files\microsoft sdks\windows\v7.0a\include\shlwapi.h(126): error C2011: “tagSFBS_FLAGS”:“enum”类型重定义 
1>          c:\program files\microsoft sdks\windows\v7.0a\include\shlwapi.h(126) : 参见“tagSFBS_FLAGS”的声明 
1>c:\program files\microsoft sdks\windows\v7.0a\include\shlwapi.h(251): error C2084: 函数“HRESULT SHLocalStrDupW(LPCWSTR,LPWSTR *)”已有主体 
1>          c:\program files\microsoft sdks\windows\v7.0a\include\shlwapi.h(250) : 参见“SHLocalStrDupW”的前一个定义 
1>c:\program files\microsoft sdks\windows\v7.0a\include\shlwapi.h(256): error C2084: 函数“HRESULT SHLocalStrDupA(LPCSTR,LPSTR *)”已有主体 
1>          c:\program files\microsoft sdks\windows\v7.0a\include\shlwapi.h(255) : 参见“SHLocalStrDupA”的前一个定义 
1>c:\program files\microsoft sdks\windows\v7.0a\include\shlwapi.h(860): error C2365: “URL_SCHEME_INVALID”: 重定义;以前的定义是“枚举数” 
1>          c:\program files\microsoft sdks\windows\v7.0a\include\shlwapi.h(860) : 参见“URL_SCHEME_INVALID”的声明 
1>c:\program files\microsoft sdks\windows\v7.0a\include\shlwapi.h(861): error C2365: “URL_SCHEME_UNKNOWN”: 重定义;以前的定义是“枚举数” 
1>          c:\program files\microsoft sdks\windows\v7.0a\include\shlwapi.h(861) : 参见“URL_SCHEME_UNKNOWN”的声明 
1>c:\program files\microsoft sdks\windows\v7.0a\include\shlwapi.h(862): error C2365: “URL_SCHEME_FTP”: 重定义;以前的定义是“枚举数” 
1>          c:\program files\microsoft sdks\windows\v7.0a\include\shlwapi.h(862) : 参见“URL_SCHEME_FTP”的声明 
1>c:\program files\microsoft sdks\windows\v7.0a\include\shlwapi.h(863): error C2365: “URL_SCHEME_HTTP”: 重定义;以前的定义是“枚举数” 
1>          c:\program files\microsoft sdks\windows\v7.0a\include\shlwapi.h(863) : 参见“URL_SCHEME_HTTP”的声明 
1>c:\program files\microsoft sdks\windows\v7.0a\include\shlwapi.h(864): error C2365: “URL_SCHEME_GOPHER”: 重定义;以前的定义是“枚举数” 
1>          c:\program files\microsoft sdks\windows\v7.0a\include\shlwapi.h(864) : 参见“URL_SCHEME_GOPHER”的声明 
1>c:\program files\microsoft sdks\windows\v7.0a\include\shlwapi.h(865): error C2365: “URL_SCHEME_MAILTO”: 重定义;以前的定义是“枚举数” 
1>          c:\program files\microsoft sdks\windows\v7.0a\include\shlwapi.h(865) : 参见“URL_SCHEME_MAILTO”的声明 
1>c:\program files\microsoft sdks\windows\v7.0a\include\shlwapi.h(866): error C2365: “URL_SCHEME_NEWS”: 重定义;以前的定义是“枚举数” 
1>          c:\program files\microsoft sdks\windows\v7.0a\include\shlwapi.h(866) : 参见“URL_SCHEME_NEWS”的声明

造成这个原因是ATL和CJLIB库的兼容性问题上,从错误上看是shlwapi.h里的代码被重定义了,ATL在定义前都会判断一下是否已经定义,而CJLIB则没有判断。解决方法是把CJLIB中的shlwapi.h包含给注释掉。可以在当前项目搜索shlwapi.h,一共有两处。

 E:\Programming\VS2010\Gh0st3.6\gh0st\CJ60Lib\Include\ModulVer.h 
E:\Programming\VS2010\Gh0st3.6\gh0st\CJ60Lib\Include\ShellTree.h

 把其中的 #include  改成 //#include  
重新编译后,错误一下少了很多,看起来也清爽了许多。

 1.1.7

 gh0st3.6\gh0st\cj60lib\cj60lib\cjsizedockbar.cpp(89): error C2440:“static_cast”: 无法从“UINT (__thiscall CCJSizeDockBar::* )(CPoint)”转换为“LRESULT (__thiscall CWnd::* )(CPoint)” 
1>          从基类型到派生类型的强制转换需要 dynamic_cast 或 static_cast

这句话定位到的是ON_WM_NCHITTEST(),其实就是消息响应函数的返回值类型不匹配,这里也可以看出VS2010和VC6.0的不同。ON_WM_NCHITTEST对应的消息函数是UINTCCJSizeDockBar::OnNcHitTest(CPoint point) ,把返回值类型改下就好了。有两处:

E:\Programming\VS2010\Gh0st3.6\gh0st\CJ60Lib\CJ60Lib\CJSizeDockBar.cpp 
UINT CCJSizeDockBar::OnNcHitTest(CPoint point)

修改为:

LRESULT CCJSizeDockBar::OnNcHitTest(CPoint point)

E:\Programming\VS2010\Gh0st3.6\gh0st\CJ60Lib\Include\CJSizeDockBar.h 
afx_msg UINT OnNcHitTest(CPoint point);

修改为:

afx_msg LRESULT OnNcHitTest(CPoint point);

后面还有一个一样的错误,只是所在类不一样,修改方法还是一样的

gh0st3.6\gh0st\cj60lib\cj60lib\cjcontrolbar.cpp(155): error C2440:“static_cast”: 无法从“UINT (__thiscall CCJControlBar::* )(CPoint)”转换为“LRESULT (__thiscall CWnd::* )(CPoint)” 
1>          从基类型到派生类型的强制转换需要 dynamic_cast 或 static_cast

这里就不再说了,请参考上面的修改。

1.1.8

gh0st3.6\gh0st\cj60lib\cj60lib\cjpagerctrl.cpp(75): error C2440: “static_cast”:无法从“BOOL (__thiscall CCJPagerCtrl::* )(NMPGSCROLL *,LRESULT *)”转换为“BOOL (__thiscall CCmdTarget::* )(NMHDR *,LRESULT *)” 
1>          在匹配目标类型的范围内没有具有该名称的函数 
gh0st3.6\gh0st\cj60lib\cj60lib\cjpagerctrl.cpp(76): error C2440: “static_cast”:无法从“BOOL (__thiscall CCJPagerCtrl::* )(NMPGCALCSIZE *,LRESULT *)”转换为“BOOL (__thiscall CCmdTarget::* )(NMHDR *,LRESULT *)” 
1>          在匹配目标类型的范围内没有具有该名称的函数

这两处的错误都是一样的,都是同一种参数类型不匹配。定位信息:

ON_NOTIFY_REFLECT_EX(PGN_SCROLL, OnPagerScroll)

ON_NOTIFY_REFLECT_EX(PGN_CALCSIZE, OnPagerCalcSize)

可以看出他们所对应的函数分别是OnPagerScroll和OnPagerCalcSize。直接在上面按F12(右键–跳转到定义处)就跳转到函数定义出了。

E:\Programming\VS2010\Gh0st3.6\gh0st\CJ60Lib\CJ60Lib\CJPagerCtrl.cpp 
BOOL CCJPagerCtrl::OnPagerScroll(NMPGSCROLL* pNMPGScroll, LRESULT* pResult)

{

    *pResult = 0;

return FALSE; // Let parent handle message

}

修改如下:

BOOL CCJPagerCtrl::OnPagerScroll(NMHDR* pNMPGScroll, LRESULT* pResult)

{

    *pResult = 0;

return FALSE; // Let parent handle message

}

===================================================

BOOL CCJPagerCtrl::OnPagerCalcSize(NMPGCALCSIZE* pNMPGCalcSize, LRESULT*pResult)

{

switch(pNMPGCalcSize->dwFlag)

修改如下:

BOOL CCJPagerCtrl::OnPagerCalcSize(NMHDR* pNMHDRPGCalcSize, LRESULT* pResult)

{

NMPGCALCSIZE *pNMPGCalcSize = (NMPGCALCSIZE *)pNMHDRPGCalcSize;

switch(pNMPGCalcSize->dwFlag)

===================================================

接着修改头文件中申明的参数类型

E:\Programming\VS2010\Gh0st3.6\gh0st\CJ60Lib\Include\CJPagerCtrl.h 
virtual BOOL OnPagerScroll(NMPGSCROLL* pNMPGScroll, LRESULT * pResult);

virtual BOOL OnPagerCalcSize(NMPGCALCSIZE * pNMPGCalcSize, LRESULT* pResult);

修改如下:

virtual BOOL OnPagerScroll(NMHDR* pNMPGScroll, LRESULT * pResult);

virtual BOOL OnPagerCalcSize(NMHDR* pNMHDRPGCalcSize, LRESULT* pResult);

1.2 编译CJ60Lib

首先还是修改字符集为ANSI,不然默认为WChar_t。这步是编译Gh0st每一个项目都需要做的,以后的操作中不再提起,请注意。如果提示A函数和W函数重定义,参数冲突等,都是这个问题,改下项目属性就能解决了。

wchar_t *类型与USHORT *的转换错误

    VC6的编译器不支持wchar_t数据类型,wchar_t实际上被定义成unsigned short,VC9的编译器已经支持wchar_t为内置数据类型,但是由一个编译选项控制,这个选项默认是打开的,也就是将wchar_t作为编译器的内置数据类型。但是OLECHAR和WCHAR的定义仍然是unsigned short,在VC6的编译环境中,两者的指针都是USHORT *,相互赋值和做为函数参数传递没有问题,但是如果wchar_t作为编译器的内置数据类型,那就意味着wchar_t *与OLECHAR *或WCHAR *是两种不同类型的指针,相互赋值就会报编译错误,下面的信息就是一个典型的错误输出:

f:\project\.....\shellpidl.cpp(290) : error C2664: 'MultiByteToWideChar' : cannot convert parameter 5 from 'USHORT *' to 'LPWSTR'
        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

解决的方法就是使用C++的reinterpret_cast操作符或使用C-style强制转换,当然也可以在项目属性设置中关闭前面提到的那个选项。

这个直接编译就能过了。用VS2010编译函数很多安全函数的警告,这个不用管他,想修改也是可以的。还有一个_WIN32_WINNT宏未定义的警告,如非必要,我就不加上去了,尽量的保持和原版的相同。要加的话,直接加在每个项目的StdAfx.h里面。

格式:#define _WIN32_WINNT 0x0500

这里的参数含义可以参看MSDN,后面有一处修改必须加,也会再次提到。

 

二.编译Gh0st

成功编译CJ60Lib界面库之后,就可以开始编译Gh0st了。

2.1 转换Gh0st3.6项目

直接用VS2010打开Gh0st3.6\gh0st.dsw 提示转换项目,确定转换就行了。这里一共三个项目:gh0st,install,svchost。编译的时候需要先编译svchost再编译install,最后才编译gh0st。

2.2 编译svchost

相同的错误修改就不再说了,参看前面的修改方法。
修改已说过的错误,再继续下面的错误修改。

2.2.1

1>common\FileManager.cpp(202): error C2440:“初始化”: 无法从“const char *”转换为“char *”
1>          转换丢失限定符

char *lpExt = strrchr(lpFile, ‘.’); 
修改为:
const char *lpExt = strrchr(lpFile, ‘.’); 

1>e:\programming\vs2010\gh0st3.6\server\svchost\common\loop.h(160): error C2440:“=”: 无法从“const char *”转换为“char *”
1>          转换丢失限定符

char *lpFileName = NULL; 

lpFileName = strrchr(lpURL, ‘/’) + 1; 

修改为:

Const char *lpFileName = NULL; 

lpFileName = strrchr(lpURL, ‘/’) + 1; 

2.2.2

1>common\ScreenSpy.cpp(355): error C2062: 意外的类型“int”

for (inti = 0, intnToJump = 0; i < nHeight; i += nToJump) 
修改为:
int i=0;

for (i = 0, nToJump = 0; i < nHeight; i += nToJump) 

2.2.3

1>common\VideoManager.cpp(123): error C4430: 缺少类型说明符 – 假定为 int。注意: C++ 不支持默认 int

定位在:
static dwLastScreen = GetTickCount(); 
这个错误前面已经提到过,是添加现式定义类型int。这里添加现式类型为 DWORD 比较好,因为后面的函数GetTickCount返回值是DWORD类型。在这里修改如下:
static DWORD dwLastScreen = GetTickCount(); 

2.2.4

1>common\ScreenManager.cpp(7): fatal error C1083: 无法打开包括文件:“winable.h”: No such file or directory

Winable头文件从VS2008里面就已经不存在了,MSDN里描述如下:

从 Visual Studio 早期版本升级项目时,您可能必须修改 WINVER 和 _WIN32_WINNT 宏,以便它们大于或等于 0×0500。
已移除 Windows API 头文件 Winable.h。而改为包括 Winuser.h。

因为Winuser默认已经包含进来了,所以直接注释这句话就行了。但是如果直接这样,引用Winable中的函数就会出现未定义错误。所以这里除了需要注释这个头文件包含,还需要注释这个文件中的_WIN32_WINNT宏定义,或者修改宏定义大于等于500。我这里直接注释掉了。

#define_WIN32_WINNT 0×0400 
#include"ScreenManager.h"
#include"until.h"
#include// BlockInput 

修改为: 

//#define _WIN32_WINNT 0×0400
#include"ScreenManager.h"
#include"until.h"
//#include  // BlockInput 

2.3 编译install

这个能直接编译通过,就算不修改默认字符集,但还是建议和前面一样,修改下默然字符。

2.4 编译gh0st

一开始编译就会有个错误提示而终止,如果不修改没法正常编译。

1>C:\Program Files\Microsoft Visual Studio 10.0\VC\atlmfc\include\afx.h(24): fatal error C1189: #error : Building MFC application with /MD[d] (CRT dll version) requires MFC shared dll version. Please #define _AFXDLL or do not use /MD[d]

 这个还是需要修改属性页。需要把代码生成里的运行时库改成/MT。如图:

修改之后重新编译就能看到很多错误了。在继续下面的错误修改之前,先把前面讲到的错误类型给修改好。

2.4.1

1>control\BtnST.cpp(4): fatal error C1083: 无法打开包括文件:“stdafx.h”: No such file or directory

提示找不到stdafx.h,其实这个文件是存在的。在属性里添加“./”的包含目录就能解决了。
在属性页的C/C++—General—Additional Include Directories 里添加。

原来的是:
CJ60lib/Include;../common;%(AdditionalIncludeDirectories)

修改后为:
./;CJ60lib/Include;../common;%(AdditionalIncludeDirectories)

如图:

2.4.2

1>e:\programming\vs2010\gh0st3.6\gh0st\TmSchema.h(27): error C2011:“BGTYPE”:“enum”类型重定义
1>          C:\Program Files\Microsoft SDKs\Windows\v7.0A\include\vssym32.h(14) : 参见“BGTYPE”的声明
1>e:\programming\vs2010\gh0st3.6\gh0st\TmSchema.h(33): error C2011: “IMAGELAYOUT”:“enum”类型重定义
1>          C:\Program Files\Microsoft SDKs\Windows\v7.0A\include\vssym32.h(25) : 参见“IMAGELAYOUT”的声明
1>e:\programming\vs2010\gh0st3.6\gh0st\TmSchema.h(38): error C2011: “BORDERTYPE”:“enum”类型重定义
1>          C:\Program Files\Microsoft SDKs\Windows\v7.0A\include\vssym32.h(35) : 参见“BORDERTYPE”的声明
1>e:\programming\vs2010\gh0st3.6\gh0st\TmSchema.h(44): error C2011: “FILLTYPE”:“enum”类型重定义
1>          C:\Program Files\Microsoft SDKs\Windows\v7.0A\include\vssym32.h(46) : 参见“FILLTYPE”的声明
1>e:\programming\vs2010\gh0st3.6\gh0st\TmSchema.h(52): error C2011: “SIZINGTYPE”:“enum”类型重定义
1>          C:\Program Files\Microsoft SDKs\Windows\v7.0A\include\vssym32.h(59) : 参见“SIZINGTYPE”的声明
1>e:\programming\vs2010\gh0st3.6\gh0st\TmSchema.h(58): error C2011: “HALIGN”:“enum”类型重定义
1>          C:\Program Files\Microsoft SDKs\Windows\v7.0A\include\vssym32.h(70) : 参见“HALIGN”的声明
1>e:\programming\vs2010\gh0st3.6\gh0st\TmSchema.h(64): error C2011: “CONTENTALIGNMENT”:“enum”类型重定义
1>          C:\Program Files\Microsoft SDKs\Windows\v7.0A\include\vssym32.h(81) : 参见“CONTENTALIGNMENT”的声明
1>e:\programming\vs2010\gh0st3.6\gh0st\TmSchema.h(70): error C2011: “VALIGN”:“enum”类型重定义

又是一堆的类型重定义错误,这次需要现式的指出Windows版本才能解决这个问题。打开stdafx.h,在其中添加 #define _WIN32_WINNT 0×0500 。下面是我的操作,实际放置的位置可以自己调整。

E:\Programming\VS2010\Gh0st3.6\gh0st\StdAfx.h

#define VC_EXTRALEAN// Exclude rarely-used stuff from Windows headers
#include         // MFC core and standard components
#include         // MFC extensions
#include 

修改如下: 

#define VC_EXTRALEAN// Exclude rarely-used stuff from Windows headers
#define _WIN32_WINNT 0×0500 
#include         // MFC core and standard components
#include         // MFC extensions
#include 

这里就说下参数的含义,0×0500是指Windows 2000,这个宏定义说明这个程序只是要在Windows 2000 及以上的操作系统上才能正常运行。0×0501 Windows XP、0×0502 Windows Server 2003、 0×0600 Windows Vista、0×0601 Windows 7。

2.4.3

1>TrueColorToolBar.cpp(42): error C2440:“static_cast”: 无法从“void (__thiscall CTrueColorToolBar::* )(NMTOOLBARA *,LRESULT *)”转换为“void (__thiscall CCmdTarget::* )(NMHDR *,LRESULT *)”
1>          在匹配目标类型的范围内没有具有该名称的函数

这个和1.1.8是一样的。这里再说下。

定位到:

ON_NOTIFY_REFLECT(TBN_DROPDOWN, OnToolbarDropDown)

可以在OnToolbarDropDown上点右键跳转到定义(F12),跳转到申明(Ctrl+Alt+F12)

E:\Programming\VS2010\Gh0st3.6\gh0st\TrueColorToolBar.cpp

Void CTrueColorToolBar::OnToolbarDropDown(NMTOOLBAR* pnmtb, LRESULT *plr) 

for (inti = 0; i < m_lstDropDownButton.GetSize(); i++) { 

修改如下:

Void CTrueColorToolBar::OnToolbarDropDown(NMHDR* NMHDRpnmtb, LRESULT *plr) 

NMTOOLBARA *pnmtb = (NMTOOLBARA *)NMHDRpnmtb; 
int i=0;

for (i = 0; i < m_lstDropDownButton.GetSize(); i++) { 

E:\Programming\VS2010\Gh0st3.6\gh0st\TrueColorToolBar.h

afx_msg void OnToolbarDropDown(NMTOOLBAR* pnmh, LRESULT* plRes);

修改如下:

afx_msg void OnToolbarDropDown(NMHDR* NMHDRpnmtb, LRESULT* plRes); 

2.5

      Gh0st就只有这些错误了。下一节将讲解连接错误。

三.解决连接错误

     到现在为止,所以代码已经没有任何错误了,但在Gh0st还是编译不成功,而错误全部是在连接错误上。下面来解决掉这些链接错误。

3.1 CJ60StaticLib链接库错误

首先我们看到的是CJ60StaticLib的链接错误

1>CJ60StaticLib.lib(CJListView.obj) : error LNK2001: 无法解析的外部符号 "protected: static struct AFX_MSGMAP const CListView::messageMap" (?messageMap@CListView@@1UAFX_MSGMAP@@B) 
1>CJ60StaticLib.lib(CJListView.obj) : error LNK2001: 无法解析的外部符号 "public: __thiscall CString::~CString(void)" (??1CString@@QAE@XZ) 
1>CJ60StaticLib.lib(CJListCtrl.obj) : error LNK2001: 无法解析的外部符号 "public: __thiscall CString::~CString(void)" (??1CString@@QAE@XZ) 
1>CJ60StaticLib.lib(CJListView.obj) : error LNK2019: 无法解析的外部符号 "public: void __thiscall CString::Empty(void)" (?Empty@CString@@QAEXXZ),该符号在函数 "public: __thiscall CCJListView::CCJListView(void)" (??0CCJListView@@QAE@XZ) 中被引用
1>CJ60StaticLib.lib(CJListCtrl.obj) : error LNK2001: 无法解析的外部符号 "public: void __thiscall CString::Empty(void)" (?Empty@CString@@QAEXXZ)

从错误上看,gh0st链接的是CJ60StaticLib.lib库,但是前面我们编译的CJ60StaticLib产生的库却是CJ60StaticLibd.lib,是CJ60StaticLib的Debug版本的库,这里链接的却是Release版的库。不信可以看下CJ60StaticLib的生成目录:

E:\Programming\VS2010\Gh0st3.6\gh0st\CJ60Lib\Lib

看些日期也就知道,我们前面编译的文件名后面都多了d。从新打开CJ60StaticLib项目。

E:\Programming\VS2010\Gh0st3.6\gh0st\CJ60Lib\CJ60Lib\CJ60Lib.sln

可以直接在界面上的修改成Release,或在项目属性里点配置成Release。如下图:

或者:

修改后如果直接这样编译,会出现类似下面的错误:

1>ShellPidl.cpp(220): error C2664: “MultiByteToWideChar”: 不能将参数 5 从“USHORT *”转换为“LPWSTR”
1>          与指向的类型无关;转换要求 reinterpret_cast、C 样式转换或函数样式转换

一看就知道是默认字符集问题,前面只在Debug模式下修改了默认不是WChar_t类型,而切换到Release模式也要记得修改。重新修改,编译CJ60StaticLib和CJ60Lib。再来看下生成目录。

E:\Programming\VS2010\Gh0st3.6\gh0st\CJ60Lib\Lib

3.2 gh0st链接错误

 

现在再来编译一次gh0st,链接错误是不是没有出现在CJ60StaticLib上了

1>C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppBuild.targets(990,5): warning MSB8012: TargetPath(E:\Programming\VS2010\Gh0st3.6\gh0st\.\Release\gh0st.exe) does not match the Linker’s OutputFile property value (E:\Programming\VS2010\Gh0st3.6\Bin\gh0st.exe). This may cause your project to build incorrectly. To correct this, please make sure that $(OutDir), $(TargetName) and $(TargetExt) property values match the value specified in %(Link.OutputFile). 
1>nafxcw.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)" (??2@YAPAXI@Z) 已经在 LIBCMT.lib(new.obj) 中定义
1>nafxcw.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete(void *)" (??3@YAXPAX@Z) 已经在LIBCMT.lib(delete.obj) 中定义
1>nafxcw.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new[](unsigned int)" (??_U@YAPAXI@Z)已经在 LIBCMT.lib(new2.obj) 中定义
1>nafxcw.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete[](void *)" (??_V@YAXPAX@Z) 已经在 LIBCMT.lib(delete2.obj) 中定义
1>../Bin/gh0st.exe : fatal error LNK1169: 找到一个或多个多重定义的符号

看错误提示,都是nafxcw.lib已经在LIBCMT.lib里定义,其实这就是VS链接库顺序的问题了,需要修正这些链接库的顺序。

打开gh0st项目的属性页面,在连接选项卡里选择Input。在忽略默认链接库(Ignore Specific Default Libraries)里可以看到原来的gh0st已经忽略了msvcrt.lib,这个对我们没有任何影响,去掉这个忽略。直接修改为:nafxcw.lib;LIBCMT.lib。然后在依赖关系(Additional Dependencies)里指定这两个库的链接顺序,在最前面添加:nafxcw.lib;LIBCMT.lib。这两个一定要在最前面。并且顺便不能乱。至于怎么看顺序,其实很简单,他不是说nafxcw.lib已经在LIBCMT.lib里定义了吗,那就是说在连接nafxcw.lib之前已经连接了LIBCMT.lib。修改如图:

四.结束

最后的运行效果如下:

如果编译之后生成的服务端,直接放到没有装VS2010的扩展库的系统下是不能运行的,只需要把提示缺少的文件从VS2010的安装目录拷贝到系统的system32下就能运行并上线了。

也可以把gh0st里的三个项目都改成Release版,这样就可以直接在其他系统中运行了。这里我就不讲解了,后续如需修改就看各自的了。

4.1 补充

在VM中的Server2003上测试时,发现这次的修改已经是Release版了,可以直接运行,不需要VS2010的扩展库支持了。以前编译的时候改动了很多地方,编译的是Debug版的,而且有警告弹窗。这次为了写本文档,尽量的保持了和原版本的一致。竟然没有以前的错误,也算是比以前的完美点了吧。

 

你可能感兴趣的:(VS 2010编译Gh0st 3.6)