英文:
How can I run a a Powershell command in VBA which contains "$env:UserName"?
问题
以下是翻译好的代码部分:
原始宏代码:
Private Sub Macro()
Dim ExecuteCommand As String
ExecuteCommand = "PowerShell -Command ""& 'C:\Program Files\R\R-4.2.2\bin\Rscript.exe' 'C:\Users\MyUser\Cool Calculations.R'"""
Shell ExecuteCommand
End Sub
您想要替换 "MyUser" 部分,改成使用 $env:UserName
,但是出现问题的宏代码如下:
Private Sub Macro()
Dim ExecuteCommand As String
ExecuteCommand = "PowerShell -Command ""& 'C:\Program Files\R\R-4.2.2\bin\Rscript.exe' 'C:\Users$env:UserName\Cool Calculations.R'"""
Shell ExecuteCommand
End Sub
您已经手动在 PowerShell 中运行了相同的命令,并且它正常工作:
& "C:\Program Files\R\R-4.2.2\bin\Rscript.exe" "C:\Users$env:UserName\Cool Calculations.R"
但是在宏中添加 $env:UserName
部分似乎不起作用。这个问题可能是因为 VBA 宏不会解释 PowerShell 变量。要在 VBA 中使用环境变量,您可以使用 VBA 的 Environ
函数。以下是修改后的宏代码:
Private Sub Macro()
Dim ExecuteCommand As String
Dim UserName As String
UserName = Environ("UserName")
ExecuteCommand = "PowerShell -Command ""& 'C:\Program Files\R\R-4.2.2\bin\Rscript.exe' 'C:\Users\" & UserName & "\Cool Calculations.R'"""
Shell ExecuteCommand
End Sub
这段代码会获取当前用户的用户名并将其替换到 PowerShell 命令中,以便宏可以正常工作。
英文:
I have the following macro which works just fine:
Private Sub Macro()
Dim ExecuteCommand As String
ExecuteCommand = "PowerShell -Command ""& 'C:\Program Files\R\R-4.2.2\bin\Rscript.exe' 'C:\Users\MyUser\Cool Calculations.R'"""
Shell ExecuteCommand
End Sub
What I want to do however, is to replace the name "MyUser" with $env:UserName
instead.
However this macro does not seem to work:
Private Sub Macro()
Dim ExecuteCommand As String
ExecuteCommand = "PowerShell -Command ""& 'C:\Program Files\R\R-4.2.2\bin\Rscript.exe' 'C:\Users$env:UserName\Cool Calculations.R'"""
Shell ExecuteCommand
End Sub
I have tried to run the command manually in PowerShell and it works correctly:
& "C:\Program Files\R\R-4.2.2\bin\Rscript.exe" "C:\Users$env:UserName\Cool Calculations.R"
I am not sure what I am doing wrong when trying to add $env:UserName
in my macro?
答案1
得分: 2
* 正如Mathias指出的,只有`"..."`字符串([可扩展字符串](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Quoting_Rules#double-quoted-strings))在Powershell中执行变量扩展(内插);`'...'`字符串([纯字符串](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Quoting_Rules#single-quoted-strings))不执行。
* 因此,你必须传递给PowerShell _最终_ 视为 `"C:\Users\$env:UserName\Cool Calculations.R"` 参数(另外提一句:考虑简化为 `"$env:USERPROFILE\Cool Calculations.R"`);因为你是从VBA调用的,这需要:
* 使用 `""...""` 将 `"` 字符嵌入到VBA `"..."` 字符串中...
* _并且_ 为了`powershell.exe`,Windows PowerShell CLI(它将其`-Command`参数作为 `"..."` 字符串接收,因此任何要保留作为命令一部分的 `"` 字符必须进行转义)
* 也就是说,你需要类似下面的内容(此处为了可读性添加了空格)
" PowerShell -Command "" & '...' \""...\"" "" "
具体代码:
Private Sub Macro()
Dim ExecuteCommand As String
ExecuteCommand = "PowerShell -Command ""& 'C:\Program Files\R\R-4.2.2\bin\Rscript.exe' ""C:\Users$env:UserName\Cool Calculations.R"""""
Shell ExecuteCommand
End Sub
<details>
<summary>英文:</summary>
<!-- language-all: vb -->
* As Mathias points out, only `"..."` strings ([expandable strings](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Quoting_Rules#double-quoted-strings)) perform variable expansion (interpolation) in Powershell; `'...'` strings ([verbatim strings](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Quoting_Rules#single-quoted-strings)) do not.
* Thus you must pass what PowerShell _ultimately_ see as a `"C:\Users$env:UserName\Cool Calculations.R"` argument (as an aside: consider simplifying to `"$env:USERPROFILE\Cool Calculations.R"`); since you're calling from VBA, this requires:
* Using `""...""` to embed `"` chars. inside a VBA `"..."` string...
* _and_ `\`-escaping for the sake of `powershell.exe`, the [Windows PowerShell CLI](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe) (which receives its `-Command` argument as a `"..."` string, so any `"` chars. to be retained as part of the command must be escaped)
* That is, you need something like the following (sic; spaces added for readability)
" PowerShell -Command "" & '...' \""...\"" "" "
Specifically:
Private Sub Macro()
Dim ExecuteCommand As String
ExecuteCommand = "PowerShell -Command ""& 'C:\Program Files\R\R-4.2.2\bin\Rscript.exe' ""C:\Users$env:UserName\Cool Calculations.R"""""
Shell ExecuteCommand
End Sub
答案2
得分: 0
mklement0的回答非常优雅,已测试可行。但我尝试了没有转义的命令,在Windows PowerShell下似乎不需要,正如Mathias建议的那样,它也可以工作。我用Get-ChildItem
cmdlet替换了我没有安装的Rscript.exe
,如下所示:
<pre><code>
Sub RunPSFromVba()
Dim ExecuteCommand As String
'ExecuteCommand = "PowerShell -Command ""& 'C:\Program Files\R\R-4.2.2\bin\Rscript.exe' 'C:\Users$env:UserName\Cool Calculations.R'"""
ExecuteCommand = "PowerShell -NoExit -Command ""& 'Get-ChildItem' 'C:\Users$env:UserName\Downloads'"""
Shell ExecuteCommand
End Sub
</code></pre>
使用PowerShell -NoExit
,我在执行后保持了PowerShell窗口的活动状态,我得到了这个屏幕截图:
希望这也对你有帮助。
英文:
mklement0's response is very elegant, tested working. But I tested the command without escape, that seems not required under Windows Powershell, as Mathias suggested, it works also. I replaced Rscript.exe
that I have not installed, by Get-ChildItem
cmdlet like this:
<pre><code>
Sub RunPSFromVba()
Dim ExecuteCommand As String
'ExecuteCommand = "PowerShell -Command ""& 'C:\Program Files\R\R-4.2.2\bin\Rscript.exe' 'C:\Users$env:UserName\Cool Calculations.R'"""
ExecuteCommand = "PowerShell -NoExit -Command ""& 'Get-ChildItem' ""C:\Users$env:UserName\Downloads"""""
Shell ExecuteCommand
End Sub
</code></pre>
With PowerShell -NoExit
, I keep the PowerShell Window alive after execution, I got this screenshot:
Hope this will also help.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论