admin管理员组文章数量:1208155
I'm working on a Windows program that adds values to the PATH environment variable. The PATH variable is semi-colon (;
) delimited, and any valid folder paths can be included. However, ;
is valid in folder paths, so paths containing semicolons must be surrounded in double quotes when being added to path:
C:\Program Files (x86);"C:\;My Folder";C:\Program Files
To avoid this issue with semicolons, my program wraps all paths in double quotes. However, someone recently informed me that Powershell does not work with quoted values in the PATH variable, as it treats the quotes as ordinary characters:
I looked at how PowerShell handles the Path variable (based on this code: PowerShell/PowerShell@16176ef/src/System.Management.Automation/engine/CommandDiscovery.cs#L1187-L1240). From what I can tell, PowerShell doesn't remove double quotes - it just splits paths wherever it sees a semicolon.
So, the PATH value C:\Program Files (x86);"C:\;My Folder";C:\Program Files
is wrongly interpreted like this (if I correctly understand what's going on):
C:\Program Files (x86)
"C:\
My Folder"
C:\Program Files
Here's a video demonstrating the behavior (this only occurs with Powershell, not with cmd): .mp4/file
What is the best way for my program to deal with this? And, more pressingly, why does Powershell not work with PATH values that have quotes (even though CMD does)?
Editing the path value to include semicolons using the manual way - Edit the system environment variables -> Path -> Edit
- causes Windows to automatically wrap the required paths in quotes, breaking Powershell. So this isn't an issue with my program or situation - it's an inherent problem with how Powershell processes the PATH.
Is this behavior intentional in Powershell? And is there a workaround, or will I have to compromise by either A. Wrapping paths that contain semicolons in quotes and allowing this buggy behavior to occur or B. not allowing semicolons in PATH?
I'm working on a Windows program that adds values to the PATH environment variable. The PATH variable is semi-colon (;
) delimited, and any valid folder paths can be included. However, ;
is valid in folder paths, so paths containing semicolons must be surrounded in double quotes when being added to path:
C:\Program Files (x86);"C:\;My Folder";C:\Program Files
To avoid this issue with semicolons, my program wraps all paths in double quotes. However, someone recently informed me that Powershell does not work with quoted values in the PATH variable, as it treats the quotes as ordinary characters:
I looked at how PowerShell handles the Path variable (based on this code: PowerShell/PowerShell@16176ef/src/System.Management.Automation/engine/CommandDiscovery.cs#L1187-L1240). From what I can tell, PowerShell doesn't remove double quotes - it just splits paths wherever it sees a semicolon.
So, the PATH value C:\Program Files (x86);"C:\;My Folder";C:\Program Files
is wrongly interpreted like this (if I correctly understand what's going on):
C:\Program Files (x86)
"C:\
My Folder"
C:\Program Files
Here's a video demonstrating the behavior (this only occurs with Powershell, not with cmd): https://www.mediafire.com/file/aih2ky9fz07x5w0/powershellpathwithsemicolonsbug.mp4/file
What is the best way for my program to deal with this? And, more pressingly, why does Powershell not work with PATH values that have quotes (even though CMD does)?
Editing the path value to include semicolons using the manual way - Edit the system environment variables -> Path -> Edit
- causes Windows to automatically wrap the required paths in quotes, breaking Powershell. So this isn't an issue with my program or situation - it's an inherent problem with how Powershell processes the PATH.
Is this behavior intentional in Powershell? And is there a workaround, or will I have to compromise by either A. Wrapping paths that contain semicolons in quotes and allowing this buggy behavior to occur or B. not allowing semicolons in PATH?
Share Improve this question edited Jan 20 at 22:09 Zeek Joseph asked Jan 19 at 23:35 Zeek JosephZeek Joseph 715 bronze badges 1- 1 how are you passing the PATH to Powershell? – sirtao Commented Jan 20 at 7:15
2 Answers
Reset to default 4iRon's helpful answer shows you how you can parse the $env:PATH
value manually into its constituent directory paths in a manner that respects double-quoted entries.[1]
As for your questions:
Is this behavior intentional in PowerShell?
I don't think so, and it is arguably a bug, as discussed in GitHub issue #24002; quoting from this comment (of mine):
Indeed, PowerShell doesn't support
"..."
-enclosed entries in$env:PATH
in direct invocation (see below), whereascmd.exe
does.
Note that POSIX-compatible shells such asbash
, like PowerShell, also do not support"..."
-enclosed entries.Arguably, PowerShell and POSIX-compatible shells either should support
"..."
-enclosed entries or support a way to escape the entry-separator character (which is;
on Windows, and:
on Unix-like platforms), but they do not.By contrast, when you use
Start-Process
, as well as the[System.Diagnostics.Process]
API withUseShellExecute = $true
, which is equivalent,"..."
-enclosed entries ARE recognized.This may come down to differences between two WinAPI functions:
CreateProcess()
as used in direct invocation and withUseShellExecute = $false
(the default) in .NET (Core) vs.ShellExecuteEx()
as used byStart-Process
by default and withUseShellExecute = $true
.Given that direct invocation in
cmd.exe
(as opposed to use of the internalstart
command) presumably also usesCreateProcess()
, there may be custom logic incmd.exe
for interpreting%PATH%
.
Is there a workaround?
Assuming that creation of short (8.3) file names is turned on (it is by default), you can take advantage of the fact that a file name containing ;
always has a short name generated for it, even if it otherwise has 8 or fewer chars. in the base name and an extension with 3 or fewer chars and that the resulting short name is guaranteed not to contain ;
or spaces; e.g.:
# -> e.g., 'C:\M_YFOL~1'
$shortFolderPath =
(New-Object -ComObject Scripting.FileSystemObject).GetFolder("C:\;My Folder").ShortPath
In other words:
Replace those
$env:PATH
entries that require"..."
enclosure for disambiguation due to embedded;
with their short (8.3) versions...... and remove the double quotes around them.
Note that the specific 8.3 names can vary depending on the presence of other folders with similar long names, so they should be determined on each machine.
[1] However, I suggest the following, improved version:
@(($env:Path | ConvertFrom-Csv -Delimiter ';' -Header (0..($env:Path -replace '[^;]').Length)).psobject.Properties.Value) -ne $null
This creates only 1 extra header per "..."
-enclosed entry that contains ;
while also ensuring that all entries are returned, even if their number exceeds 99. Any resulting extra field values are then eliminated with the -ne $null
filter.
"Powershell does not work with quoted values in the PATH variable, as it treats the quotes as ordinary characters:"
Afaik, PowerShell doesn't have any native command (or automated variable) at all that returns a list of paths from the environment path for you. Meaning, you have to script this yourself.
If you take the easy way and just split the environment path like $env:Path -split ';'
you might indeed end up with issues where you have a literal path that contains a semicolumn. This means you have to come up with a smarter way to split you path or use an existing converter/parser.
Knowing that the ConvertFrom-Csv
cmdlet is very close to what you want to do, you might consider to use that:
($Env:Path | ConvertFrom-Csv -Delimiter ';' -Header (0..99)).PSObject.Properties.Value
C:\Program Files (x86)
C:\;My Folder
C:\Program Files
Explanation
$Env:Path
contains a single string with all the environment path joined with a semicolumn (;
)ConvertFrom-Csv -Delimiter ';'
splits the environment path using the semicolumn as a delimiter and also takes care about quoted values and spaces around the delimiter.-Header (0..99)
defines a numeric header (from0
up to99
[1]) for each value
ConvertFrom-Csv
returns aPSCustomObject
, to retrieve all it's properties you use the hiddenPSObject
property:.PSObject.Properties
- Although there will be a lot of headers with an empty values using the PowerShell member access enumeration by adding the
.Value
property will simply return all the values that are not$Null
. Note that this is build on aConvertFrom-Csv
inconsistency where the last empty cells in the last row ofcsv
file are considered$Null
(rather than an empty string), see: #17702
- Although there will be a lot of headers with an empty values using the PowerShell member access enumeration by adding the
- This is a hardcoded value for the maximum number of paths expected in the environment string which is in fact unknown. To limit the number of headers to cover at least all paths, you might use the helpful command suggested by mklement0 instead:
@((($env:Path) | ConvertFrom-Csv -Delimiter ';' -Header (0..($env:Path -replace '[^;]').Length)).psobject.Properties.Value) -ne $null
本文标签: powershellWindows Semicolons in PathStack Overflow
版权声明:本文标题:powershell - Windows Semicolons in Path - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738724493a2108950.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论