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:
cl HelloWorld.cpp
for a console application (I am almost sure you've known or heard of the classical hello, world program.); or
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:
if( str == ".aps" || str == ".ncb" || str == ".obj"
|| str == ".opt" || str == ".plg" ||
str.Right(2) == ".o" ) {
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.