View unanswered posts | View active topics It is currently 31 Jul 2014 03:26



Post new topic Reply to topic  [ 44 posts ]  Go to page Previous  1, 2, 3
foolproof counting of arguments 
Author Message
Expert

Joined: 12 Feb 2011 21:02
Posts: 1185
Location: United States (east coast)
Post Re: foolproof counting of arguments
Liviu wrote:
jeb wrote:
But piping do the same as the exit, as the pipe itself creates two seperate sub-tasks for each side.
The prompt disappears in the child task which is never visible.
Haven't followed this in any depth, but it doesn't look quite the same. The pipe closes both ends without any obvious 'exit' being typed in and/or piped through.
jeb wrote:
So the pipe doesn't solve the problem this way.
Streams 3/4 redirection is foggy enough to me that I can't even spell out what the "problem" might be, let alone solve it ;-)

I think I understand what jeb is saying. The pipe is not restoring the streams. It forces the stream manipulation to occur in a child CMD.EXE process that leaves the parent CME.EXE streams alone.

--------------------

Redirection is one wacky world :lol:

I haven't fully analyzed the results to arrive at a pattern yet. But here are some interesting test cases with results.

Code:
@echo off
if "%~1" neq "" goto :test
prompt $g
cls
for /l %%n in (1 1 21) do (
  del file?.stream 2>nul
  echo(
  echo =====================================================
  cmd /c "test %%n"
  echo(
  for %%f in (file*) do (
    echo(
    echo %%f contents
    echo -----------------------------
    type %%f
  )
)
del file?.stream 2>nul
prompt
exit /b


:test
echo on & call :test%1
echo echo to stream1
>&2 echo echo to stream2
>&3 echo echo to stream3
>&4 echo echo to stream4
exit /b

:test1
echo off
exit /b

:test2
echo off 1>file1.stream
exit /b

:test3
echo off 2>file2.stream
exit /b

:test4
echo off 3>file3.stream
exit /b

:test5
echo off 4>file4.stream
exit /b

:test6
echo off 1>file1.stream 2>file2.stream 3>file3.stream 4>file4.stream
exit /b

:test7
echo off 1>file1.stream 2>file2.stream 3>file3.stream
exit /b

:test8
echo off 2>file2.stream 3>file3.stream 4>file4.stream
exit /b

:test9
echo off 1>file1.stream 3>file3.stream 4>file4.stream
exit /b

:test10
echo off 1>file1.stream 2>file2.stream 4>file4.stream
exit /b

:test11
echo off 1>file1.stream 2>file2.stream
exit /b

:test12
echo off 1>file1.stream 3>file3.stream
exit /b

:test13
echo off 1>file1.stream 4>file4.stream
exit /b

:test14
echo off 2>file2.stream 3>file3.stream
exit /b

:test15
echo off 2>file2.stream 4>file4.stream
exit /b

:test16
echo off 3>file3.stream 4>file4.stream
exit /b

:test17
echo off 1>nul 2>nul 3>file3.stream 4>file4.stream
exit /b

:test18
echo off 1>nul 2>nul 3>file3.stream
exit /b

:test19
echo off 1>nul 2>nul 4>file4.stream
exit /b

:test20
echo off 1>nul 3>file3.stream
exit /b

:test21
echo off 2>nul 4>file4.stream
exit /b


Results:
Code:
=====================================================

>echo off
echo to stream1
echo to stream2
echo to stream3
The handle could not be duplicated
during redirection of handle 1.


=====================================================

>echo off  1>file1.stream
echo to stream1
echo to stream2
echo to stream3
The handle could not be duplicated
during redirection of handle 1.


file1.stream contents
-----------------------------

=====================================================

>echo off  2>file2.stream
echo to stream1
echo to stream2
echo to stream3
The handle could not be duplicated
during redirection of handle 1.


file2.stream contents
-----------------------------

=====================================================

>echo off  3>file3.stream
echo to stream1
echo to stream2
echo to stream3
The handle could not be duplicated
during redirection of handle 1.


file3.stream contents
-----------------------------

=====================================================

>echo off  4>file4.stream
echo to stream1
echo to stream2
echo to stream3
The handle could not be duplicated
during redirection of handle 1.


file4.stream contents
-----------------------------

=====================================================

>echo off  1>file1.stream 2>file2.stream 3>file3.strea
echo to stream3
echo to stream4


file1.stream contents
-----------------------------

file2.stream contents
-----------------------------

file3.stream contents
-----------------------------
echo to stream1

file4.stream contents
-----------------------------
echo to stream2

=====================================================

>echo off  1>file1.stream 2>file2.stream 3>file3.strea
echo to stream2
echo to stream3


file1.stream contents
-----------------------------

file2.stream contents
-----------------------------

file3.stream contents
-----------------------------
echo to stream1
echo to stream4

=====================================================

>echo off  2>file2.stream 3>file3.stream 4>file4.strea
echo to stream1
echo to stream4


file2.stream contents
-----------------------------

file3.stream contents
-----------------------------
echo to stream2

file4.stream contents
-----------------------------
echo to stream3

=====================================================

>echo off  1>file1.stream 3>file3.stream 4>file4.strea
echo to stream2
echo to stream4


file1.stream contents
-----------------------------

file3.stream contents
-----------------------------
echo to stream1

file4.stream contents
-----------------------------
echo to stream3

=====================================================

>echo off  1>file1.stream 2>file2.stream 4>file4.strea
echo to stream1
echo to stream3
echo to stream4


file1.stream contents
-----------------------------

file2.stream contents
-----------------------------

file4.stream contents
-----------------------------
echo to stream2

=====================================================

>echo off  1>file1.stream 2>file2.stream
echo to stream1
echo to stream2
echo to stream3
The handle could not be duplicated
during redirection of handle 1.


file1.stream contents
-----------------------------

file2.stream contents
-----------------------------

=====================================================

>echo off  1>file1.stream 3>file3.stream
echo to stream2
echo to stream3


file1.stream contents
-----------------------------

file3.stream contents
-----------------------------
echo to stream1
echo to stream4

=====================================================

>echo off  1>file1.stream 4>file4.stream
echo to stream1
echo to stream2
echo to stream3
The handle could not be duplicated
during redirection of handle 1.


file1.stream contents
-----------------------------

file4.stream contents
-----------------------------

=====================================================

>echo off  2>file2.stream 3>file3.stream
echo to stream1
echo to stream3
echo to stream4


file2.stream contents
-----------------------------

file3.stream contents
-----------------------------
echo to stream2

=====================================================

>echo off  2>file2.stream 4>file4.stream
echo to stream1
echo to stream2
echo to stream3
The handle could not be duplicated
during redirection of handle 1.


file2.stream contents
-----------------------------

file4.stream contents
-----------------------------

=====================================================

>echo off  3>file3.stream 4>file4.stream
echo to stream1
echo to stream2
echo to stream3
The handle could not be duplicated
during redirection of handle 1.


file3.stream contents
-----------------------------

file4.stream contents
-----------------------------

=====================================================

>echo off  1>nul 2>nul 3>file3.stream 4>file4.stream
echo to stream3
echo to stream4


file3.stream contents
-----------------------------
echo to stream1

file4.stream contents
-----------------------------
echo to stream2

=====================================================

>echo off  1>nul 2>nul 3>file3.stream
echo to stream2
echo to stream3


file3.stream contents
-----------------------------
echo to stream1
echo to stream4

=====================================================

>echo off  1>nul 2>nul 4>file4.stream
echo to stream1
echo to stream3
echo to stream4


file4.stream contents
-----------------------------
echo to stream2

=====================================================

>echo off  1>nul 3>file3.stream
echo to stream2
echo to stream3


file3.stream contents
-----------------------------
echo to stream1
echo to stream4

=====================================================

>echo off  2>nul 4>file4.stream
echo to stream1
echo to stream2
echo to stream3
The handle could not be duplicated
during redirection of handle 1.


file4.stream contents
-----------------------------


Dave Benham


15 Feb 2012 11:36
Profile
Expert

Joined: 13 Jan 2012 21:24
Posts: 440
Post Re: foolproof counting of arguments
dbenham wrote:
Redirection is one wacky world :lol:

I haven't fully analyzed the results to arrive at a pattern yet. But here are some interesting test cases with results.

Interesting... Though I'd say first pattern which jumps to the eye is random chaos ;-)

Not directly related, but another >&3 odd behavior noted in my Feb 6th post at http://groups.google.com/group/alt.msdos.batch.nt/browse_thread/thread/b5d5f5e3e17f024b/c24bcb7982c42ab2?lnk=raot.

Liviu


15 Feb 2012 19:27
Profile
Expert

Joined: 12 Feb 2011 21:02
Posts: 1185
Location: United States (east coast)
Post Re: foolproof counting of arguments
jeb wrote:
I create a completly other way of capturing the parameters into a file
Code:
@echo on
@echo Hello1 1>stream1.txt 2>stream2.txt 3>stream3.txt 4>stream4.txt
rem # %* #
@echo off
type stream3.txt > con
exit /b


This is adapted from the code of walid2me SO: Commenting multiple lines in DOS batch file

The only problem is to restore the standard handles :!:
As after the code even the prompt isn't visible anymore

I can get close :!:
By some weird chaining effect I can redirect the output back to con. Stream 1 (stdout) is not quite normal when finished because CLS does not work, and the stream3.txt is still left open until the CMD.EXE session terminates. I imagine there are additional oddities lurking somewhere.

test.bat
Code:
@echo on 1>nul 3>stream3.txt
rem # %* #
@echo off 1>nul 3>nul 4>con
type stream3.txt

command line session
Code:
>cmd
Microsoft Windows [Version 6.0.6002]
Copyright (c) 2006 Microsoft Corporation.  All rights reserved.

>test Hello world

>rem # Hello world #

>cls

>del stream3.txt
C:\Users\public\utils\stream3.txt
The process cannot access the file because it is being used by another process.

>exit

>del stream3.txt

>


I can work with both stdout and stderr if I want. From the command line:
Code:
>cmd
Microsoft Windows [Version 6.0.6002]
Copyright (c) 2006 Microsoft Corporation.  All rights reserved.

>echo on 1>nul 2>nul 3>stream3.txt 4>stream4.txt
echo stdout message
echo stderr message >&2
echo on 1>nul 2>nul 3>nul 4>nul 5>con 6>con

>type stream3.txt

>stdout message

>
>
>type stream4.txt
stderr message

>dir doesNotExist
 Volume in drive C is OS
 Volume Serial Number is EE2C-5A11

 Directory of C:\Users\public\utils

File Not Found

>dir doesNotExist 1>nul
File Not Found

>dir doesNotExist 2>nul
 Volume in drive C is OS
 Volume Serial Number is EE2C-5A11

 Directory of C:\Users\public\utils


>del stream3.txt
C:\Users\public\utils\stream3.txt
The process cannot access the file because it is being used by another process.

>del stream4.txt
C:\Users\public\utils\stream4.txt
The process cannot access the file because it is being used by another process.

>exit

>del stream3.txt

>del stream4.txt

>


While experimenting I learned that CLS sends a form feed character <FF> (0x0C) to the screen. If you redirect CLS to con, then you get a graphical representation of the <FF> character on the screen. I can use CLS behavior to get <FF> in a variable:
Code:
@echo off
setlocal
for /f %%A in ('cls') do set FF=%%A
set FF


Dave Benham


19 Feb 2012 18:28
Profile

Joined: 23 Dec 2011 13:59
Posts: 1764
Post Re: foolproof counting of arguments
dbenham wrote:
jeb wrote:
While experimenting I learned that CLS sends a form feed character <FF> (0x0C) to the screen. If you redirect CLS to con, then you get a graphical representation of the <FF> character on the screen. I can use CLS behavior to get <FF> in a variable:
Code:
@echo off
setlocal
for /f %%A in ('cls') do set FF=%%A
set FF


Dave Benham

Sweet. Now we have all 3 covered. CR LF and FF


19 Feb 2012 18:55
Profile
Expert

Joined: 12 Feb 2011 21:02
Posts: 1185
Location: United States (east coast)
Post Re: foolproof counting of arguments
StackOverflow user Erbert has discovered that reversing the order of the redirection, (high numbered file handles before low numbers), prevents the "permanent" redirection: http://stackoverflow.com/a/9880156/1012053


Dave Benham


26 Mar 2012 16:29
Profile
Expert

Joined: 13 Jan 2012 21:24
Posts: 440
Post Re: foolproof counting of arguments
dbenham wrote:
StackOverflow user Erbert has discovered that reversing the order of the redirection, (high numbered file handles before low numbers), prevents the "permanent" redirection: http://stackoverflow.com/a/9880156/1012053

Interesting, thanks for the pointer. That said, I don't think the case is closed. For one thing, replacing "3" with some other handle number e.g. "4" or "5" gives different output/behavior. What's observed there may well be the result of some crosstalk with cmd's own internal usage of handle 3.

Liviu


28 Mar 2012 22:38
Profile
Expert

Joined: 30 Aug 2007 08:05
Posts: 666
Location: Germany
Post Re: foolproof counting of arguments
In my opinion, stream3 and stream4 are the destinations of stdout and stderr, they will be used when stream1 or stream2 are not redirected.

So if you write
Code:
echo test1
echo test1r 1> stream1.txt


In the first case the text will be "redirected" to stream3, and as the destination of stream3 is CON, the text will be displayed
And in the second case stream3 will not be used, as there is an explicit redirection

(Only a guess) :)
jeb


29 Mar 2012 00:20
Profile
Expert

Joined: 12 Feb 2011 21:02
Posts: 1185
Location: United States (east coast)
Post Re: foolproof counting of arguments
I believe I have figured it out :!: :D

When a stream is redirected, the current definition is held in (transfered to) the 1st available (undefined) stream. When the redirection ends, the held definition is restored back to the original stream, and the holding stream is undefined again.

For example
Code:
1>out.txt echo Hello world!
While the redirection is in effect, 1 is directed to the file, and 3 holds the original definition of 1 (stdout). Stream 2 couldn't be used to hold the stdout definition because it is already being used by stderr. Once redirection is over, 1 is restored to the definition held in 3 (stdout), and 3 is undefined again. (Edit - typos fixed on 2012-04-03)

The weirdness starts when a chain of redirections occurs. The redirection chaining works fine on the way in. But on the way out, restoration is only performed 1 level deep.
Code:
1>out1.txt 3>out2.txt echo Hello world!
First 1 is directed to file out1.txt and 3 holds the definition of stdout, but then 3 is directed to out2.txt and 4 holds the definition of stdout. But once redirection is over, 1 is restored to the definition of 3(out2.txt), 3 is restored to the definition of 4(stdout), and 4 is undefined.

Here is a script I used to "prove" my theory
Code:
@echo off
2>nul 3>nul 1>nul 5>nul 6>nul (
  REM while redirection is in effect
  REM 2=nul, 3=nul, 4=stderr
  REM 1=nul, 5=nul, 6=nul, 7=stdout
  1>&7 echo stdout via stream7
  2>&4 1>&2 echo stderr via stream4
  1>&7 echo -------------------------
)
REM Prior redirection is now over,
REM but handles are only restored one level deep
REM 2=nul, 3=stderr, 4=undefined
REM 1=nul, 5=nul, 6=stdout, 7=undefined
1>&6 echo stdout via stream6
2>&3 1>&2 echo stderr via stream3
1>&6 echo -------------------------

1>nul 4>&6 2>nul 8>&3 (
  REM while redirection is in effect
  REM 5=nul(unchanged)
  REM 1=nul, 4=6=stdout, 7=nul(from 4 from 1 before redirection)
  REM 2=nul, 8=3=stdout, 9=nul(from 8 from 2 before redirection)
  1>&6 echo stdout via stream6
  1>&4 echo stdout via stream4 (via stream6^)
  2>&3 1>&2 echo stderr via stream3
  2>&8 1>&2 echo stderr via stream8 (via stream3^)
  1>&6 echo -------------------------
)
REM 1=6=stdout, 4=nul, 7=undefined
REM 2=3=stderr, 8=nul, 9=undefined
echo restored stdout (via stream6)
1>&6 echo stdout via stream6
1>&2 echo restored stderr (via stream3)
1>&3 echo stderr via stream3
1>&6 echo -------------------------

And here are the results
Code:
stdout via stream7
stderr via stream4
-------------------------
stdout via stream6
stderr via stream3
-------------------------
stdout via stream6
stdout via stream4 (via stream6)
stderr via stream3
stderr via stream8 (via stream3)
-------------------------
restored stdout (via stream6)
stdout via stream6
restored stderr (via stream3)
stderr via stream3
-------------------------

-----------------------------------------------------------

Now we can use jeb's idea to safely capture the arguments, and have stdout restored to almost normal when done. (remember the original topic of this thread :) :!:)
Code:
@echo on 1>args.txt 3>&1
rem # %* #
@echo off 1>nul 4>&3
type args.txt
echo -------------
1>&3 echo stream1 and stream3 both point to stdout
echo -------------
del args.txt
1>&4 echo stream4 is left open pointing to args.txt
type args.txt
exit /b

stdout is normal except that both stream1 and stream3 point to stdout, whereas normally stream 3 is undefined. This might not be so bad.

More problematic is the fact that stream4 is left open pointing to args.txt, and it will remain open until the CMD shell is terminated. :(


Dave Benham


Last edited by dbenham on 03 Apr 2012 11:24, edited 2 times in total.



29 Mar 2012 13:26
Profile
Expert

Joined: 12 Feb 2011 21:02
Posts: 1185
Location: United States (east coast)
Post Re: foolproof counting of arguments
My prior post had a test case that enabled me to derive the rules, but it wasn't very definitive proof.

Here is a new test case that better proves the theory.
Code:
@echo off
2>file2.txt 3>file3.txt 1>file1.txt 5>file5.txt 6>file6.txt (
  REM while redirection is in effect
  REM 2=file2.txt, 3=file3.txt, 4=stderr
  REM 1=file1.txt, 5=file5.txt, 6=file6.txt, 7=stdout
  dir /b nonExistentFile
       echo Inside 1st redirection: stream1
  1>&2 echo Inside 1st redirection: stream2
  1>&3 echo Inside 1st redirection: stream3
  1>&4 echo Inside 1st redirection: stream4
  1>&5 echo Inside 1st redirection: stream5
  1>&6 echo Inside 1st redirection: stream6
  1>&7 echo Inside 1st redirection: stream7
  1>&7 (
    echo -----------------------
    echo file1:
    type file1.txt
    echo -----------------------
    echo file2:
    type file2.txt
    echo -----------------------
    echo file3:
    type file3.txt
    echo -----------------------
    echo file5:
    type file5.txt
    echo -----------------------
    echo file6:
    type file6.txt
    echo =============================
  )
)
REM Prior redirection is now over,
REM but handles are only restored one level deep
REM 2=file3.txt, 3=stderr, 4=undefined
REM 1=file5.txt, 5=file6.txt, 6=stdout, 7=undefined
dir /b nonExistentFile
     echo After 1st redirection: stream1
1>&2 echo After 1st redirection: stream2
1>&3 echo After 1st redirection: stream3
1>&4 echo After 1st redirection: stream4
1>&5 echo After 1st redirection: stream5
1>&6 echo After 1st redirection: stream6
1>&7 echo After 1st redirection: stream7
1>&6 (
  echo -----------------------
  echo file1:
  type file1.txt
  echo -----------------------
  echo file2:
  type file2.txt
  echo -----------------------
  echo file3:
  type file3.txt
  echo -----------------------
  echo file5:
  type file5.txt
  echo -----------------------
  echo file6:
  type file6.txt
  echo =============================
)

1>&6 4>&6 2>&3 8>&3 (
  REM while redirection is in effect
  REM 3=stderr(unchanged), 5=file6.txt(unchanged), 6=stdout(unchanged),
  REM 1=6=stdout, 4=6=stdout, 7=file5.txt(from 4 from 1 before redirection)
  REM 2=3=stderr, 8=3=stderr, 9=file3.txt(from 8 from 2 before redirection)
  dir /b nonExistentFile
       echo Inside 2nd redirection: stream1
  1>&2 echo Inside 2nd redirection: stream2
  1>&3 echo Inside 2nd redirection: stream3
  1>&4 echo Inside 2nd redirection: stream4
  1>&5 echo Inside 2nd redirection: stream5
  1>&6 echo Inside 2nd redirection: stream6
  1>&7 echo Inside 2nd redirection: stream7
  1>&8 echo Inside 2nd redirection: stream8
  1>&9 echo Inside 2nd redirection: stream9
  1>&6 (
    echo -----------------------
    echo file1:
    type file1.txt
    echo -----------------------
    echo file2:
    type file2.txt
    echo -----------------------
    echo file3:
    type file3.txt
    echo -----------------------
    echo file5:
    type file5.txt
    echo -----------------------
    echo file6:
    type file6.txt
    echo =============================
  )
)
REM Prior redirection is now over,
REM 3=stderr(unchanged), 5=file6.txt(unchanged), 6=stdout(unchanged),
REM 1=6=stdout, 4=file5.txt, 7=undefined
REM 2=3=stderr, 8=file3.txt, 9=undefined
dir /b nonExistentFile
     echo After 2nd redirection: stream1
1>&2 echo After 2nd redirection: stream2
1>&3 echo After 2nd redirection: stream3
1>&4 echo After 2nd redirection: stream4
1>&5 echo After 2nd redirection: stream5
1>&6 echo After 2nd redirection: stream6
1>&7 echo After 2nd redirection: stream7
1>&8 echo After 2nd redirection: stream8
1>&9 echo After 2nd redirection: stream9
echo -----------------------
echo file1:
type file1.txt
echo -----------------------
echo file2:
type file2.txt
echo -----------------------
echo file3:
type file3.txt
echo -----------------------
echo file5:
type file5.txt
echo -----------------------
echo file6:
type file6.txt
echo =============================

And here are the results
Code:
>test
Inside 1st redirection: stream4
Inside 1st redirection: stream7
-----------------------
file1:
Inside 1st redirection: stream1
-----------------------
file2:
File Not Found
Inside 1st redirection: stream2
-----------------------
file3:
Inside 1st redirection: stream3
-----------------------
file5:
Inside 1st redirection: stream5
-----------------------
file6:
Inside 1st redirection: stream6
=============================
After 1st redirection: stream3
After 1st redirection: stream6
-----------------------
file1:
Inside 1st redirection: stream1
-----------------------
file2:
File Not Found
Inside 1st redirection: stream2
-----------------------
file3:
Inside 1st redirection: stream3
File Not Found
After 1st redirection: stream2
The handle could not be duplicated
during redirection of handle 1.
-----------------------
file5:
Inside 1st redirection: stream5
After 1st redirection: stream1
After 1st redirection: stream4
-----------------------
file6:
Inside 1st redirection: stream6
After 1st redirection: stream5
=============================
File Not Found
Inside 2nd redirection: stream1
Inside 2nd redirection: stream2
Inside 2nd redirection: stream3
Inside 2nd redirection: stream4
Inside 2nd redirection: stream6
Inside 2nd redirection: stream8
-----------------------
file1:
Inside 1st redirection: stream1
-----------------------
file2:
File Not Found
Inside 1st redirection: stream2
-----------------------
file3:
Inside 1st redirection: stream3
File Not Found
After 1st redirection: stream2
The handle could not be duplicated
during redirection of handle 1.
Inside 2nd redirection: stream9
-----------------------
file5:
Inside 1st redirection: stream5
After 1st redirection: stream1
After 1st redirection: stream4
Inside 2nd redirection: stream7
-----------------------
file6:
Inside 1st redirection: stream6
After 1st redirection: stream5
Inside 2nd redirection: stream5
=============================
File Not Found
After 2nd redirection: stream1
After 2nd redirection: stream2
After 2nd redirection: stream3
After 2nd redirection: stream6
After 2nd redirection: stream7
The handle could not be duplicated
during redirection of handle 1.
-----------------------
file1:
Inside 1st redirection: stream1
-----------------------
file2:
File Not Found
Inside 1st redirection: stream2
-----------------------
file3:
Inside 1st redirection: stream3
File Not Found
After 1st redirection: stream2
The handle could not be duplicated
during redirection of handle 1.
Inside 2nd redirection: stream9
After 2nd redirection: stream8
-----------------------
file5:
Inside 1st redirection: stream5
After 1st redirection: stream1
After 1st redirection: stream4
Inside 2nd redirection: stream7
After 2nd redirection: stream4
-----------------------
file6:
Inside 1st redirection: stream6
After 1st redirection: stream5
Inside 2nd redirection: stream5
After 2nd redirection: stream5
=============================

>del file1.txt

>del file2.txt

>del file3.txt
....file3.txt
The process cannot access the file because it is being used by another process.

>del file5.txt
....file5.txt
The process cannot access the file because it is being used by another process.

>del file6.txt
....file6.txt
The process cannot access the file because it is being used by another process.

>

The results exactly match my expectations. There are 2 cases that took a while for me to figure out.

After the 1st redirection is over, stream 4 is undefined. Yet when I redirect 1 to &4, I get the output in file5.txt. What I believe happens is this:
- Before the redirection, 1 is directed to file5.txt, and 4 is undefined.
- CMD gets the instruction to redirect 1 to &4
- - first the current definition (file5.txt) is stored in the first available undefined stream, which happens to be 4.
- - then the redirection is completed and 1 is redirected to the current definition of 4, which is now file5.txt

After the 2nd redirection is over, stream 7 is undefined. Yet when I redirect 1 to &7, I get the output on stdout.
- Before the redirection, 1 is going to stdout, and 7 is undefined
- CMD gets the instruction to redirect 1 to &7
- - first the current definition (stdout) is stored in the first available undefined stream, which happens to be 7.
- - then the redirection is completed and 1 is redirected to the current definition of 7, which is now stdout.

When all is done, file1.txt and file2.txt are closed. But files 3, 5 and 6 are left open and locked until the CMD session is terminated.


Dave Benham


29 Mar 2012 21:44
Profile
Expert

Joined: 30 Aug 2007 08:05
Posts: 666
Location: Germany
Post Re: foolproof counting of arguments
It's really awkful :shock: :!:

I like this type of analyses, it's a really new insight into batch/cmd mechanics.

But I don't understand why someone (MS) create it this way.
Even when I was a poor beginner I wouldn't produce such solutions.

But it was a great investigation of Dave to figure out how it works. :D

jeb


04 Apr 2012 10:43
Profile

Joined: 25 Aug 2012 21:33
Posts: 1
Post Re: foolproof counting of arguments
Hi !

What about this code :

Quote:
set tmp=%1
set tmp=%tmp:~0,1%
:: Double the doublequote seems to be better with if using [ ].Characters " = [ & ^ etc are handled
set tmp=%tmp:"=""%
if ["%tmp%"] == ["~0,1"] GOTO :ARGUMENT_NOT_DEFINED
if ["%tmp%"] == [""] GOTO :ARGUMENT_NOT_DEFINED

:ARGUMENT_DEFINED
REM your stuff
GOTO :EOF

:ARGUMENT_NOT_DEFINED
REM your other stuff
GOTO :EOF


25 Aug 2012 21:53
Profile
Expert

Joined: 13 Jan 2012 21:24
Posts: 440
Post Re: foolproof counting of arguments
Astyan wrote:
What about this code

Fails if you pass it for example either

=
^&
^<

and similar others, too.

Liviu


25 Aug 2012 23:03
Profile
Expert

Joined: 12 Feb 2011 21:02
Posts: 1185
Location: United States (east coast)
Post Re: foolproof counting of arguments
And it is much more complicated than need be for the cases that don't fail. The code could be simplified to:
Code:
set test=%1
if defined test (echo arg1 is defined) else echo arg1 is not defined

BUT, as Liviu has already pointed out, the SET statement can fail under many circumstances.


Dave Benham


26 Aug 2012 00:15
Profile
Expert

Joined: 06 Dec 2011 22:15
Posts: 710
Location: México City, México
Post Re: foolproof counting of arguments
I would like to add some technical information to this thread just to complete it. I copied this info from "Microsoft MS-DOS Programmer's Reference" manual for DOS Version 5 (Microsoft Press, 1991). Although the manual is (old!) DOS specific, the point stated here is performed in the same way in modern Windows cmd.exe command-line window, that is: how the redirection of a standard handle to/from a disk file is achieved?

When any command is executed in a command-line window or Batch file, it inherits from its parent process these three standard handles: 0 (STDIN) connected to keyboard, 1 (STDOUT) connected to screen, and 2 (STDERR) connected to screen (although in original DOS there are also 3=STDPRN and 4=STDAUX standard handles open). In Windows/DOS Batch files, the handles 3 to 9 are available to open additional files (in normal programs the last number is the value of FILES= in CONFIG.SYS file, usually 20). There are two DOS file handle management functions important for this topic:

Code:
Int 21H, Function 45H: Duplicate File Handle

    mov     bx, OldHandle       ;handle to duplicate, for example: 1 (STDOUT)
    mov     ah, 45H             ;function: Duplicate File Handle
    int     21H                 ;call DOS function
    mov     NewHandle, ax       ;store new handle

This function creates a new file handle that can be used to read from or write to the same file or device that is associated with the original handle.

The number of the new handle is the first available number (the same way than in Open File function), for example: 3.

Code:
Int 21H, Function 46H: Force Duplicate File Handle

    mov     bx, OpenHandle      ;handle of file or device
    mov     cx, DuplicateHandle ;new handle for same file or device
    mov     ah, 46H             ;function: Force Duplicate File Handle
    int     21H                 ;call DOS function

This function forces the specified duplicate handle to identify the same open file or device identified by the OpenHandle parameter.
DuplicateHandle must not exceed the current limit of available handles.
After a program uses this function, both handles can be used to read from or write to the file or device specified by OpenHandle.
If DuplicateHandle identifies an open file, MS-DOS closes that file.

Lets pass to review the method that the programmer's manual specify to achieve a redirection of STDOUT in a similar way than this command-line: ANYCOMMAND > DISKFILE.TXT

Code:
5.4.3 Standard-Device Redirection

A parent program can redirect a standard device for the child program by associating the standard-device handle with a new device or file before it starts the child program. To do this, the parent program should follow these steps:

1  Duplicate the standard-device handle by using Duplicate File Handle (Function 45H).

    mov     bx, 1               ;handle to duplicate: STDOUT
    mov     ah, 45H             ;function: Duplicate File Handle
    int     21H                 ;call DOS function

2  Save the duplicate handle.

    mov     NewHandle, ax       ;store new handle               ;NewHandle = 3 (associated with the screen)

3  Open the new file or device.

    mov     dx, offset FileName ;dx points to name of file or device (like "diskfile.txt",0)
    mov     ah, 3DH             ;function: Open File with Handle
    int     21H                 ;call DOS function
    mov     handle, ax          ;handle of file or device       ;handle = 4 (next available handle)

4  With the new handle retrieved in step 3, modify the standard-device handle by using Force Duplicate File Handle (Function 46H).

    mov     bx, handle          ;handle of file or device       ;bx = 4 (associated with diskfile.txt)
    mov     cx, 1               ;new handle for same file or device ;standard STDOUT
    mov     ah, 46H             ;function: Force Duplicate File Handle
    int     21H                 ;call DOS function              ;now STDOUT is associated with diskfile.txt

The standard-device handle should now identify the same file or device as the new handle.                               

5  Load and run the child program.

A parent program can restore the original standard-device handle by using Force Duplicate File Handle and specifying the duplicate handle saved in step 2.

    mov     bx, NewHandle       ;handle of file or device       ;bx = 3 (associated with the screen)
    mov     cx, 1               ;new handle for same file or device ;standard STDOUT
    mov     ah, 46H             ;function: Force Duplicate File Handle
    int     21H                 ;call DOS function              ;now STDOUT is re-associated with the screen
                                                                ;at the same time, handle 1 of diskfile.txt is closed
                                                                ;but handles 4 and 3 remains open until the program ends


Previous description explain the behaviour of all redirection combinations that can be achieved in a Batch file or command line.

Antonio


02 Nov 2013 21:10
Profile
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 44 posts ]  Go to page Previous  1, 2, 3


Who is online

Users browsing this forum: Bing [Bot], Yahoo [Bot] and 17 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Forum style by Vjacheslav Trushkin for Free Forums/DivisionCore.