info - libreria system.io en c#
Compruebe si existe un archivo ejecutable en la ruta de Windows (5)
Si ejecuto un proceso con ShellExecute
(o en .net con System.Diagnostics.Process.Start()
), el proceso del nombre del archivo para iniciar no necesita ser una ruta completa.
Si quiero iniciar el bloc de notas, puedo usar
Process.Start("notepad.exe");
en lugar de
Process.Start(@"c:/windows/system32/notepad.exe");
porque el directorio c:/windows/system32
es parte de la variable de entorno PATH.
¿Cómo puedo verificar si existe un archivo en la RUTA sin ejecutar el proceso y sin analizar la variable PATH?
System.IO.File.Exists("notepad.exe"); // returns false
(new System.IO.FileInfo("notepad.exe")).Exists; // returns false
pero necesito algo como esto:
System.IO.File.ExistsOnPath("notepad.exe"); // should return true
y
System.IO.File.GetFullPath("notepad.exe"); // (like unix which cmd) should return
// c:/windows/system32/notepad.exe
¿Hay una clase predefinida para hacer esta tarea disponible en el BCL?
Creo que no hay nada incorporado, pero podrías hacer algo como esto con System.IO.File.Exists :
public static bool ExistsOnPath(string fileName)
{
return GetFullPath(fileName) != null;
}
public static string GetFullPath(string fileName)
{
if (File.Exists(fileName))
return Path.GetFullPath(fileName);
var values = Environment.GetEnvironmentVariable("PATH");
foreach (var path in values.Split('';''))
{
var fullPath = Path.Combine(path, fileName);
if (File.Exists(fullPath))
return fullPath;
}
return null;
}
Esto es arriesgado, hay mucho más que simplemente buscar en los directorios en el PATH. Prueba esto:
Process.Start("wordpad.exe");
El ejecutable se almacena en c: / Archivos de programa / Windows NT / Accessories en mi máquina, ese directorio no está en la ruta.
Las teclas HKCR / Applications y HKLM / SOFTWARE / Microsoft / Windows / CurrentVersion / App Paths también desempeñan un papel en la búsqueda de ejecutables. Estoy bastante seguro de que hay más minas terrestres como esta, la virtualización de directorios en versiones de 64 bits de Windows podría hacer que te tropieces, por ejemplo.
Para que esto sea más confiable, creo que necesitas pinvoke AssocQueryString (). No estoy seguro, nunca tuve la necesidad. El mejor enfoque es sin duda no tener que hacer la pregunta.
La respuesta aceptada establece que no hay nada incorporado, pero esto no es cierto. Existe un PathFindOnPath WinAPI estándar para hacer esto, está disponible desde Windows 2000.
Ok, una mejor manera de pensar ...
Utiliza el comando where , que está disponible al menos en Windows 7 / Server 2003:
public static bool ExistsOnPath(string exeName)
{
try
{
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.FileName = "where";
p.StartInfo.Arguments = exeName;
p.Start();
p.WaitForExit();
return p.ExitCode == 0;
}
catch(Win32Exception)
{
throw new Exception("''where'' command is not on path");
}
}
public static string GetFullPath(string exeName)
{
try
{
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.FileName = "where";
p.StartInfo.Arguments = exeName;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
if (p.ExitCode != 0)
return null;
// just return first match
return output.Substring(0, output.IndexOf(Environment.NewLine));
}
catch(Win32Exception)
{
throw new Exception("''where'' command is not on path");
}
}
Persigo la misma cosa y creo que la mejor opción que tengo ahora es usar llamadas nativas a CreateProcess para crear un proceso suspendido y mirar hacia el éxito; terminando el proceso inmediatamente después. Terminar un proceso suspendido no debe incurrir en ningún recurso sangrado [citación necesaria :)]
Puede que no sea capaz de descubrir la ruta que realmente se usó, sino un simple requerimiento como ExistsOnPath (), hasta que haya una solución mejor.