¿Cómo convertir una ruta relativa en una ruta absoluta en una aplicación de Windows?

90

¿Cómo convierto una ruta relativa en una ruta absoluta en una aplicación de Windows?

Sé que podemos usar server.MapPath () en ASP.NET. Pero, ¿qué podemos hacer en una aplicación de Windows?

Quiero decir, si hay una función incorporada de .NET que puede manejar eso ...

Amit Dhall
fuente
2
¿Se refiere a una ruta relativa al directorio actual, en otras palabras, al directorio de trabajo, o relativa a la ubicación del .exe?
Tobias Hertkorn
2
Hay dos tipos de rutas relativas. Uno si tiene la forma "A \ B \ C" y no implica una base en particular. El otro tiene la forma ". \ A \ B" o ".. \ A \ B"; esos son relativos al directorio de trabajo actual.
MSalters
1
@Amit Dhall: Por cierto, es bueno aceptar y votar las respuestas que te ayuden.
Francis B.

Respuestas:

183

Has probado:

string absolute = Path.GetFullPath(relative);

? Tenga en cuenta que utilizará el directorio de trabajo actual del proceso, no el directorio que contiene el ejecutable. Si eso no ayuda, aclare su pregunta.

Jon Skeet
fuente
4
¿No dependería de dónde inicie la aplicación, ni de dónde se encuentre el exe? De acuerdo, la pregunta no es muy clara al respecto.
Tobias Hertkorn
1
Como dices, la pregunta no está clara. GetFullPath se resolverá desde el directorio de trabajo actual. Editaré mi respuesta para indicar esto.
Jon Skeet
1
Si se inicia una aplicación a través del Explorador de Windows, parece que el directorio actual y el directorio del ensamblaje en ejecución son los mismos (al menos hasta que se haga algo para que sean diferentes). Esto es cierto incluso si usa un atajo al ejecutable donde el atajo reside en un lugar completamente diferente.
H2ONaCl
19

Si desea obtener la ruta relativa a su .exe, use

string absolute = Path.Combine(Application.ExecutablePath, relative);
Tobias Hertkorn
fuente
4
Solo ten cuidado con Path.Combine. Si la parte 'relativa' comienza con una barra, es posible que no haga lo que cree que haría.
Mediodía Silk
2
@silky: bueno, entonces no es relativo, ¿verdad?
Tor Haugen
1
Parece Path.Combineque ni siquiera puede manejar rutas relativas a la unidad. Simplemente ignora la ruta inicial que parece. Estoy publicando mi propia solución completa.
Nyerguds
3
Esto no puede manejar una ruta relativa. Solo acepta un directorio y un nombre de archivo. Si el segundo argumento comienza con algo parecido .., producirá basura.
Jonathan Wood
1
@JonathanWood En realidad, esa "basura" (rutas que las incluyen ..) es perfectamente aceptada y resuelta por todos los sistemas de manipulación de archivos en .Net. Si le molesta, ejecútelo absolute = Path.GetFullPath(absolute).
Nyerguds
15

Este funciona para rutas en diferentes unidades, para rutas relativas a unidades y para rutas relativas reales. Diablos, incluso funciona si basePathno es realmente absoluto; siempre usa el directorio de trabajo actual como respaldo final.

public static String GetAbsolutePath(String path)
{
    return GetAbsolutePath(null, path);
}

public static String GetAbsolutePath(String basePath, String path)
{
    if (path == null)
        return null;
    if (basePath == null)
        basePath = Path.GetFullPath("."); // quick way of getting current working directory
    else
        basePath = GetAbsolutePath(null, basePath); // to be REALLY sure ;)
    String finalPath;
    // specific for windows paths starting on \ - they need the drive added to them.
    // I constructed this piece like this for possible Mono support.
    if (!Path.IsPathRooted(path) || "\\".Equals(Path.GetPathRoot(path)))
    {
        if (path.StartsWith(Path.DirectorySeparatorChar.ToString()))
            finalPath = Path.Combine(Path.GetPathRoot(basePath), path.TrimStart(Path.DirectorySeparatorChar));
        else
            finalPath = Path.Combine(basePath, path);
    }
    else
        finalPath = path;
    // resolves any internal "..\" to get the true full path.
    return Path.GetFullPath(finalPath);
}
Nyerguds
fuente
1
Gran solución porque combina la ruta absoluta o relativa de acuerdo con una ruta base. En mi opinión, el argumento relativoPath debería cambiarse a AbsoluteOrRelativePath, ya que es lo que realmente representa. Gracias
Julio Nobre
1
Bueno, si ya es una ruta absoluta, es solo un caso especial, de verdad ... la función todavía está destinada a resolver rutas relativas, jajaja. Lo nombré así aquí para dejar en claro qué parámetro es cuál;)
Nyerguds
1
@JulioNobre especialmente porque los argumentos aquí se invierten en comparación con Path.Combine. Eso se soluciona fácilmente, pero lo evito ya que a menudo lo uso para resolver rutas relativas en el directorio de trabajo, y dar un valor nulo como primer argumento parece extraño.
Nyerguds
1
Aprecio su consejo, pero solo intento usar este ayudante cuando necesito combinar una ruta base con otra ruta que puede ser relativa a esa ruta base o absoluta. Por eso he preferido adoptar la siguiente firma: GetAbsolutePath (String BasePath, String RelativeOrAbsolutePath). Si algún argumento es nulo, se genera una excepción para reforzar que ambos son obligatorios para usar este método. Nuevamente, gracias :-)
Julio Nobre
2
Sí, eso es sensato. Sin embargo, no puedo molestarme en editar esto solo para hacer malabares con algunos argumentos.
Nyerguds
1

Es un tema un poco más antiguo, pero podría ser útil para alguien. He resuelto un problema similar, pero en mi caso, la ruta no estaba al principio del texto.

Entonces aquí está mi solución:

public static class StringExtension
{
    private const string parentSymbol = "..\\";
    private const string absoluteSymbol = ".\\";
    public static String AbsolutePath(this string relativePath)
    {
        string replacePath = AppDomain.CurrentDomain.BaseDirectory;
        int parentStart = relativePath.IndexOf(parentSymbol);
        int absoluteStart = relativePath.IndexOf(absoluteSymbol);
        if (parentStart >= 0)
        {
            int parentLength = 0;
            while (relativePath.Substring(parentStart + parentLength).Contains(parentSymbol))
            {
                replacePath = new DirectoryInfo(replacePath).Parent.FullName;
                parentLength = parentLength + parentSymbol.Length;
            };
            relativePath = relativePath.Replace(relativePath.Substring(parentStart, parentLength), string.Format("{0}\\", replacePath));
        }
        else if (absoluteStart >= 0)
        {
            relativePath = relativePath.Replace(".\\", replacePath);
        }
        return relativePath;
    }
}

Ejemplo:

Data Source=.\Data\Data.sdf;Persist Security Info=False;
Data Source=..\..\bin\Debug\Data\Data.sdf;Persist Security Info=False;
vesi
fuente
1
Um. Estás reinventando la rueda. Path.GetFullPathresuelve. \ y .. \ automáticamente. Además, está agregando la AbsolutePathfunción de extensión a la clase String en general ... puede ser un poco exagerado.
Nyerguds
1
¿Me equivoco al decir que Path.GetFullPath siempre considera el directorio base como el directorio actual del AppDomain de la aplicación? En este caso, Path.GetFullPath no puede devolver la ruta completa desde un directorio diferente. El siguiente algoritmo, sin embargo, toma esto en consideración ... Quiero decir, solo tiene que agregar otro parámetro opcional que reemplazaría el CurrentDomainDirectory.
Samuel