Come convertire un percorso relativo in un percorso assoluto in un'applicazione Windows?


92

Come si converte un percorso relativo in un percorso assoluto in un'applicazione Windows?

So che possiamo usare server.MapPath () in ASP.NET. Ma cosa possiamo fare in un'applicazione Windows?

Voglio dire, se esiste una funzione integrata .NET in grado di gestirlo ...


2
Intendi un percorso relativo alla directory corrente, in altre parole la directory di lavoro, o relativo alla posizione del file .exe?
Tobias Hertkorn,

2
Esistono due tipi di percorsi relativi. Uno se della forma "A \ B \ C" e non implica una base particolare. L'altro ha la forma ". \ A \ B" o ".. \ A \ B"; quelli sono relativi alla directory di lavoro corrente.
MSalters

1
@Amit Dhall: A proposito, è una buona cosa accettare e dare un voto positivo alle risposte che ti aiutano.
Francis B.

Risposte:


184

Hai provato:

string absolute = Path.GetFullPath(relative);

? Notare che ciò utilizzerà la directory di lavoro corrente del processo, non la directory contenente l'eseguibile. Se ciò non aiuta, chiarisci la tua domanda.


4
Non dipende da dove avvii l'app, non da dove si trova l'exe? Certo, la domanda non è davvero chiara su questo.
Tobias Hertkorn,

1
Come dici tu, la domanda non è chiara. GetFullPath verrà risolto dalla directory di lavoro corrente. Modificherò la mia risposta per indicarlo.
Jon Skeet,

1
Se un'applicazione viene avviata tramite Windows Explorer, sembra che la directory corrente e la directory dell'assembly in esecuzione siano le stesse (almeno fino a quando non viene fatto qualcosa per renderle diverse). Questo è vero anche se si utilizza una scorciatoia per l'eseguibile in cui la scorciatoia risiede da qualche parte completamente diversa.
H2ONaCl

19

Se vuoi ottenere il percorso relativo al tuo .exe, usa

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

4
Fai solo attenzione con Path.Combine. Se la parte "relativa" inizia con una barra, potrebbe non fare quello che pensi.
Noon Silk

2
@silky: beh, allora non è relativo, vero?
Tor Haugen

1
Sembra Path.Combinenon possa nemmeno gestire i percorsi relativi all'unità. Ignora semplicemente il percorso iniziale che sembra. Sto postando la mia soluzione completa.
Nyerguds

3
Questo non può gestire un percorso relativo. Accetta solo una directory e un nome file. Se il secondo argomento inizia con qualcosa di simile .., produrrà spazzatura.
Jonathan Wood,

1
@JonathanWood In realtà, quella "spazzatura" (percorsi che includono ..in essi) è perfettamente accettata e risolta da tutti i sistemi di manipolazione dei file in .Net. Se ti dà fastidio, eseguilo absolute = Path.GetFullPath(absolute).
Nyerguds

15

Questo funziona per percorsi su unità diverse, per percorsi relativi a unità e per percorsi relativi effettivi. Diamine, funziona anche se basePathnon è effettivamente assoluto; usa sempre la directory di lavoro corrente come fallback finale.

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
Ottima soluzione perché combina percorso assoluto o relativo secondo un percorso di base. A mio parere, l'argomento relativePath dovrebbe essere rinominato in AbsoluteOrRelativePath, poiché è ciò che rappresenta realmente. Grazie
Julio Nobre

1
Bene, se è già un percorso assoluto, è solo un caso speciale, davvero ... la funzione è ancora pensata per risolvere percorsi relativi, lol. L'ho appena chiamato così qui per chiarire quale parametro è quale;)
Nyerguds

1
@ JulioNobre soprattutto perché gli argomenti qui sono invertiti rispetto a Path.Combine. È facilmente risolvibile, ma lo evito poiché lo uso spesso per risolvere i percorsi relativi sulla directory di lavoro e dare null come primo arg sembra strano.
Nyerguds

1
Apprezzo il tuo consiglio, ma intendo usare questo aiuto solo quando ho bisogno di combinare un percorso di base con un altro percorso che può essere relativo a quel percorso di base o assoluto. Ecco perché ho preferito adottare la seguente firma: GetAbsolutePath (String BasePath, String RelativeOrAbsolutePath). Se un argomento è nullo, viene sollevata un'eccezione per confermare che entrambi sono obbligatori per utilizzare questo metodo. Ancora una volta, grazie :-)
Julio Nobre

2
Sì, è ragionevole. Non posso essere disturbato a modificare questo solo per destreggiarsi tra qualche discussione.
Nyerguds

1

È un argomento un po 'più vecchio, ma potrebbe essere utile per qualcuno. Ho risolto un problema simile, ma nel mio caso il percorso non era all'inizio del testo.

Quindi ecco la mia soluzione:

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

Esempio:

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

1
Um. Stai reinventando la ruota. Path.GetFullPathrisolve. \ e .. \ automaticamente. Inoltre, stai aggiungendo la AbsolutePathfunzione di estensione alla classe String in generale ... potrebbe essere un po 'eccessivo.
Nyerguds

1
Sbaglio dicendo che Path.GetFullPath considera sempre la directory di base come la directory corrente dell'AppDomain dell'applicazione. In questo caso, Path.GetFullPath non è in grado di restituire il percorso completo da una directory diversa. Il seguente algoritmo, tuttavia, prende in considerazione questo ... Voglio dire, devi solo aggiungere un altro parametro opzionale che sarebbe una sostituzione di CurrentDomainDirectory.
Samuel,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.