You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
MockPath.GetFullPath does not match windows behavior. #1044
Describe the bug
In a special case of a rooted, but not absolute path, MockPath.GetFullPath produces results which differ from what i get using System.IO.Path.GetFullPath
changed the title [-]MockPath.GetFullPath does does not match windows behavior. [/-][+]MockPath.GetFullPath does not match windows behavior. [/+]on Oct 8, 2023
Some additional that might help fixing this issue:
In Windows (with DOS origins) there is a current directory per drive letter which was/is super handy when working on the command-line, e.g.
C:
CD\Source
D:
CD\Target
E:
DIR C:
DIR D:
XCOPY C:*.* D: /S
which translates to
Set the current drive to C:
Set the current folder on C: to C:\Source
Set the current drive to D:
Set the current folder on D: to D:\Target
Set the current drive to E: (just for the sake of this demo)
List the content of the current folder on C:
List the content of the current folder on D:
Copy everything from the current folder on C: to the current folder on D: (recursively)
The current folder per drive letter is stored in environment variables that are hidden by .NET and that are called =<drive letter>: (e.g. =C:, =D:).
They can be retrieved by using the following sample code:
[STAThread]
internal static void Main(string[] args) {
Dictionary<string, string> variablePairs = GetCurrentFolderPerDriveLetter();
Console.WriteLine($"You have {variablePairs.Count} folders per drive letter set:");
foreach (KeyValuePair<string, string> pair in variablePairs.OrderBy(e => e.Key)) {
Console.WriteLine($"{pair.Key}: {pair.Value}");
}
}
public static Dictionary<string, string> GetCurrentFolderPerDriveLetter() {
List<string> environmentVariablePairs = GetEnvironmentVariablePairs();
Dictionary<string, string> result = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (string variablePair in environmentVariablePairs) {
int equalSign = variablePair.LastIndexOf('=');
if (equalSign != 3) continue;
string key = variablePair.Substring(0, equalSign);
if (key[0] != '=') continue;
if (key[2] != ':') continue;
if (key[1] == ':') continue;
key = key[1].ToString();
string value = variablePair.Substring(equalSign + 1);
result[key] = value;
}
return result;
}
public static Dictionary<string, string> GetUnfilteredEnvironmentVariables() {
List<string> environmentVariablePairs = GetEnvironmentVariablePairs();
Dictionary<string, string> result = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (string variablePair in environmentVariablePairs) {
int equalSign = variablePair.LastIndexOf('=');
if (equalSign < -1) continue;
string key = variablePair.Substring(0, equalSign);
string value = variablePair.Substring(equalSign + 1);
result[key] = value;
}
return result;
}
private static unsafe List<string> GetEnvironmentVariablePairs() {
char* envStrings = Win32Native.GetEnvironmentStrings();
if (envStrings is null) {
return [];
}
List<string> result = [];
try {
// Iterate through the environment strings (null-terminated pairs)
char* current = envStrings;
while (*current != '\0') {
string envVar = new string(current);
result.Add(envVar);
current += envVar.Length + 1; // Move to the next string
}
} finally {
// Free the allocated memory
Win32Native.FreeEnvironmentStrings(envStrings);
}
return result;
}
private static class Win32Native {
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
[ResourceExposure(ResourceScope.Machine)]
internal static unsafe extern char* GetEnvironmentStrings();
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
[ResourceExposure(ResourceScope.Machine)]
internal static unsafe extern bool FreeEnvironmentStrings(char* pStrings);
}
Usually there is no current directory per drive letter set when not working on the command-line, to see a result, start your development environment from the command-line after changing into some folders on different drives first.
Activity
[-]MockPath.GetFullPath does does not match windows behavior. [/-][+]MockPath.GetFullPath does not match windows behavior. [/+]vbreuss commentedon Oct 9, 2023
@AnakinRaW :
Are you sure, your test is correct?
The provided input
"d:test.txt"is no valid (rooted) path. Maybe it should be@"d:\test.txt"instead?AnakinRaW commentedon Oct 9, 2023
i'm sure my test is correct. even microsoft documented this case in their code comments:
https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/IO/Path.cs#L297
vbreuss commentedon Oct 10, 2023
Thanks for the clarification, @AnakinRaW !
I was not aware of this format, but after looking around, it is also documented in the File path formats on Windows systems :-)
fgreinacher commentedon Oct 10, 2023
Wow, what a fancy feature.
fix: support relative path with drive information in `Path.GetFullPat…
oni-shiro commentedon Apr 23, 2025
Hey is this issue fixed? Then we can close it out.
vbreuss commentedon Apr 23, 2025
@oni-shiro : No, this issue is not yet fixed; only on Testably.Abstractions.
HugoRoss commentedon Aug 19, 2025
Some additional that might help fixing this issue:
In Windows (with DOS origins) there is a current directory per drive letter which was/is super handy when working on the command-line, e.g.
which translates to
The current folder per drive letter is stored in environment variables that are hidden by .NET and that are called
=<drive letter>:(e.g.=C:,=D:).They can be retrieved by using the following sample code:
Usually there is no current directory per drive letter set when not working on the command-line, to see a result, start your development environment from the command-line after changing into some folders on different drives first.