I want to write a function that converts regular path to path that includes environment variables:
For example:
C:\Windows\SomePath
convert to:
%Windir%\SomePath
How would I do that and is this possible?
Here is what I'm trying to do, but problem is, I need to check the string for all possible variables, is there some more automatic way? such that -replace operator wont be needed
function Format-Path
{
param (
[parameter(Mandatory = $true)]
[string] $FilePath
)
if (![System.String]::IsNullOrEmpty($FilePath))
{
# Strip away quotations and ending backslash
$FilePath = $FilePath.Trim('"')
$FilePath = $FilePath.TrimEnd('\\')
}
$FilePath = $FilePath -replace "C:\\Windows", "%Windir%"
$FilePath = $FilePath -replace "C:\\ProgramFiles", "%ProgramFiles%"
$FilePath = $FilePath -replace "C:\\ProgramFiles (x86)", "%ProgramFiles (x86)%"
# ETC.. the list goes on..
return $FilePath
}
# test case
Format-Path '"C:\Windows\SomePath\"'
Output is:
%Windir%\SomePath
EDIT:
Invalid input or bad code isn't really the problem because in the end the $Path can be easily checked with:
Test-Path -Path ([System.Environment]::ExpandEnvironmentVariables($FilePath))
The code below is my take on this. There's some peculiarities with the path and backslash manipulations, so I tried to explain everything in comments.
There is one key take away and that is that unbounded string searches such as those performed by
-replace,-like,.Contains(), etc. and can produce undesirable results when the value of one variable's path is a substring of either another variable's path or a directory's path. For example, given%ProgramFiles%(C:\Program Files) and%ProgramFiles(x86)%(C:\Program Files (x86)), the pathC:\Program Files (x86)\Testcould be transformed into%ProgramFiles% (x86)\Testinstead of%ProgramFiles(x86)%\Testif%ProgramFiles%happens to be tested before%ProgramFiles(x86)%.The solution is to only compare a variable's path to a complete path segment. That is, in the case of the path
C:\Program Files (x86)\Test, the comparisons would go like this...C:\Program Files (x86)\Test. No variables match.C:\Program Files (x86).%ProgramFiles(x86)%matches. No further ancestor paths (i.e.C:) are tested.%ProgramFiles%will never match because the partial pathC:\Program Filesis not tested.By only testing against complete path segments it does not matter in what order the variables are compared to the candidate path.
Using this test code...
...I get this result...
Note that candidate ancestor paths are always searched first with a trailing slash and then without. This means that in the unlikely event there are two variable paths that differ only by the presence or absence of a trailing slash, the variable with the trailing slash will be matched. Thus, as seen above,
C:\My Directory\Testwill become%MyDirectoryWithSlash%Test, which looks a little strange. By reversing the order of the firstforeachloop in the function from......to...
...the relevant output changes to this...