Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Clean Visual Studio Workspaces

0.00/5 (No votes)
6 Jul 2005 3  
Clean Viusal Studio workspaces by deleting folders such as Release, Debug etc. and intermediate files.

Important notice

Folder options take precedence over File deletion options. If you check "Clean Release folders", all files and subfolders (including .exe, .dll, .lib, .ocx) in all Release folders will be erased even if you uncheck "Output files (.exe .dll .lib .ocx)" in the File deletion options.

Introduction

After writing dozens of projects (editing source codes, compiling, linking, debugging, etc.) in Visual Studio, I found the source directory (D:\Cpp) taking so much space. This is annoying since my laptop has very limited capacity. So, the question is:

How do we clean our workspaces?

For a small number of workspaces, we could manually delete the intermediate files (which file is an intermediate file is described below) generated by Visual Studio. For tens (or even hundreds) of workspaces, we need to manage it in a nicer fashion. This is my motivation for creating this project.

The project is a MFC dialog-based application, which I think every buddy in CodeProject could benefit from it. It utilizes a few controls, such as button, ListBox, checkbox, a couple of Visual C++ directory and/or file related functions, such as RemoveDirectory and DeleteFile, and a class called CFileFind.

Intermediate file types

Normally, we do not need the Release and Debug folders and all the files included after our projects compile successfully. Same thing for the intermediate files, which are described below. Most of the information presented here was excerpted from Microsoft's web site, which could be visited here.

Intermediate files generated by the debugger:

File extension Source Contents
.pch Debug Precompiled header file.
.pdb Debug The program debug database file.

Intermediate files generated by the compiler:

File extension Source Contents
.bsc Compiling The browser code file.
.idb Compiling The state file, containing dependency information between source files and class definitions.
.sbr Compiling Source browser intermediate file. The input file for BSCMAKE.

Intermediate files generated by the linker:

File extension Source Contents
.ilk Linking Incremental link file. See /INCREMENTAL for more information.
.map Linking A text file containing linker information. Use the /Fm compiler option to name the map file. See /MAP for more information.

Intermediate files generated by Visual Studio:

File extension Source Contents
.aps Resource Binary version of the current resource script file; used for quick loading.
.ncb Solution This file is a binary file used by ClassView and is specific to the local machine.
.o Object files, compiled but not linked.
.obj Object files, compiled but not linked.
.opt This is a binary file that is the workspace options file for the local computer.
.plg build log file. It is an HTML file which you can view in i.e. or other browsers.

Output files (most often they are our products):

File extension Source Contents
.exe Output your product.
.dll Output your DLL product.
.lib Output the library file which stores information about your .dll file.
.ocx Output our ActiveX controls.

Other files:

File extension Source Contents
.scc Other source safe file (contribution from Indivara in this forum.)

Note: *I understand it is a tough task to make this list 100% complete. Thus, I am expecting your contributions, just the way you contributed to codeproject.

Handling the folders

In general, the Release and Debug folders are there. What we do is the following:

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

The reason is that the function:

RemoveDirectory(strDirName)

can only remove empty directories. Occasionally, we may have subfolders under Release or Debug. Let us assume we have the following directory structure:

D:\Cpp
  |--- HelloWorld
     |--- Release
           |--- Precious Data Folder 1 (may well contain the 
                                        user's valuable data) 
           |--- Precious Data Folder 2
     |--- Debug 
     |--- HelloWorld.dsw

Then we are forced to delete all the files in folders Precious Data Folder 1 and Precious Data Folder 2 first, then remove these two directories, and finally, we can handle the Release folder itself. Hence we have to solve the problem recursively. The code snippet below demonstrates how to use CFileFind class to do the job --- and you may need some time to digest it if you are really a beginner.

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
}

Warning: After you press the clean button, all files and folders in the Release and/or Debug folders, with Precious Data Folder 1 and Precious Data Folder 2 included, are permanently gone.

As a programmer or a would-be one, you won't put any data into the Release and/or Debug folders manually, so there is no risk for you. However, there exists a chance when the user may have some value data in there. Consequently, you may think of rewriting/modifying the code and giving a warning after the button is pressed and before the actual deletion.

We have two choices about the empty folders: keep or remove them. If the end user checks the checkbox "Keep empty folders",

they will be kept; otherwise they are erased. There are some good reasons to keep them, though. For example, my DLL project has a post-build step (you can press Alt + F7 to access the project settings) which copies the .dll and .lib file to a test application's Release folder. In this case, I require my test application's Release folder to be there.

Handling the intermediate files

Now let us go back to handle intermediate files which reside in the workspace directory. By definition,

workspace directory := the directory where the files xxx.dsw and/or or xxx.dsp reside.

One thing first: we may have a workspace containing two or more projects, each residing in its own (sub)folder. If so, we have a bunch of .dsp files. But we always have one and only one .dsw file. In this case, workspace directory is the directory containing the .dsw file plus subdirectories each containing a .dsp file.

You may ask when the intermediate files are generated in the workspace directory. Good question! You may have many answers. But one answer reads like this: some old-fashioned guy like me, prefer to build simple projects using command line:

//classical hello, world program

cl HelloWorld.cpp

for a console application (I am almost sure you've known or heard of the classical hello, world program.); or

// classical skeleton SDK or Win32 program (like 

// these in Petzold's "Programming Windows 95")

cl HellowWorldWin.cpp kernel32.lib user32.lib gdi32.lib

for a simple SDK application. The compiling and linking process described above will generate .obj and other intermediate files in the workspace directory. What is more, you may have manually copied outputs of your DLL project (.dll and .lib files) to the test application workspace directory.

The deletion of these files is an easy task, no need of recursive stuff. We just need to check the file extensions, see the code snippet below:

// 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);
    }
}

It might be good to give the end user some info about what files are being deleted. We can do this by updating the ListBox as below:

m_ctlList.AddString(strFileName);

UpdateData(FALSE);

Logging

If the user clicks "Log to a file", the cleaning process, which indicates what files and/or folders have been deleted, is written to a file named "Cleaning Log.txt". The writing (or serialization, to keep up with the terminology in OOP) procedure utilized the CArchive class. It is a relatively easy job --- we just need to write the strings stored in the ListBox to a file. However, there is a subtlety here: the CArchive::WriteString function does not write carriage return (CR) and form feed (LF).

You may think of handling it by adding a new line as follows:

ar.WriteString(str + "\n")

But when you open the log file in Notepad, there are no new lines produced. It turns out that the following code snippet works.

ar.WriteString(str + "\r\n")

The escape "\r" stands for carriage return (in case you forgot what you've learned from your first C/C++ language course. Frankly, I did.)

Conclusion

In this article, we demonstrate how to delete intermediate folders and/or files generated by Visual Studio using

RemoveDirectory(...)

and

DeleteFile(...)

and the class

CFileFind

Hope this makes life a little bit easier for programmers and/or developers who read CodeProject.

Comments

  • There is a chance that some (novice) users may have a lot of files in the Release and/or Debug folders. This program, however, will delete all the files in Release and/or Debug folders without asking your permission. It'd be better to understand what you are doing first. I am not responsible for any data loss since the program and the source code is provided as is, so use them at your own risk;
  • When we have hundreds of workspaces to clean, the main program comes to a halt. Thus, we may need a work thread to do the nasty job and a UI thread to maintain the user interface. I have no plan for adding multi-thread support for this project. Simply put, the user could fire up the cleaning process when a cup of coffee or tea is to be consumed;
  • We could log all the deleted files and/or folders in a file, although the ListBox does give some info;
  • My project setting has a post-build step, which will copy the .exe file to the user's desktop:
    copy Release\*.exe "%USERPRROFILE%\Desktop"

    which works perfectly in Win XP, but may not work at all in Win9x.

Acknowledgement

Several CodeProjecters have pointed out bugs, improvement suggestions, and I am grateful to them:

  • Blake V. Miller for a bug in the code, which has been corrected in the newly uploaded source code;
  • Indivara for his .scc file extension;
  • slim for his link to another similar (may well be better, I assumed) project;
  • owillebo for his detailed description of a DOS script solution.

Update list

  • July 1st, 2005

    first public release and minor modifications following several viewers suggestion;

  • July 2nd, 2005

    added the option for logging the cleaning process, which tells the user what files and/or directories have been removed;

  • July 6th, 2005

    corrected the bug of the edit box by adding a EN_CHANGE handler and modified the article a little bit,

  • July 7th, 2005

    .idl is a source file/interface extension generated by MIDL. Removed the deletion of files of this type.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here