【问题标题】:Is it possible to return error code to VBA from batch file?是否可以从批处理文件向 VBA 返回错误代码?
【发布时间】:2014-03-19 06:50:11
【问题描述】:

我的批处理文件:

SET username=%1
SET password=%2

net use "\\gessel\toys\name" %password% /user:shops\%username%
ECHO.%ERRORLEVEL%
:copy
Xcopy "\\gessel\toys\name\babytoys" "%appdata%\shops" /S /E
ECHO.%ERRORLEVEL%

IF ERRORLEVEL 0 goto disconnect
goto end
:disconnect 
net use "\\gessel\toys\name\babytoys" /delete
goto end
:end
EXIT /B %ERRORLEVEL%

我已经从VBA调用了上面的批处理文件,代码如下:

call Shell(Environ$("COMSPEC") & " /c " & path & username & password, vbHide)

上面的代码运行良好。但我需要验证文件是否在 VBA 中复制。假设客户输入了错误的用户名和密码,那么他将无法获得玩具信息。然后我必须显示一个消息框,显示消息为“输入信息错误”。所以为此我尝试了这样的代码:

sub submit_click

    Dim as error as integer
    error = Shell(Environ$("COMSPEC") & " /c " & path & username & password, vbHide)
    if error <> 0
        MsgBox "Provided info wrong", vbOKOnly, "Failure"
    end if
end sub

但是上面的代码不起作用。即使用户名和密码正确,它也总是返回值。但是,如果我运行批处理文件,它会正确返回值,例如正确的详细信息为 0,错误的数据为 2 或 4。请任何人帮助我从批处理文件中捕获错误代码并将其传递给 VBA。

【问题讨论】:

    标签: vba batch-file excel


    【解决方案1】:

    ERRORLEVEL 变量的值随着每个命令的执行(或多或少)而变化。因此,当您的批处理文件中的代码正在执行时,每个命令都会生成一个更改。您需要存储该值以供以后处理,或者在您的情况下,在每个步骤中以适当的值退出:

    SET "username=%~1"
    SET "password=%~2"
    
    rem This will be tested for a errorlevel value of 1 or greater. In this case, 
    rem no further processing will be done if errors found, so we return our own 
    rem value to the calling process
    
    net use "\\gessel\toys\name" %password% /user:shops\%username% 
    if errorlevel 1 exit /b 100
    
    rem We are connected, and will disconnect no matter if xcopy worked or failed
    rem So, the result of the command will be stored to later return the adecuate value
    
    Xcopy "\\gessel\toys\name\babytoys" "%appdata%\shops" /S /E
    set "exitCode=%errorlevel%"
    
    net use "\\gessel\toys\name\babytoys" /delete
    
    EXIT /B %exitCode%
    

    现在,在 vba 代码中,可以测试 error 变量的值 100(我们从网络使用错误中返回的值)或从 xcopy 返回的任何值。

    现在我们有了一个可以工作的批处理文件,让我们使用 Excel。

    不,VBA 中的Shell 函数不能满足您的要求。 Shell的返回值是正在运行的进程的id。 Shell 不等待进程结束,所以不能返回退出码。

    但是,WshShell 对象可以满足您的需求。

    Dim oSHELL, batchFile, user, password, exitCode
        Set oSHELL = VBA.CreateObject("WScript.Shell")
        batchFile="myBatchFile.cmd"
        user="myUserName"
        password="this is my password"
    
        ' Quote strings to avoid problems with spaces
        ' The arguments are WhatToRun, WindowStyle (0=hide), WaitForProcessToEnd
        exitCode = oSHELL.Run(""""+batchFile+""" """+user+""" """+password+"""", 0, True)
    

    【讨论】:

    • 谢谢。我已根据您的建议修改了代码。但我遇到了另一个问题。如果我单独运行批处理文件,它看起来不错。但是从代码中它总是复制文件,即使我错误地提供了数据。你能帮忙吗?
    • @viji,我正在测试,我无法使用无效数据执行net use 命令,但没有设置错误级别。设置errorlevel 后,批处理文件在net use 后退出该行并且不复制任何文件。您可以尝试在您的系统中使用命令行中的无效数据执行命令,看看它是否设置了错误级别以及它设置了哪个值?
    • 我试过了。这看起来不错的样子。但是这条线需要很多时间来执行 "exitCode = oSHELL.Run(""""+batchFile+""" """+user+""" """+password+"""", 0, True)" 我的意思是它不会返回到应用程序。是否可以在批处理文件执行之前设置等待或睡眠时间?
    • 但如果我单独运行批处理文件,则需要 2 或 3 秒。你有什么想法吗?
    • @viji,函数调用中的最后一个参数 (True) 表示调用在批处理文件完成之前不应返回。如果它不等待被调用进程结束,则无法访问退出代码(它还没有完成)。您认为它应该具有的具体行为是什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-27
    • 2017-05-16
    • 1970-01-01
    • 2010-09-24
    • 2018-09-02
    • 2020-07-11
    相关资源
    最近更新 更多