The simplest way to resolve a relative and/or non-normalized path (one with components such as .. and .) to a normalized full path, directly as a string, is to use the Convert-Path cmdlet:
Convert-Path -LiteralPath "C:\Folder\..\Folder2"
In the context of your command (note that Add-Content appends to a preexisting target file; to write the given content only, use Set-Content):
Add-Content "d:\textfile.txt" (Convert-Path -LiteralPath "C:\Folder\..\Folder2")
Note:
Unlike Resolve-Path, Convert-Path returns a file-system-native path, which is generally preferable.
- This means that file-system paths that are based on PowerShell-only drives (created with
New-PSDrive) are resolved to the underlying native file-system location, as understood by outside processes too. (E.g., if MyDrive: is mapped to C:\Projects, Convert-Path -LiteralPath MyDrive:\Foo returns C:\Projects\Foo)
Like Resolve-Path, Convert-Path requires that the item the path refers to exist - which is an unfortunate limitation, discussed in GitHub issue #2993.
If the input path refers to a nonexistent file or directory:
.NET offers the [System.IO.Path]::GetFullPath() method, which offers the same functionality also for nonexistent paths.
The challenge is that relative paths are resolved to .NET's current (working) directory, which usually differs from PowerShell's - see this answer for more information.
In PowerShell (Core) 7+, you can work around this problem by specifying the reference path (to resolve the relative path against) explicitly:
# Note: The 'System.' prefix in the type literal is optional.
[IO.Path]::GetFullPath("C:\Folder\..\Folder2", $PWD.ProviderPath)
The automatic $PWD variable refers to PowerShell's current location (directory). Note the use of .ProviderPath, which again ensures uses of a file-system-native path. For maximum robustness - to guard agains the case where the current PowerShell location isn't a file-system location - use (Get-Location -PSProvider FileSystem).ProviderPath.
In Windows PowerShell, where this method overload isn't available, a more cumbersome approach is needed, as suggested by Theo:
# Note: If you don't need to *normalize* the path (resolving . and .. components),
# the [IO.Path]::Combine() call alone is enough.
[IO.Path]::GetFullPath(
[IO.Path]::Combine($PWD.ProviderPath, "C:\Folder\..\Folder2")
)
[IO.Path]::Combine() conditionally combines the first path given with the second one, if the latter is relative - otherwise, the latter is used as-is.
[IO.Path]::GetFullPath() then ensures normalization of the resulting full path (to resolve any . and .. components); if that isn't required, just calling [IO.Path]::Combine() will do.