Notice: This website is an unofficial Microsoft Knowledge Base (hereinafter KB) archive and is intended to provide a reliable access to deleted content from Microsoft KB. All KB articles are owned by Microsoft Corporation. Read full disclaimer for more details.

How to recursively search folders by using Visual C++


For a Microsoft Visual Basic .NET version of this article, see
306666 .
For a Microsoft C# .NET version of this article, see
303974 .

This article refers to the following Microsoft .NET Framework Class Library namespaces:
  • System.IO
  • System.ComponentModel
  • System.Windows.Forms
  • System.Drawing

IN THIS TASK

↑ Back to the top


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.

Back to the top

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
Back to the top

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.

Back to the top

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 Locatebox, 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:
    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.
Back to the top

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;
}
Back to the top

↑ Back to the top


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.

Back to the top

↑ Back to the top


Keywords: kbvcpp2005rtmsweep, kbvcpp2005rtmapplies, kbwiprotr, kbwiproauthor, kbhowtomaster, kbio, kb

↑ Back to the top

Article Info
Article ID : 307009
Revision : 6
Created on : 6/10/2019
Published on : 6/10/2019
Exists online : False
Views : 1820