When the program starts, it checks its command line arguments. The first one is always the name of the executing program. If there is a second argument, then it should be the name of a directory dragged onto the executable or sent to the program via the Send To menu so the program enters it in the Directory TextBox.
(To make using this program easy, I added it to my Send To menu. Then I can right-click a directory, open the Send To menu, and select this program to make it search the directory. For more information on adding items to the Send To menu, see Add items to the "Send To" menu.)
When you click the Search button, the program clears its results list, makes a DirectoryInfo object representing the start directory, and calls the ListFiles function.
ListFiles uses the DirectoryInfo object's GetFiles method to get a list of files that match the file pattern. If there is no target string to look for, the program simply adds the files to the result list.
If there is a target string, the program uses System.IO.File.ReadAllText to read the file's contents into a string. If the target is in the file, the program adds the file to the list.
After searching the files in this directory, the program uses the DirectoryInfo object's GetDirectories method to get a list of its subdirectories. The program calls ListFiles recursively to search each subdirectory.
The result isn't as fancy as Windows Explorer's search. You can't search by file date, size, author, rating, or any of the other zillion things you would never want to use in a search.
However, it works and can search any kind of file. It's even a lot faster than Windows' search. Now if Microsoft would just get a clue. Perhaps they can include a working search tool in the next version of Windows.