解决方案(.sln)文件

原文:Solution (.Sln) File

关于VS2008和VS2010中.sln文件(解决方案文件)的介绍MSDN中只有英文版,现翻译供读者参考,希望对您有帮助。水平有限文中难免有错误,欢迎大家指正,拜谢~

解决方案就是Visual Studio中用来组织项目的结构。他的作用类似于VB6.0中的Windows程序组(.vbg)文件以及VC6.0中的项目工作区(.dsw)文件。解决方案将项目的状态信息保存在.sln文件(该文件是基于文本,而且是可共享的)和.suo文件(该文件是二进制的,而且是解决方案中可选的)中。更多关于.suo的信息请查看解决方案中用户可选.suo文件

如果你的VSPackage由于在.sln文件中被引用而加载,那么编译环境调用ReadSolutionProps读取.sln文件。

.sln文件包含基于文本的信息,编译环境通过这些信息找到并且加载他引用到的持久数据和VSPackages项目。当用户打开解决方案的时候编译环境通过包含在.sln文件中的preSolution,Project,postSolution信息加载解决方案,包含在解决方案中的项目以及任何和解决方案有联系的持久信息。

每个项目的文件都包含额外的信息,编译环境通过读取这些信息把项目中所需的项目补充完整。数据持久层是受项目控制的;所以数据一般不包含在.sln文件中。尽管你可以有意的将项目信息写入.sln文件中。更多的信息请参考Project PersistenceOpening 和Saving Project Items

解决方案文件内容

.sln的文件都是由几部分如图所示的下列代码构成的,他被保存在解决方案浏览器的底部。更多有关解决方案注释章节的信息,参见Extending Solution Explorer

 

 

   1:  Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Project1", "Project1.vbproj", "{8CDD8387-B905-44A8-B5D5-07BB50E05BEA}"
   2:  EndProject
   3:  Global
   4:    GlobalSection(SolutionNotes) = postSolution
   5:         Name1 = Note2
   6:         Issue1 = N
   7:         Text1 = This is a shared note.
   8:         Name2 = Note3
   9:         Issue2 = N
  10:         Text2 = This is also a shared note. The second of two shared notes.
  11:         NumNotes = 2
  12:    EndGlobalSection
  13:    GlobalSection(SolutionConfiguration) = preSolution
  14:         ConfigName.0 = Debug
  15:         ConfigName.1 = Release
  16:    EndGlobalSection
  17:    GlobalSection(ProjectDependencies) = postSolution
  18:    EndGlobalSection
  19:    GlobalSection(ProjectConfiguration) = postSolution
  20:     {8CDD8387-B905-44A8-B5D5-07BB50E05BEA}.Debug.ActiveCfg = Debug|.NET
  21:     {8CDD8387-B905-44A8-B5D5-07BB50E05BEA}.Debug.Build.0 = Debug|.NET
  22:     {8CDD8387-B905-44A8-B5D5-07BB50E05BEA}.Release.ActiveCfg = Release|.NET
  23:     {8CDD8387-B905-44A8-B5D5-07BB50E05BEA}.Release.Build.0 = Release|.NET
  24:    EndGlobalSection
  25:    GlobalSection(ExtensibilityGlobals) = postSolution
  26:    EndGlobalSection
  27:    GlobalSection(ExtensibilityAddIns) = postSolution
  28:    EndGlobalSection
  29:  EndGlobal

 

编译环境执行如下顺序的工作去加载解决方案

1.       编译环境读取.sln文件的全局语句并且处理所有的标记为preSolution的语句。在上文的例子中,有这样的声明:

 

 

   1:    GlobalSection(SolutionConfiguration) = preSolution
   2:         ConfigName.0 = Debug
   3:         ConfigName.1 = Release

 

当编译环境读取到GlobalSection(‘name’)标记的时候,他通过注册表将名字映射到VSPackage中。关键字name应该在注册表的[HKLM/<Application ID Registry Root>/SolutionPersistence]目录下。关键字的默认值是写入VSPackage目录的Package GUID (REG_SZ)中的。

2.  环境加载VSPackage的时候,为IVsPersistSolutionProps接口调用VSpackage的QueryInterface,并且通过文件中的数据调用ReadSolutionProps方法,所以VSPackage能够存储数据。编译环境对每个有preSolution的地方重复做上面那样的操作。

3.  编译环境循环遍历项目的模块。那好,这里有一个项目(让我们来分析一下)

 

 

   1:  Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Project1",
   2:  "Project1.vbproj", "{8CDD8387-B905-44A8-B5D5-07BB50E05BEA}"
   3:  EndProject

 

上面这段代码中包含独一无二的项目全局唯一标识符(GUID)以及项目类型的全局唯一标识符(GUID)。这些信息被编译环境用来寻找项目文件爱你或者那些属于解决方案的文件,还有那些任何项目需要的特定的VSPackage。项目的全局唯一标识符(GUID)被传递到IVsProjectFactory用来加载和项目有关的特殊的VSPackage,然后这个项目被载入。在上面的代码中被载入的VSPackage是Visual Basic。

 

每个项目中都存在一个唯一的项目实例ID,只有这样这个项目才能被其他解决方案中需要他的项目使用。理想状态下,如果解决方案和项目在源代码控制之下,项目的路径应该和解决方案的路径是相关的。当解决方案被第一次加载时,项目文件不能够存在于用户的电脑中。将项目文件存放在和解决方案文件相关的服务文件中,通过这个方法将相对简单的找到项目文件或者将项目文件复制到用户的电脑中。然后编译环境复制并加载剩下的项目所需文件。

4.  根据项目的.sln文件中包含的信息编译环境加载每一个项目文件。项目本身很好的填充项目的层次而且加载任何嵌入的项目。

5.  然后编译环境执行被标记为postSolution的那些全局语句。下面就是上文代码片段中的一个例子。

 

 

   1:  GlobalSection(SolutionNotes) = postSolution
   2:         Name1 = Note2
   3:         Issue1 = N
   4:         Text1 = This is a shared note.
   5:         Name2 = Note3
   6:         Issue2 = N
   7:         Text2 = This is also a shared note. The second of two shared notes.
   8:         NumNotes = 2
   9:    EndGlobalSection

 

正如上面的这种情况,在.sln文件中有两个共享的note.Note1没有包含在文件中,因为他标记为不共享。他的内容放在.suo文件中。语句中的每个有名字值组成的条目和每个note是一一对应的。更多有关实现解决方案Note的内容请查看Extending Solution Explorer

6.  最后.sln文件执行完毕,解决方案在解决方案浏览器中显示出来,并等待用户的操作。

 

如果有关项目的任何VSPackage加载失败, OnProjectLoadFailure方法将被调用而且每个解决方案中的项目将尝试取消在加载过程中的改变。如果解析发生错误,尽可能的收集有关解决方案文件的资料而且编译环境显示一个对话框警告这个解决方案已经被破坏了。

 

当解决方案被保存或者被关闭的时候QuerySaveSolutionProps方法将被调用并传到层次结构检查解决方案中是否存在那些需要保存到.sln文件中的改变。在VSQUERYSAVESLNPROPS中传递到QuerySaveSolutionProps的一个空值表明这个信息将被保存。如果值不为空表明保存的信息是特殊的项目,这取决于IVsHierarchy接口

 

如果有信息被保存IVsSolutionPersistence接口将被指向SaveSolutionProps的方法调用。然后WriteSolutionProps方法将被编译环境调用,这个方法用来检验与来自IPropertyBag的接口对应的名字值并且将相关信息写入.sln文件中。

 

为了检验来自IPropertyBag接口的信息是否被保存SaveSolutionPropsWriteSolutionProps对象被编译环境递归调用,直到所有的更改被写进.sln文件。用这种方法可以确保解决方案的信息可以保存并且下次可以顺利打开解决方案。

 

每个加载的VSPackage都被列举用来查看是否有需要保存到.sln文件的东西。只有在加载的时候才需要注册码。编译环境知道所有的加载的包,因为当解决方案保存的时候他们就被记录下来了。

 

只有.sln包含preSolution和postSolution中的条目。在.suo文件中没有相似的语句,因为解决方案需要正确的被加载。.suo文件包含用户的可选项,比如个人的注释,这些是不需要被共享或者被源码控制的。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include <graphics.h> // 引用图形库头文件 #include <conio.h> #include<time.h> #if 0 int main1() { initgraph(640, 480); MOUSEMSG m; int r;// 创建绘图窗口,大小为 640x480 像素 while (1) { m = GetMouseMsg(); switch (m.uMsg) { case WM_MOUSEMOVE: setcolor(RGB(rand() % 91 + 10, rand() % 91 + 10, rand() % 91 + 10)); if (m.mkLButton) { circle(m.x, m.y, rand() % 91 + 10); break; } else if (m.mkRButton) { r = rand() % 91 + 10; rectangle(m.x - r, m.y - r, m.x + r, m.y + r); } } } _getch(); // 按任意键继续 closegraph(); // 关闭绘图窗口 } const int BoardW = 5; const int BoardH = 5; const int GridSz = 100; const int Edge = 30; void drawGrid() { setbkcolor(RGB(0, 162, 232));//背景颜色 cleardevice();//用当前背景颜色全涂色 setcolor(RGB(0, 0, 0));//边框用黑线 for (int i = 0; i <= BoardH; ++i) { line(Edge, Edge + i*GridSz, Edge + BoardW*GridSz, Edge + i*GridSz); } for (int i = 0; i <= BoardH; ++i) { line(Edge + i*GridSz, Edge, Edge + i*GridSz, Edge + BoardH*GridSz); } } void drawLayout(int layout[BoardH][BoardW]) { int r = GridSz * 4 / 10; int x, y; setcolor(RGB(255, 201, 14));//棋子边的颜色 setfillcolor(RGB(255, 201, 14));//棋子的填充色 for (int i = 0; i<BoardH; i++) { for (int j = 0; j<BoardW; j++) { if (1 == layout[i][j]) { x = Edge + j*GridSz + GridSz / 2; y = Edge + i*GridSz + GridSz / 2; fillcircle(x, y, r); } } } } void UpdateLayout(int Layout[BoardH][BoardW], int x, int y) { if (x <= Edge || x >= Edge + BoardW*GridSz || y <= Edge || y >= Edge + BoardH*GridSz) { return; } int i, j; i = (y - Edge) / GridSz; j = (x - Edge) / GridSz; Layout[i][j] = 1 - Layout[i][j]; if (i - 1 >= 0) { Layout[i - 1][j] = 1 - Layout[i - 1][j]; } if (i + 1 < BoardH) { Layout[i + 1][j] = 1 - Layout[i + 1][j]; } if (j - 1 >= 0) { Layout[i][j - 1] = 1 - Layout[i][j - 1]; } if (j + 1 < BoardW) { Layout[i][j + 1] = 1 - Layout[i][j + 1]; } } int isGameOver(int layout[BoardH][BoardW]) { int sum = 0; for (int i = 0; i < BoardH; i++) { for (int j = 0; j<BoardW; j++) { sum += layout[i][j]; } } if (0 == sum) { return 1; } else { return 0; } } int initLayout(int layout[BoardH][BoardW]) { int k = 0; srand((int)time(0)); for (int i = 0; i<BoardH; i++) { for (int j = 0; j<BoardW; j++) { k = rand() % 5; if (0 == k || 1 == k) { layout[i][j] = k; } } } return layout[BoardH][BoardW]; } int main() { int layout[BoardH][BoardW] = { 0 };//layout 布局 (棋盘的布局) HWND hwnd; hwnd = initgraph(BoardW*GridSz + 2 * Edge, BoardH*GridSz + 2 * Edge); while (1) { initLayout(layout); drawGrid();//画棋盘 drawLayout(layout);//画棋盘布局 MOUSEMSG m; while (!isGameOver(layout)) { m = GetMouseMsg(); switch (m.uMsg) { case WM_LBUTTONDOWN: UpdateLayout(layout, m.x, m.y); break; } drawGrid();//画棋盘 drawLayout(layout);//画棋盘布局 } MessageBox(hwnd, _T("恭喜过关!"), _T("提示"), MB_OK); } _getch(); closegraph(); return 0; } #endif //贴图 #if 0 int main() { initgraph(640, 480); IMAGE imgMask, imgSrc; loadimage(&imgMask;, _T("./mask.jpg")); loadimage(&imgSrc;, _T("./src.jpg")); putimage(100, 200, &imgMask;, SRCAND); putimage(100, 200, &imgSrc;, SRCPAINT); _getch(); closegraph(); return 0; } #endif //时间及文本显示 #if 0 int main() { initgraph(640, 480); time_t start, end; time(&start;); _getch(); time(&end;); TCHAR s[128]; _stprintf(s, _T("相隔时间:%d秒"), (end - start)); settextcolor(RGB(255, 255, 0)); settextstyle(100, 0, _T("隶书")); outtextxy(0, 0, s); _getch(); closegraph(); return 0; } #endif //声音播放 #if 0 #include"mmsystem.h" #pragma comment(lib,"winmm.lib") int main() { mciSendString(_T("open BGM.mp3 alias bgm"), NULL, 0, NULL); mciSendString(_T("open 123.mp3 123 bgm"), NULL, 0, NULL); while (1) { char key = _getch(); switch (key) { case 'p': mciSendString(_T("seek bgm to 0"), NULL, 0, NULL); mciSendString(_T("play bgm"), NULL, 0, NULL); break; //case 's': // mciSendString(_T("stop bgm"), NULL, 0, NULL); // break; case 't': mciSendString(_T("pause bgm"), NULL, 0, NULL); break; case 'r': mciSendString(_T("resume bgm"), NULL, 0, NULL); break; case 'c': goto lp; break; case 'o': mciSendString(_T("play 123"), NULL, 0, NULL); break; } } lp: mciSendString(_T("close bgm"), NULL, 0, NULL); return 0; } #endif #if 0 #include <stdio.h> #include <stdlib.h> #include <time.h> int main() { srand(time(NULL));//1970.1.1 00:00:00 for (int i = 0; i < 10; ++i) { printf("%d,", rand()); } return 0; } /* 伪随机 */ #endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值