清理 Visual Studio 工作区






4.22/5 (14投票s)
2005年6月30日
8分钟阅读

154469

2029
通过删除 Release、Debug 等文件夹和中间文件来清理 Visual Studio 工作区。
重要通知
文件夹选项优先于文件删除选项。如果您勾选“清理 Release 文件夹”,所有 Release 文件夹中的文件和子文件夹(包括 .exe、.dll、.lib、.ocx)都将被擦除,即使您在文件删除选项中取消勾选“输出文件(.exe .dll .lib .ocx)”也是如此。
引言
在 Visual Studio 中编写了数十个项目(编辑源代码、编译、链接、调试等)之后,我发现源目录 (D:\Cpp) 占用了太多空间。这很烦人,因为我的笔记本电脑容量非常有限。所以问题是
我们如何清理我们的工作区?
对于少量的工作区,我们可以手动删除 Visual Studio 生成的中间文件(哪些文件是中间文件将在下面描述)。对于数十个(甚至数百个)工作区,我们需要以更优雅的方式进行管理。这是我创建这个项目的动机。
该项目是一个基于 MFC 对话框的应用程序,我认为 CodeProject 中的每个人都可以从中受益。它利用了一些控件,例如 button
、ListBox
、checkbox
,以及一些 Visual C++ 目录和/或文件相关的函数,例如 RemoveDirectory
和 DeleteFile
,以及一个名为 CFileFind
的类。
中间文件类型
通常,在我们的项目成功编译后,我们不需要 Release 和 Debug 文件夹以及其中包含的所有文件。中间文件也是如此,如下所述。这里提供的大部分信息摘自 Microsoft 网站,您可以在此处访问。
调试器生成的中间文件
文件扩展名 | 来源 | 目录 |
.pch | Debug | 预编译头文件。 |
.pdb | Debug | 程序调试数据库文件。 |
编译器生成的中间文件
文件扩展名 | 来源 | 目录 |
.bsc | 编译 | 浏览器代码文件。 |
.idb | 编译 | 状态文件,包含源文件和类定义之间的依赖信息。 |
.sbr | 编译 | 源浏览器中间文件。BSCMAKE 的输入文件。 |
链接器生成的中间文件
文件扩展名 | 来源 | 目录 |
.ilk | 链接 (Linking) | 增量链接文件。有关更多信息,请参阅 /INCREMENTAL。 |
.map | 链接 (Linking) | 包含链接器信息的文本文件。使用 /Fm 编译器选项命名映射文件。有关更多信息,请参阅 /MAP。 |
Visual Studio 生成的中间文件
文件扩展名 | 来源 | 目录 |
.aps | Resource | 当前资源脚本文件的二进制版本;用于快速加载。 |
.ncb | 解决方案 | 此文件是 ClassView 使用的二进制文件,并且特定于本地计算机。 |
.o | 目标文件,已编译但未链接。 | |
.obj | 目标文件,已编译但未链接。 | |
.opt | 这是一个二进制文件,是本地计算机的工作区选项文件。 | |
.plg | 构建日志文件。它是一个 HTML 文件,您可以在 i.e. 或其他浏览器中查看。 |
输出文件(通常是我们的产品)
文件扩展名 | 来源 | 目录 |
.exe | 输出 | 您的产品。 |
.dll | 输出 | 您的 DLL 产品。 |
.lib | 输出 | 存储有关您的 .dll 文件的信息的库文件。 |
.ocx | 输出 | 我们的 ActiveX 控件。 |
其他文件
文件扩展名 | 来源 | 目录 |
.scc | 其他 | 源代码安全文件(来自此论坛中的 Indivara 的贡献)。 |
注意:*我知道制作这个列表并使其 100% 完整是一项艰巨的任务。因此,我期待您的贡献,就像您为 codeproject 贡献一样。
处理文件夹
通常,Release 和 Debug 文件夹都在那里。我们做的是以下事情
// Pseudo code:
// First, we delete all the files in the folder
// then we remove the empty folder
原因是该函数
RemoveDirectory(strDirName)
只能删除空目录。偶尔,我们可能在 Release 或 Debug 下有子文件夹。让我们假设我们有以下目录结构
D:\Cpp
|--- HelloWorld
|--- Release
|--- Precious Data Folder 1 (may well contain the
user's valuable data)
|--- Precious Data Folder 2
|--- Debug
|--- HelloWorld.dsw
那么我们被迫先删除 Precious Data Folder 1 和 Precious Data Folder 2 文件夹中的所有文件,然后删除这两个目录,最后,我们可以处理 Release 文件夹本身。因此,我们必须递归地解决问题。下面的代码片段演示了如何使用 CFileFind
类来完成这项工作——如果您真的是初学者,您可能需要一些时间来消化它。
void CCleanWorkspaceDlg::RecursiveDelete(CString szPath) { CFileFind ff; CString path = szPath; if(path.Right(1) != "\\") path += "\\"; path += "*.*"; BOOL bResult = ff.FindFile(path); while(bResult) { bResult = ff.FindNextFile(); if(!ff.IsDots() && !ff.IsDirectory()) // a file { CString str; str.Format("Deleting file %s", ff.GetFilePath()); DelShow(str); // delete the file DeleteFile(ff.GetFilePath()); } else if(ff.IsDots()) // . and/or .. continue; else if(ff.IsDirectory()) // a dir and we go recursive { path = ff.GetFilePath(); RecursiveDelete(path); RemoveDirectory(path); } } ff.Close(); // don't forget to close it }
警告:在您按下清理按钮后,Release 和/或 Debug 文件夹中的所有文件和文件夹,包括 Precious Data Folder 1 和 Precious Data Folder 2,都将被永久删除。
作为一名程序员或准程序员,您不会手动将任何数据放入 Release 和/或 Debug 文件夹中,因此对您来说没有风险。但是,存在用户可能在其中放置一些有价值的数据的可能性。因此,您可能会考虑重写/修改代码,并在按下按钮之后但在实际删除之前给出警告。
我们对空文件夹有两种选择:保留或删除。如果最终用户勾选“保留空文件夹”复选框,
它们将被保留;否则它们将被擦除。尽管保留它们有一些充分的理由。例如,我的 DLL 项目有一个构建后步骤(您可以按 Alt + F7 访问项目设置),它将 .dll 和 .lib 文件复制到测试应用程序的 Release 文件夹。在这种情况下,我要求我的测试应用程序的 Release 文件夹存在。
处理中间文件
现在让我们回到处理位于工作区目录中的中间文件。根据定义,
工作区目录 := xxx.dsw 和/或 xxx.dsp 文件所在的目录。
首先要说明一点:我们可能有一个工作区包含两个或更多项目,每个项目都位于其自己的(子)文件夹中。如果是这样,我们会有很多 .dsp 文件。但我们总是只有一个 .dsw 文件。在这种情况下,工作区目录是包含 .dsw 文件的目录加上每个包含 .dsp 文件的子目录。
您可能会问中间文件何时在工作区目录中生成。好问题!您可能有很多答案。但其中一个答案是这样的:像我这样的一些老式家伙,喜欢使用命令行构建简单的项目
//classical hello, world program
cl HelloWorld.cpp
对于控制台应用程序(我几乎可以肯定您已经知道或听说过经典的 hello, world 程序);或者
// classical skeleton SDK or Win32 program (like // these in Petzold's "Programming Windows 95") cl HellowWorldWin.cpp kernel32.lib user32.lib gdi32.lib
对于一个简单的 SDK 应用程序。上面描述的编译和链接过程将在工作区目录中生成 .obj 和其他中间文件。更重要的是,您可能已经手动将 DLL 项目的输出(.dll 和 .lib 文件)复制到测试应用程序工作区目录。
删除这些文件是一项简单的任务,不需要递归操作。我们只需要检查文件扩展名,请参阅下面的代码片段
// delete intermediate files if( str == ".aps" || str == ".ncb" || str == ".obj" || str == ".opt" || str == ".plg" || str.Right(2) == ".o" ) { // a bug pointed out by Blake V. Miller if(m_bIntermediate) { CString str; str.Format("Deleting file %s",strFileName); DelShow(str); DeleteFile(strFileName); } }
最好向最终用户提供一些关于正在删除哪些文件的信息。我们可以通过如下更新列表框来做到这一点
m_ctlList.AddString(strFileName); UpdateData(FALSE);
日志记录
如果用户点击“记录到文件”,清理过程(指示哪些文件和/或文件夹已被删除)将被写入名为“Cleaning Log.txt”的文件。写入(或序列化,以保持 OOP 中的术语)过程利用了 CArchive
类。这是一项相对容易的工作——我们只需要将存储在列表框中的字符串写入文件。但是,这里有一个微妙之处:CArchive::WriteString
函数不写入回车符 (CR) 和换页符 (LF)。
您可能会考虑通过添加新行来处理它,如下所示
ar.WriteString(str + "\n")
但是当您在记事本中打开日志文件时,没有产生新行。结果表明以下代码片段有效。
ar.WriteString(str + "\r\n")
转义符“\r
”代表回车符(如果您忘记了在第一个 C/C++ 语言课程中学到的内容。坦率地说,我忘了。)
结论
在本文中,我们演示了如何使用以下方式删除 Visual Studio 生成的中间文件夹和/或文件
RemoveDirectory(...)
和
DeleteFile(...)
和类
CFileFind
希望这能让阅读 CodeProject 的程序员和/或开发人员的生活更轻松一些。
注释
- 有些(新手)用户可能在 Release 和/或 Debug 文件夹中有大量文件。但是,此程序将在未经您许可的情况下删除 Release 和/或 Debug 文件夹中的所有文件。最好先了解您正在做什么。我不对任何数据丢失负责,因为程序和源代码按原样提供,因此使用风险自负;
- 当我们有数百个工作区要清理时,主程序会停止。因此,我们可能需要一个工作线程来完成讨厌的工作,以及一个 UI 线程来维护用户界面。我没有计划为该项目添加多线程支持。简而言之,用户可以在喝一杯咖啡或茶时启动清理过程;
- 我们可以将所有已删除的文件和/或文件夹记录到文件中,尽管列表框确实提供了一些信息;
- 我的项目设置有一个构建后步骤,它会将 .exe 文件复制到用户的桌面
copy Release\*.exe "%USERPRROFILE%\Desktop"
这在 Win XP 中完美运行,但在 Win9x 中可能根本不起作用。
致谢
几位 CodeProject 用户指出了错误、改进建议,我对此表示感谢
- Blake V. Miller 指出了代码中的一个错误,该错误已在新上传的源代码中得到纠正;
- Indivara 贡献了他的 .scc 文件扩展名;
- slim 提供了另一个类似(可能更好,我猜)项目的链接;
- owillebo 详细描述了 DOS 脚本解决方案。
更新列表
- 2005 年 7 月 1 日
首次公开发布并根据几位观众的建议进行了小幅修改;
- 2005 年 7 月 2 日
添加了记录清理过程的选项,该选项告诉用户哪些文件和/或目录已被删除;
- 2005 年 7 月 6 日
通过添加
EN_CHANGE
处理程序纠正了编辑框的错误,并对文章进行了一些修改, - 2005 年 7 月 7 日
.idl 是 MIDL 生成的源文件/接口扩展名。已删除此类文件的删除。