Windows批处理编程是否支持异常处理?如果没有,有没有办法有效地模拟批处理文件中的异常处理?

我想要能够在任何CALL级别的批处理脚本中“抛出异常”,并且CALL堆栈重复弹出,直到找到一个活动的“TRY块”,因此“CATCH块”可以处理异常完全进行或进行一些清理,并继续弹出CALL堆栈.如果从未处理异常,则会终止批处理,并且控制将返回到具有错误消息的命令行上下文.

已经有couple posted ways to terminate batch processing at any CALL depth,但是这些技术中没有一个允许通常通过异常处理在其他语言中提供的任何结构化清理活动.

注意:这是一个我已经知道最近才发现的好答案的情况,我想分享这个信息

Windows批处理脚本当然没有任何正式的异常处理 – 考虑到这个语言是多么原始的,这并不奇怪.我从来没有想过有效的异常处理可能被黑客入侵.

但是,在Russian site关于错误的GOTO声明的行为的一些惊人的发现(我不知道该说什么,我看不懂俄语). An English summary was posted at DosTips,行为进一步调查.

事实证明,(GOTO)2> NUL的行为几乎与EXIT / B相同,除了已经解析的代码块中的连接命令在有效返回之后仍然在CALLER的上下文中执行!

这是一个简短的例子,它演示了大部分的重点.

@echo off
setlocal enableDelayedExpansion
set "var=Parent Value"
(
  call :test
  echo This and the following line are not executed
  exit /b
)
:break
echo How did I get here^^!^^!^^!^^!
exit /b

:test
setlocal disableDelayedExpansion
set "var=Child Value"
(goto) 2>nul & echo var=!var! & goto :break
echo This line is not executed

:break
echo This line is not executed

– 输出 –

var=Parent Value
How did I get here!!!!

这个功能是完全意想不到的,而且功能强大而有用.它已被用于:

>创建PrintHere.bat – 这是“nix这里的文件功能的仿真”
>创建一个RETURN.BAT utility,任何批处理“函数”可以方便地通过ENDLOCAL屏障返回任何值,几乎没有任何限制.该代码是jeb’s original idea的丰富版本.

现在我也可以添加异常处理列表:-)

该技术依赖于一个称为EXCEPTION.BAT的批处理实用程序来定义用于指定TRY / CATCH块的环境变量“宏”,以及抛出异常.

在可以实现TRY / CATCH块之前,必须使用以下命令定义宏:

call exception init

然后TRY / CATCH块用以下语法定义:

:calledRoutine
setlocal
%@Try%
  REM normal code goes here
%@EndTry%
:@Catch
  REM Exception handling code goes here
:@EndCatch

可以随时通过以下方式抛出异常:

call exception throw  errorNumber  "messageString"  "locationString"

当抛出异常时,它会使用(GOTO)2> NUL迭代地弹出CALL堆栈,直到它找到一个活动的TRY / CATCH,然后它分支到CATCH块并执行该代码.一系列异常属性变量可用于CATCH块:

> exception.Code – 数字异常代码
> exception.Msg – 异常消息字符串
> exception.Loc – 描述抛出异常的位置的字符串
> exception.Stack – 一个从CATCH块跟踪调用堆栈(或命令行,如果没有被捕获)的字符串,一直到异常来源.

如果异常被完全处理,则应该通过调用异常清除来清除异常,并且该脚本正常进行.如果异常没有被完全处理,那么一个新的异常可以抛出一个全新的异常.堆栈或旧的堆栈可以保存与

call exception rethrow  errorNumber  "messageString"  "locationString"

如果未处理异常,则会打印一个“未处理的异常”消息,包括四个异常属性,所有批处理都将终止,并将控制返回到命令行上下文.

以下是使所有这些可能的代码 – 完整的文档嵌入在脚本中,并可以通过异常帮助或异常/?从命令行获取.

EXCEPTION.BAT

::EXCEPTION.BAT Version 1.4
::
:: Provides exception handling for Windows batch scripts.
::
:: Designed and written by Dave Benham,with important contributions from
:: DosTips users jeb and siberia-man
::
:: Full documentation is at the bottom of this script
::
:: History:
::   v1.4 2016-08-16  Improved detection of command line delayed expansion
::                    using an original idea by jeb
::   v1.3 2015-12-12  Added paged help option via MORE
::   v1.2 2015-07-16  Use COMSPEC instead of OS to detect delayed expansion
::   v1.1 2015-07-03  Preserve ! in exception attributes when delayed expansion enabled
::   v1.0 2015-06-26  Initial versioned release with embedded documentation
::
@echo off
if "%~1" equ "/??" goto pagedHelp
if "%~1" equ "/?" goto help
if "%~1" equ "" goto help
shift /1 & goto %1


:throw  errCode  errMsg  errLoc
set "exception.Stack="
:: Fall through to :rethrow


:rethrow  errCode  errMsg  errLoc
setlocal disableDelayedExpansion
if not defined exception.Restart set "exception.Stack=[%~1:%~2] %exception.Stack%"
for /f "delims=" %%1 in ("%~1") do for /f "delims=" %%2 in ("%~2") do for /f "delims=" %%3 in ("%~3") do (
  setlocal enableDelayedExpansion
  for /l %%# in (1 1 10) do for /f "delims=" %%s in (" !exception.Stack!") do (
    (goto) 2>NUL
    setlocal enableDelayedExpansion
    if "!!" equ "" (
      endlocal
      setlocal disableDelayedExpansion
      call set "funcName=%%~0"
      call set "batName=%%~f0"
      if defined exception.Restart (set "exception.Restart=") else call set "exception.Stack=%%funcName%%%%s"
      setlocal EnableDelayedExpansion
      if !exception.Try! == !batName!:!funcName! (
        endlocal
        endlocal
        set "exception.Code=%%1"
        if "!!" equ "" (
          call "%~f0" setDelayed
        ) else (
          set "exception.Msg=%%2"
          set "exception.Loc=%%3"
          set "exception.Stack=%%s"
        )
        set "exception.Try="
        (CALL )
        goto :@Catch
      )
    ) else (
      for %%V in (Code Msg Loc Stack Try Restart) do set "exception.%%V="
      if "^!^" equ "^!" (
        call "%~f0" showDelayed
      ) else (
        echo(
        echo Unhandled batch exception:
        echo   Code = %%1
        echo   Msg  = %%2
        echo   Loc  = %%3
        echo   Stack=%%s
      )
      echo on
      call "%~f0" Kill
    )>&2
  )
  set exception.Restart=1
  setlocal disableDelayedExpansion
  call "%~f0" rethrow %1 %2 %3
)
:: Never reaches here


:init
set "@Try=call set exception.Try=%%~f0:%%~0"
set "@EndTry=set "exception.Try=" & goto :@endCatch"
:: Fall through to :clear


:clear
for %%V in (Code Msg Loc Stack Restart Try) do set "exception.%%V="
exit /b


:Kill - Cease all processing,ignoring any remaining cached commands
setlocal disableDelayedExpansion
if not exist "%temp%\Kill.Yes" call :buildYes
call :CtrlC <"%temp%\Kill.Yes" 1>nul 2>&1
:CtrlC
@cmd /c exit -1073741510

:buildYes - Establish a Yes file for the language used by the OS
pushd "%temp%"
set "yes="
copy nul Kill.Yes >nul
for /f "delims=(/ tokens=2" %%Y in (
  '"copy /-y nul Kill.Yes <nul"'
) do if not defined yes set "yes=%%Y"
echo %yes%>Kill.Yes
popd
exit /b


:setDelayed
setLocal disableDelayedExpansion
for %%. in (.) do (
  set "v2=%%2"
  set "v3=%%3"
  set "vS=%%s"
)
(
  endlocal
  set "exception.Msg=%v2:!=^!%"
  set "exception.Loc=%v3:!=^!%"
  set "exception.Stack=%vS:!=^!%"
)
exit /b


:showDelayed -
setLocal disableDelayedExpansion
for %%. in (.) do (
  set "v2=%%2"
  set "v3=%%3"
  set "vS=%%s"
)
for /f "delims=" %%2 in ("%v2:!=^!%") do for /f "delims=" %%3 in ("%v3:!=^!%") do for /f "delims=" %%s in ("%vS:!=^!%") do (
  endlocal
  echo(
  echo Unhandled batch exception:
  echo   Code = %%1
  echo   Msg  = %%2
  echo   Loc  = %%3
  echo   Stack=%%s
)
exit /b


:-?
:help
setlocal disableDelayedExpansion
for /f "delims=:" %%N in ('findstr /rbn ":::DOCUMENTATION:::" "%~f0"') do set "skip=%%N"
for /f "skip=%skip% tokens=1* delims=:" %%A in ('findstr /n "^" "%~f0"') do echo(%%B
exit /b


:-??
:pagedHelp
setlocal disableDelayedExpansion
for /f "delims=:" %%N in ('findstr /rbn ":::DOCUMENTATION:::" "%~f0"') do set "skip=%%N"
((for /f "skip=%skip% tokens=1* delims=:" %%A in ('findstr /n "^" "%~f0"') do @echo(%%B)|more /e) 2>nul
exit /b


:-v
:/v
:version
echo(
for /f "delims=:" %%A in ('findstr "^::EXCEPTION.BAT" "%~f0"') do echo %%A
exit /b


:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:::DOCUMENTATION:::

EXCEPTION.BAT is a pure batch script utility that provides robust exception
handling within batch scripts. It enables code to be placed in TRY/CATCH blocks.
If no exception is thrown,then only code within the TRY block is executed.
If an exception is thrown,the batch CALL stack is popped repeatedly until it
reaches an active TRY block,at which point control is passed to the associated
CATCH block and normal processing resumes from that point. Code within a CATCH
block is ignored unless an exception is thrown.

An exception may be caught in a different script from where it was thrown.

If no active TRY is found after throwing an exception,then an unhandled
exception message is printed to stderr,all processing is terminated within the
current CMD shell,and control is returned to the shell command line.

TRY blocks are specified using macros. ObvIoUsly the macros must be defined
before they can be used. The TRY macros are defined using the following CALL

    call exception init

Besides defining @Try and @EndTry,the init routine also explicitly clears any
residual exception that may have been left by prior processing.

A TRY/CATCH block is structured as follows:

    %@Try%
      REM any normal code goes here
    %@EndTry%
    :@Catch
      REM exception handling code goes here
    :@EndCatch

- Every TRY must have an associated CATCH.

- TRY/CATCH blocks cannot be nested.

- Any script or :labeled routine that uses TRY/CATCH must have at least one
  SETLOCAL prior to the appearance of the first TRY.

- TRY/CATCH blocks use labels,so they should not be placed within parentheses.
  It can be done,but the parentheses block is broken when control is passed to
  the :@Catch or :@EndCatch label,and the code becomes difficult to interpret
  and maintain.

- Any valid code can be used within a TRY or CATCH block,including CALL,GOTO,:labels,and balanced parentheses. However,GOTO cannot be used to leave a
  TRY block. GOTO can only be used within a TRY block if the label appears
  within the same TRY block.

- GOTO must never transfer control from outside TRY/CATCH to within a TRY or
  CATCH block.

- CALL should not be used to call a label within a TRY or CATCH block.

- CALLed routines containing TRY/CATCH must have labels that are unique within
  the script. This is generally good batch programming practice anyway.
  It is OK for different scripts to share :label names.

- If a script or routine recursively CALLs itself and contains TRY/CATCH,then
  it must not throw an exception until after execution of the first %@Try%

Exceptions are thrown by using

    call exception throw  Code  Message  Location

where

    Code = The numeric code value for the exception.

    Message = A description of the exception.

    Location = A string that helps identify where the exception occurred.
               Any value may be used. A good generic value is "%~f0[%~0]",which expands to the full path of the currently executing
               script,followed by the currently executing routine name
               within square brackets.

The Message and Location values must be quoted if they contain spaces or poison
characters like & | < >. The values must not contain additional internal quotes,and they must not contain a caret ^.

The following variables will be defined for use by the CATCH block:

  exception.Code  = the Code value
  exception.Msg   = the Message value
  exception.Loc   = the Location value
  exception.Stack = traces the call stack from the CATCH block (or command line
                    if not caught),all the way to the exception.

If the exception is not caught,then all four values are printed as part of the
"unhandled exception" message,and the exception variables are not defined.

A CATCH block should always do ONE of the following at the end:

- If the exception has been handled and processing can continue,then clear the
  exception deFinition by using

    call exception clear

  Clear should never be used within a Try block.

- If the exception has not been fully handled,then a new exception should be
  thrown which can be caught by a higher level CATCH. You can throw a new
  exception using the normal THROW,which will clear exception.Stack and any
  higher CATCH will have no awareness of the original exception.

  Alternatively,you may rethrow an exception and preserve the exeption stack
  all the way to the original exception:

    call exception rethrow  Code  Message  Location

  It is your choice as to whether you want to pass the original Code and/or
  Message and/or Location. Either way,the stack will preserve all exceptions
  if rethrow is used.

  Rethrow should only be used within a CATCH block.


One last restriction - the full path to EXCEPTION.BAT must not include ! or ^.


This documentation can be accessed via the following commands

    constant stream:   exception /?   OR  exception help
    paged via MORE:    exception /??  OR  exception pagedHelp

The version of this utility can be accessed via

    exception /v  OR  exception version


EXCEPTION.BAT was designed and written by Dave Benham,with important
contributions from DosTips users jeb and siberia-man.

Development history can be traced at:
  http://www.dostips.com/forum/viewtopic.PHP?f=3&t=6497

以下是测试EXCEPTION.BAT功能的脚本.该脚本递归调用自身7次.每个迭代都有两个CALL,一个到a:标签,表示正常的异常传播,另一个到演示脚本CALL的异常传播的脚本.

当从递归调用返回时,如果迭代计数是3的倍数(迭代3和6),则会抛出异常.

每个CALL都有自己的异常处理程序,通常会报告异常,然后重新抛出一个修改的异常.但如果迭代次数为5,那么处理异常并恢复正常处理.

@echo off

:: Main
setlocal enableDelayedExpansion
if not defined @Try call exception init

set /a cnt+=1
echo Main Iteration %cnt% - Calling :Sub
%@Try%
(
  call :Sub
  call echo Main Iteration %cnt% - :Sub returned %%errorlevel%%
)
%@EndTry%
:@Catch
  setlocal enableDelayedExpansion
  echo(
  echo Main Iteration %cnt% - Exception detected:
  echo   Code     = !exception.code!
  echo   Message  = !exception.msg!
  echo   Location = !exception.loc!
  echo Rethrowing modified exception
  echo(
  endlocal
  call exception rethrow -%cnt% "Main Exception^!" "%~f0<%~0>"
:@EndCatch
echo Main Iteration %cnt% - Exit
exit /b %cnt%


:Sub
setlocal
echo :Sub Iteration %cnt% - Start
%@Try%
  if %cnt% lss 7 (
    echo :Sub Iteration %cnt% - Calling "%~f0"
    call "%~f0"
    %= Show any non-exception return code (demonstrate ERRORLEVEL is preserved if no exception) =%
    call echo :Sub Iteration %cnt% - testException returned %%errorlevel%%
  )
  %= Throw an exception if the iteration count is a multiple of 3 =%
  set /a "1/(cnt%%3)" 2>nul || (
    echo Throwing exception
    call exception throw -%cnt% "Divide by 0 exception^!" "%~f0<%~0>"
  )
%@EndTry%
:@Catch
  setlocal enableDelayedExpansion
  echo(
  echo :Sub Iteration %cnt% - Exception detected:
  echo   Code     = !exception.code!
  echo   Message  = !exception.msg!
  echo   Location = !exception.loc!
  endlocal
  %= Handle the exception if iteration count is a multiple of 5,else rethrow it with new properties =%
  set /a "1/(cnt%%5)" 2>nul && (
    echo Rethrowing modified exception
    echo(
    call exception rethrow -%cnt% ":Sub Exception^!" "%~f0<%~0>"
  ) || (
    call exception clear
    echo Exception handled
    echo(
  )
:@EndCatch
echo :Sub Iteration %cnt% - Exit
exit /b %cnt%

– 输出 –

Main Iteration 1 - Calling :Sub
:Sub Iteration 1 - Start
:Sub Iteration 1 - Calling "C:\test\testException.bat"
Main Iteration 2 - Calling :Sub
:Sub Iteration 2 - Start
:Sub Iteration 2 - Calling "C:\test\testException.bat"
Main Iteration 3 - Calling :Sub
:Sub Iteration 3 - Start
:Sub Iteration 3 - Calling "C:\test\testException.bat"
Main Iteration 4 - Calling :Sub
:Sub Iteration 4 - Start
:Sub Iteration 4 - Calling "C:\test\testException.bat"
Main Iteration 5 - Calling :Sub
:Sub Iteration 5 - Start
:Sub Iteration 5 - Calling "C:\test\testException.bat"
Main Iteration 6 - Calling :Sub
:Sub Iteration 6 - Start
:Sub Iteration 6 - Calling "C:\test\testException.bat"
Main Iteration 7 - Calling :Sub
:Sub Iteration 7 - Start
:Sub Iteration 7 - Exit
Main Iteration 7 - :Sub returned 7
Main Iteration 7 - Exit
:Sub Iteration 6 - testException returned 7
Throwing exception

:Sub Iteration 6 - Exception detected:
  Code     = -6
  Message  = Divide by 0 exception!
  Location = C:\test\testException.bat<:Sub>
Rethrowing modified exception


Main Iteration 6 - Exception detected:
  Code     = -6
  Message  = :Sub Exception!
  Location = C:\test\testException.bat<:Sub>
Rethrowing modified exception


:Sub Iteration 5 - Exception detected:
  Code     = -6
  Message  = Main Exception!
  Location = C:\test\testException.bat<C:\test\testException.bat>
Exception handled

:Sub Iteration 5 - Exit
Main Iteration 5 - :Sub returned 5
Main Iteration 5 - Exit
:Sub Iteration 4 - testException returned 5
:Sub Iteration 4 - Exit
Main Iteration 4 - :Sub returned 4
Main Iteration 4 - Exit
:Sub Iteration 3 - testException returned 4
Throwing exception

:Sub Iteration 3 - Exception detected:
  Code     = -3
  Message  = Divide by 0 exception!
  Location = C:\test\testException.bat<:Sub>
Rethrowing modified exception


Main Iteration 3 - Exception detected:
  Code     = -3
  Message  = :Sub Exception!
  Location = C:\test\testException.bat<:Sub>
Rethrowing modified exception


:Sub Iteration 2 - Exception detected:
  Code     = -3
  Message  = Main Exception!
  Location = C:\test\testException.bat<C:\test\testException.bat>
Rethrowing modified exception


Main Iteration 2 - Exception detected:
  Code     = -2
  Message  = :Sub Exception!
  Location = C:\test\testException.bat<:Sub>
Rethrowing modified exception


:Sub Iteration 1 - Exception detected:
  Code     = -2
  Message  = Main Exception!
  Location = C:\test\testException.bat<C:\test\testException.bat>
Rethrowing modified exception


Main Iteration 1 - Exception detected:
  Code     = -1
  Message  = :Sub Exception!
  Location = C:\test\testException.bat<:Sub>
Rethrowing modified exception


Unhandled batch exception:
  Code = -1
  Msg  = Main Exception!
  Loc  = C:\test\testException.bat<testException>
  Stack= testException [-1:Main Exception!]  :Sub [-1::Sub Exception!]  C:\test\testException.bat [-2:Main Exception!]  :Sub [-2::Sub Exception!]  C:\test\testException.bat [-3:Main Exception!]  :Sub [-3::Sub Exception!]  [-3:Divide by 0 exception!]

最后,这里是一系列简单的脚本,显示了即使中间脚本对它们没有任何知识也可以有效地使用异常!

开始使用一个简单的分割脚本实用程序,分割两个数字并打印结果:

divide.bat

:: divide.bat  numerator  divisor
@echo off
setlocal
set /a result=%1 / %2 2>nul || call exception throw -100 "Division exception" "divide.bat"
echo %1 / %2 = %result%
exit /b

请注意,如果脚本检测到错误,脚本会引发异常,但是它不会捕获异常.

现在我将编写一个对批处理异常完全天真的分割测试工具.

testDivide.bat

@echo off
for /l %%N in (4 -1 0) do call divide 12 %%N
echo Finished successfully!

–OUTPUT–

C:\test>testDivide
12 / 4 = 3
12 / 3 = 4
12 / 2 = 6
12 / 1 = 12

Unhandled batch exception:
  Code = -100
  Msg  = Division exception
  Loc  = divide.bat
  Stack= testDivide divide [-100:Division exception]

请注意,由于没有处理由divide.bat引发的异常,最终的ECHO将不会执行.

最后我会写一个主脚本,调用天真的testDivide并正确处理异常:

master.bat

@echo off
setlocal
call exception init

%@Try%
  call testDivide
%@EndTry%
:@Catch
  echo %exception.Msg% detected and handled
  call exception clear
:@EndCatch
echo Finished Successfully!

– 输出 –

C:\test>master
12 / 4 = 3
12 / 3 = 4
12 / 2 = 6
12 / 1 = 12
Division exception detected and handled
Finished Successfully!

主脚本能够成功地捕获由divide.bat引发的异常,即使它必须通过testDivide.bat,它不了解异常.很酷 :-)

现在,这并不是所有与错误处理有关的事情的灵丹妙药:

>有许多语法和代码布局限制,在内置文档中已经完全描述.但没有什么太糟糕.
>没有办法自动将所有错误视为例外.所有异常必须由代码显式抛出.这可能是一件好事,因为错误报告是按惯例处理的 – 没有严格的规则.一些程序不符合惯例.例如,HELP ValidCommand返回ERRORLEVEL 1,这通常意味着一个错误,而HELP InvalidCommand返回ERRORLEVEL 0,这意味着成功.
>此批处理异常技术无法捕获并处理致命的运行时错误.例如GOTO:NonExistentLabel仍然会立即终止所有批处理,没有任何机会来捕获错误.

您可以在http://www.dostips.com/forum/viewtopic.php?f=3&t=6497跟随EXCEPTION.BAT的发展.将来会发布任何未来的发展.我可能不会更新此StackOverflow文章.

批处理文件 – Windows批处理是否支持异常处理?的更多相关文章

  1. iOS 10 Safari问题在DOM中不再包含元素

    使用此链接,您可以重现该错误.https://jsfiddle.net/pw7e2j3q/如果您点击元素并从dom中删除它,然后单击链接测试.你应该看到旧的元素弹出选择.是否有一些黑客来解决这个问题?解决方法我能够重现这个问题.问题是,每当您尝试删除其更改事件上的选择框时,iOS10都无法正确解除对选择框的绑定.要解决此问题,您需要将代码更改事件代码放在具有一些超时

  2. ios – 有没有办法针对存档版本(.ipa)运行XCTest(UI)?

    要么我们可以单独构建和测试,以便我们可以先构建并在以后对该构建进行测试吗?

  3. ios app如何“知道”运行单元测试

    我知道我可以用xcodebuild开始我的应用程序的单元测试,但我想知道是什么告诉应用程序在启动期间运行测试,它是一个发送到应用程序的特殊参数,还是以不同的方式编译以运行测试?

  4. ios – 我可以安全地在@try catch块中包装’CoreData无法解决错误’错误

    )是的,我偶尔会得到’CoreData无法完成故障’的错误.在我的特定应用程序中,这通常发生在一种“数据绑定”过程中,因此我可以安全地丢弃故障对象并继续前进.我想通过在@try-catch块中包装数据绑定的循环内部并且只跳过我得到CoreData错误的行来完成此操作.我可以使用CoreData安全地执行此操作吗?

  5. 你如何压缩iOS上的Realm DB?

    我想定期在iOS上压缩一个Realm实例来恢复空间.我认为该过程是将数据库复制到临时位置,然后将其复制回来并使用新的default.realm文件.我的问题是Realm()就像一个单例并且回收对象,所以我无法真正关闭它并告诉它打开新的default.realm文件.这里的文档(https://realm.io/docs/objc/latest/api/Classes/RLMRealm.html)建

  6. ios – 如何在Swift中正确转换为子类?

    我有一个带有许多不同单元格的UITableView,基于数据源内容数组中的内容,它们应该显示自定义内容.在这里我得到了错误UITableViewCell没有属性customLabelQuestionTableViewCell有哪些.我的演员到QuestionTableViewCell有什么问题?解决方法问题不是你的演员,而是你的细胞宣言.您将其声明为可选的UITableViewCell,并且该声明

  7. xcode – 添加OCMock会导致Test启动主应用程序而不是运行测试

    我正在尝试将Ocmock添加到我现有的Cocoa项目中,但我遇到了一个我没有看到其他人覆盖的奇怪问题.我最终将它分离到以下内容:如果我只是将Ocmock.framework引用添加到我的项目中(即以某种方式将其拖到LinkBinaryWithLibraries构建阶段),当我运行测试时,真正的应用程序将被启动.没有Ocmock,输出正常:使用Ocmock框架链接(部分输出):此后,其他应用程序输出

  8. Xcode:用于条件DEBUG / TEST代码的预处理器宏

    我在我的代码(例如AppDelegate.m)中有不应该为单元测试编译的部分,例如当您在创建新项目时选择“添加单元测试”时,目标是由Xcode设置的.在项目文件中,我已将标志CONfigURATION_TESTS添加到内置目标的MyAppTests的预处理器宏中,但未添加到MyApp目标.这是我发现的许多帖子中的建议方式.但是这不起作用,因为(我猜)MyAppTests目标将MyApp目标作为依赖

  9. ios – 嵌套递归函数

    我试图做一个嵌套递归函数,但是当我编译时,编译器崩溃.这是我的代码:编译器记录arehere解决方法有趣的…它似乎也许在尝试在定义之前捕获到内部的引用时,它是bailing?以下修复它为我们:当然没有嵌套,我们根本没有任何问题,例如以下工作完全如预期:我会说:报告!

  10. ios – 捕获NSKeyedUnarchiver异常

    在Swift中,如果无法取消存档数据,NSKeyedUnarchiver.unarchiveObjectWithData(data)将抛出异常.在某些情况下,我们无法保证数据是否未损坏,例如从文件读取时.我不知道Swift中的try/catch机制,也不知道像canUnarchive这样有助于防止异常的方法.除了在Obj-C中实现try/catch之外,还有一个纯Swift解决方案来解决这个问题吗

随机推荐

  1. static – 在页面之间共享数据的最佳实践

    我想知道在UWP的页面之间发送像’selectedItem’等变量的最佳做法是什么?创建一个每个页面都知道的静态全局变量类是一个好主意吗?

  2. .net – 为Windows窗体控件提供百分比宽度/高度

    WindowsForm开发的新手,但在Web开发方面经验丰富.有没有办法为Windows窗体控件指定百分比宽度/高度,以便在用户调整窗口大小时扩展/缩小?当窗口调整大小时,可以编写代码来改变控件的宽度/高度,但我希望有更好的方法,比如在HTML/CSS中.在那儿?

  3. 使用Windows Azure查询表存储数据

    我需要使用特定帐户吗?>将应用程序部署到Azure服务后,如何查询数据?GoogleAppEngine有一个数据查看器/查询工具,Azure有类似的东西吗?>您可以看到的sqlExpressintance仅在开发结构中,并且一旦您表示没有等效,所以请小心使用它.>您可以尝试使用Linqpad查询表格.看看JamieThomson的thispost.

  4. windows – SetupDiGetClassDevs是否与文档中的设备实例ID一起使用?

    有没有更好的方法可以使用DBT_DEVICEARRIVAL事件中的数据获取设备的更多信息?您似乎必须指定DIGCF_ALLCLASSES标志以查找与给定设备实例ID匹配的所有类,或者指定ClassGuid并使用DIGCF_DEFAULT标志.这对我有用:带输出:

  5. Windows Live ID是OpenID提供商吗?

    不,WindowsLiveID不是OpenID提供商.他们使用专有协议.自从他们的“测试版”期结束以来,他们从未宣布计划继续它.

  6. 如果我在代码中进行了更改,是否需要重新安装Windows服务?

    我写了一个Windows服务并安装它.现在我对代码进行了一些更改并重新构建了解决方案.我还应该重新安装服务吗?不,只需停止它,替换文件,然后重新启动它.

  7. 带有双引号的字符串回显使用Windows批处理输出文件

    我正在尝试使用Windows批处理文件重写配置文件.我循环遍历文件的行并查找我想要用指定的新行替换的行.我有一个’函数’将行写入文件问题是%Text%是一个嵌入双引号的字符串.然后失败了.可能还有其他角色也会导致失败.如何才能使用配置文件中的所有文本?尝试将所有“在文本中替换为^”.^是转义字符,因此“将被视为常规字符你可以尝试以下方法:其他可能导致错误的字符是:

  8. .net – 将控制台应用程序转换为服务?

    我正在寻找不同的优势/劣势,将我们长期使用的控制台应用程序转换为Windows服务.我们为ActiveMQ使用了一个叫做java服务包装器的东西,我相信人们告诉我你可以用它包装任何东西.这并不是说你应该用它包装任何东西;我们遇到了这个问题.控制台应用程序是一个.NET控制台应用程序,默认情况下会将大量信息记录到控制台,尽管这是可配置的.任何推荐?我们应该在VisualStudio中将其重建为服务吗?我使用“-install”/“-uninstall”开关执行此操作.例如,seehere.

  9. windows – 捕获外部程序的STDOUT和STDERR *同时*它正在执行(Ruby)

    哦,我在Windows上:-(实际上,它比我想象的要简单,这看起来很完美:…是的,它适用于Windows!

  10. windows – 当我试图批量打印变量时,为什么我得到“Echo is on”

    我想要执行一个简单的批处理文件脚本:当我在XP中运行时,它给了我预期的输出,但是当我在Vista或Windows7中运行它时,我在尝试打印值时得到“EchoisOn”.以下是程序的输出:摆脱集合表达式中的空格.等号(=)的两侧可以并且应该没有空格BTW:我通常在@echo关闭的情况下启动所有批处理文件,并以@echo结束它们,所以我可以避免将代码与批处理文件的输出混合.它只是使您的批处理文件输出更好,更清洁.

返回
顶部