วันอาทิตย์ที่ 7 เมษายน พ.ศ. 2556

ปูพื้นฐานแบตช์ไฟล์ 4

อา...และแล้ววันนี้...จะปูพื้นฐานอะไรดี...เกี่ยวกับ แบตช์ไฟล์ ล่อของยากเลย...วันนี้จัดหนักด้วยคำสั่ง If ว่าแล้วก็ร่ายภาษาอังกฤษมา...
if /? >HelpIf.TXT
อ่ะเปิดดู

Performs conditional processing in batch programs.

IF [NOT] ERRORLEVEL number command
IF [NOT] string1==string2 command
IF [NOT] EXIST filename command

  NOT               Specifies that Windows XP should carry out
                    the command only if the condition is false.

  ERRORLEVEL number Specifies a true condition if the last program run
                    returned an exit code equal to or greater than the
                    specified.

  string1==string2  Specifies a true condition if the specified text st
                    match.

  EXIST filename    Specifies a true condition if the specified filenam
                    exists.

  command           Specifies the command to carry out if the condition
                    met.  Command can be followed by ELSE command which
                    will execute the command after the ELSE keyword if
                    specified condition is FALSE

The ELSE clause must occur on the same line as the command after the IF
example:

    IF EXIST filename. (
        del filename.
    ) ELSE (
        echo filename. missing.
    )

The following would NOT work because the del command needs to be termin
by a newline:

    IF EXIST filename. del filename. ELSE echo filename. missing

Nor would the following work, since the ELSE command must be on the sam
as the end of the IF command:

    IF EXIST filename. del filename.
    ELSE echo filename. missing

The following would work if you want it all on one line:

    IF EXIST filename. (del filename.) ELSE echo filename. missing

If Command Extensions are enabled IF changes as follows:

    IF [/I] string1 compare-op string2 command
    IF CMDEXTVERSION number command
    IF DEFINED variable command

where compare-op may be one of:

    EQU - equal
    NEQ - not equal
    LSS - less than
    LEQ - less than or equal
    GTR - greater than
    GEQ - greater than or equal

and the /I switch, if specified, says to do case insensitive string
compares.  The /I switch can also be used on the string1==string2 form
of IF.  These comparisons are generic, in that if both string1 and
string2 are both comprised of all numeric digits, then the strings are
converted to numbers and a numeric comparison is performed.

The CMDEXTVERSION conditional works just like ERRORLEVEL, except it is
comparing against an internal version number associated with the Comman
Extensions.  The first version is 1.  It will be incremented by one whe
significant enhancements are added to the Command Extensions.
CMDEXTVERSION conditional is never true when Command Extensions are
disabled.

The DEFINED conditional works just like EXISTS except it takes an
environment variable name and returns true if the environment variable
is defined.

%ERRORLEVEL% will expand into a string representation of
the current value of ERRORLEVEL, provided that there is not already
an environment variable with the name ERRORLEVEL, in which case you
will get its value instead.  After running a program, the following
illustrates ERRORLEVEL use:

    goto answer%ERRORLEVEL%
    :answer0
    echo Program had return code 0
    :answer1
    echo Program had return code 1

You can also using the numerical comparisons above:

    IF %ERRORLEVEL% LEQ 1 goto okay

%CMDCMDLINE% will expand into the original command line passed to
CMD.EXE prior to any processing by CMD.EXE, provided that there is not
already an environment variable with the name CMDCMDLINE, in which case
you will get its value instead.

%CMDEXTVERSION% will expand into a string representation of the
current value of CMDEXTVERSION, provided that there is not already
an environment variable with the name CMDEXTVERSION, in which case you

ใครเก่งภาษาอังกฤษ...ก็แปลไป...อาจจะเป็นโปรแกรมเมอร์มือฉมัง...ส่วนผม...ฮ่าฮ่าฮ่า...อ่านไม่ออก เดาอีกแล้วครับท่าน...
IF [NOT] ERRORLEVEL number command ; การทำงานคือ ถ้า DOS หรือโปรแกรมบน DOS มีการส่งค่า ตัวเลขผ่านโปรแกรมมาเป็น เลขใด... ให้ทำงานในคำสั่งที่ระบุ
***เสริม...หลายคนอาจงงว่า...แบทช์ไฟล์มีแต่รับค่า Errorlevel แต่จะส่งค่านี้บ้างทำยังไง ***ตอบจากประสบการณ์ ว่า ไม่ได้ถ้าผ่านแบตช์ไฟล์ แต่ถ้ายิงสคริปคำสั่งผ่าน DeBug.EXE นั้นทำได้ เช่นถ้าจะส่ง Errorlevel 5 ไปยังโมดูลอื่น...ต้องสร้างสคริปคำสั่งของ DeBug.EXE ดังนี้

echo N 5.com>5.Scr ; หมายถึงสร้างแฟ้ม 5.com ผ่านแฟ้ม 5.Scr
echo A 100>>5.Scr ; ไปยังตำแหน่ง Assembler ของ DOS
echo mov AX,4C05>>5.Scr ; คำสั่ง Assembly หมายถึง เรียก ฟักช์ชั่น 4C ส่งคืนค่า Errorlevel คือ 05 หรือ 5 ฐานสิบ
echo int 21>>5.Scr ; เรียกดอสอินเตอร์รัพต์
echo RCX>>5.Scr ; สคริปดีบักอ่านค่าในรีจีสเตอร์ CX
echo 5>>5.Scr ; ค่าที่อ่านคือ 5 (เพื่อเขียน 5.com 5 Byte)
echo W>>5.Scr ; สคริปดีบักเขียนแฟ้ม
echo Q>>5.Scr ; สคริปดีบักออก
debug<5.scr ; ดีบักคอมพายน์สคริป Scr

และเรียก 5.comทำงานตานนี้

5.com ; เรียก 5.com ทำงาน
echo ErrorLevel Is %errorlevel% ; ผลที่ได้คือ แสดงหมายเลข Errorlevel
pause ; หยุดหน้าจอชั่วคราว...รอรับคีย์

ส่วนการทำงานเชิงลึกของ DeBug.EXE ...ขอ อุ๊บ! ไว้ก่อนให้ติดตามต่อไป***
จากตัวอย่างจะแสดงให้เห็นว่า... Errorlevel นี้จริงๆ แล้วมันเป็นการ Interface หรือการเชื่อมต่อกับโปรแกรม Application ของ DOS กับแบตช์ไฟล์ ผ่าน บริการ 4C ดอสอินเตอร์รัพต์ นั้นเอง ซึ่งผมลองประยุกต์ใช้ echo ret 05 ; คำสั่ง Assembly คืนค่าผ่าน Return ในรีจีสเตอร์ AL เช่นกัน แต่ทำงานกับ
แบตช์ไฟล์เองไม่ได้...จึงต้องใช้งานวิธีทีเดิมต่อไป เมื่อนำ 5.com มาทดสอบจะเป็นดังนี้

5.com ; เรียก 5.com ทำงาน
IF NOT ERRORLEVEL 5 Msg %username% "IF NOT ERRORLEVEL 5 ถูกข้ามไป..." ; คำสั่งนี้...จะถูกเมินเฉยเพราะ IF NOT ERRORLEVEL 5 มันหมายความว่าไม่เท่ากับ Errorlevel 5
IF ERRORLEVEL 5 Msg %username% "เกิดข้อผิดพลาดหมายเลข 5 นะจ๊ะ" ; ในคำสั่งนี้เอง DOS จะทำงานทันที
IF NOT ERRORLEVEL 5 Msg %username% "IF NOT ERRORLEVEL 5 ยังทำงานนะ" ; ในคำสั่งนี้ก็เช่นกัน DOS ก็ทำงานถึงแม้จะมีความหมายไม่เหมือนบรรทัดบน...แต่มันรวมถึง Errorlevel 4 ถึง Errorlevel 1 ด้วย มันจึงทำงาน

IF [NOT] string1==string2 command
IF [NOT] string1==string2 command ; คือการเปรียบเทียบข้อความ...ร่วมถึงตัวเลขด้วย (COMMAND.COM คำนวนตัวเลขไม่ได้) ซึ่งปัจจุบัน... DOS ฉลาดขึ้นมาก เทียบชั้นภาษาระดับสูง ทำให้มันมีความซับซ้อนกว่าแต่ก่อนมากมาย

IF A==a Msg %Username% "A เท่ากับ a" ; คำสั่งนี้...มันจะเปรียบเทียบ A ตัวพิมพ์ใหญ่ เท่ากับ a ตัวพิมพ์เล็กหรือไม่
IF NOT A==a Msg %Username% "A ไม่เท่ากับ a" ; คำสั่งนี้...มันจะเปรียบเทียบ A ตัวพิมพ์ใหญ่ ไม่เท่ากับ a ตัวพิมพ์เล็กหรือไม่
***ผลที่ได้คือ มันไม่เท่ากัน

ทีนี้...รู้สึกว่า...การเขียนโปรแกรมแบบเปรียบเทียบที่ละบรรทัด...มันเป็นภาษาแบตช์ไฟล์ยุคโบราณที่เราเรียกมันว่า "อินเตอร์พลีต" หรือ "ทำงานทีละบรรทัด" ความเป็นจริง CMD.EXE ก็ยังให้แบตช์ไฟล์ทำงานอย่างนั้นอยู่...เพียงแต่เพิ่มลูกเล่นให้เขียนเหมือนภาษาระดับสูง แบบ C++
เรียนแบบภาษาโครงสร้างเพื่อความสบรูณ์แบบและเข้าใจง่าย...และมันก็ทำได้ดี เราจึงไม่นิยมเขียนการเปรียบเทียบคำสั่งแบตช์ไฟล์แบบนั้นอีกต่อไปแล้ว...ให้เขียนแบบนี้

IF A==a (Msg %Username% "A เท่ากับ a") ELSE (Msg %Username% "A ไม่เท่ากับ a") ; ความหมายก็เช่นเดิมกับตัวอย่างด้านบนเพียงแต่ว่า ใส่ วงเล็บเพื่อความเข้าใจง่าย...และ ELSE เอง ก็มีความหมายคำสั่งด้านตรงกันข้ามกับ IF จึงนิยามแทนคำว่า NOT ได้เช่นกัน หรือจะเขียนแบบ วรรคให้ตรงกันแบบ โปรแกรมเมอร์ที่ถนัด HTML หรือ C เองก็ตามอย่างนี้

IF A==a (
  Msg %Username% "A เท่ากับ a"
) ELSE (
  Msg %Username% "A ไม่เท่ากับ a"
)
; ความหมายก็เช่นเดิมเหมือนกัน

แต่ผู้เขียนถนัด VB ซึ่งเป็นภาษาแบบบรรทัดยาวๆ จึงเสนอตัวอย่างในโปรแกรมต่อไป...ในรูปแบบที่ผู้เขียนถนัดแล้วกัน

IF A=="A" (Msg %Username% "A เท่ากับ A(เครื่องหมายคำพูด)") ELSE (Msg %Username% "A ไม่เท่ากับ A(เครื่องหมายคำพูด)") ; หมายถึงให้เปรียบเทียบว่า...ถ้ามีเครื่องหมายคำพูด...จะเท่ากันไหม? คำตอบคือ "ไม่เท่ากัน"


IF [NOT] EXIST filename command 
IF [NOT] EXIST filename command ; ค้นหาแฟ้มและโฟลเดอร์ว่ามีอยู่จริงหรือไม่

คำสั่ง
IF EXIST %systemroot%\SYSTEM32\CMD.EXE (
  MSG %username% "พบแฟ้ม CMD.EXE"
) ELSE (
  MSG %username% "ไม่พบแฟ้ม..."
)
*** ผลที่ได้คือ พบแฟ้ม 

ส่วนการหาโฟลเดอร์ที่ต้องการว่ามีอยู่หรือไม่ให้ตามนี้

คำสั่ง
IF EXIST %systemroot%\SYSTEM32 (
  MSG %username% "พบ Folder \System32"
) ELSE (
  MSG %username% "ไม่พบ Folder..."
)

*** ผลที่ได้คือ พบ Folder
EQU - equal
NEQ - not equal
LSS - less than
LEQ - less than or equal
GTR - greater than
GEQ - greater than or equal

การใช้เงื่อนไขเพื่อเปรียบเทียบค่า...
คำสั่ง
IF 1+1 EQU 2 (MSG %USERNAME% "เท่ากัน") ELSE (MSG %USERNAME% "ไม่เท่ากัน") ; ผลคือ ไม่เท่ากัน

คำสั่ง
IF 2 EQU 2 (MSG %USERNAME% "เท่ากัน") ELSE (MSG %USERNAME% "ไม่เท่ากัน") ; ผลคือ เท่ากัน

คำสั่ง
IF 1+1 EQU 1+1 (MSG %USERNAME% "เท่ากัน") ELSE (MSG %USERNAME% "ไม่เท่ากัน") ; ผลคือ เท่ากัน

คำสั่ง
IF 1+1 NEQ 2 (MSG %USERNAME% "ไม่เท่ากัน") ELSE (MSG %USERNAME% "เท่ากัน") ; ผลคือ ไม่เท่ากัน

คำสั่ง
IF 2 NEQ 2 (MSG %USERNAME% "ไม่เท่ากัน") ELSE (MSG %USERNAME% "เท่ากัน") ; ผลคือ เท่ากัน

คำสั่ง
IF 1+1 NEQ 1+1 (MSG %USERNAME% "ไม่เท่ากัน") ELSE (MSG %USERNAME% "เท่ากัน") ; ผลคือ เท่ากัน

คำสั่ง
IF 1 LSS 2 (MSG %USERNAME% "1 น้อยกว่า 2") ELSE (MSG %USERNAME% "1 ไม่น้อยกว่า 2")  ; ผลคือ 1 น้อยกว่า 2

คำสั่ง
IF 2 GTR 1 (MSG %USERNAME% "2 มากกว่า 1") ELSE (MSG %USERNAME% "2 ไม่มากกว่า 1")  ; ผลคือ 2 มากกว่า 1

คำสั่ง
IF 1 LEQ 2 (MSG %USERNAME% "1 น้อยกว่าหรือเท่ากับ 2") ELSE (MSG %USERNAME% "1 ไม่น้อยกว่าเท่ากับ 2")  ; ผลคือ 1 น้อยกว่าหรือเท่ากับ 2

คำสั่ง
IF 2 GEQ 1 (MSG %USERNAME% "2 มากกว่าหรือเท่ากับ 1") ELSE (MSG %USERNAME% "2 ไม่มากกว่าหรือเท่ากับ 1")  ; ผลคือ 2 มากกว่าหรือเท่ากับ 1


IF CMDEXTVERSION number command
IF CMDEXTVERSION number command ; คำสั่งนี้ผู้เขียนยังไม่ทราบแน่ชัดว่า...เกี่ยวกับ Version ยังไงแต่ที่ทดสอบดู

กับ CMD.EXE บนวินโดวส์ 7 เป็นดังนี้

คำสั่ง
IF CMDEXTVERSION 2 MSGBOX %USERNAME% "OK" ; หมายเลข EXTVERSION 2 กล่องข้อความขึ้น OK

IF DEFINED variable command
IF DEFINED variable command ; หมายถึง ถ้ามีการนิยามตัวแปรดังกล่าวให้ทำงานในคำสั่ง...

คำสั่ง
IF DEFINED USERNAME MSG %USERNAME% "พบตัวแปรยูสเซอร์เนมส์...ค่าในตัวแปรคือ %USERNAME%" ; ผลคือแสดงกล่องข้อความและ ค่าในตัวแปร USRENAME

ทีนี้...คราวหน้า...ร่ายยาวเรื่องของ ตัวแปร...Environment

3 ความคิดเห็น:

  1. เยี่ยมครับ อยากรู้ให้ลึกกว่านี้อีก

    ตอบลบ
  2. ไม่ระบุชื่อ7 พฤศจิกายน 2556 02:24

    ขอบคุณครับ อ่านหลายหน้าแล้วครับ ^_^ ได้ความรู้มากเลยครับ

    ตอบลบ