65.9K
CodeProject 正在变化。 阅读更多。
Home

清理 Visual Studio 工作区

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.22/5 (14投票s)

2005年6月30日

8分钟阅读

viewsIcon

154469

downloadIcon

2029

通过删除 Release、Debug 等文件夹和中间文件来清理 Visual Studio 工作区。

重要通知

文件夹选项优先于文件删除选项。如果您勾选“清理 Release 文件夹”,所有 Release 文件夹中的文件和子文件夹(包括 .exe.dll.lib.ocx)都将被擦除,即使您在文件删除选项中取消勾选“输出文件(.exe .dll .lib .ocx)”也是如此。

引言

在 Visual Studio 中编写了数十个项目(编辑源代码、编译、链接、调试等)之后,我发现源目录 (D:\Cpp) 占用了太多空间。这很烦人,因为我的笔记本电脑容量非常有限。所以问题是

我们如何清理我们的工作区?

对于少量的工作区,我们可以手动删除 Visual Studio 生成的中间文件(哪些文件是中间文件将在下面描述)。对于数十个(甚至数百个)工作区,我们需要以更优雅的方式进行管理。这是我创建这个项目的动机。

该项目是一个基于 MFC 对话框的应用程序,我认为 CodeProject 中的每个人都可以从中受益。它利用了一些控件,例如 buttonListBoxcheckbox,以及一些 Visual C++ 目录和/或文件相关的函数,例如 RemoveDirectoryDeleteFile,以及一个名为 CFileFind 的类。

中间文件类型

通常,在我们的项目成功编译后,我们不需要 ReleaseDebug 文件夹以及其中包含的所有文件。中间文件也是如此,如下所述。这里提供的大部分信息摘自 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 贡献一样。

处理文件夹

通常,ReleaseDebug 文件夹都在那里。我们做的是以下事情

// Pseudo code:
// First, we delete all the files in the folder
// then we remove the empty folder

原因是该函数

RemoveDirectory(strDirName)

只能删除空目录。偶尔,我们可能在 ReleaseDebug 下有子文件夹。让我们假设我们有以下目录结构

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 1Precious 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 1Precious 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 生成的源文件/接口扩展名。已删除此类文件的删除。

© . All rights reserved.