How to recursively search folders by using Visual C++

Article translations Article translations
Article ID: 307009 - View products that this article applies to.
This article was previously published under Q307009
Expand all | Collapse all

On This Page

SUMMARY

This step-by-step article describes how to recursively search subfolders for files, beginning with a root folder, by using code. This task is known as directory recursion. You can specify a search string so that you can search for files that match a certain criteria. Each part of the code in this article is explained, and a working code sample is also provided.

Directory recursion is a common I/O task for developers. The FileSystemObject object makes this task easy for Component Object Model (COM) programs, but this task is easier in Visual C++ .NET 2002. Similar to the FileSystemObject object, the classes in the System.IO namespace provide an object-oriented way to access files and folders.

Requirements

The following list outlines the recommended hardware, software, network infrastructure, and service packs that you need:
  • Microsoft Visual C++ .NET or Microsoft Visual C++ 2005

Enable Directory Recursion

The file and directory manipulation classes reside in the System::IO namespace. Before you work with these classes, add the following code:
using <mscorlib.dll>
using namespace System;
using namespace System::IO;
The System::IO namespace provides many options for working with files and with folders. The System::IO namespace not only provides classes that you can create an instance of, but it also provides file and directory utility classes. These classes contain static methods that you can call without having to declare a variable of that type. For example, you can use the Directory class to obtain the subfolders of a folder.

The following code uses the static GetDirectories method of the Directory class to return an array of strings. This array contains folder paths to the subfolders of the C:\ folder, if any exist:
String* directories[] = Directory::GetDirectories("C:\\");
				
The Directory class also contains the GetFiles method. You can use GetFiles to retrieve a string array of files that match a certain criteria. The following code sample uses the GetFiles method to retrieve all files in the C:\ folder with a .dll file name extension:
String* files[] = Directory::GetFiles("C:\\", "*.dll");
				
You can use the GetDirectories method and the GetFiles method of the Directory class to recursively search for files that match the search string. Use the following method to perform the recursion:
	 void DirSearch(String* sDir)
	 {
		 try
		 {
			 // Find the subfolders in the folder that is passed in.
			 String* d[] = Directory::GetDirectories(sDir);
			 int numDirs = d->get_Length();
			 
			 for (int i=0; i < numDirs; i++)
			 {
				 // Find all the files in the subfolder.
				 String* f[] = Directory::GetFiles(d[i],textBox1->Text);
				 int numFiles = f->get_Length();

				 for (int j=0; j < numFiles; j++)
				 {
					 listBox1->Items->Add(f[j]);
				 }
				 DirSearch(d[i]);
			 }
		 }
		 catch (System::Exception* e)
		 {
			 MessageBox::Show(e->Message);
		 }
	 }
The previous code passes a string to the DirSearch function. This string value is the full path of the folder that you want to search. You can use theGetDirectories method to retrieve the subfolders of the folder that is passed into your procedure. Because the GetDirectories method returns an array, you can use a for statement to iterate over each subfolder. For each subfolder, use the GetFiles method to iterate over the files in that folder. The value of the text box on your form is passed to the GetFiles method. The text box contains the search string that filters the results that the GetFiles method returns. When the file matches the search criteria, it is added to your list box. For each subfolder that is located, call the DirSearch function again, and then pass a subfolder. You may use this recursive call to search all subfolders of a root folder that you specify.

Create the Sample

  1. Start Microsoft Visual Studio .NET 2003 or Microsoft Visual Studio 2005.
  2. On the File menu, point to New, and then click Project.
  3. Under Project Types, click Visual C++ .NET.

    Note In Microsoft Visual C++ 2005, Visual C++ .NET is changed to Visual C++.
  4. Under Templates, click Windows Forms Application (.NET).
  5. In the Name box, type RecursiveSearchCPP. In the Locate box, type C:\, and then click OK.
  6. Open the Form1 form in Design view, and then press F4 to open the Properties window.
  7. In the Properties window, expand the Size folder. In the Width field, type 700. In the Height field, type 320.
  8. Add two Label controls, one TextBox control, one ComboBox control, one ListBox control, and one Button control to the Form1 form.
  9. In the Properties window, change the Location, the Size, the TabIndex, and the Text properties as follows:
    Collapse this tableExpand this table
    Control IDLocationSizeTabIndexText
    label18, 16144, 165Search for files that contain:
    textBox18, 40120, 204*.dll
    label28, 96120, 253Look in:
    button1608, 24875, 250&Search
    listBox1152, 8530, 2251
    comboBox18, 128120, 252C:\\
  10. In the InitializeComponent method for the combo box, add the following code to enlist all the network drives that are available on the computer:
    // Enlist all the network drives that are available on the computer.
    String* p_logicalDrives[] = __gc new String*[];
    comboBox1->Items->Clear();
    p_logicalDrives = Directory::GetLogicalDrives();
    int numDrives = p_logicalDrives->get_Length();
    
    for (int i=0; i< numDrives; i++)
    {
    	comboBox1->Items->Add(p_logicalDrives[i]);
    }
  11. Double-click on the Search button, and then paste the following code in the method:
    // Clear the list box.
    listBox1->Items->Clear();
    // You do not have the option to change the values of the files to be searched
    // until the search is completed. Therefore, the following value is false.
    textBox1->Enabled = false;
    comboBox1->Enabled = false;
    
    button1->Text = S"Searching...";
    this->Cursor = Cursors::WaitCursor;
    Application::DoEvents();
    
    // Callthe recursive search method.
    DirSearch(comboBox1->Text);
    button1->Text = S"Search";
    this->Cursor = Cursors::Default;
    
    // After the search is completed, the search criteria is enabled 
    //and you can add other search criteria to search the files recursively.
    textBox1->Enabled = true;
    comboBox1->Enabled = true;
    
  12. To build the application, press CTRL+F5 to build.
  13. Run the application.

Complete Code Sample

// Form1.h
#pragma once

namespace RecursiveSearchCPP
{
	using namespace System;
	using namespace System::ComponentModel;
	using namespace System::Collections;
	using namespace System::Windows::Forms;
	using namespace System::Data;
	using namespace System::Drawing;
	using namespace System::IO;

	/// <summary> 
	/// Summary for Form1
	///
	/// WARNING: If you change the name of this class, you must change the 
	///          Resource File Name property for the managed resource compiler tool 
	///          that is associated with all .resx files that this class depends on.  Otherwise,
	///          the designers will not be able to interact correctly with localized
	///          resources that are associated with this form.
	/// </summary>
	public __gc class Form1 : public System::Windows::Forms::Form
	{	
	public:
		Form1(void)
		{
			InitializeComponent();
		}
  
	protected:
		void Dispose(Boolean disposing)
		{
			// Form::Dispose(Disposing);
			if (disposing && components)
			{
				components->Dispose();
			}
			__super::Dispose(disposing);
		}
	private: System::Windows::Forms::Label *  label1;
	private: System::Windows::Forms::TextBox *  textBox1;
	private: System::Windows::Forms::Label *  label2;
	private: System::Windows::Forms::Button *  button1;
	private: System::Windows::Forms::ListBox *  listBox1;
	private: System::Windows::Forms::ComboBox *  comboBox1;

	private:
		/// <summary>
		/// This is the required designer variable.
		/// </summary>
		System::ComponentModel::Container * components;

		/// <summary>
		/// This is the required method for Designer support. Do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		void InitializeComponent(void)
		{
			this->label1 = new System::Windows::Forms::Label();
			this->textBox1 = new System::Windows::Forms::TextBox();
			this->label2 = new System::Windows::Forms::Label();
			this->button1 = new System::Windows::Forms::Button();
			this->listBox1 = new System::Windows::Forms::ListBox();
			this->comboBox1 = new System::Windows::Forms::ComboBox();
			this->SuspendLayout();
			// 
			// label1
			// 
			this->label1->Location = System::Drawing::Point(8, 16);
			this->label1->Name = S"label1";
			this->label1->Size = System::Drawing::Size(144, 16);
			this->label1->TabIndex = 5;
			this->label1->Text = S"Search for files containing:";
			// 
			// textBox1
			// 
			this->textBox1->Location = System::Drawing::Point(8, 40);
			this->textBox1->Name = S"textBox1";
			this->textBox1->Size = System::Drawing::Size(120, 20);
			this->textBox1->TabIndex = 4;
			this->textBox1->Text = S"*.dll";
			// 
			// label2
			// 
			this->label2->Location = System::Drawing::Point(8, 96);
			this->label2->Name = S"label2";
			this->label2->Size = System::Drawing::Size(120, 23);
			this->label2->TabIndex = 3;
			this->label2->Text = S"Look in:";
			// 
			// button1
			// 
			this->button1->Location = System::Drawing::Point(608, 248);
			this->button1->Name = S"button1";
			this->button1->TabIndex = 0;
			this->button1->Text = S"&Search";
			this->button1->Click += new System::EventHandler(this, button1_Click);
			// 
			// listBox1
			// 
			this->listBox1->Location = System::Drawing::Point(152, 8);
			this->listBox1->Name = S"listBox1";
			this->listBox1->Size = System::Drawing::Size(530, 225);
			this->listBox1->TabIndex = 1;
			// 
			// comboBox1
			//
			// Enlist all the network drives that are available on the computer.
			//
			String* p_logicalDrives[] = __gc new String*[];
			comboBox1->Items->Clear();
			p_logicalDrives = Directory::GetLogicalDrives();
	        int numDrives = p_logicalDrives->get_Length();
			for (int i=0; i< numDrives; i++)
			{
				comboBox1->Items->Add(p_logicalDrives[i]);
			}
			this->comboBox1->Location = System::Drawing::Point(8, 128);
			this->comboBox1->Name = S"comboBox1";
			this->comboBox1->Size = System::Drawing::Size(120, 25);
			this->comboBox1->TabIndex = 2;
			this->comboBox1->Text = S"C:\\";

			// 
			// Form1
			// 
			this->AutoScaleBaseSize = System::Drawing::Size(5, 13);
			this->ClientSize = System::Drawing::Size(688, 286);
			this->Controls->Add(this->comboBox1);
			this->Controls->Add(this->listBox1);
			this->Controls->Add(this->button1);
			this->Controls->Add(this->label2);
			this->Controls->Add(this->textBox1);
			this->Controls->Add(this->label1);
			this->Name = S"Form1";
			this->Text = S"Form1";
			this->ResumeLayout(false);

		}

	private: System::Void button1_Click(System::Object *  sender, System::EventArgs *  e)
	 {
  		//Clears the list box		
  		listBox1->Items->Clear();
  		// You do not have option to change the values of the files to be searched
  		// until the search is completed. Therefore, the value of the following is false.
 	 	textBox1->Enabled = false;
  		comboBox1->Enabled = false;

 	 	button1->Text = S"Searching...";
 		 this->Cursor = Cursors::WaitCursor;
  		Application::DoEvents();

  		// Call the recursive search method.
  		DirSearch(comboBox1->Text);
  		button1->Text = S"Search";
  		this->Cursor = Cursors::Default;
  
  		// After the search is completed, the search criteria is enabled 
  		// and you can add other search criteria to search the files recursively.
  		textBox1->Enabled = true;
  		comboBox1->Enabled = true;
	 }

	 void DirSearch(String* sDir)
	 {
		 try
		 {
			 // Find the subfolders in the folder that is passed in.
			 String* d[] = Directory::GetDirectories(sDir);
			 int numDirs = d->get_Length();
			 
			 for (int i=0; i < numDirs; i++)
			 {
				 // Find all the files in the subfolder.
				 String* f[] = Directory::GetFiles(d[i],textBox1->Text);
				 int numFiles = f->get_Length();

				 for (int j=0; j < numFiles; j++)
				 {
					 listBox1->Items->Add(f[j]);
				 }
				 DirSearch(d[i]);
			 }
		 }
		 catch (System::Exception* e)
		 {
			 System::Console::WriteLine(e->Message);
		 }
	 }
};
}

//Form1.cpp
#include "stdafx.h"
#include "Form1.h"
#include <windows.h>

using namespace RecursiveSearchCPP;

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	System::Threading::Thread::CurrentThread->ApartmentState = System::Threading::ApartmentState::STA;
	Application::Run(new Form1());
	return 0;
}

REFERENCES

For more information about how to create Windows Forms in managed extensions for Visual C++ .NET 2002, see the "ManagedCWinFormWiz" sample in Visual Studio .NET Help.

Properties

Article ID: 307009 - Last Review: August 28, 2007 - Revision: 3.2
APPLIES TO
  • Microsoft Visual C++ 2005 Express Edition
  • Microsoft Visual C++ .NET 2003 Standard Edition
Keywords: 
kbhowtomaster kbio KB307009

Give Feedback

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com