![]() |
Versión:
Biblioteca multiproceso escrita en C# que permite encontrar archivos de forma recursiva mediante patrones o delegados personalizados, con métodos estáticos y API basada en eventos. |
- Búsqueda recursiva de archivos por patrón (
*.txt) o por delegadoFunc<FileInfo, bool> - Métodos estáticos síncronos y asíncronos (
GetFiles,GetFilesFast,GetFilesFastAsync) - API por instancia con eventos (
FilesFound,SearchCompleted) y cancelación - Búsqueda en varias carpetas con
FileSearchMultiple - Paralelismo mediante pool de hilos (
GetFilesFast*,StartSearchAsync) - Compatible con Windows XP y superior (.NET Framework 4.0)
- Las excepciones
UnauthorizedAccessExceptionse suprimen durante el recorrido
- .NET Framework 4.0 o superior
- Windows XP o posterior
- Visual Studio 2015+ (requerido por
nameofen validaciones; recomendado VS 2019/2022)
Requiere Windows, Visual Studio (o Build Tools) con soporte para .NET Framework 4.0 y NuGet.
Salida: NETFastSearchLibrary\bin\Release\NETFastSearchLibrary.dll (+ .XML de documentación).
Nota — firma y NuGet: Los builds locales no están firmados. CI firma el DLL con strong name (
PublicKeyTokena8ab9e59c05f5f54). El.nupkgse publica sin Author Signing; nuget.org aplica Repository Signing. La confianza viene del paquete en nuget.org publicado por tu cuenta, no de compilar un fork.
nuget restore NETFastSearchLibrary.sln
msbuild NETFastSearchLibrary.sln /p:Configuration=Release /p:Platform="Any CPU"
msbuild NETFastSearchLibrary.sln /p:Configuration=Release /p:Platform="Any CPU" /p:OfficialBuild=true
Requiere NETFastSearchLibrary/EMZApps.snk (clave en secreto de CI, no versionada).
Install-Package NETFastSearchLibrary.Legacy
Paquete firmado por el autor (Authenticode) y publicado desde CI oficial en nuget.org.
Si el paquete aún no está publicado, use Releases o compilación manual mientras tanto.
- Descargue la última versión desde Releases o compile la solución.
- Copie
NETFastSearchLibrary.dllen su proyecto. - Agregue la referencia: Explorador de soluciones → clic derecho en Referencias → Agregar referencia → Examinar.
- Establezca la plataforma de destino en .NET Framework 4.0 como mínimo.
- Agregue al inicio del archivo:
using NETFastSearchLibrary;| Miembro | Descripción |
|---|---|
GetFiles(folder, pattern) |
Búsqueda recursiva en un hilo |
GetFiles(folder, isValid) |
Búsqueda con delegado en un hilo |
GetFilesFast(...) |
Búsqueda paralela (pool de hilos) |
GetFilesFastAsync(...) |
Variante asíncrona |
StartSearch() / StartSearchAsync() |
Búsqueda con eventos en tiempo real |
StopSearch() |
Detiene la búsqueda activa |
Constructores de instancia aceptan patrón o delegado, opcionalmente CancellationTokenSource, ExecuteHandlers y suppressOperationCanceledException.
Igual que FileSearch, pero el constructor recibe List<string> de carpetas raíz.
| Valor | Comportamiento |
|---|---|
InCurrentTask |
Los manejadores de FilesFound se ejecutan en la tarea que encontró los archivos |
InNewTask |
Los manejadores se ejecutan en una tarea nueva |
using System.Collections.Generic;
using System.IO;
using NETFastSearchLibrary;
// Un hilo — devuelve la lista al terminar
List<FileInfo> files = FileSearch.GetFiles(@"C:\Users", "*.txt");
// Varios hilos — más rápido en procesadores multinúcleo
List<FileInfo> fast = FileSearch.GetFilesFast(@"C:\Users", "*SomePattern*.txt");
// Asíncrono
Task<List<FileInfo>> task = FileSearch.GetFilesFastAsync(@"C:\", "a?.txt");using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using NETFastSearchLibrary;
Task<List<FileInfo>> task = FileSearch.GetFilesFastAsync(@"D:\", (f) =>
{
return (f.Name.Contains("Pattern") || f.Name.Contains("Pattern2")) &&
f.LastAccessTime >= new DateTime(2018, 3, 1) && f.Length > 1073741824;
});
// Con expresión regular
Task<List<FileInfo>> mp3 = FileSearch.GetFilesFastAsync(@"D:\", (f) =>
Regex.IsMatch(f.Name, @".*Imagine[\s_-]Dragons.*\.mp3$"));using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading;
using NETFastSearchLibrary;
class Searcher
{
private static readonly object locker = new object();
private FileSearch searcher;
private List<FileInfo> files;
public Searcher()
{
files = new List<FileInfo>();
}
public void StartSearch()
{
CancellationTokenSource tokenSource = new CancellationTokenSource();
searcher = new FileSearch(@"C:\", (f) =>
Regex.IsMatch(f.Name, @".*[iI]magine[\s_-][dD]ragons.*\.mp3$"),
tokenSource);
searcher.FilesFound += (sender, arg) =>
{
lock (locker)
{
arg.Files.ForEach(f =>
{
files.Add(f);
Console.WriteLine("File: {0}", f.FullName);
});
if (files.Count >= 10)
searcher.StopSearch();
}
};
searcher.SearchCompleted += (sender, arg) =>
{
Console.WriteLine(arg.IsCanceled ? "Search stopped." : "Search completed.");
Console.WriteLine("Quantity: {0}", files.Count);
};
searcher.StartSearchAsync();
}
}Los manejadores de
FilesFoundno son thread-safe. Uselocko colecciones deSystem.Collections.Concurrent.
using System.Collections.Generic;
using System.IO;
using System.Threading;
using NETFastSearchLibrary;
List<string> folders = new List<string>
{
@"C:\Users\Public",
@"C:\Windows\System32",
@"D:\Program Files"
};
FileSearchMultiple multiple = new FileSearchMultiple(folders, (f) =>
f.Extension == ".cs" && f.Name.Contains("Program"),
new CancellationTokenSource());
multiple.FilesFound += (s, e) => { /* ... */ };
multiple.StartSearchAsync();FileSearch searcher = new FileSearch(
@"D:\Program Files",
(f) => Regex.IsMatch(f.Name, @".{1,5}[Ss]ome[Pp]attern\.txt$") && f.Length >= 8192,
tokenSource,
ExecuteHandlers.InNewTask,
suppressOperationCanceledException: true);| Limitación | Detalle |
|---|---|
| Solo archivos | No incluye búsqueda de directorios (DirectorySearch no está en esta versión) |
| Solo Windows | Requiere .NET Framework 4.0; no corre en Linux/macOS |
| Rutas largas | En Windows, habilite LongPathsEnabled en el registro (HKLM\...\FileSystem) |
InNewTask |
Las excepciones no se propagan al hilo llamador; use SearchCompleted |
| Sin pausa | No hay PauseSearch/ResumeSearch (disponible en NetcoreFSL) |
| Junctions / symlinks | Se detectan ciclos por ruta canónica visitada; enlaces pueden listar el mismo destino una vez |
Si su proyecto puede usar .NET 8, considere migrar a NetcoreFSL:
Legacy (FileSearch) |
NetcoreFSL (FSL) |
|---|---|
GetFilesFast(folder, pattern) |
new FSL(...); fsl.FileSearch(); + evento FilesFound |
Func<FileInfo, bool> |
No disponible — solo patrones |
FileSearchMultiple |
Una instancia FSL por carpeta |
StopSearch() |
CancelSearch() |
| — | FolderSearch(), PauseSearch(), multiplataforma |
Documentación detallada: docs/CI.md.
El workflow .github/workflows/release.yml se ejecuta al pushear un tag v*.*.* (ej. v1.0.5):
- Compila Release con strong name (
OfficialBuild=true) - Empaqueta
NETFastSearchLibrary.Legacy.nuspec - Publica en nuget.org vía Trusted Publishing (OIDC, sin API key permanente)
- Crea GitHub Release con assets
Author Signing (certificado Authenticode) es opcional: si agregás NUGET_SIGN_CERT_PFX y NUGET_SIGN_CERT_PASSWORD en GitHub, el workflow firmará el .nupkg automáticamente.
| Secreto | Obligatorio | Descripción |
|---|---|---|
NUGET_USER |
Sí | Username nuget.org de quien creó la política Trusted Publishing |
EMZAPPS_SNK |
Sí | EMZApps.snk en base64 |
NUGET_SIGN_CERT_PFX |
No | .pfx Authenticode en base64 (futuro Author Signing) |
NUGET_SIGN_CERT_PASSWORD |
No | Contraseña del .pfx |
Crear environment: repo → Settings → Environments → New environment → nuget-publish.
Exportar EMZAPPS_SNK:
./scripts/build-dist.sh --export-snk-base64nuget.org → cuenta → Trusted Publishing → política con:
| Campo | Valor |
|---|---|
| Package owner | alanjmrt94 |
| Repository Owner | alanjmrt94 |
| Repository | NETFastSearchLibrary |
| Workflow File | release.yml |
| Environment | nuget-publish |
No hace falta API Key ni certificado registrado para publicar (Repository Signing automático en nuget.org).
Opción A — GitHub Actions (recomendado): actualizar versión en AssemblyInfo.cs, commitear, luego:
git tag -a v1.0.5 -m "Release v1.0.5"
git push origin v1.0.5Opción B — Script local + CI: compila/empaqueta localmente, crea tag y GitHub Release; NuGet lo publica CI al recibir el tag.
Windows:
.\scripts\release.ps1 -Version 1.0.5Linux:
./scripts/build-dist.sh --release 1.0.5Solo artefactos en dist/ (sin tag ni NuGet):
.\scripts\release.ps1 -Version 1.0.5 -DistOnlySalida: dist/<version>/ con DLL, XML, .nupkg y metadatos.
NETFastSearchLibrary/
├── .github/workflows/ # CI (unsigned) y Release (firmado + NuGet OIDC)
├── docs/CI.md # GitHub Actions, Trusted Publishing, troubleshooting
├── scripts/ # release.ps1 (Windows), build-dist.sh (Linux)
├── NETFastSearchLibrary/ # Biblioteca (.NET Framework 4.0)
│ ├── fsl.ico # Icono del ensamblado
│ ├── NETFastSearchLibrary.Legacy.nuspec
│ └── FileSearch/ # Clases de búsqueda
├── logo_base.png # Logo para documentación
├── LICENSE # MIT
├── CHANGELOG.md
└── README.md
La versión se define en NETFastSearchLibrary/Properties/AssemblyInfo.cs:
AssemblyVersion:1.0.5.0AssemblyInformationalVersion:1.0.5 (.NET Framework 4.0, Legacy)
MIT — Copyright (c) 2021-2026 alanjmrt94 (EMZ Apps)
