关于vba:在WScript.Shell对象中调用Run时无法识别环境变量

Environment Variables not recognized when calling Run in WScript.Shell object

如果我在命令行中运行命令Rscript"C:/TEMP/test.R",它将正常工作,并且脚本将按预期运行。 一旦尝试在VBA代码中运行它,它就不会将Rscript识别为有效命令。

1
2
3
4
Dim shell_obj As Object
Set shell_obj = VBA.CreateObject("WScript.Shell")
Dim errorCode As Integer
errorCode = shell_obj.Run("Rscript""C:/TEMP/test.R""", 1, True)

当我查看WScript.Shell使用的PATH变量时,我发现它不包含带有Rscript路径的系统变量。

1
2
3
4
5
6
7
8
9
Dim shell_obj As Object
Dim wshSystemEnv As Object
Set shell_obj = VBA.CreateObject("WScript.Shell")

' This one does not include the path to the Rscript'
Debug.Print shell_obj.ExpandEnvironmentStrings("%PATH%")
Set wshSystemEnv = shell_obj.Environment("SYSTEM")
' This one includes the path to the Rscript'
Debug.Print wshSystemEnv("PATH")

我可以强制WScript.Shell对象使用系统环境吗? 或者至少使用其变量?

Cmd:
enter image description here

VBA(版本1):

enter image description here

VBA(版本2):

enter image description here


EDIT: See bottom of post.

希望你会在我的(冗长的)观点中找到一些用处... :-)

好。

测试命令行准备情况

可以从Windows命令行按原样运行的任何命令(包括RScript)也可以使用VBA Shell函数或Windows WScript.Shell方法运行。

好。

问题是,您的cmd字符串尚未准备好命令行。可以通过点击 Windows Key + R并粘贴您的cmd字符串变量的内容来确认:

好。

1
Rscript"**path**/test.R"

我目前尚未安装rscript.exe,但我怀疑如果尝试在"运行"窗口或命令行中手动运行命令,将会收到错误消息。如果它不在那里运行,显然不会在VBA Shell中运行。

好。

据我了解,双星号是您使用Java符号的方式,R中的R与^插入符号相同,用于计算指数。

好。

引用环境变量

要在VBA中返回Windows PATH环境变量,可以使用VBA的Environ函数。

好。

要在命令行内联插入值环境变量,您可以用% percent %符号将其包围,例如%path%

好。

Windows的PATH环境变量

PATH不返回单个文件夹。这是Windows应检查以查找一个试图运行的可执行文件的文件夹列表。

好。

When a command is entered in a command shell or a system call is made by a program to execute a program, the system first searches the current working directory and then searches the path, examining each directory from left to right, looking for an executable filename that matches the command name given.

Ok.

The Windows system directory (typically C:\WINDOWS\system32) is typically the first directory in the path, followed by many (but not all) of the directories for installed software packages.

Ok.

默认值PATH(来自Windows 7的全新安装)的示例为:

好。

1
%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem

%path%, this includes%SystemRoot%`一样,在Windows 7上默认为字符串:

好。

1
C:\Windows

检查环境变量

您可以验证PATH环境标签的值:

好。

  • 命中 Windows Key + R
  • 键入cmd并单击Enter。 (应该打开一个命令行窗口。)
  • 键入或粘贴echo %path%,然后单击Enter
  • 好。

    将显示Window PATH环境变量的内容。

    好。

    您还可以从Windows中检查环境变量:

    好。

  • Windows Key 并键入env(以进行搜索)
  • 单击Edit the system environment variables。 (有一个类似的选项" ...为您的帐户",该选项并不完全相同。)
  • 单击 <kbd>Environment Variables...</kbd>
    img
  • 好。

    Note: Although you technically can change the PATH in this window, I would not recommend doing so, especially with PATH since it is split up into System and User folders, and Windows likes certain folders in certain areas, and some changes don't take effect until reboot but others do, and blah blah blah, trust me: it's easier to do from the command line.

    Ok.

    您的代码有什么问题?

    因此,基于所有这些,看来您要运行的命令是:

    好。

    1
    Rscript"C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem/test.R"

    ...这显然行不通。

    好。

    获取或设置当前工作文件夹/目录

    我只能推测您要完成的工作。

    好。

    我怀疑您不打算返回整个PATH变量,而是只对当前的工作文件夹感兴趣。

    好。

    如果是这样,则根本不需要指定文件夹。 Shell命令已经在"当前"文件夹中执行。

    好。

    您可以使用VBA CurDir()函数检查当前目录或文件夹的一种方法,例如:

    好。

    1
    Debug.Print CurDir()

    CurDir的值可以使用ChDir语句更改。

    好。

    类似功能

    请注意,CurDur()命令经常与类似的功能混淆,例如:

    好。

  • Application.Path,它返回Excel应用程序的路径,或者
  • ActiveWorkbook.Path,它返回活动工作簿的保存位置(如果未保存,则为空字符串)。
  • 好。

    可能的解决方案:(如何在VBA中的当前路径中运行rScript)

  • 如果您的R脚本和rscript.exe都在当前工作文件夹中,则仅用一行VBA运行它:

    好。

    1
    Shell"rscript.exe test.R", vbNormalFocus
  • 如果您要求VBA在恢复VBA之前等待Shell命令的执行完成,则可以执行以下操作:

    好。

    1
    CreateObject("WScript.Shell").Run"rscript.exe test.R", vbNormalFocus, True
  • 好。

    更多信息:

    我通常会提出指向我用来验证答案的任何站点的链接,因此,这肯定是我研究最多的答案,因为我从来没有这么长的列表...这次我省略了一些!

    好。

  • 堆栈溢出:从VBA运行R脚本
  • MSDN:Shell功能(VBA)
  • MSDN:Environ功能(VBA)
  • R-Blogger:从命令行向R脚本传递参数
  • 堆栈溢出:R.exeRcmd.exerscript.exeRterm.exe:有什么区别?
  • 堆栈交换:统计信息:R中的双星**?
  • 维基百科:PATH(变量)
  • 堆栈溢出:Windows 10中PATH变量的默认值
  • 超级用户:Windows 7的默认PATH
  • MSDN:CurDir()功能(VBA)
  • MSDN:ChDir()语句(VBA)
  • MSDN:Application.Path(Excel / VBA)
  • MSDN:ActiveWorkbook.Path(Excel / VBA)
  • 堆栈溢出:等待Shell命令完成
  • MSDN论坛:wscript.shellshell.application之间的区别
  • 堆栈溢出:通过Windows命令提示符运行R脚本的步骤
  • 好。

    One More Demo of What's Wrong With Your Code:

    I have a batch file named test.bat located in C:\WINDOWS. My PATH environment variable contains C:\WINDOWS (among other things).

    Ok.

    如果我转到根文件夹C:\中的命令提示符,然后键入test.bat

    好。

    img1

    好。

    ...它可以正常运行(即使我的文件不在该文件夹中,因为c:\windows文件夹位于PATH变量之内。)

    好。

    但是,如果我转到命令提示符并键入C:\test.bat

    好。

    img2

    好。

    ...这是行不通的。它找不到文件,因为我指定了文件所在的文件夹。

    好。

    ---在VBA中,如果我运行命令Shell"test.bat",1

    好。

    img3

    好。

    ...它可以正常运行(即使我的文件不在该文件夹中,因为c:\windows文件夹位于PATH变量之内。)

    好。

    但是,如果在VBA中运行命令Shell"c:\test.bat",1

    好。

    img4

    好。

    ...这是行不通的。它找不到文件,因为指定了*文件所在的文件夹**。

    好。

    Both VBA and the Shell command are behaving the same way, when given the same information.

    Ok.


    好。


    如果您最近修改了系统PATH变量,则必须重新启动运行VBA的Office应用程序。 VBA向WScript发送路径变量,并且仅在重新启动后重新读取。 重新启动后,它将从系统中重新读取PATH变量,并将新的正确路径发送到WScript。

    我遇到过同样的问题。 我已经更新了系统PATH变量,但是WScript.Shell对象正在从Excel中传递路径变量,而不是从系统中读取。 Excel在启动时已读取路径,并且不知道它已更改。 关闭Excel并重新打开后,WScript拥有更新的路径变量,并且脚本成功执行。