China DOS Union

-- Unite DOS · Advance DOS · Grow DOS --

Union site: www.cn-dos.net Forum site: www.cn-dos.net/forum
DOS stands for freedom, openness and progress. Let us work hard, learn from the openness and GNU spirit of FreeDOS and Linux, and together build and grow a free GNU GPL world!

中国DOS联盟论坛
The time now is 2026-06-25 14:38
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » [Discussion] The Oddities in Batch Programming DigestI View 35,161 Replies 26
Original Poster Posted 2004-06-20 00:00 ·  中国 山西 运城 联通
元老会员
★★★★
Batchinger
Credits 4,432
Posts 1,512
Joined 2002-10-18 00:00
23-year member
UID 19
Gender Male
Status Offline


The Odd Side of Batch Programming


  The purpose of this topic is to discuss and answer the various technical questions involved in The Odd Side of Batch Programming (http://www.cn-dos.net/forum/viewthread.php?tid=8905).

  I welcome everyone to offer your own opinions and suggestions on the following topics.

  1. Questions about the technologies and techniques involved in that topic;
  2. Improvements to the technologies and techniques involved in that topic;
  3. Topics not covered there, but highly challenging within the field of batch programming;

  At the same time, in order to keep the board tidy and orderly, and also because of my own limitations in time and interest, I ask everyone to avoid raising the following kinds of topics, and I cannot guarantee any reply to them.

  1. Topics that merely praise or contain no real content;
  2. Topics completely unrelated to batch programming;
  3. Topics asking for batch programming materials;
  4. Topics asking for a line-by-line detailed explanation;

  I hope it can help everyone (myself included) deepen our understanding of batch programming and improve our level, and I also hope everyone will do their part to help maintain its order.


[ Last edited by willsort on 2005-10-13 at 13:03 ]
※ Batchinger 致 Bat Fans:请访问 批处理编程的异类 ,欢迎交流与共享批处理编程心得!
Floor 2 Posted 2005-01-17 00:00 ·  中国 山西 大同 中移铁通
元老会员
★★★★
Batchinger
Credits 4,432
Posts 1,512
Joined 2002-10-18 00:00
23-year member
UID 19
Gender Male
Status Offline
FDISK Command-Line Parameters


FDISK is still a very commonly used partitioning tool, and the fact that it supports command-line operation is no longer some “undisclosed secret.” As early as 1999, people had already discovered some special parameters of FDISK and applied them in batch files, so automatic partitioning no longer seemed too far away. However, many problems still need to be solved, and determining hard disk size still cannot be done by relying on fdisk alone.

Although there are third-party tools such as gdisk, being able to accomplish the corresponding functions using DOS's own commands still has great practical potential.

Below is my translation of foreign materials about FDISK command-line parameters. There are similar documents in China as well, but none of them seem as comprehensive as the one below.

(CREDIT: This copy of the file comes from Michael Jacobsen at http://www.jacobsen.sdn.dk/fdisk)

Cracking FDISK

Background

This article mainly discusses the undocumented switch parameters you can use in FDISK. These switches let you use FDISK in non-interactive mode; for example, you can use it this way in a batch file.
These switches work normally in the FDISK included with Windows 95 OSR2(MS-DOS 71).
Many people have contributed to this article. If you have any comments, suggestions, or questions, you can send me an e-mail .
I have not found a way in FDISK to delete existing partitions, so I wrote a small utility myself (INSTHELP) to clear the partition table. Please use it with caution.

Variables used in this article:
{size} Partition size in Mb - FDISK will round up
{disk} Hard disk number, for example: the first hard disk is 1

Command directory
/STATUS Displays the current partition layout
/MBR Rebuilds the master boot record of the first hard disk
/PRI Creates a primary partition
/PRIO Creates a FAT16-format primary partition
/EXT Creates an extended partition
/LOG Creates a logical drive
/LOGO Creates a FAT16-format logical drive
/FPRMT Prompts for FAT32/FAT16 format in interactive mode
/Q Skips the forced reboot on exit; this information was provided by Mike Cowen and Paul Helsen
/X Does not use LBA partitioning; this information was provided by Francisco
/ACTOK Does not check disk integrity; this information was provided by Svend Christensen
/CMBR Rebuilds the master boot record of the specified hard disk; this information was provided by Francisco

/STATUS – Displays the current partition layout
FDISK /STATUS
==If you have an extended partition with no defined logical drives, the information for the extended partition will not be displayed.

/MBR – Rebuilds the master boot record of the first hard disk
This is useful when the master boot record has been infected by a virus. Using /MBR can clear the virus.
FDISK /MBR

/PRI – Creates and activates a primary partition
Creates and activates a primary partition of size {size} on disk number {disk}.
FDISK /PRI:{size} {disk}
==If {size} is larger than the size of the hard disk, the primary partition will take up all space.

/PRIO – Creates and activates a FAT16 primary partition
Usage is the same as /PRI

/EXT – Creates an extended partition
Creates an extended partition of size {size} on disk {disk} (for placing logical drives).
FDISK /EXT:{size} {disk}
==If {size} is larger than the remaining available space, the extended partition will use all available space, so you can avoid needing to know the exact amount of free space when using this switch.

/LOG – Creates a logical drive
Use /LOG to create a logical drive of size {size}. It must be used together with /EXT.
FDISK /EXT:{size} {disk} /LOG:{size}
==/LOG must be used together with /EXT, and the {size} for both switches must be the same. Also, {size} must be less than or equal to the available space.

/LOGO – Creates a FAT16 logical drive
Usage is the same as /LOG

/FPRMT – Prompts for FAT32/FAT16 in interactive mode
With /FPRMT, you will not be asked on the startup screen whether to support large hard disks, but you will be asked for FAT16/FAT32 partition format each time a partition is created.
FDISK /FPRMT
==Additional information provided by Jeff Richards: Note that the partition format prompt applies to all partitions, so this option can be used to force FDISK to create FAT32 partitions smaller than 540MB (by default, FAT32 format is only used for partitions larger than 540MB).

/Q – Skips the forced reboot when exiting FDISK
With /Q, the computer will not reboot after modifying the partition table, but I don't recall DOS 7X FDISK rebooting the computer anyway. Maybe that's because I usually use the FDISK from boot disks.
FDISK /Q
==I cannot verify this switch; this information was provided by Mike Cowen and Paul Helsen

/X - Does not use LBA partitioning
With /X, you will not get LBA partitions. For details, see Micro Firmware Technical Support.
FDISK /X
==I cannot verify this switch; this information was provided by Francisco.

/ACTOK – Does not check disk integrity
Using /ACTOK will skip checking disk integrity, making FDISK faster.
FDISK /ACTOK
==Note: It does not always work. Please tell me about your experience using /ACTOK. I cannot verify this switch; this information was provided by Svend Christensen.

/CMBR – Rebuilds the master boot record on the specified hard disk
Same usage as /MBR except that you need to specify the disk number.
FDISK /CMBR {disk}
==I cannot verify this switch; this information was provided by Francisco.

Notes on /PRI, /PRIO and /LOG, /LOGO

As far as I know, when PRI and LOG are used to create partitions, if the partition is larger than 512MB then a FAT32 partition is created; if it is smaller than 512MB then a FAT16 partition is created. PRIO and LOGO, on the other hand, will create FAT16 partitions regardless of whether the partition is larger than 512MB (similar in effect to FDISK in DOS5/6).

Passing keystrokes through a pipe

You can pass keystrokes to FDISK using a key file containing carriage returns {CR:0x0D}. Most editors cannot insert a carriage return {CR:0x0D} without a linefeed {LF:0x0A}, so you need to use a hex editor to do this. See CREATE.TXT and ERASE.TXT.

Example 1a – Create an extended partition:
FDISK < CREATE.TXT
Example 1b – Create an extended partition without checking disk integrity:
FDISK /ACTOK < CREATE.TXT
Example 2 – Delete the extended partition created by example 1a/1b:
FDISK < ERASE.TXT
All information about piped input was provided by Svend Christensen.

Disclaimer: The FDISK and other programs involved in this article are highly risky. Use them at your own responsibility.

Updated by Michael Jacobsen on August 22, 1999
※ Batchinger 致 Bat Fans:请访问 批处理编程的异类 ,欢迎交流与共享批处理编程心得!
Floor 3 Posted 2005-01-22 00:00 ·  中国 浙江 宁波 电信
中级用户
Credits 221
Posts 33
Joined 2003-03-22 00:00
23-year member
UID 1218
Gender Male
Status Offline
willsort, hello. How can block comments be implemented in a batch file? My idea is this: doskey /*=goto %explain%doskey */=:%explain% The problem is how to make the variable %explain% increase in order. In the webmaster's batch article, he mentioned "COUNT is a calculation tool for variables. For example, if the original value of C is 1, after executing COUNT C the value of C becomes 2. BE is a powerful batch enhancement tool included in Norton Utilties 8.0. KPUSH is a keyboard buffer tool." Do you happen to have this COUNT command? And one more question, which I think would also be commonly used in batch files: how can keyboard input be loaded into a variable? Is there any command like input? For example:
@echo offecho Please enter your name:input %1 After execution reaches input, it would prompt the user for input. After the user enters something, it would save that input into a variable for later use. Looking forward to your reply! Thanks in advance.
Floor 4 Posted 2005-03-18 00:00 ·  中国 山西 临汾 中移铁通
元老会员
★★★★
Batchinger
Credits 4,432
Posts 1,512
Joined 2002-10-18 00:00
23-year member
UID 19
Gender Male
Status Offline
Re Hero Not Lustful:

  I'm very sorry. Because there have been very few people paying attention to this thread, I also lost enthusiasm for paying attention to it. But seeing your question makes me very happy.

Below is the reply I made in the new topic you posted; quoted in full:

Just as dosforever said, DOSKEY macro commands can only be used at the command line and cannot be used in batch files.
Generally speaking, block/section comments do not appear in large numbers in batch files, because batch files themselves are not very large. If they are large, using rem or :: is also ideal. The comment style you mentioned is probably mainly used during statement debugging in batch files. Only when debugging many sections at the same time (which is also rare) would there be a need for automatically increasing comment label numbers.


  Also, there is a fairly common method for block comments in batch files:

     goto start
Comment content,
= can be multi-line text,
= can include redirection symbols and other special characters
= as long as it does not include the line :start
:start


  Also, there are various other forms of comments, for example:
1. :: comment content (after the first colon, any non-alphanumeric character can also follow)
2. rem comment content (redirection symbols and pipe symbols cannot appear)
3. echo comment content (redirection symbols and pipe symbols cannot appear)〉nul
4. if not exist nul comment content (redirection symbols and pipe symbols cannot appear)
5. :comment content (the comment text must not duplicate an existing label)
6. %comment content% (can be used as an inline comment; redirection symbols and pipe symbols cannot appear)
7. goto label comment content (can be used to explain the condition and action of goto)
8. :label comment content (can be used for the execution content of the section below the label)

And so on; there are many such forms.
------------------------------------------------
2005.07.18

  Recent findings show that under Win9x and MSDOS, DOSKEY macro commands can be invoked in batch files by special methods, but it still does not provide any obvious help on the subject of block comments. Example below:

  echo macro_name | call

  

[ Last edited by willsort on 2005-7-18 at 14:18 ]
※ Batchinger 致 Bat Fans:请访问 批处理编程的异类 ,欢迎交流与共享批处理编程心得!
Floor 5 Posted 2005-09-26 23:02 ·  中国 山西 运城 中移铁通
元老会员
★★★★
Batchinger
Credits 4,432
Posts 1,512
Joined 2002-10-18 00:00
23-year member
UID 19
Gender Male
Status Offline

  People who write batch files often must be very familiar with patterns like "if string1==string2 command arguments". Since string1/2 can reference variables, empty values may appear, so it becomes necessary to prevent syntax errors in the if statement when string1/2 is empty.

  And the method we most often use is an anti-empty character. At first there were many choices for anti-empty characters, for example:

  if #%1==# goto end
if == goto end
if %1!==! goto end

  However, with deeper use of batch files, all of the above anti-empty characters were eliminated. The key reason is that they cannot avoid syntax errors when string1/2 contains spaces. For example, the statement below is a syntax error:

  if == goto end

  At this point, a pair of double quotes seems to become the only choice:

  if "%1"=="my project" goto end

  However, it is still not the best choice. If string1/2 contains both quotes and spaces, then the syntax error we hate to see will appear again:

  if "%1"=="my project:"code for oop"" goto oop

  So what should we do next? Don't ask me, I don't know the answer!


The above content is reposted from
{16327} Solving Difficult Batch Problems: Choosing Anti-Empty Characters
http://www.cn-dos.net/forum/viewthread.php?tid=16327
※ Batchinger 致 Bat Fans:请访问 批处理编程的异类 ,欢迎交流与共享批处理编程心得!
Floor 6 Posted 2005-09-26 23:05 ·  中国 山西 运城 中移铁通
元老会员
★★★★
Batchinger
Credits 4,432
Posts 1,512
Joined 2002-10-18 00:00
23-year member
UID 19
Gender Male
Status Offline

  Another related issue is the guard character after a path variable.

  When we use an environment variable to refer to a path, we generally refer to it directly, for example:

  %temp%\_temp.bat

  But there is a problem with this: if %temp% is the root directory of some drive, such as C:\, then the above reference becomes:
  
  C:\\_temp.bat

  A double backslash appears in the path, and in MS-DOS and Win9x this will cause a syntax error, so some people use the method of adding a dot after the variable, namely:

  %temp%.\_temp.bat

  In that case, if %temp% is the root directory, the result of the reference is C:\.\_temp.bat; if it is not the root directory (for example C:\temp), then it is C:\temp.\_temp.bat.

  This makes use of the ambiguity shown by the dot in different usages: in the former usage, it represents the current directory, and the current directory under the root directory is naturally still the root directory; while in the latter usage, it represents the separator between the main name and the extension in a directory name, and since there is no actual extension after the dot, C:\temp. still represents the C:\temp directory.

  However, this brings a new problem: what should be done if a special reference symbol for a relative path appears in the path? For example, if %temp% is . meaning the current directory, or .. meaning the parent directory, then the reference %temp%.\_temp.bat becomes:

  ..\_temp.bat or ...\_temp.bat

  These obviously are not the results we need either, so what should we do?

  The answer is in your hands :-)


The above content is reposted from
{16327} Difficult Batch Problems and Solutions: Choosing a Guard Character Against Empty Characters
http://www.cn-dos.net/forum/viewthread.php?tid=16327
※ Batchinger 致 Bat Fans:请访问 批处理编程的异类 ,欢迎交流与共享批处理编程心得!
Floor 7 Posted 2005-09-26 23:29 ·  中国 山西 运城 中移铁通
元老会员
★★★★
Batchinger
Credits 4,432
Posts 1,512
Joined 2002-10-18 00:00
23-year member
UID 19
Gender Male
Status Offline
This seems like a very simple problem. In the great majority of batch files I have seen and written, directory detection uses this classic format:

if exist directory\nul command argument(s)

It can be said that the originator of this trick really had a very deep understanding of DOS. At the very least, he discovered the complex and subtle relationship between the device-management mechanism represented by nul and the file-management mechanism. The nul device, like . and .., can be referenced directly under most paths without causing a system error.

But just as .. cannot be referenced under the root directory (this was changed in NT CMD), nul also has its limitations.

When we load DOSLFN in an MSDOS7.10 environment to enable long filename support, some BUGs in DOSLFN will escape the \NUL reference, and then a file will be judged as a directory.


C:\>echo.>test.txt

C:\>if exist test.txt\nul echo Exist dir "test.txt"
Exist dir "test.txt"

C:\>


If this were only a doslfn problem, then we could disable DOSLFN and move the testing ground to a CD. Because CDs use the unique CDFS file system, the \NUL reference fails there, and directories still cannot be recognized, though at least files will not be mistaken for directories.


E:\>dir /ad /b
BOOT
DOS71

E:\>if exist boot\nul echo Exist dir "BOOT"

E:\>


Now let us move on to the newer CMD@WinXP. If the directory name contains spaces, then its existence cannot be recognized by using the long filename.


C:\>md "my test"

C:\>if not exist "my test"\nul echo Not exist "my test"
Not exist "my test"

C:\>if not exist "my test\nul" echo Not exist "my test"
Not exist "my test"

C:\>


[ Last edited by willsort on 2005-10-26 at 11:16 ]
※ Batchinger 致 Bat Fans:请访问 批处理编程的异类 ,欢迎交流与共享批处理编程心得!
Floor 8 Posted 2005-09-27 00:41 ·  中国 辽宁 锦州 中移铁通
荣誉版主
★★★
Credits 1,338
Posts 356
Joined 2005-07-15 12:09
20-year member
UID 40733
Gender Male
Status Offline
On Determining Whether a Directory Exists

With the method if exist directory\nul command argument(s)
as long as the directory contains spaces, it will fail to match correctly no matter what.
In actual use, I generally use the following method:


md "my test"
cd "my test" &&echo Exist directory "test"

This is very accurate, but it also has a drawback, namely that it will enter that directory.
Floor 9 Posted 2005-09-27 17:10 ·  中国 山西 运城 中移铁通
元老会员
★★★★
Batchinger
Credits 4,432
Posts 1,512
Joined 2002-10-18 00:00
23-year member
UID 19
Gender Male
Status Offline
Re Wu Naihe:

Because of time constraints, the previous post was made before it was finished, so many issues were left out.

For directory names containing spaces, you can use the 8.3 short name for detection, or you can also use the following method:

if exist "my test\*" echo Exist directory "my test"

Of course, like your method, this only works in the NT-series command line, so compatibility is far from good enough.

Under DOS, I am considering a dir+find solution. It is not very mature yet, as follows:

dir directory /ad | find ".." i>nul
if not errorlevel 1 echo Exist directory "directory"

But it also has drawbacks, for example it cannot correctly determine directories like “e:\”.

As for your md+cd solution, entering the directory is not much of a problem, since you can exit with cd.., but it cannot handle cross-partition paths, so you need to use cd /d instead. Then returning to the previous path becomes more troublesome, and in addition you need to suppress the error messages that the C command may produce.

pushd "e:\test_path" 2>nul && echo Exist directory "e:\test_path" && popd

But a solution that can only be used under NT is still far too limited.

[ Last edited by willsort on 2005-9-27 at 17:55 ]
※ Batchinger 致 Bat Fans:请访问 批处理编程的异类 ,欢迎交流与共享批处理编程心得!
Floor 10 Posted 2005-10-13 11:29 ·  中国 山西 大同 中移铁通
元老会员
★★★★
Batchinger
Credits 4,432
Posts 1,512
Joined 2002-10-18 00:00
23-year member
UID 19
Gender Male
Status Offline
Determining the Extension in a Filename


This thread arose from the 7th question by 英雄不色 in {1515:8762}.

7.How do you determine a file extension in a batch file? To achieve effects like the following.

if "%1" == "*.dll" goto dll
if "%1""=="*.inf" goto inf



1、If the file referred to by the filename is a single file, and that file exists, and it does not contain a path specification, then the following method can be used;

for %%x in (*.dll) do if exist "%1" goto dll
for %%x in (*.inf) do if exist "%1" goto inf


2、If the file referred to by the filename is a single file, but it does not exist, and it does not contain a path specification, then the following method can be used;

if not exist %temp%\_getext_\nul md %temp%\_getext_
echo _getext_> %temp%\_getext_\%1
if exist %temp%\_getext_\*.dll goto dll
if exist %temp%\_getext_\*.inf goto inf


3、If the program is running in an NT-series command-line environment, and there is only one dot in the filename separating the main filename and the extension, then the following method can be used;

for /f "delims=. tokens=2" %%x in ("%1") do set _ext=%%x
if "%_ext%"=="dll" goto dll
if "%_ext%"=="inf" goto dll


4、Third-party tools such as Strings and aset can be used to get the file extension, but their support for long filenames and Chinese filenames may not be very good.

[ Last edited by willsort on 2005-10-13 at 13:01 ]
※ Batchinger 致 Bat Fans:请访问 批处理编程的异类 ,欢迎交流与共享批处理编程心得!
Floor 11 Posted 2005-10-13 13:21 ·  中国 四川 南充 电信
超级版主
★★★★
我爱DOS
Credits 5,310
Posts 2,044
Joined 2005-09-26 12:00
20-year member
UID 42843
Gender Male
From 四川南充
Status Offline
Floor 12 Posted 2005-12-02 22:41 ·  中国 辽宁 锦州 中移铁通
荣誉版主
★★★
Credits 1,338
Posts 356
Joined 2005-07-15 12:09
20-year member
UID 40733
Gender Male
Status Offline
to willsort

After several searches, I still found nothing regarding some issues with the PING command, so I could only measure the difference in the %time% variable before and after executing ping and observe the pattern in actual tests. I believe you have long since done such tests, so I won't post the specific data. My conclusions are as follows:
With the delay method ping -n x 127.0.0.1>nul, whether the x value is large or small, the error is basically about the same and is acceptable.
With the delay method ping -n x -w y 0.0.0.1>nul, the longer the delay time, the greater the error, and it can even become ridiculously large, so it is not acceptable.
So I suggest trying not to use the second method.

Also, regarding ping/n 1 127.1, you can look at this article.
http://biz.chinabyte.com/255/2012255.shtml

One more point: the author did not mention how numeric addresses beginning with zero are interpreted, for example: ping 0123.1.1.1. Here the zero-leading number 0123 will be parsed as octal, equivalent to ping 83.1.1.1.
  ☆开始\运行 (WIN+R)☆
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul

Floor 13 Posted 2005-12-04 21:20 ·  中国 山西 运城 中移铁通
元老会员
★★★★
Batchinger
Credits 4,432
Posts 1,512
Joined 2002-10-18 00:00
23-year member
UID 19
Gender Male
Status Offline
Re Wu Naihe:

As for the ping delay issue, the conclusion I finally reached was also to use 3.1 rather than 3.2.

Scheme 3.2 has at least the following problems:

1. There seems to be some delay when ping sends packets, and this delay is not the fixed 500 milliseconds I once mentioned, but changes with the network environment and system environment. Yesterday's measured value was about 200~300ms; today it is somewhat higher, around 400~500ms.

2. The timeout behavior of ping -w requires more preconditions. I tried disabling my local connection, and the timeout did not take effect.

As for the problem you mentioned, that the longer the delay the greater the error, that may be because you adjust the delay length through x. You can achieve delay precision similar to scheme 3.1 by adjusting the y value (in milliseconds).

Reference link:
The Odd Side of Batch Programming — Clock
http://www.cn-dos.net/forum/viewthread.php?tid=8905#pid54227
※ Batchinger 致 Bat Fans:请访问 批处理编程的异类 ,欢迎交流与共享批处理编程心得!
Floor 14 Posted 2005-12-05 00:06 ·  中国 辽宁 锦州 中移铁通
荣誉版主
★★★
Credits 1,338
Posts 356
Joined 2005-07-15 12:09
20-year member
UID 40733
Gender Male
Status Offline
:to willsort
I adjusted both x and y values. For longer delays I increased the y value as much as possible, and for shorter delays I reduced the y value as much as possible. That can indeed produce small errors, but the time conversion is rather troublesome.
  ☆开始\运行 (WIN+R)☆
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul

Floor 15 Posted 2006-01-10 15:03 ·  中国 山西 大同 中移铁通
元老会员
★★★★
Batchinger
Credits 4,432
Posts 1,512
Joined 2002-10-18 00:00
23-year member
UID 19
Gender Male
Status Offline
The following is reposted from the help room on this site:
http://www.cn-dos.net/forum/viewthread.php?tid=12892#pid95281

Several Technical Discussions on HDKP
============================================================================

Author: Will Sort
Date: 2005-04-22
Version: 1-20050505
Keywords: HDKP, %comspec%, command interpreter, drive check, disk check, command-line loop
Abstract: Related discussion of HDKP disk checking and disk traversal in terms of algorithm and details
----------------------------------------------------------------------------

Background

Full name: Hard Drive Killer Pro
Version: the commonly circulated version is 4.0 (including the bat version and the exe version compressed from bat), latest version 5.0beta
Author: Munga Bunga (Australia)
Date: version 4.0 was completed no later than May 2001
Platform: according to the original author, this program can work under DOS/Win3.x/9x/NT/2000 and other systems, suitable for
  90% of the computers in the world; XP and 2003 did not yet exist at that time
Purpose: to destroy, or say “clean,” all data on all hard disks, floppy disks, and flash disks in a computer. Of course, due to its
  long history, most currently popular antivirus software can remove it.
----------------------------------------------------------------------------

Preface

  I first saw this reposted batch program in A Simple Batch Tutorial. The author of the tutorial listed it as the finale among the excellent program examples. At the time, because I had considerable hostility toward any programs with words like Killer/Hacking in them, I only glanced at it briefly and did not read it carefully. Later I again saw this program reposted in a thread by brother “Shenxian Beibei” on the “Union DOS Forum”, but for similar reasons, I only skimmed through to see whether there were any replies worth noting, then casually closed it, to the point that I later did not even see brother Climbing's invitation.

  In mid-April I began reading old batch-related threads on the “Union DOS Forum,” and several times I saw the suggestion “study it carefully” in the sticky digest index by brother Climbing. At last I opened brother “Shenxian Beibei”'s old thread again. By then, brother wangsea had already done a fine job of annotating it, so my task was simply to enjoy the fruits of others' labor.

  But unfortunately, too many problems and flaws appeared in this program. Some problems, such as the invalid format switch /autoSample and :Sampledrv, were obviously not slips by the original author, but seemed specially modified by some interested person or interested program; some other problems, such as dedecated and elapse, I do not know whether they were Australian dialect or accidental mistakes by the author; as for the remaining problems, the main person responsible can definitely be said to be the author himself.

  Of course, for the sake of fairness and universality in discussion, I found the original link for this program and tried to download it, but the download failed. I tried several other methods as well, but the versions I found were no different from the one by “Shenxian Beibei.” In the end, I decided to continue using the latter as the basis for discussion, so what I am discussing is only the merits and faults of the code, not the merits and faults of the author.
----------------------------------------------------------------------------

Main text

  There is no denying that the program does indeed use some advanced techniques, and the most important manifestation of these techniques is the disk checking program (drivechk.bat). But it should be noted that drivechk.bat was not the author's own original creation. Its original author was Tom Lavedas, which is exactly why the author wrote “Except for.” However, it is possible that the author did not thoroughly understand this program and only made some simple modifications, or that the author cited an earlier program by Lavedas, so this section of code has some problems.

  Below is a part of the program that dynamically generates drivechk.bat

echo @echo off >drivechk.bat
echo @prompt %%%%comspec%%%% /f /c vol %%%%1: $b find "Vol" > nul >{t}.bat
%comspec% /e:2048 /c {t}.bat >>drivechk.bat
del {t}.bat
echo if errorlevel 1 goto enddc >>drivechk.bat

  The purpose of this section is to write the following code into drivechk.bat. Brother wangsea has already analyzed the process, so I will not repeat the details.

%comspec% /f /c vol %1: | find "Vol" > nul
if errorlevel 1 goto enddc

  First, the line “echo @echo off >drivechk.bat” is not necessary. Because drivechk.bat is a dynamically generated called program, when it is called by call, it inherits the echo off state of the calling program.

  Only when it is called with %comspec% /c might “echo off” be needed, because %comspec% /c creates a new layer of command-interpreter environment, and in this new environment the echo state is reset. That is also why the program can obtain the modified command prompt through %comspec% /e:2048 /c {t}.bat: it is exactly the statement to be written into drivechk.bat.

  Second, “%%%%comspec%%%%” in the second line can be completely changed to “%comspec%”. The function of “%%%%” is to delay the substitution of %comspec%, so that %comspec% is not replaced by the path of the command interpreter until drivechk.bat is executed; but that is unnecessary, because the called drivechk.bat and the main calling program must run in the same environment, so it makes no difference whether the substitution happens earlier or later.

  Moreover, I suggest directly changing %comspec% to command. Because in NT-type command-line environments, %comspec% usually points to cmd.exe, which differs from command.com in many ways—for example, the code page differs in non-English systems, causing find "Vol" /c to fail. And in early MS-DOS environments, %comspec% may also point to non-standard command interpreters such as NDOS, whose switch parameters and execution output may both cause the %comspec% line to fail. The biggest problem with using command directly is that it might not be in the current path or %Path%, but that is almost impossible.

  Third, “find "Vol" > nul” should be “find "Vol" $g nul”, otherwise “> nul” cannot be written into drivechk.bat, and that may cause the find message to “leak” when drivechk is called. When the program calls it, the author tried to avoid this hidden problem through “call drivechk.bat %%a >nul”, but he may not have known that this “>nul” is ineffective for call batch processing.

  Only by calling a batch file through %comspec% /c can its output be redirected or piped. But even so, some output from executing vol %1: may still be impossible to suppress—for example, error messages produced when accessing a nonexistent or unready drive, because they use error-device output rather than the standard console, so they are not passed through the pipe. The solution is to add a pair of ctty nul and ctty con statements before and after %comspec% /c. However, ctty is supported only in MS-DOS and the 9x command line; in NT-type command lines such as XP, ctty was removed. In such environments, error messages can only be redirected through 2> nul.

  Fourth, “if errorlevel 1 goto enddc” ignores many problems. In MS-DOS or the 9x command line, using vol to access an existing but unready drive will still produce Vol information output, but the program will not jump to the end at that time; in addition, when a read-only CD or flash disk is accessed, there will also be Vol information output.

  So in order to remedy these two defects, the program later uses dir | find "bytes" to test the readiness situation, and then uses dir | find "0 bytes" to check for read-only CDs. But locked flash disks still cannot be judged correctly. Perhaps by the time the program was completed, the locking function on flash disks was still uncommon.

  The statement for detecting whether a disk is readable can also be replaced with dir %1:\nul|find "\" , and checking whether a disk is writable can use copy /y _writed_.tag %1: and if exist %1:_writed_.tag for judgment. Of course, these statements still all need to run inside the shell of %comspec% /f/c. But there are still some problems we might not think of—for example, on a shared drive in Virtual PC, I can only create and modify files, but cannot delete them. As for other things such as network drives and memory virtual drives, I have not discussed them in more detail. On such details, professional programs may perhaps do better.

  Fifth, there is another relatively simple technique in the program, namely disk traversal in :Sampledrv. Using the For statement for loop-style traversal may be the usual practice in batch programming, yet in some situations that practice may not be optimal.

  In fact, very early on, people used more flexible command-line loops to deal with many problems that For could hardly solve. For example, when there are multiple statements after do, we have to put these statements into a batch file and call them; but the characteristics of for determine that it makes repeated multiple calls during execution, while the advantage of a command-line loop is that it needs only one call, and what remains is just shift and goto inside the program. This saves quite a lot of performance, because call consumes far more performance resources than shift and goto.

  Sixth, let us discuss the necessity of dynamically generating drivechk.bat. This is not about the necessity of drivechk.bat itself, but about the necessity of generating it dynamically. We may guess that the reason the program goes to such trouble to generate this code dynamically, rather than statically embedding it in the main program, is mainly that it can use it for loop traversal during disk checking. However, the author may not have noticed or realized that static code can accomplish the same task. This means that all the detours the entire program takes in writing drivechk.bat are unnecessary, and we can completely find a more direct and shorter route.

  By embedding code that the program needs to use repeatedly as a module within itself, and then repeatedly calling that module, one can achieve an effect similar to calling dynamic code. In plain terms, a module means a whole section of code beginning with a label and ending with goto end, and to call this module you only need to use call %0 : lablename together with if "%1"==":" goto %2.

Structure of the calling program
CODE:
...
:: Call-type call to itself
call %0 : labelname
...
:: Goto-type call to itself
%0 : lablename
...
:: Call-type call to another Bat
call bat_name : labelname
...
:: Goto-type call to another Bat
bat_name : lablename
...
Structure of the called program (which may also be the calling program)
CODE:
@echo off
if "%1"==":" goto %2
...
:labelname
:: module code section
...
goto end
...
:end
----------------------------------------------------------------------------

Conclusion

  My purpose in writing this article, as mentioned in the abstract, is to try to discuss some technical characteristics and details concerning disk checking and command-line loops, not to provide technical support for HDKP or similar malicious programs. As for the purpose for which HDKP was written, I personally still maintain an opposing attitude. This program is probably, just as the author hoped, useful only to “a very special person that does not want to be named.” To me, it is merely an imperfect combination of technique and conception.

  I know that professional third-party programs for disk checking have long already existed, such as dready.com. But as a technical branch of batch programming, discussing it is still beneficial: it can help us understand system working principles more deeply and become more familiar with the environment in which we work. Also, as far as batch files are concerned, not relying on third-party programs still has considerable advantages and value.
----------------------------------------------------------------------------

References:

01. I hope some friend can write a complete annotation for this batch file
  http://www.cn-dos.net/dosbbs/dispbbs.asp?boardid=9&id=12892

02. China DOS Union Forum Help Room Digest Index
  http://bbs.cn-dos.net/dispbbs.asp?boardid=9&id=13226

03. Hard Drive Killer Pro (HDKP) - The Hackology Network
  http://www.hackology.com/programs/hdkp/ginfo.shtml

04. Safely Testing the Status of All Types of Drives - Tom Lavedas
  http://www.pressroom.com/~tglbatch/testdrv.html

05. Avoiding Drive Not Ready - alt.msdos.batch
  http://groups-beta.google.com/group/alt.msdos.batch/browse_thread/thread/
   df0213182e13de5b/fa2abe726f972567?q=%22:_end%22+label+name&rnum=2&hl=en
=============================================================================
※ Batchinger 致 Bat Fans:请访问 批处理编程的异类 ,欢迎交流与共享批处理编程心得!
Forum Jump: