Como converter um caminho relativo em um caminho absoluto em um aplicativo do Windows?


89

Como faço para converter um caminho relativo em um caminho absoluto em um aplicativo do Windows?

Eu sei que podemos usar server.MapPath () no ASP.NET. Mas o que podemos fazer em um aplicativo do Windows?

Quer dizer, se houver uma função integrada .NET que pode lidar com isso ...


2
Você quer dizer um caminho relativo para o diretório atual, em outras palavras, o diretório de trabalho ou relativo à localização do .exe?
Tobias Hertkorn,

2
Existem dois tipos de caminhos relativos. Um é da forma "A \ B \ C" e não implica uma base particular. O outro tem a forma ". \ A \ B" ou ".. \ A \ B"; aqueles são relativos ao diretório de trabalho atual.
MSalters de

1
@Amit Dhall: A propósito, é bom aceitar e votar positivamente na (s) resposta (s) que o ajudam.
Francis B.

Respostas:


180

Você tentou:

string absolute = Path.GetFullPath(relative);

? Observe que isso usará o diretório de trabalho atual do processo, não o diretório que contém o executável. Se isso não ajudar, esclareça a sua questão.


3
Isso não dependeria de onde você inicia o aplicativo, não dependendo de onde o exe está situado? Concedido, a questão não é muito clara sobre isso.
Tobias Hertkorn,

1
Como você disse, a questão não é clara. GetFullPath resolverá a partir do diretório de trabalho atual. Vou editar minha resposta para indicar isso.
Jon Skeet,

1
Se um aplicativo é iniciado através do Windows Explorer, parece que o diretório atual e o diretório do assembly em execução são os mesmos (pelo menos até que algo seja feito para torná-los diferentes). Isso é verdade mesmo se você usar um atalho para o executável onde o atalho reside em algum lugar completamente diferente.
H2ONaCl

19

Se você deseja obter o caminho relativo ao seu .exe, use

string absolute = Path.Combine(Application.ExecutablePath, relative);

4
Basta ter cuidado com Path.Combine. Se a parte 'relativa' começar com uma barra, ela pode não funcionar como você imagina.
Noon Silk,

2
@silky: bem, então não é relativo, é?
Tor Haugen,

1
Parece Path.Combineque nem consegue lidar com caminhos relativos à unidade. Ele simplesmente ignora o caminho inicial que parece. Estou postando minha própria solução completa.
Nyerguds

3
Isso não pode lidar com um caminho relativo. Ele só aceita um diretório e um nome de arquivo. Se o segundo argumento começar com algo semelhante .., ele produzirá lixo.
Jonathan Wood

1
@JonathanWood Na verdade, esse "lixo" (caminhos que os incluem ..) é perfeitamente aceito e resolvido por todos os sistemas de manipulação de arquivos em .Net. Se isso o incomoda, execute absolute = Path.GetFullPath(absolute)-o.
Nyerguds

16

Este funciona para caminhos em unidades diferentes, para caminhos relativos à unidade e para caminhos relativos reais. Caramba, até funciona se o basePathnão for absoluto; ele sempre usa o diretório de trabalho atual como fallback 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);
}

1
Ótima solução porque combina o caminho absoluto ou relativo de acordo com um caminho base. Na minha opinião, o argumento relativePath deve ser renomeado para AbsoluteOrRelativePath, uma vez que é o que realmente representa. Obrigado
Julio Nobre

1
Bem, se já é um caminho absoluto, isso é apenas um caso especial, sério ... a função ainda serve para resolver caminhos relativos, lol. Acabei de
nomeá-

1
@JulioNobre especialmente porque os argumentos aqui são invertidos em comparação com Path.Combine. Isso é facilmente corrigido, mas eu o evito, já que geralmente o uso para resolver caminhos relativos no diretório de trabalho, e dar null como primeiro argumento parece estranho.
Nyerguds

1
Agradeço seu conselho, mas pretendo usar esse auxiliar apenas quando precisar combinar um caminho de base com outro caminho que pode ser relativo a esse caminho de base ou absoluto. É por isso que preferi adotar a seguinte assinatura: GetAbsolutePath (String BasePath, String RelativeOrAbsolutePath). Se algum argumento for nulo, uma exceção é levantada para reforçar que ambos são obrigatórios para usar este método. Mais uma vez, obrigado :-)
Julio Nobre

2
Sim, isso é sensato. Não posso ser incomodado em editar isso apenas para manipular alguns argumentos.
Nyerguds

2

É um assunto um pouco mais antigo, mas pode ser útil para alguém. Resolvi um problema semelhante, mas, no meu caso, o caminho não estava no início do texto.

Então aqui está minha solução:

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;
    }
}

Exemplo:

Data Source=.\Data\Data.sdf;Persist Security Info=False;
Data Source=..\..\bin\Debug\Data\Data.sdf;Persist Security Info=False;

1
Hum. Você está reinventando a roda. Path.GetFullPathresolve. \ e .. \ automaticamente. Além disso, você está adicionando a AbsolutePathfunção de extensão à classe String em geral ... pode ser um pouco exagero.
Nyerguds

1
Estou errado ao dizer que Path.GetFullPath sempre considera o diretório base como o diretório atual do AppDomain do aplicativo. Nesse caso, Path.GetFullPath não pode retornar o caminho completo de um diretório diferente. O algoritmo a seguir, no entanto, leva isso em consideração ... Quer dizer, você apenas tem que adicionar outro parâmetro opcional que seria uma substituição de CurrentDomainDirectory.
Samuel
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.