সাবরুটাইন থেকে ব্যাচ ফাইলটি প্রস্থান করুন


20

সাবউটিনের ভিতর থেকে আমি কীভাবে ব্যাচ ফাইল থেকে বেরিয়ে যেতে পারি?

আমি যদি এক্সিট কমান্ডটি ব্যবহার করি তবে আমি কেবল সেই লাইনে ফিরে আসি যেখানে আমি সাবরুটিনকে ডেকেছিলাম এবং মৃত্যুদন্ড কার্যকর হয়।

এখানে একটি উদাহরণ:

@echo off
ECHO Quitting...
CALL :QUIT
ECHO Still here!
GOTO END

:QUIT
EXIT /B 1

:END
EXIT /B 0

আউটপুট:

Quitting...
Still here!

হালনাগাদ:

এটি যথাযথ উত্তর নয়, তবে আমি এর লাইনে কিছু করে শেষ করেছি:

@echo off
CALL :SUBROUTINE_WITH_ERROR || GOTO HANDLE_FAIL
ECHO You shouldn't see this!
GOTO END

:SUBROUTINE_WITH_ERROR
ECHO Simulating failure...
EXIT /B 1

:HANDLE_FAIL
ECHO FAILURE!
EXIT /B 1

:END
ECHO NORMAL EXIT!
EXIT /B 0

এর ডাবল পাইপ বিবৃতি:

CALL :SUBROUTINE_WITH_ERROR || GOTO HANDLE_FAIL

সংক্ষিপ্ত জন্য:

CALL :SUBROUTINE_WITH_ERROR 
IF ERRORLEVEL 1 GOTO HANDLE_FAIL    

আমি এখনও জানতে আগ্রহী যে কলারকে পরিস্থিতিটি পরিচালনা করার পরিবর্তে সাব্রুটিন থেকে সরাসরি প্রস্থান করার উপায় আছে কিনা তবে এটি কমপক্ষে কাজটি সম্পন্ন করে।


আপডেট # 2: উপরের পদ্ধতিতে ডাকা অন্য সাব্রোটিনের মধ্যে থেকে সাব্রুটিন কল করার সময় আমি সাব্রোটাইনগুলির মধ্যে থেকে এইভাবে কল করি:

CALL :SUBROUTINE_WITH_ERROR || EXIT /B 1

এইভাবে, ত্রুটিটি "মূল" পর্যন্ত ফিরে প্রচার করে, তাই কথা বলতে। ব্যাচের প্রধান অংশটি ত্রুটি পরিচালনাকারী GOTO: ব্যর্থতা দিয়ে ত্রুটিটি পরিচালনা করতে পারে

উত্তর:


21

এটি আপনার ব্যাচের ফাইলের শীর্ষে যুক্ত করুন:

@ECHO OFF
SETLOCAL

IF "%selfWrapped%"=="" (
  REM this is necessary so that we can use "exit" to terminate the batch file,
  REM and all subroutines, but not the original cmd.exe
  SET selfWrapped=true
  %ComSpec% /s /c ""%~0" %*"
  GOTO :EOF
)

তারপরে আপনি কেবল কল করতে পারেন:

  • EXIT [errorLevel] আপনি যদি পুরো ফাইলটি থেকে বেরিয়ে আসতে চান
  • EXIT /B [errorLevel] বর্তমান সাবরুটাইন থেকে প্রস্থান করতে
  • GOTO :EOF বর্তমান সাবরুটাইন থেকে প্রস্থান করতে

প্রকৃতপক্ষে উল্লেখের জন্য +1GOTO :EOF
আফরাজায়

1
খুব সুন্দর. আমি একটা ছোট পরিবর্তন, দায়িত্ব অর্পণ করেছি %~0পরিবর্তনশীল পরিবর্তে true: if not "%selfwrapped%"=="%~0" ( set selfwrapped=%~0 .... )। আপনি একে অপরকে কল করে এমন একাধিক ব্যাচের স্ক্রিপ্টগুলিতে একই কৌশলটি ব্যবহার করতে পারেন।
গোলেজট্রোল

এটি একটি দুর্দান্ত সমাধান। আপনি কী মনে করেন যে এটি কীভাবে কাজ করে তা ব্যাখ্যা করার জন্য এটি কোনও সম্পাদনযোগ্য? আমার সমস্ত কিছু আনপ্যাক করতে এবং এটি বুঝতে পেরেছিলাম যে এটি আসলে একটি নেস্টেড সেন্টিমিডি.এক্সে থেকে %~0সমস্ত আর্গুমেন্ট ( %*) দিয়ে ব্যাচ ফাইলকে ( ) ডেকে /sআনে এবং %ComSpec%আর্গুমেন্টটি যেভাবে ডাবল কোটগুলি চারপাশে পরিচালনা করে তা নিয়ন্ত্রণ করতে ব্যবহৃত হয় কল করুন।
শান

@ সিয়ান আমি দেখতে পাচ্ছি যে ব্রিভিটি বেশিরভাগ লোকের জন্য আরও দরকারী। আমি এটি লেখার পর থেকে 7 বছরে আরও ডক্সের জন্য জিজ্ঞাসা করা হয়নি, সুতরাং এটির উচ্চ চাহিদা রয়েছে বলে মনে হয় না। আমি এও মনে করি যে লোকেরা নিজেরাই জিনিসগুলি সন্ধান করছে এবং ডকিং / ফ্রেগমেন্টিং ডক্স না করে তার কিছু মূল্য রয়েছে। তবে হয়ত আরও কিছু লোক জিজ্ঞাসা করলে আমি কিছু যুক্ত করতে পারি। এটি একটি সিডাব্লুও তাই আপনিও কোনও সম্পাদনার প্রস্তাব দিতে পারেন
মের্লিন মরগান-গ্রাহাম

3

এই এক সামান্য সমন্বয় সম্পর্কে?

@echo off
ECHO Quitting...
CALL :QUIT
:: The QUIT subroutine might have set the error code so let's take a look.
IF ERRORLEVEL 1 GOTO :EOF
ECHO Still here!
GOTO END

:QUIT
EXIT /B 1

:END
EXIT /B 0

আউটপুট:

Quitting...

প্রযুক্তিগতভাবে এটি সাবরোটিনের মধ্যে থেকে প্রস্থান করে না। বরং, এটি কেবল সাবউটিনের ফলাফলটি পরীক্ষা করে এবং সেখান থেকে পদক্ষেপ নেয়।


2
ধন্যবাদ, এটি অবশ্যই কাজটি সম্পন্ন করবে এবং আমি যদি এর থেকে আরও ভাল উত্তর না পাই তবে আমাকে তা করতে হবে। তবে, আমি আমার লম্বা এবং জটিল ব্যাচের ফাইলটিতে প্রতিটি কলের পরে সেই লাইনটি আটকাতে চাই না।
বাদামী

1

আপনি যদি পদ্ধতিটি থেকে ফিরে আসতে না চান তবে ব্যবহার করবেন না call: পরিবর্তে ব্যবহার করুন goto

@echo off
ECHO Quitting...
GOTO :QUIT
ECHO Will never be there!
GOTO END

:QUIT
EXIT /B 1

:END
EXIT /B 0

প্রশ্নের মূল বিষয় হ'ল সাবরুটাইনগুলি (কীভাবে কল ব্যবহার করে) এটি কীভাবে করা যায় তাই এটি এর উত্তর দেয় না।
স্টিভ ক্রেন

1

আমি আমার ব্যাচের ফাইলগুলিতে হ্যান্ডলিংয়ে ত্রুটি রেখেছি। আপনি এর মতো ত্রুটি হ্যান্ডলারদের কল করতে পারেন:

CALL :WARNING "This is" "an important" "warning."

এবং এখানে ব্যাচের ফাইলটির সমাপ্তি:

::-------------------------------------------------------------------
::  Decisions
::-------------------------------------------------------------------
:INFO
IF "_DEBUG"=="true" (
  ECHO INFO: %~1
  IF NOT "%~2"=="" ECHO          %~2
  IF NOT "%~3"=="" ECHO          %~3
)
EXIT /B 0
:WARNING
ECHO WARNING: %~1
IF NOT "%~2"=="" ECHO          %~2
IF NOT "%~3"=="" ECHO          %~3
EXIT /B 0
:FAILURE
ECHO FAILURE: %~1
IF NOT "%~2"=="" ECHO          %~2
IF NOT "%~3"=="" ECHO          %~3
pause>nul
:END
ECHO Closing Server.bat script
FOR /l %%a in (5,-1,1) do (TITLE %TITLETEXT% -- closing in %%as&PING.exe -n 2 -w 1 127.0.0.1>nul)

1

এটি বর্তমান প্রসঙ্গে এবং পিতামাতার প্রসঙ্গটি থেকে বেরিয়ে আসবে (অর্থাত্‍ যখন একটি callগভীর সাব্রুটাইন স্ক্রিপ্টের অভ্যন্তরে নির্বাহ করা হবে):

(goto) 2>nul || exit /b

অথবা, যদি আপনার ত্রুটিযুক্ত 0 প্রয়োজন হয়:

(goto) 2>nul || (
    type nul>nul
    exit /b
)

মূলত, (goto) 2>nulত্রুটিযুক্তটিকে 1 এ সেট করে (কোনও ত্রুটি আউটপুট না করে), পিতামৃত প্রসঙ্গে ডাবল পাইপ কার্যকর হওয়ার পরে প্যারেন্ট প্রসঙ্গ এবং কোডে এক্সিকিউশনটি প্রদান করে। type nul>nulত্রুটিযুক্তকে 0 তে সেট করে।

UPD:

একাধিকবার মৃত্যুদণ্ড কার্যকর করার জন্য কয়েকবার শৃঙ্খলাবদ্ধ করুন (goto) 2>nul ||:

(goto) 2>nul || (goto) 2>nul || (goto) 2>nul || (
    type nul>nul
    exit /b
)

প্রসঙ্গটি একবারের পরিবর্তনশীল সংখ্যাকে ফেরত দিতে এখানে একটি পুনরাবৃত্ত সাববারটাইন রয়েছে:

:Kill
(goto) 2>nul || (
    set /a depth=%1-1
    if %1 GEQ 1 (
        call:Kill !depth!
    )
    (goto) 2>nul || (type nul>nul)
)

পুনরাবৃত্তি ফাংশন থেকে কল করা হলে:

@echo off
setlocal EnableDelayedExpansion
call:Recurs 5
echo This won't be printed
exit /b

:Recurs
set /a ri+=1
echo %ri%
if %ri% LSS %1 (
    call:Recurs %1
)
echo This will be printed only once
call:Kill %1
exit /b

আউটপুট হবে:

1
2
3
4
5
This will be printed only once
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.