简体   繁体   English

如何在 windows PATH 中设置 Rust 的货物目录?

[英]How to set Rust's cargo directory in windows PATH?

I want unnatended install of rust, so I did this little script:我想要无人值守安装 rust,所以我做了这个小脚本:

Write-Host "Installing Rust..." -ForegroundColor Cyan
$exePath = "$env:TEMP\rustup-init.exe"

Write-Host "Downloading..."
(New-Object Net.WebClient).DownloadFile('https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe', $exePath)

Write-Host "Installing..."
cmd /c start /wait $exePath -y
Remove-Item $exePath

$addPath = "$env:USERPROFILE\.cargo\bin"
[Environment]::SetEnvironmentVariable('PATH', $env:PATH, $addPath)

but I get但我明白了

  virtualbox-iso: Cannot convert argument "target", with value: "C:\Users\vagrant\.cargo\bin", for "SetEnvironmentVariable" to type
    virtualbox-iso: "System.EnvironmentVariableTarget": "Cannot convert value "C:\Users\vagrant\.cargo\bin" to type
    virtualbox-iso: "System.EnvironmentVariableTarget". Error: "Unable to match the identifier name C:\Users\vagrant\.cargo\bin to a valid

it looks like a text cannot be converted to a PATH type?看起来文本无法转换为 PATH 类型? What does it mean?这是什么意思?

The immediate solution to your problem is that you need to call [Environment]::SetEnvironmentVariable() as follows:您的问题的直接解决方案是您需要调用[Environment]::SetEnvironmentVariable() ,如下所示:

# Modify the user-level PATH definition.
# To modify the machine-level definition, use 'Machine' instead of user 'User',
# but you then need to run with ELEVATION (as admin).
# !! SEE CAVEATS BELOW.
[Environment]::SetEnvironmentVariable('PATH', ($env:PATH + ";$addPath"), 'User')

That is, as Herohtar points out, the method expects only a complete, new value, as the second parameter, and its third parameter specifies the target scope for the persistent, registry-based environment-variable definition.也就是说,正如Herohtar 所指出的,该方法只需要一个完整的新值作为第二个参数,它的第三个参数指定目标 scope用于持久的、基于注册表的环境变量定义。

Caveats :注意事项

  • The process-level $env:PATH value is a composite value of the machine-level and user-level definitions in the registry, so with the command above you're in effect duplicating entries from the respective other scope.进程级别的$env:PATH值是注册表中机器级别和用户级别定义的复合值,因此使用上面的命令实际上是从相应的其他 scope复制条目。

  • Additionally, redefining the variable this way replaces any entries in the value that are defined in terms of other environment variables with the expanded , literal values.此外,以这种方式重新定义变量会将值中根据其他环境变量定义的任何条目替换为扩展的文字值。

    • $env:PATH contains expanded values to begin with, but even reading the unexpanded value directly from the registry won't work, because [Environment]::SetEnvironmentVariable() invariably writes the given string as a REG_SZ value (literal string) rather than as an REG_EXPAND_SZ value (string that may contain %FOO% -style references to other environment variables). $env:PATH一开始就包含扩展值,但即使直接从注册表中读取未扩展的值也不起作用,因为[Environment]::SetEnvironmentVariable()总是将给定字符串写入为REG_SZ值(文字字符串)而不是作为REG_EXPAND_SZ值(可能包含对其他环境变量的%FOO%样式引用的字符串)。 Similarly, [Environment]::GetEnvironmentVariable() only reports expanded values.同样, [Environment]::GetEnvironmentVariable()仅报告扩展值。

A proper solution requires quite a bit of extra work, as discussed in this answer , which contains helper function Add-Path .正确的解决方案需要相当多的额外工作,如本答案中所述,其中包含帮助程序 function Add-Path

A pragmatic shortcut - if you're willing to accept that your registry definitions are converted to literal strings - is the following:一个实用的快捷方式-如果您愿意接受将注册表定义转换为文字字符串- 如下:

  • Read the current definition - for the target scope only - from the registry , via [Environment]::GetEnvironmentVariable()通过[Environment]::GetEnvironmentVariable()从注册表中读取当前定义 - 仅针对目标 scope

  • Add to this scope-specific value and save it back to the same scope.添加到此范围特定的值并将其保存回相同的 scope。

  • Additionally, you may want to add the new entry to the in-process definition of $env:PATH so that the change takes immediate effect.此外,您可能希望将新条目添加到$env:PATH的进程内定义中,以便更改立即生效。

Here is the solution in the context of a streamlined version of your code:这是您的代码的简化版本的上下文中的解决方案:

Write-Host "Installing Rust..." -ForegroundColor Cyan
$exePath = "$env:TEMP\rustup-init.exe"

Write-Host "Downloading..."
Invoke-WebRequest 'https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe' -OutFile $exePath

Write-Host "Installing..."
& $exePath -y
Remove-Item $exePath

$addPath = "$env:USERPROFILE\.cargo\bin"
$scope = 'User' # Change to 'Machine', if needed, which then requires ELEVATION.
[Environment]::SetEnvironmentVariable(
  'PATH', 
  ([Environment]::GetEnvironmentVariable('PATH', $scope) + ";$addPath"), 
  $scope
)

# Also update the current process' definition
$env:PATH += ";$addPath"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM