1 安装与配置
1.1 编译gtest:
下载gtest1.7.0版本,(本人通过下载),解压后,文件目录下图所示:
打开msvc文件夹,打开gtest或gtest_md工程文件。进行编译。
编译方法:
如果需要生成动态库(DLL),则需要3步:1.将“配置类型”改为“动态库”。2.修改编译宏定义:
gtest->属性->配置属性->C/C++->预处理器->预处理器定义,将_LIB改为_USRDLL,并添加宏GTEST_CREATE_SHARED_LIBRARY=1。3.修改运行时库,将 gtest->属性->配置属性->C/C++->代码生成->运行库,改为MDd。
编译完毕后,会在$GTEST_ROOT\gtest\debug目录下生成gtestd.lib静态库文件.为了方便编写单元测试代码,在$GTEST_ROOT目录下新建lib目录,将我们刚才生成的gtestd.lib拷贝到$GTEST_ROOT\lib目录下。
编译之后,在msvc里面的Debug或是Release目录里看到编译出来的gtestd.lib或是gtest.lib文件。
在根目录下,新建lib文件夹,将lib文件放入。
1.2 配置gtest:
建立工程后,分别配置gtest的include路径、lib路径和Runtime Library。
第一:在Release和Debug模式下编译GTest,分别生成gtest.lib和gtestd.lib
在我们新建的使用GTest测试的工程中,Release和Debug模式要分别使用上面两个对应的lib文件。
第二:设置好我们的工程的代码生成(属性Properties-->C++-->代码生成Code Generation)中的运行时库(Runtime Library)。
Release模式为:Multi-threaded( /MT)
Debug模式为:Muti-threadedDebug(/MTd)
在本次使用中,选用的时MDd模式,即多线程调试DLL。
2 使用方法
测试Demo:
#include <gtest/gtest.h>
int Foo(int a,int b)
{
if(0 == a||0 == b)
throw "don't do that";
int c = a%b;
if (0 == c)
{
return b;
}
return Foo(b,c);
}
TEST(FooTest,HandleNoneZeroInput)
{
EXPECT_EQ(2,Foo(4,10));
EXPECT_EQ(6,Foo(30,18));
}
int main(int argc, _TCHAR* argv[])
{
testing::InitGoogleTest(&argc,argv);
return RUN_ALL_TESTS();
}
2.1 断言
断言主要分为ASSERT和EXPECT两个系列。
1. ASSERT_* 系列的断言,当检查点失败时,退出当前函数(注意:并非退出当前案例)。
2. EXPECT_* 系列的断言,当检查点失败时,继续往下执行。
例:
// int型比较,预期值:3,实际值:Add(1, 2)
EXPECT_EQ(3, Add(1, 2));
//
当实际值与预期值不相等时会输出error。
为了能更好的识别,可以使用<<操作符自定义输出:
如:EXPECT_EQ(x[i], y[i]) << "Vectorsx and y differ at index " << i;//在输出时将会输出这句话。
布尔值检查
Fatal assertion
Nonfatal assertion
Verifies
ASSERT_TRUE(condition);
EXPECT_TRUE(condition);
condition is true
ASSERT_FALSE(condition);
EXPECT_FALSE(condition);
condition is false
数值型数据检查
Fatal assertion
Nonfatal assertion
Verifies
ASSERT_EQ(expected, actual);
EXPECT_EQ(expected, actual);
expected == actual
ASSERT_NE(val1, val2);
EXPECT_NE(val1, val2);
val1 != val2
ASSERT_LT(val1, val2);
EXPECT_LT(val1, val2);
val1 < val2
ASSERT_LE(val1, val2);
EXPECT_LE(val1, val2);
val1 <= val2
ASSERT_GT(val1, val2);
EXPECT_GT(val1, val2);
val1 > val2
ASSERT_GE(val1, val2);
EXPECT_GE(val1, val2);
val1 >= val2
字符串检查
Fatal assertion
Nonfatal assertion
Verifies
ASSERT_STREQ(expected_str, actual_str);
EXPECT_STREQ(expected_str, actual_str);
the two C strings have the same content
ASSERT_STRNE(str1, str2);
EXPECT_STRNE(str1, str2);
the two C strings have different content
ASSERT_STRCASEEQ(expected_str, actual_str);
EXPECT_STRCASEEQ(expected_str, actual_str);
the two C strings have the same content, ignoring case
ASSERT_STRCASENE(str1, str2);
EXPECT_STRCASENE(str1, str2);
the two C strings have different content, ignoring case
其中:
*STREQ*和*STRNE*同时支持char*和wchar_t*类型的,*STRCASEEQ*和*STRCASENE*只接收char*。
显示返回成功或失败
直接返回成功:
SUCCEED();
返回失败:
Fatal assertion
Nonfatal assertion
FAIL();
ADD_FAILURE();
异常检查
Fatal assertion
Nonfatal assertion
Verifies
ASSERT_THROW(statement, exception_type);
EXPECT_THROW(statement, exception_type);
statement throws an exception of the given type
ASSERT_ANY_THROW(statement);
EXPECT_ANY_THROW(statement);
statement throws an exception of any type
ASSERT_NO_THROW(statement);
EXPECT_NO_THROW(statement);
statement doesn't throw any exception
谓词断言
在使用EXPECT_TRUE或ASSERT_TRUE时,有时希望能够输出更加详细的信息,比如检查一个函数的返回值TRUE还是FALSE时,希望能够输出传入的参数是什么,以便失败后好跟踪。因此提供了如下的断言:
Fatal assertion
Nonfatal assertion
Verifies
ASSERT_PRED1(pred1, val1);
EXPECT_PRED1(pred1, val1);
pred1(val1) returns true
ASSERT_PRED2(pred2, val1, val2);
EXPECT_PRED2(pred2, val1, val2);
pred2(val1, val2) returns true
...
...
...
还可以自定义输出格式,通过如下:
Fatal assertion
Nonfatal assertion
Verifies
ASSERT_PRED_FORMAT1(pred_format1, val1);`
EXPECT_PRED_FORMAT1(pred_format1, val1);
pred_format1(val1) is successful
ASSERT_PRED_FORMAT2(pred_format2, val1, val2);
EXPECT_PRED_FORMAT2(pred_format2, val1, val2);
pred_format2(val1, val2) is successful
...
...
...
注意:pred_format的返回值必须testing::AssertionResult(),这个返回值相当于bool类型,当成功是,返回testing::AssertionSuccess(),testing::AssertionFailure();
浮点型检查
Fatal assertion
Nonfatal assertion
Verifies
ASSERT_FLOAT_EQ(expected, actual);
EXPECT_FLOAT_EQ(expected, actual);
the two float values are almost equal
ASSERT_DOUBLE_EQ(expected, actual);
EXPECT_DOUBLE_EQ(expected, actual);
the two double values are almost equal
对相近的两个数比较:
Fatal assertion
Nonfatal assertion
Verifies
ASSERT_NEAR(val1, val2, abs_error);
EXPECT_NEAR(val1, val2, abs_error);
the difference between val1 and val2 doesn't exceed the given absolute error
2.2 事件机制
gtest的事件一共有3种:
1. 全局的,所有案例执行前后。
2. TestSuite级别的,在某一批案例中第一个案例前,最后一个案例执行后。
3. TestCase级别的,每个TestCase前后。
全局事件
必须写一个类,继承testing::Environment类,实现里面的SetUp和TearDown方法。
1. SetUp()方法在所有案例执行前执行
2. TearDown()方法在所有案例执行后执行
TestSuite事件
需要写一个类,继承testing::Test,然后实现两个静态方法
1. SetUpTestCase() 方法在第一个TestCase之前执行
2. TearDownTestCase() 方法在最后一个TestCase之后执行
TestCase事件
TestCase事件是挂在每个案例执行前后的,实现方式和上面的几乎一样,不过需要实现的是SetUp方法和TearDown方法:
1. SetUp()方法在每个TestCase之前执行
2. TearDown()方法在每个TestCase之后执行
2.3 参数化测试
参数化测试提供了简化的参数测试方法,可以一次性的测试多组参数,而不用编写重复性的代码。
首先,必须添加一个类,继承testing::TestWithParam<T>,其中T就是你需要参数化的参数类型,比如上面的例子,我需要参数化一个int型的参数
class IsPrimeParamTest :public::testing::TestWithParam<int>
{
};
其次,告诉gtest你拿到参数的值后,具体做些什么样的测试。这里,要使用一个新的宏TEST_P,在TEST_P宏里,使用GetParam()获取当前的参数的具体值。
TEST_P(IsPrimeParamTest,HandleTrueReturn)
{
int n = GetParam();
EXPECT_TRUE(IsPrime(n));
}
最后,使用INSTANTIATE_TEST_CASE_P这宏来告诉gtest你要测试的参数范围:
INSTANTIATE_TEST_CASE_P(TrueReturn,IsPrimeParamTest, testing::Values(3, 5, 11, 23, 17));
第一个参数是测试案例的前缀,可以任意取。
第二个参数是测试案例的名称,需要和之前定义的参数化的类的名称相同,如:IsPrimeParamTest
第三个参数是可以理解为参数生成器,上面的例子使用test::Values表示使用括号内的参数。Google提供了一系列的参数生成的函数:
Range(begin, end[, step])
范围在begin~end之间,步长为step,不包括end
Values(v1, v2, ..., vN)
v1,v2到vN的值
ValuesIn(container) and ValuesIn(begin, end)
从一个C类型的数组或是STL容器,或是迭代器中取值
Bool()
取false 和 true 两个值
Combine(g1, g2, ..., gN)
它将g1,g2,...gN进行排列组合,g1,g2,...gN本身是一个参数生成器,每次分别从g1,g2,..gN中各取出一个值,组合成一个元组(Tuple)作为一个参数。
说明:这个功能只在提供了<tr1/tuple>头的系统中有效。gtest会自动去判断是否支持tr/tuple,如果你的系统确实支持,而gtest判断错误的话,你可以重新定义宏GTEST_HAS_TR1_TUPLE=1。
2.4 死亡测试
死亡测试即对程序的崩溃进行检测。
死亡测试的测试用例名称(test_case_name)规定要以DeathTest结尾,因为gtest优先运行死亡测试。
需要注意的是,DeathTest在*NIX环境下才会自动产生内存转储文件(core文件),windows下需要进行设置。
致命断言
非致命断言
说明
ASSERT_DEATH(statement, regex`);
EXPECT_DEATH(statement, regex`);
statement是引起程序崩溃的代码语句。
regex是一个正则表达式,用来匹配异常时在stderr中输出的内容,当不指定regex的时候,传入空字符串””。
ASSERT_DEATH_IF_SUPPORTED(statement, regex`);
EXPECT_DEATH_IF_SUPPORTED(statement, regex`);
如果当前系统支持死亡测试,则按照*_DEATH的方式运行死亡测试,否则不做检查
ASSERT_EXIT(statement, predicate, regex`);
EXPECT_EXIT(statement, predicate, regex`);
……
*_EXIT(statement, predicate, regex`)
1. statement是被测试的代码语句
2. predicate 在这里必须是一个委托,接收int型参数,并返回bool。只有当返回值为true时,死亡测试案例才算通过。gtest提供了一些常用的predicate:
testing::ExitedWithCode(exit_code)
如果程序正常退出并且退出码与exit_code相同则返回true
testing::KilledBySignal(signal_number) // Windows下不支持
如果程序被signal_number信号kill的话就返回true
3. regex是一个正则表达式,用来匹配异常时在stderr中输出的内容
注意:*_DEATH其实是对*_EXIT进行的一次包装,*_DEATH的predicate判断进程是否以非0退出码退出或被一个信号杀死。
例子:
TEST(ExitDeathTest, Demo)
{
EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), "");
}
注意:ASSERT_EXIT(EXPECT_EXIT)断言要求程序的退出码与pred中的exitcode一致,否则断言失败,修改一下上面的例子:
死亡测试运行方式
1. fast方式(默认的方式)
testing::FLAGS_gtest_death_test_style= "fast";
2. threadsafe方式
testing::FLAGS_gtest_death_test_style= "threadsafe";
Trace跟踪:
SCOPE_TRACE(message)
SCOPE_TRACE需要与{ }作用域符号一起使用,在作用域内失败的断言,都会打上SCOPE_TRACE中定义的跟踪信息。还是举例说明。
TEST(SubRoutingTest,HaveScopeAssert)
{
{
SCOPED_TRACE("errorhere");
SubTest(9);
}
SubTest(2);
}
在测试循环体时,可加入标志,表示在那一次循环时出现的问题。
测试demo:
#include <gtest/gtest.h>
#include<gtest/gtest-death-test.h>
void demo()
{
int*p = NULL;
*p= 30;
SCOPED_TRACE("errorhere");//定义trace跟踪
}
TEST(demoDeathTest,hahaha)
{
EXPECT_DEATH(demo(),"");//测试demo是否会引起崩溃
}
TEST(exitDeathTest,yes)
{
testing::FLAGS_gtest_death_test_style= "threadsafe";//设置死亡测试的运行方式是threadsafe
EXPECT_EXIT(_exit(1),testing::ExitedWithCode(1),"");//测试退出值是否一致
}
int main(int argc, char* argv[])
{
testing::InitGoogleTest(&argc,argv);
returnRUN_ALL_TESTS();
}
运行结果:
疑问:当使用预编译模式下的int _tmain(int argc,_TCHAR* argv[])时,使用gtest测试会出现死循环。(typedef wchar_t _TCHAR)
测试:当注释掉所有TEST后,执行正常,当存在TEST时,即出现死循环。
2.5 运行参数
对于运行参数,gtest提供了三种设置的途径:
1. 系统环境变量
2. 命令行参数
3. 代码中指定FLAG
因为提供了三种途径,就会有优先级的问题, 有一个原则是,最后设置的那个会生效。不过总结一下,通常情况下,比较理想的优先级为:
命令行参数 > 代码中指定FLAG > 系统环境变量
注:在gtest中,在测试套件或者测试用例,测试夹具的命名的前面加上DISABLED_,gtest认为这样的测试是被禁用了的。
运行标志
在testing::GTEST_FLAG宏中,指定要设置的标志,例如:
testing::GTEST_FLAG(output) = "xml";
运行标志必须要在testing::InitGoogleTest(&argc, argv);执行前设置。
官方文档中介绍了的运行标志如下:
运行标志
说明
filter
同--gtest_filter
also_run_disabled_tests
同---gtest_also_run_disabled_tests
repeat
同--gtest_repeat(--gtest_repeat=[COUNT])
color=(yes|no|auto)
同---gtest_color=(yes|no|auto) 默认auto
print_time
同---gtest_print_time(gtest_print_time=0或1)默认打印
output
同---gtest_output(--gtest_output=xml:d:\foo.xml 指定输出到d:\foo.xml)
break_on_failure
同---gtest_break_on_failure
catch_exceptions
同---gtest_catch_exceptions
测试demo:
#include <gtest/gtest.h>
#include <iostream>
using namespace std;
void demo()
{
inti = 0;
while(i!= 10)
{++i;}
}
TEST(demoDEATHTEST,hahaha)
{
EXPECT_DEATH(demo(),"")<<"sosurprised,why?";
}
TEST(demoTEST,heiheihei)
{
EXPECT_EXIT(_exit(1),testing::ExitedWithCode(1),"");
}
int main(int argc, char* argv[])
{
testing::FLAGS_gtest_death_test_style= "fast";
testing::GTEST_FLAG(output)= "xml";//写在InitGoogleTest之前
testing::GTEST_FLAG(color)= "yes";//设置颜色为彩色
testing::GTEST_FLAG(repeat)= 2;//设置测试重复2次
testing::InitGoogleTest(&argc,argv);
returnRUN_ALL_TESTS();
}
结果:
3 遇到的问题:
1.在vs2008中无法打开GTEST中的“msvc”中的gtest解决方案。
问题提示:
a)解决方法:
b)修改sln文件,按附录后的diff文件修改对应的sln文件。
c)修改vcproject文件,按附录后的diff文件修改所有的vcproject文件。
2.编译gtest.sln出错(gtest_prod_test、gtest_unittest会出错):
a)解决方法:
b)属性,配置属性,C/C++,代码生成,运行库,多线程调试(/MTd)。
c)属性,配置属性,链接器,命令行,附加选项:,添加“/NODEFAULTLIB:libCMT”。
4 附录:
修改gtest.sln文件(-号表示删去,+号表示添加)
-Microsoft Visual Studio Solution File, Format Version8.00
+Microsoft Visual Studio Solution File, Format Version10.00
+# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}")= "gtest", "gtest.vcproj","{C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}"
- ProjectSection(ProjectDependencies)= postProject
- EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}")= "gtest_main", "gtest_main.vcproj","{3AF54C8A-10BF-4332-9147-F68ED9862032}"
- ProjectSection(ProjectDependencies)= postProject
- EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}")= "gtest_unittest", "gtest_unittest.vcproj","{4D9FDFB5-986A-4139-823C-F4EE0ED481A1}"
- ProjectSection(ProjectDependencies)= postProject
- EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}")= "gtest_prod_test", "gtest_prod_test.vcproj","{24848551-EF4F-47E8-9A9D-EA4D49BC3ECA}"
- ProjectSection(ProjectDependencies)= postProject
- EndProjectSection
EndProject
Global
- GlobalSection(SolutionConfiguration)= preSolution
- Debug = Debug
- Release = Release
+ GlobalSection(SolutionConfigurationPlatforms)= preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
EndGlobalSection
- GlobalSection(ProjectConfiguration)= postSolution
- {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Debug.ActiveCfg= Debug|Win32
- {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Debug.Build.0= Debug|Win32
- {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Release.ActiveCfg= Release|Win32
- {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Release.Build.0= Release|Win32
- {3AF54C8A-10BF-4332-9147-F68ED9862032}.Debug.ActiveCfg= Debug|Win32
- {3AF54C8A-10BF-4332-9147-F68ED9862032}.Debug.Build.0= Debug|Win32
- {3AF54C8A-10BF-4332-9147-F68ED9862032}.Release.ActiveCfg= Release|Win32
- {3AF54C8A-10BF-4332-9147-F68ED9862032}.Release.Build.0= Release|Win32
- {4D9FDFB5-986A-4139-823C-F4EE0ED481A1}.Debug.ActiveCfg= Debug|Win32
- {4D9FDFB5-986A-4139-823C-F4EE0ED481A1}.Debug.Build.0= Debug|Win32
- {4D9FDFB5-986A-4139-823C-F4EE0ED481A1}.Release.ActiveCfg= Release|Win32
- {4D9FDFB5-986A-4139-823C-F4EE0ED481A1}.Release.Build.0= Release|Win32
- {24848551-EF4F-47E8-9A9D-EA4D49BC3ECA}.Debug.ActiveCfg= Debug|Win32
- {24848551-EF4F-47E8-9A9D-EA4D49BC3ECA}.Debug.Build.0= Debug|Win32
- {24848551-EF4F-47E8-9A9D-EA4D49BC3ECA}.Release.ActiveCfg= Release|Win32
- {24848551-EF4F-47E8-9A9D-EA4D49BC3ECA}.Release.Build.0= Release|Win32
+ GlobalSection(ProjectConfigurationPlatforms)= postSolution
+ {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Debug|Win32.ActiveCfg= Debug|Win32
+ {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Debug|Win32.Build.0= Debug|Win32
+ {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Release|Win32.ActiveCfg= Release|Win32
+ {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Release|Win32.Build.0= Release|Win32
+ {3AF54C8A-10BF-4332-9147-F68ED9862032}.Debug|Win32.ActiveCfg= Debug|Win32
+ {3AF54C8A-10BF-4332-9147-F68ED9862032}.Debug|Win32.Build.0= Debug|Win32
+ {3AF54C8A-10BF-4332-9147-F68ED9862032}.Release|Win32.ActiveCfg= Release|Win32
+ {3AF54C8A-10BF-4332-9147-F68ED9862032}.Release|Win32.Build.0= Release|Win32
+ {4D9FDFB5-986A-4139-823C-F4EE0ED481A1}.Debug|Win32.ActiveCfg= Debug|Win32
+ {4D9FDFB5-986A-4139-823C-F4EE0ED481A1}.Debug|Win32.Build.0= Debug|Win32
+ {4D9FDFB5-986A-4139-823C-F4EE0ED481A1}.Release|Win32.ActiveCfg= Release|Win32
+ {4D9FDFB5-986A-4139-823C-F4EE0ED481A1}.Release|Win32.Build.0= Release|Win32
+ {24848551-EF4F-47E8-9A9D-EA4D49BC3ECA}.Debug|Win32.ActiveCfg= Debug|Win32
+ {24848551-EF4F-47E8-9A9D-EA4D49BC3ECA}.Debug|Win32.Build.0= Debug|Win32
+ {24848551-EF4F-47E8-9A9D-EA4D49BC3ECA}.Release|Win32.ActiveCfg= Release|Win32
+ {24848551-EF4F-47E8-9A9D-EA4D49BC3ECA}.Release|Win32.Build.0= Release|Win32
EndGlobalSection
- GlobalSection(ExtensibilityGlobals)= postSolution
+ GlobalSection(SolutionProperties)= preSolution
+ HideSolutionNode = FALSE
EndGlobalSection
- GlobalSection(ExtensibilityAddIns)= postSolution
- EndGlobalSection
EndGlobal
修改gtest_md.sln文件(-号表示删去,+号表示添加)
-Microsoft Visual Studio Solution File, Format Version8.00
+Microsoft Visual Studio Solution File, Format Version10.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}")= "gtest-md", "gtest-md.vcproj","{C8F6C172-56F2-4E76-B5FA-C3B423B31BE8}"
- ProjectSection(ProjectDependencies)= postProject
- EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}")= "gtest_main-md", "gtest_main-md.vcproj","{3AF54C8A-10BF-4332-9147-F68ED9862033}"
- ProjectSection(ProjectDependencies)= postProject
- EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}")= "gtest_prod_test-md", "gtest_prod_test-md.vcproj","{24848551-EF4F-47E8-9A9D-EA4D49BC3ECB}"
- ProjectSection(ProjectDependencies)= postProject
- EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}")= "gtest_unittest-md", "gtest_unittest-md.vcproj","{4D9FDFB5-986A-4139-823C-F4EE0ED481A2}"
- ProjectSection(ProjectDependencies)= postProject
- EndProjectSection
EndProject
Global
- GlobalSection(SolutionConfiguration)= preSolution
+ GlobalSection(SolutionConfigurationPlatforms)= preSolution
Debug= Debug
Release= Release
EndGlobalSection
- GlobalSection(ProjectConfiguration)= postSolution
+ GlobalSection(ProjectConfigurationPlatforms)= postSolution
{C8F6C172-56F2-4E76-B5FA-C3B423B31BE8}.Debug.ActiveCfg= Debug|Win32
{C8F6C172-56F2-4E76-B5FA-C3B423B31BE8}.Debug.Build.0= Debug|Win32
{C8F6C172-56F2-4E76-B5FA-C3B423B31BE8}.Release.ActiveCfg= Release|Win32
@@ -38,8 +30,7 @@ Global
{4D9FDFB5-986A-4139-823C-F4EE0ED481A2}.Release.ActiveCfg= Release|Win32
{4D9FDFB5-986A-4139-823C-F4EE0ED481A2}.Release.Build.0= Release|Win32
EndGlobalSection
- GlobalSection(ExtensibilityGlobals)= postSolution
+ GlobalSection(SolutionProperties)= preSolution
+ HideSolutionNode = FALSE
EndGlobalSection
- GlobalSection(ExtensibilityAddIns)= postSolution
- EndGlobalSection
EndGlobal
修改msvc中各*.vcproj文件(-号表示删去,+号表示添加)
- Version="7.10"
+ Version="9.00"