<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6454686814995217416</id><updated>2011-11-27T17:33:02.412-08:00</updated><title type='text'>Batcheero</title><subtitle type='html'>Windows Batch Programming, Tips, Tricks and Pitfalls.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>27</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-6300905723386260743</id><published>2009-01-23T23:47:00.001-08:00</published><updated>2009-01-23T23:47:53.750-08:00</updated><title type='text'>Numbered Output Redirection</title><content type='html'>&lt;p&gt;Today my boss pointed out something to me which is kind of shocking even though you already know how stupid the command processor is.&amp;#160; Now we all know &lt;font face="Courier New" color="#0000ff"&gt;2&amp;gt;&lt;/font&gt; is for redirecting &lt;font face="Courier New" color="#0000ff"&gt;stderr&lt;/font&gt;.&amp;#160; Simply &lt;font face="Courier New" color="#0000ff"&gt;&amp;gt;&lt;/font&gt; or &lt;font face="Courier New" color="#0000ff"&gt;1&amp;gt;&lt;/font&gt; is &lt;font face="Courier New" color="#0000ff"&gt;stdout&lt;/font&gt;.&amp;#160; For &lt;font face="Courier New" color="#0000ff"&gt;stdin&lt;/font&gt; you use &lt;font face="Courier New" color="#0000ff"&gt;&amp;lt;&lt;/font&gt; or (less widely known) &lt;font face="Courier New" color="#0000ff"&gt;0&amp;lt;&lt;/font&gt;.&lt;/p&gt;  &lt;p&gt;But what if you do &lt;font face="Courier New" color="#0000ff"&gt;3&amp;gt;&lt;/font&gt; or &lt;font face="Courier New" color="#0000ff"&gt;4&amp;gt;&lt;/font&gt; or &lt;font face="Courier New" color="#0000ff"&gt;5&amp;lt;&lt;/font&gt;?&amp;#160; Surely it does not interpret that as some special file handle?&amp;#160; Well, if you thought that, you’d be wrong.&amp;#160; Just like I was.&amp;#160; Try this:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New" color="#0000ff"&gt;echo Hi 3&amp;gt; out.txt&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;You’d expect to see &lt;font face="Courier New" color="#0000ff"&gt;Hi 3&lt;/font&gt;, wouldn’t you?&amp;#160; But nooooo, you’ll see &lt;font face="Courier New" color="#0000ff"&gt;Hi&lt;/font&gt; instead.&lt;/p&gt;  &lt;p&gt;Where does the &lt;font face="Courier New" color="#0000ff"&gt;3&lt;/font&gt; go?&amp;#160; Well, the good interpreter thinks it’s a special file handle.&amp;#160; Crazy isn’t it?&amp;#160; But what if you really want to print &lt;font face="Courier New" color="#0000ff"&gt;Hi 3&lt;/font&gt;?&amp;#160; What do you do?&amp;#160; Thankfully the solution is easy and pretty obvious.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New" color="#0000ff"&gt;echo Hi 3 &amp;gt; out.txt&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Yup, just put a space between &lt;font face="Courier New" color="#0000ff"&gt;3&lt;/font&gt; and &lt;font face="Courier New" color="#0000ff"&gt;&amp;gt;&lt;/font&gt;, and you’re good to go.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-6300905723386260743?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/6300905723386260743/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=6300905723386260743' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/6300905723386260743'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/6300905723386260743'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2009/01/numbered-output-redirection.html' title='Numbered Output Redirection'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-7918913677668624016</id><published>2008-11-16T01:56:00.001-08:00</published><updated>2008-11-16T01:56:49.201-08:00</updated><title type='text'>Quotes In For Loop Set</title><content type='html'>&lt;p&gt;One thing that just bit me the other day is how &lt;font face="Courier New" color="#0000ff"&gt;for /F&lt;/font&gt; loop treats a set enclosed in quotes as a literal string rather than a file name.&amp;#160; This is actually mentioned in the help for page, but still, this is something I did not anticipate.&lt;/p&gt;  &lt;p&gt;Consider this example:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New" color="#0000ff"&gt;set FILEPATH=”c:\some dir with space\somefile.txt”&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Now I wanted to go through the lines in that file, so naturally I tried to do this:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New" color="#0000ff"&gt;for /F %i in (%FILEPATH%) do (echo %i)&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;What do I get?&amp;#160; I get:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New" color="#0000ff"&gt;c:\some&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Why?&amp;#160; Well, it turns out &lt;font face="Courier New" color="#0000ff"&gt;for /F&lt;/font&gt; treats anything in the set with quotes as a string instead of a filename.&amp;#160; OK, so let me try without the quotes then.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New" color="#0000ff"&gt;set FILEPATH=c:\some dir with space\somefile.txt&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New" color="#0000ff"&gt;for /F %i in (%FILEPATH%) do (echo %i)&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;But now I get this error:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New" color="#0000ff"&gt;The system cannot find the file c:\some.&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;So it refuses to recognize the filename with spaces if I remove the quotes.&amp;#160; So what to do then?&amp;#160; The ugly way, unfortunately.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font face="Courier New" color="#0000ff"&gt;set FILEPATH=”c:\some dir with space\somefile.txt”&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font face="Courier New" color="#0000ff"&gt;for /F “usebackq” %i in (`type %FILEPATH%`) do (echo %i)&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Sigh…&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-7918913677668624016?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/7918913677668624016/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=7918913677668624016' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/7918913677668624016'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/7918913677668624016'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2008/11/quotes-in-for-loop-set.html' title='Quotes In For Loop Set'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-7030821895540308867</id><published>2008-03-06T12:58:00.001-08:00</published><updated>2008-03-06T12:58:58.026-08:00</updated><title type='text'>Setx Escape Character</title><content type='html'>&lt;p&gt;I recently found out that there is something rather strange with how &lt;font face="Courier New" color="#0000a0"&gt;setx&lt;/font&gt; interprets character you pass to it when setting a variable.&amp;nbsp; It appears that &lt;font face="Courier New" color="#0000a0"&gt;setx&lt;/font&gt; has singled out &lt;font face="Courier New" color="#0000a0"&gt;\"&lt;/font&gt; as an escaped character.&amp;nbsp; So if you want to set variable &lt;font face="Courier New" color="#0000a0"&gt;MYVAR&lt;/font&gt; to have the value of &lt;font face="Courier New" color="#0000a0"&gt;My name is "Batcheero"&lt;/font&gt;, here's how you do it:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;setx MYVAR "My name is \"Batcheero\""&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;This is weird because I don't know of any other Windows commands that does this without specifically saying that it is taking regular expressions (like &lt;font face="Courier New" color="#0000a0"&gt;findstr /R&lt;/font&gt;).&amp;nbsp; And the other weird thing is, &lt;font face="Courier New" color="#0000a0"&gt;\"&lt;/font&gt; seems to be the only pair that it escapes.&amp;nbsp; If you try &lt;font face="Courier New" color="#0000a0"&gt;\'&lt;/font&gt; or &lt;font face="Courier New" color="#0000a0"&gt;\n&lt;/font&gt; or &lt;font face="Courier New" color="#0000a0"&gt;\\&lt;/font&gt;, it treats those verbatim.&lt;/p&gt; &lt;p&gt;The bad thing about this singled out treatment is, you have to be careful not to pass a value that ends with a backslash to &lt;font face="Courier New" color="#0000a0"&gt;setx&lt;/font&gt;.&amp;nbsp; For example, if you have a path of a directory that ends with a backslash, which is quite common, then you are in trouble.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;set MYPATH=c:\program files\my app\&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;setx /M MYPATH "%MYPATH%"&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;This is going to be fine in the current context, but what gets set in global machine environment is &lt;font face="Courier New" color="#0000a0"&gt;c:\program files\my app"&lt;/font&gt; (notice the double quote in the end instead of backslash), which is definitely not what you want.&lt;/p&gt; &lt;p&gt;Just one more thing to worry about in Batch world.&amp;nbsp; Let me know if you are aware of other commands that has this kind of behavior.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-7030821895540308867?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/7030821895540308867/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=7030821895540308867' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/7030821895540308867'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/7030821895540308867'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2008/03/setx-escape-character.html' title='Setx Escape Character'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-3035344232656880065</id><published>2008-02-14T00:57:00.001-08:00</published><updated>2008-02-14T00:57:39.147-08:00</updated><title type='text'>Set And Setx</title><content type='html'>&lt;p&gt;Everybody knows to use &lt;font face="Courier New" color="#0000a0"&gt;set&lt;/font&gt; to set environment variable values.&amp;nbsp; And I guess everybody should know &lt;font face="Courier New" color="#0000a0"&gt;setx&lt;/font&gt;.&amp;nbsp; The crucial differences between set and &lt;font face="Courier New" color="#0000a0"&gt;setx&lt;/font&gt; are:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;font face="Courier New" color="#0000a0"&gt;set&lt;/font&gt; takes effect in local cmd context.&amp;nbsp; Meaning once you exit or close the cmd window, you lose the environment variable.&lt;/li&gt; &lt;li&gt;&lt;font face="Courier New" color="#0000a0"&gt;setx&lt;/font&gt; takes effect in future cmd context.&amp;nbsp; So you won't see the environment variable and its value in the current cmd.&amp;nbsp; You need to open a new cmd window to see it.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;This really leads to one obvious conclusion: always use &lt;font face="Courier New" color="#0000a0"&gt;set&lt;/font&gt; and &lt;font face="Courier New" color="#0000a0"&gt;setx&lt;/font&gt; side by side if you want to set something globally but you want to see it in effect immediately.&lt;/p&gt; &lt;p&gt;A good example is if you want to set an environment variable containing your current IP address.&amp;nbsp; You would do something like this:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;ipconfig | findstr IPv4 &amp;gt; %TEMP%\ipaddress.out&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#408080"&gt;REM This will give you something like this&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#408080"&gt;REM IPv4 Address. . . . . . . . . . . : 192.168.1.3&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#408080"&gt;REM You then parse the output file, taking the second token after splitting at the ":"&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;for /F "delims=: tokens=2" %i in (%TEMP%\ipaddress.out) do (&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; set IPADDR=%i&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;)&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#008080"&gt;REM Then remove the spaces&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;set IPADDR=%IPADDR: =%&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#008080"&gt;REM Then to persist this in the system environment, you call setx.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;setx /M IPADDR %IPADDR%&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Now of course &lt;font face="Courier New" color="#0000a0"&gt;setx&lt;/font&gt; is much more powerful than simply calling it the way I did in the above example.&amp;nbsp; Take a look at &lt;font face="Courier New" color="#0000a0"&gt;setx /?&lt;/font&gt; to see the complete options.&amp;nbsp; For example the above usage can also be done using &lt;font face="Courier New" color="#0000a0"&gt;setx&lt;/font&gt; alone.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;ipconfig | findstr IPv4 &amp;gt; %TEMP%\ipaddress.out&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#008080"&gt;REM Then you use setx to read its value from a file, keying in on a string, &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font color="#008080"&gt;&lt;font face="Courier New"&gt;REM and get the value relative to that string.&lt;/font&gt;&lt;font face="Courier New"&gt; In this case we key in on the ":" &lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#008080"&gt;REM and get the token after that.&amp;nbsp; And setx coordinates start at 0, not 1.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;setx /M IPADDR /F %TEMP%\ipaddress.out /R 0,1 ":"&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The reason I hardly ever use this is because most of the time I need the environment variable defined in the current context first, and then also persisting it for future cmd contexts.&amp;nbsp;&amp;nbsp; The second example above only does it for future context.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-3035344232656880065?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/3035344232656880065/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=3035344232656880065' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/3035344232656880065'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/3035344232656880065'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2008/02/set-and-setx.html' title='Set And Setx'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-729661744794513151</id><published>2008-01-21T14:32:00.001-08:00</published><updated>2008-01-21T14:32:33.819-08:00</updated><title type='text'>Creating Compressed Directory</title><content type='html'>&lt;p&gt;Often times I find myself in need of creating a directory with compressed attribute turned on, so I can put some text log files in with less space consumption.&amp;nbsp; While &lt;font face="Courier New" color="#0000a0"&gt;md&lt;/font&gt; or &lt;font face="Courier New" color="#0000a0"&gt;mkdir&lt;/font&gt; doesn't support doing this directly, you can create the directory and later apply the compression attribute, so that any subsequent files copied to that directory will be compressed.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;md SomeDir&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;compact /C SomeDir&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;copy SomeText.log SomeDir&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;That does it.&amp;nbsp; Not the most useful thing in the world.&amp;nbsp; But hey, you never know when you will need it.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-729661744794513151?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/729661744794513151/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=729661744794513151' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/729661744794513151'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/729661744794513151'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2008/01/creating-compressed-directory.html' title='Creating Compressed Directory'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-1056032454396505376</id><published>2008-01-18T15:16:00.001-08:00</published><updated>2008-01-18T15:16:02.305-08:00</updated><title type='text'>Out Parameter In Function Call</title><content type='html'>&lt;p&gt;Let's say you write a function or procedure or sub program or whatever you want to call it in batch.&amp;nbsp; How do you pass back a value to the caller?&amp;nbsp; You can of course set an environment variable, but that's like setting a global variable.&amp;nbsp; And that's not very nice if you need to call the function multiple times and only use the value after all function calls are made.&lt;/p&gt; &lt;p&gt;Consider this example:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;@echo off &lt;/font&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;call :GETVALUE&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;set INPUT1=%USERINPUT%&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;call :GETVALUE&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;set INPUT2=%USERINPUT%&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;echo %INPUT1% %INPUT2%&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;goto :EOF &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;&lt;/font&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;:GETVALUE&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;set /P USERINPUT=Input?&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;goto :EOF&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Like I said, it's doable, but not very nice.&amp;nbsp; I find it more soothing to the eyes if I can pass the variable name as an argument to the function.&amp;nbsp; And here's how you do it:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;@echo off &lt;/font&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;call :GETVALUE INPUT1&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;call :GETVALUE INPUT2&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;echo %INPUT1% %INPUT2%&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;goto :EOF &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;&lt;/font&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;:GETVALUE&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;set /P %1=Input?&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;goto :EOF&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Nice and simple.&amp;nbsp; All you need to do is remember that you can use &lt;font face="Courier New" color="#0000a0"&gt;%1&lt;/font&gt; and other &lt;font face="Courier New" color="#0000a0"&gt;%&amp;lt;number&amp;gt;&lt;/font&gt; on the left hand side of an assignment.&amp;nbsp; And it makes you think for a second that you are programming a real scripting language.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-1056032454396505376?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/1056032454396505376/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=1056032454396505376' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/1056032454396505376'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/1056032454396505376'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2008/01/out-parameter-in-function-call.html' title='Out Parameter In Function Call'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-2052345358441896962</id><published>2008-01-17T15:10:00.001-08:00</published><updated>2008-01-17T15:10:26.836-08:00</updated><title type='text'>Escape Characters</title><content type='html'>&lt;p&gt;I know this is going to be a confusing year, because my first post of this year is on a topic I don't really understand.&lt;/p&gt; &lt;p&gt;For some time now I have been confused what the correct method to escape certain characters from being interpreted when I try to print them out.&amp;nbsp; Let's say I want to print this line:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;&amp;lt; &amp;amp; &amp;gt;&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;I can't just say&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;echo &amp;lt; &amp;amp; &amp;gt;&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Because I'll get an error that way (try it yourself if you don't believe me).&amp;nbsp; I have to escape those special characters.&amp;nbsp; To do that I can use the caret (&lt;font face="Courier New" color="#0000a0"&gt;^&lt;/font&gt;).&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;echo ^&amp;lt; ^&amp;amp; ^&amp;gt;&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Nice and easy.&amp;nbsp; But then if I want to print this line:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;%SYSTEMDRIVE%&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The batch interpreter does something really baffling.&amp;nbsp; If I'm doing it from command line, I can escape it with a caret like other special characters.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;echo ^%SYSTEMDRIVE^%&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;But it I do it from inside a batch file, that no longer works.&amp;nbsp; I have to escape the &lt;font face="Courier New" color="#0000a0"&gt;%&lt;/font&gt; not with a caret, but with another &lt;font face="Courier New" color="#0000a0"&gt;%&lt;/font&gt;.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;echo %%SYSTEMDRIVE%&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Confuse the hell out of me, I tell you.&amp;nbsp; So now I live by these rules:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Always escape special characters using a caret in front of the special character.&lt;/li&gt; &lt;li&gt;Except when you are in a batch file and need to escape a &lt;font face="Courier New" color="#0000a0"&gt;%&lt;/font&gt;, then use a &lt;font face="Courier New" color="#0000a0"&gt;%%&lt;/font&gt;.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;I hope that helps some of you.&amp;nbsp; Oh wait, nobody reads this blog but me.&amp;nbsp; Oh, well.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-2052345358441896962?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/2052345358441896962/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=2052345358441896962' title='16 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/2052345358441896962'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/2052345358441896962'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2008/01/escape-characters.html' title='Escape Characters'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-63646284425006657</id><published>2007-10-19T16:35:00.001-07:00</published><updated>2007-10-19T16:35:34.365-07:00</updated><title type='text'>Label at the End of Block</title><content type='html'>&lt;p&gt;One thing I hate about batch file is, there is no real language definition you can refer to (or is there?).&amp;nbsp; So a lot of things I have to find out by myself the hard way.&lt;/p&gt; &lt;p&gt;Here's an example of this:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;@echo off&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;for /L %%i in (1,1,10) do (&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;&amp;nbsp; if %%i GEQ 5 goto :NOPRINT&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;&amp;nbsp; echo %%i&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;&amp;nbsp; :NOPRINT&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;) &lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;This gives an error saying that ") was unexpected at this time".&amp;nbsp; It is obvious what this means, and it is obvious how to fix it.&amp;nbsp; Just put a comment between the label and the closing bracket. &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;@echo off&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;for /L %%i in (1,1,10) do (&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;&amp;nbsp; if %%i GEQ 5 goto :NOPRINT&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;&amp;nbsp; echo %%i&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;&amp;nbsp; :NOPRINT&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;&amp;nbsp; &lt;strong&gt;REM can't have label immediately preceding closing bracket&lt;/strong&gt;&lt;br&gt;) &lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;I know this is not really anything useful, just a rant, that's all.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-63646284425006657?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/63646284425006657/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=63646284425006657' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/63646284425006657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/63646284425006657'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2007/10/label-at-end-of-block.html' title='Label at the End of Block'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-4945508514998475189</id><published>2007-10-19T16:25:00.001-07:00</published><updated>2007-10-19T16:25:55.950-07:00</updated><title type='text'>Evil Delayed Expansion</title><content type='html'>&lt;p&gt;Wait, what's this?&amp;nbsp; How come something so useful as delayed expansion (see previous posts &lt;a href="http://batcheero.blogspot.com/2007/06/how-to-enabledelayedexpansion.html"&gt;here&lt;/a&gt; and &lt;a href="http://batcheero.blogspot.com/2007/07/dynamic-variable-name.html"&gt;here&lt;/a&gt; to see how useful it is) be evil?&amp;nbsp; Well, it's not the feature itself that's evil, but rather the way you can end up spending a long time trying to figure out what's wrong if you make a simple, stupid mistake.&lt;/p&gt; &lt;p&gt;What mistake am I talking about?&amp;nbsp; Consider this:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;@echo off &lt;/font&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;setlocal enabledelayedexpansion &lt;/font&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;set COUNT=0 &lt;/font&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;for /L %%i in (1,1,10) do ( &lt;/font&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;&amp;nbsp; set /A COUNT=%COUNT% + 1 &lt;/font&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;&amp;nbsp; echo !COUNT!&lt;br&gt;)&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Simple enough, you said.&amp;nbsp; And you must have spotted the bug (if you have not, try to run it and see what happens).&amp;nbsp; Now, of course if the loop body is much more complicated it would not be as easy.&amp;nbsp; You see, the problem is that what you are doing is completely legal.&amp;nbsp; Having &lt;font face="Courier New" color="#0000a0"&gt;%COUNT%&lt;/font&gt; in the loop body is fine as long as you don't expect it to be delay-expanded.&amp;nbsp; It's a feature, but when you make that silly mistake (or more likely, someone else in your team), then it's not going to be pleasant to hunt the problem down.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-4945508514998475189?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/4945508514998475189/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=4945508514998475189' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/4945508514998475189'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/4945508514998475189'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2007/10/evil-delayed-expansion.html' title='Evil Delayed Expansion'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-8829374798331301992</id><published>2007-09-26T22:43:00.001-07:00</published><updated>2007-09-26T22:43:26.056-07:00</updated><title type='text'>Using WaitFor</title><content type='html'>&lt;p&gt;In Vista, there is a command called &lt;font face="Courier New" color="#0000a0"&gt;waitfor&lt;/font&gt;, which as the name suggests, waits for a signal.&amp;nbsp; It is also the command to send the signal to awaiting &lt;font face="Courier New" color="#0000a0"&gt;waitfor&lt;/font&gt; instances.&amp;nbsp; Since &lt;font face="Courier New" color="#0000a0"&gt;waitfor&lt;/font&gt; comes with a timeout option, it's a good substitute for &lt;font face="Courier New" color="#0000a0"&gt;sleep&lt;/font&gt; (which, until I found out about waitfor, really was the number one thing I could not understand why it's missing from standard Windows command).&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;waitfor /T 10 SomeSignal&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The above&amp;nbsp;command will simply times out after 10 seconds.&lt;/p&gt; &lt;p&gt;OK, I lied.&amp;nbsp; There is actually a real substitute for &lt;font face="Courier New" color="#0000a0"&gt;sleep&lt;/font&gt; in Windows.&amp;nbsp; It's the &lt;font face="Courier New" color="#0000a0"&gt;timeout&lt;/font&gt; command.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;timeout /T 10&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;That command does the exact same thing as the &lt;font face="Courier New" color="#0000a0"&gt;waitfor&lt;/font&gt; example, but you can cut short the sleep for &lt;font face="Courier New" color="#0000a0"&gt;waitfor&lt;/font&gt; with some signal, whereas for &lt;font face="Courier New" color="#0000a0"&gt;timeout&lt;/font&gt; you cut it short by pressing a key.&lt;/p&gt; &lt;p&gt;But obviously&amp;nbsp;the purpose of&amp;nbsp;the &lt;font face="Courier New" color="#0000a0"&gt;waitfor&lt;/font&gt; command is to allow you to start some&amp;nbsp;long running command, do some other shorter things, and &amp;nbsp;wait for the long running command to finish before continuing.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;REM Let's pretend we need to setup something&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;start cmd /c "DoSetup.exe &amp;amp; waitfor /S %COMPUTERNAME% /SI ThisSignal"&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;DoSomethingElse.exe&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;waitfor /T 60 ThisSignal&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The first &lt;font face="Courier New" color="#0000a0"&gt;waitfor&lt;/font&gt; sends the signal, the second waits for the signal.&amp;nbsp; Of course you want to make sure &lt;font face="Courier New" color="#0000a0"&gt;DoSomethingElse.exe&lt;/font&gt; actually finishes before &lt;font face="Courier New" color="#0000a0"&gt;DoSetup.exe&lt;/font&gt; for this to work.&amp;nbsp; Otherwise the second &lt;font face="Courier New" color="#0000a0"&gt;waitfor&lt;/font&gt; will just timeout.&amp;nbsp; And I'd advise against waiting forever in the second &lt;font face="Courier New" color="#0000a0"&gt;waitfor&lt;/font&gt;, since if your &lt;font face="Courier New" color="#0000a0"&gt;DoSetup.exe&lt;/font&gt; fails or crashes and exits early, you'll most likely end up waiting too late for a signal that's already sent.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-8829374798331301992?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/8829374798331301992/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=8829374798331301992' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/8829374798331301992'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/8829374798331301992'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2007/09/using-waitfor.html' title='Using WaitFor'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-2697534820426241693</id><published>2007-08-04T11:16:00.001-07:00</published><updated>2007-08-04T11:16:14.290-07:00</updated><title type='text'>Adding Accounts To Local Admin Group</title><content type='html'>&lt;p&gt;Well, OK, it's not only for adding accounts to local admin group.&amp;nbsp; You can use the commands I'm about to show here to add accounts to any local group.&amp;nbsp; But I use it most often for making some account a local admin on a machine.&lt;/p&gt; &lt;p&gt;It's a pretty well known command actually.&amp;nbsp; Say I want to add my domain account as local admin on a machine.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;net localgroup Administrators MYDOMAIN\batcheero /ADD&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Or you can do the same thing to add another group to local admin.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;net localgroup Administrators SomeOtherGroup /ADD&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;So yeah, you already know that, of course.&amp;nbsp; But what if you have a service running on some remote machine under that machine's local system account, and you want that service to have admin access to your local machine?&amp;nbsp; Well, for that, you need to add the machine account of the remote machine to your local machine.&amp;nbsp; How do you do that?&amp;nbsp; Well to do that, you&amp;nbsp;use the command&amp;nbsp;ever so slightly differently.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;net localgroup Administrators MYDOMAIN\remotemachine$ /ADD&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Notice the &lt;font face="Courier New" color="#0000a0"&gt;$&lt;/font&gt; sign at the end of &lt;font face="Courier New" color="#0000a0"&gt;MYDOMAIN\remotemachine$&lt;/font&gt;.&amp;nbsp; This tells the command it's a machine account, and not to be confused with a regular user account, where there is no &lt;font face="Courier New" color="#0000a0"&gt;$&lt;/font&gt; sign at the end.&lt;/p&gt; &lt;p&gt;I know what you're asking.&amp;nbsp; Why oh why, dont' they just make another&amp;nbsp;switch to say that it's a machine account?&amp;nbsp; Well, like always, that would be too easy now wouldn't it?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-2697534820426241693?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/2697534820426241693/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=2697534820426241693' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/2697534820426241693'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/2697534820426241693'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2007/08/adding-accounts-to-local-admin-group.html' title='Adding Accounts To Local Admin Group'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-2784086524127772637</id><published>2007-07-25T17:52:00.001-07:00</published><updated>2007-07-25T17:52:56.634-07:00</updated><title type='text'>Regex Using Findstr</title><content type='html'>&lt;p&gt;OK, so I'm reeeeally busy these days, and I only have time to post a lame-ass topic like this one.&amp;nbsp; I mean, who wouldn't know about using &lt;font face="Courier New" color="#0000a0"&gt;findstr&lt;/font&gt; to search for regular expressions in a file, right?&lt;/p&gt; &lt;p&gt;Anyway, to do that you all you have to do is pass the &lt;font face="Courier New" color="#0000a0"&gt;/R&lt;/font&gt; option, and put the regular expression as &lt;font face="Courier New" color="#0000a0"&gt;/C&lt;/font&gt; option argument.&amp;nbsp; Say you want to search for every lines in a file that begins with a &lt;font face="Courier New" color="#0000a0"&gt;Foo &lt;/font&gt;and ends with a &lt;font face="Courier New" color="#0000a0"&gt;Bar&lt;/font&gt;, with any string in between.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;findstr /R /C:"^Foo.*Bar$" some.txt&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;To make it search recursively in a directory, use the &lt;font face="Courier New" color="#0000a0"&gt;/S&lt;/font&gt; option.&amp;nbsp; If you want to ignore case, use the &lt;font face="Courier New" color="#0000a0"&gt;/I&lt;/font&gt; option.&lt;/p&gt; &lt;p&gt;OK, gotta go.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-2784086524127772637?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/2784086524127772637/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=2784086524127772637' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/2784086524127772637'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/2784086524127772637'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2007/07/regex-using-findstr.html' title='Regex Using Findstr'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-2788284675869579847</id><published>2007-07-18T17:26:00.001-07:00</published><updated>2008-01-17T14:48:33.959-08:00</updated><title type='text'>Turning Off Screen Saver from Registry</title><content type='html'>&lt;p&gt;I have found myself in a situation where I would like to have my screen saver deactivated.&amp;nbsp; I know, you can do it from the display property just fine, but sometimes I want to be able to do that from the command line so I can make that part of a setup script that I run for all my machines.&lt;/p&gt; &lt;p&gt;There are a couple of registry keys you need to tweak to turn it off.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;HKCU\Control Panel\Desktop\ScreenSaveActive&amp;nbsp; :&amp;nbsp; "0"&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;HKCU\Control Panel\Desktop\SCRNSAVE.EXE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :&amp;nbsp; ""&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The first one is the one that really matters.&amp;nbsp; You are basically turning it off just by setting that to &lt;font face="Courier New" color="#0000a0"&gt;0&lt;/font&gt;.&amp;nbsp; But this will leave whatever default screensaver in the second registry, and that has the rather undesirable effect of showing that as the active screensaver if you open your display property.&lt;/p&gt; &lt;p&gt;Setting the second registry to an empty string basically just sets the active screensaver to none, which is consistent with how you would do it from the display property.&lt;/p&gt; &lt;p&gt;To actually set those values up in the command line, you can put the registry keys and values in a &lt;font face="Courier New" color="#0000a0"&gt;.reg&lt;/font&gt; file the way I did it in the &lt;a href="http://batcheero.blogspot.com/2007/06/how-to-enabledelayedexpansion.html"&gt;Delayed Expansion&lt;/a&gt; article, or you can do it using the &lt;font face="Courier New" color="#0000a0"&gt;reg&lt;/font&gt; utility.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;reg add "HKCU\Control Panel\Desktop" /v "ScreenSaveActive" /t REG_SZ /d "0" /f&lt;/font&gt;  &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;reg add "HKCU\Control Panel\Desktop" /v "SCRNSAVE.EXE" /t REG_SZ /d "" /f&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The &lt;font face="Courier New" color="#0000a0"&gt;/v&lt;/font&gt; switch specified the value (not to be confused with data), &lt;font face="Courier New" color="#0000a0"&gt;/t&lt;/font&gt; specifies the type of that value, and &lt;font face="Courier New" color="#0000a0"&gt;/d&lt;/font&gt; specifies the data you want to set the value to.&amp;nbsp; We also want to do &lt;font face="Courier New" color="#0000a0"&gt;/f&lt;/font&gt; so it does not prompt us when it sees that the values already exist.&amp;nbsp; Do a &lt;font face="Courier New" color="#0000a0"&gt;reg /?&lt;/font&gt; to find out more about the reg command.&amp;nbsp; And to check if they're indeed modified, you can use the &lt;font face="Courier New" color="#0000a0"&gt;reg query&lt;/font&gt; option.  &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;reg query "HKCU\Control Panel\Desktop" /v "ScreenSaveActive" /t REG_SZ&lt;/font&gt;  &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;reg query "HKCU\Control Panel\Desktop" /v "SCRNSAVE.EXE" /t REG_SZ&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The meaning of the switches are as before, except this time we don't use the &lt;font face="Courier New" color="#0000a0"&gt;/d&lt;/font&gt; and &lt;font face="Courier New" color="#0000a0"&gt;/f&lt;/font&gt; option.&amp;nbsp; If you need to check if a particular value is set or not, you can simply pipe it to a &lt;font face="Courier New" color="#0000a0"&gt;findstr&lt;/font&gt; and see if it finds the value you are looking for.&amp;nbsp; For easiest result, you might want to use the &lt;font face="Courier New" color="#0000a0"&gt;findstr&lt;/font&gt; regular expression option.  &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;reg query "HKCU\Control Panel\Desktop" /v "ScreenSaveActive" /t REG_SZ | findstr /R /C:"ScreenSaveActive.*0"&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;if "%errorlevel%" EQU "0" (&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;&amp;nbsp; echo Screensaver is off&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;) else (&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;&amp;nbsp; echo Screensaver is on&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;)&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;As you can see, &lt;font face="Courier New" color="#0000a0"&gt;reg&lt;/font&gt; is a pretty useful command to get and set registry keys and as long as you know what to change, it will get the job done for you.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-2788284675869579847?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/2788284675869579847/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=2788284675869579847' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/2788284675869579847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/2788284675869579847'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2007/07/turning-off-screen-saver-from-registry.html' title='Turning Off Screen Saver from Registry'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-546830132065188695</id><published>2007-07-13T15:27:00.001-07:00</published><updated>2007-10-19T16:01:12.484-07:00</updated><title type='text'>Dynamic Variable Name</title><content type='html'>&lt;p&gt;Sometimes I find myself missing the ability to use arrays in batch scripts. OK, a lot of times. So to get around that, I often have to resort to using variable names that start with the same string and end with numbers. Like &lt;span style="color: #0000a0; font-family: courier new"&gt;VAR1&lt;/span&gt;, &lt;span style="color: #0000a0; font-family: courier new"&gt;VAR2&lt;/span&gt;, etc.&lt;/p&gt; &lt;p&gt;Now I know that is lame but it gets the job done. But what if I want to create these variables dynamically? I mean, if I want to read a file, and assign each line in the file to a separate variable, I need to know how many lines there are in the file, otherwise I'm screwed. Right? Well, not quite.&lt;/p&gt; &lt;p&gt;What I find is, some people quite often missed the fact that you can use variable expansion as a name of a new variable in batch. I guess that's because it's rather counter intuitive from other programming languages.&lt;/p&gt; &lt;p&gt;Anyway, the following example reads a file, assign each line to a new variable name and prints the file back, line by line, in reverse order.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;span style="color: #0000a0; font-family: courier new"&gt;@echo off&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #0000a0; font-family: courier new"&gt;setlocal enabledelayedexpansion&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #0000a0; font-family: courier new"&gt;set COUNT=0&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #0000a0; font-family: courier new"&gt;for /F "tokens=*" %%n in (foo.txt) do (&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #0000a0; font-family: courier new"&gt;&amp;nbsp; set /A COUNT=!COUNT! + 1&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #0000a0; font-family: courier new"&gt;&amp;nbsp; echo %%n&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #0000a0; font-family: courier new"&gt;&amp;nbsp; set LINE!COUNT!=%%n&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #0000a0; font-family: courier new"&gt;) &lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #0000a0; font-family: courier new"&gt;for /L %%c in (!COUNT!,-1,1) do (&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #0000a0; font-family: courier new"&gt;&amp;nbsp; echo !LINE%%c!&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #0000a0; font-family: courier new"&gt;) &lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;First of all, you need to enable delayed expansion for this to work (see my &lt;a href="http://batcheero.blogspot.com/2007/06/how-to-enabledelayedexpansion.html"&gt;earlier post&lt;/a&gt; about that). Then you want to treat everything on one line as one value, so you use the &lt;span style="color: #0000a0; font-family: courier new"&gt;"tokens=*"&lt;/span&gt; option for the firs &lt;span style="color: #0000a0; font-family: courier new"&gt;for&lt;/span&gt; loop.  &lt;p&gt;In that first loop you maintain a count, and create a new variable named &lt;span style="color: #0000a0; font-family: courier new"&gt;LINE!COUNT!&lt;/span&gt; in each iteration, and assign the whole line to that new variable. See how simple that was?&lt;/p&gt; &lt;p&gt;The second loop just iterates through the count backward using the &lt;span style="color: #0000a0; font-family: courier new"&gt;for /L&lt;/span&gt; option, and print the variables in that reverse order. Now take a look at how I'm printing the line. I use &lt;span style="color: #0000a0; font-family: courier new"&gt;!LINE%%c!&lt;/span&gt; which uses both the &lt;span style="color: #0000a0; font-family: courier new"&gt;!&lt;/span&gt; and the &lt;span style="color: #0000a0; font-family: courier new"&gt;%&lt;/span&gt; to allow the proper expansion of the variable name.&lt;/p&gt; &lt;p&gt;You can also replace the second loop with some other thing like string replacement.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;span style="color: #0000a0; font-family: courier new"&gt;echo. &amp;amp; echo Replace all 'h' with 'y' &amp;amp; echo. &lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #0000a0; font-family: courier new"&gt;for /L %%c in (1,1,!COUNT!) do (&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #0000a0; font-family: courier new"&gt;&amp;nbsp; set CURRLINE=!LINE%%c!&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #0000a0; font-family: courier new"&gt;&amp;nbsp; set CURRLINE=!CURRLINE:h=y!&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #0000a0; font-family: courier new"&gt;&amp;nbsp; echo !CURRLINE!&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #0000a0; font-family: courier new"&gt;)&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Voila! Quick and dirty poorman's implementation of UNIX &lt;span style="color: #0000a0; font-family: courier new"&gt;tr&lt;/span&gt; command. Of course you don't need to even save the lines to their own separate variables to do that. You can just do the replacement as you read the lines, and print the line out all in the same loop iteration. But hey, that's why they're called examples.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-546830132065188695?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/546830132065188695/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=546830132065188695' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/546830132065188695'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/546830132065188695'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2007/07/dynamic-variable-name.html' title='Dynamic Variable Name'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-5853599386497857151</id><published>2007-07-11T23:00:00.001-07:00</published><updated>2007-07-13T15:28:26.087-07:00</updated><title type='text'>Never Edit A Running Batch Script</title><content type='html'>&lt;p&gt;If&amp;nbsp;you have a long running batch script, you should be careful to never edit and then save the newly edited file while the script is running.&lt;/p&gt; &lt;p&gt;Consider the following simple example.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;@echo off&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;:START&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;echo hello&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;pause&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;goto START&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;echo oops&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;goto :EOF&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Now run it, and while it's waiting for your input to continue, open the file again, and remove the first line, &lt;font face="Courier New" color="#0000a0"&gt;@echo off&lt;/font&gt; and save the file.&amp;nbsp; Now once you give your input to let it continue, instead of executing the next line after &lt;font face="Courier New" color="#0000a0"&gt;pause&lt;/font&gt;, which is &lt;font face="Courier New" color="#0000a0"&gt;goto START&lt;/font&gt;, it executes the next line after that, so you will see this output.  &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;hello&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;Press any key to continue . . .&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;oops&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The reason it skips a line is because you just deleted a line.&amp;nbsp; The batch processor executes your script line by line, and it does not load your script in memory when it starts.&amp;nbsp; Instead, it remembers which line it needs to fetch next, and when it finishes executing the current line, it reads the file again and gets that next line.&amp;nbsp; Now obviously changing the content of the script file while you are executing it will give you undesirable execution order of your script.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-5853599386497857151?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/5853599386497857151/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=5853599386497857151' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/5853599386497857151'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/5853599386497857151'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2007/07/never-edit-running-batch-script.html' title='Never Edit A Running Batch Script'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-7255383902467232024</id><published>2007-07-08T11:47:00.001-07:00</published><updated>2007-07-08T11:47:37.236-07:00</updated><title type='text'>Environment Variable Editing</title><content type='html'>&lt;p&gt;Say you have and environment variable, and you want to tweak the value, change it a little bit, get the first few letters, or whatever.&amp;nbsp; You can do this using command processor's built-in variable substring and string substitution feature.&lt;/p&gt; &lt;p&gt;This is really useful feature that I like to use all the time.&amp;nbsp; Here's an example of how I can compose&amp;nbsp;my own&amp;nbsp;date string in the &lt;font face="Courier New" color="#0000a0"&gt;YYYY.MM.DD&lt;/font&gt; format out of the regular &lt;font face="Courier New" color="#0000a0"&gt;%DATE%&lt;/font&gt; environment variable that I covered &lt;a href="http://batcheero.blogspot.com/2007/06/printing-date-and-time.html"&gt;here&lt;/a&gt;.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;set MY_YYYY=%DATE:~-4%&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;set MY_MM=%DATE:~4,2%&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;set MY_DD=%DATE:~7,2%&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;set MY_DATE=%MY_YYYY%.%MY_MM%.%MY_DD%&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The first line takes the substring of &lt;font face="Courier New" color="#0000a0"&gt;%DATE%&lt;/font&gt; starting from the 4th character from the end, which gives me the year.&amp;nbsp; The second line takes the two characters starting from position 4.&amp;nbsp; Similarly on the third line, I got the two characters starting from position 7.&amp;nbsp; The last line simply concatenates them together into the format I wanted.&lt;/p&gt; &lt;p&gt;I can use substring to determine if today is Sunday for example.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;if /I "%DATE:~0,3%" EQU "Sun" (&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; echo Today is Sunday&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;)&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;So that shows you how to do substring.&amp;nbsp; Another cool usage of this is in doing string substitution.&amp;nbsp; Here's an example where I am replacing the year with my own string.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;set MY_DATE=%DATE:2007=9999%&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;This will replace the year &lt;font face="Courier New" color="#0000a0"&gt;2007&lt;/font&gt; with &lt;font face="Courier New" color="#0000a0"&gt;9999&lt;/font&gt;.&amp;nbsp; You can also simply leave the substitution string empty to remove a string from the variable value.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;set MY_DATE=%DATE:2007=%&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;That will remove all occurrences of &lt;font face="Courier New" color="#0000a0"&gt;2007&lt;/font&gt; from the value.&amp;nbsp; I usually find this really handy to remove certain directories from my &lt;font face="Courier New" color="#0000a0"&gt;PATH&lt;/font&gt;.&lt;/p&gt; &lt;p&gt;You can also use this for testing if a certain string exists in a variable.&amp;nbsp; Take a look at the following example where I want to see if today is Sunday like the earlier example, but using substring.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;if "%DATE:Sun=%" EQU "%DATE%" (&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; echo No, today is not Sunday&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;) else (&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; echo Today is Sunday&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;)&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;As you can see, what I did there is remove the string &lt;font face="Courier New" color="#0000a0"&gt;Sun&lt;/font&gt; from the date, and if it is successfully removed, it means today is Sunday, and the condition will become false.&amp;nbsp; If it does not find the string &lt;font face="Courier New" color="#0000a0"&gt;Sun&lt;/font&gt;, the condition will be true and we know today is not Sunday.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-7255383902467232024?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/7255383902467232024/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=7255383902467232024' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/7255383902467232024'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/7255383902467232024'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2007/07/environment-variable-editing.html' title='Environment Variable Editing'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-138673369442204691</id><published>2007-07-06T22:18:00.001-07:00</published><updated>2007-07-13T14:28:09.257-07:00</updated><title type='text'>Never Set Errorlevel</title><content type='html'>&lt;p&gt;What I mean is, don't ever have an environment variable named &lt;span style="font-family:Courier New;color:#0000a0;"&gt;errorlevel&lt;/span&gt;.  That's just a bad idea.  Windows command processor will take your definition every time.  This means if you set your &lt;span style="font-family:Courier New;color:#0000a0;"&gt;errorlevel&lt;/span&gt;, subsequent check for any command's &lt;span style="font-family:Courier New;color:#0000a0;"&gt;errorlevel&lt;/span&gt; will not work.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;set errorlevel=0&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;call some_command_that_returns_non_zero.cmd&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;if  "%errorlevel%" EQU "0" (&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;    echo SUCCESS&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;) else (&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;    echo FAIL&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;)&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;You will always get &lt;span style="font-family:Courier New;color:#0000a0;"&gt;errorlevel&lt;/span&gt; set to &lt;span style="font-family:Courier New;color:#0000a0;"&gt;0&lt;/span&gt; or whatever value you happen to have it set to.  So the check in the above snippet will always return success.&lt;/p&gt;&lt;p&gt;Well, OK, I admit.  When I said above that your subsequent &lt;span style="font-family:Courier New;color:#0000a0;"&gt;errorlevel&lt;/span&gt; check will not work, I lied.  The other way of checking &lt;span style="font-family:Courier New;color:#0000a0;"&gt;errorlevel&lt;/span&gt; will still work.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;set errorlevel=0&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;call some_command_that_returns_non_zero.cmd&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;if  errorlevel 1 (&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;    echo FAIL&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;) else (&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;    echo SUCCESS&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;)&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;That would still work.  But just save yourself some trouble and stay away from it.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-138673369442204691?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/138673369442204691/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=138673369442204691' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/138673369442204691'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/138673369442204691'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2007/07/never-set-errorlevel.html' title='Never Set Errorlevel'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-4709528375364409370</id><published>2007-07-06T20:43:00.001-07:00</published><updated>2007-07-13T14:26:17.609-07:00</updated><title type='text'>Perl In Batch Clothing</title><content type='html'>&lt;p&gt;As someone who writes a lot of scripts, Perl is my language of choice. But it does not mean I can live without Windows batch. Sometimes though, it is necessary to combine the two by disguising a Perl script as a batch file. &lt;p&gt;When might this come in handy? Well, to be honest I can't really think of any right now, but this is certainly cool. This trick is not a batch file trick per se. It's really a Perl trick, and you'll see soon enough why that is. But I'd like to put it here just the same because hey, it's got some batch scripting in it. &lt;p&gt;To write your Perl script as a batch file, all you have to do is add a few lines at the top of your Perl script, rename the script extension to &lt;span style="font-family:Courier New;color:#0000a0;"&gt;.bat&lt;/span&gt; or &lt;span style="font-family:Courier New;color:#0000a0;"&gt;.cmd&lt;/span&gt;, and you're done. &lt;blockquote&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;@echo off &lt;/span&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;perl -x %~dpf0 %* &lt;/span&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;exit /b %errorlevel% &lt;/span&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;#!perl &lt;/span&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;use strict; &lt;/span&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;print "Hey $ARGV[0] I'm in Perl!\n"; &lt;/span&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;exit 0; &lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;This file, being a batch file, is executed by the command processor as any batch file. It reads each line and executes that line. &lt;p&gt;The first line is straightforward. The second line is really the trick. Doing &lt;span style="font-family:Courier New;color:#0000a0;"&gt;perl -x&lt;/span&gt; tells Perl to read the file you pass as argument, &lt;span style="font-family:Courier New;color:#0000a0;"&gt;%~dpf0&lt;/span&gt;, which is the complete path of the batch script, and ignore anything in the file until it finds the &lt;span style="font-family:Courier New;color:#0000a0;"&gt;#!perl&lt;/span&gt; line. Then it treats it like any other Perl script. &lt;p&gt;The last argument on that line is simply passing all the command line arguments you pass to your batch script to the Perl as well. &lt;p&gt;So try and invoke the script. Let's say you named the script foo.bat. &lt;blockquote&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;foo.bat Batcheero&lt;/span&gt; &lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;You'll see the following printed output. &lt;blockquote&gt;&lt;p&gt;&lt;span style="font-family:Courier New;color:#0000a0;"&gt;Hey Batcheero I'm in Perl! &lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Like I said, not much real use I can think of, but it's nifty all the same.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-4709528375364409370?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/4709528375364409370/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=4709528375364409370' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/4709528375364409370'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/4709528375364409370'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2007/07/perl-in-batch-clothing.html' title='Perl In Batch Clothing'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-4365974120273074784</id><published>2007-07-02T00:03:00.001-07:00</published><updated>2007-07-02T00:03:30.559-07:00</updated><title type='text'>Function Call In Batch</title><content type='html'>&lt;p&gt;In any programming language, you can write functions or procedures to factor out a piece of code you use often.&amp;nbsp; In batch you can do the same.&amp;nbsp; Two ways you can do it.&amp;nbsp; You can create a separate batch file, and call it from inside the batch file you're scripting, or you can make it as an in-file function.&lt;/p&gt; &lt;p&gt;To call a separate batch file, it's really simple.&amp;nbsp; All you have to do is precede the batch name with the &lt;font face="Courier New" color="#0000a0"&gt;call&lt;/font&gt; operative, and you're good to go.&amp;nbsp; And example I like to use is to print a log entry both on console and into an output file.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;REM PrLog.bat&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;REM &amp;nbsp;This batch file prints&amp;nbsp;the message&amp;nbsp;to the console and to&amp;nbsp;an output file specified in the&amp;nbsp;environment&amp;nbsp;variable OUTP&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;echo %*&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;echo %* &amp;gt;&amp;gt; %OUTP%&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;REM End of file&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Now&amp;nbsp;every time we want to use this in a separate batch file all we have to do is call it after making sure you initialize the output file.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;REM Initialize OUTP just once&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;set OUTP=%TEMP%\output.txt&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;del /y %OUTP%&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;REM Subsequently you just call the PrLog.bat with the message as arguments&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;call PrLog.bat&amp;nbsp;Hello world&lt;/font&gt;&amp;nbsp;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Now this is nice and dandy, but you now have two files to watch for.&amp;nbsp; And if you need to copy your script, you need to make sure you don't forget to copy &lt;font face="Courier New" color="#0000a0"&gt;PrLog.bat&lt;/font&gt; too.&lt;/p&gt; &lt;p&gt;The more integrated way of doing this is to simply put the &lt;font face="Courier New" color="#0000a0"&gt;PrLog&lt;/font&gt; function in file.&amp;nbsp; To do this we need a label preceding the function, and end it with a &lt;font face="Courier New" color="#0000a0"&gt;goto :EOF&lt;/font&gt; or an &lt;font face="Courier New" color="#0000a0"&gt;exit /b&lt;/font&gt;.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;REM Initialize OUTP just once&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;set OUTP=%TEMP%\output.txt&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;del /y %OUTP%&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;REM Subsequently you just call the&amp;nbsp;:PRLOG function label&amp;nbsp;with the message as arguments&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;call&amp;nbsp;:PRLOG&amp;nbsp;Hello world&amp;nbsp;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;goto :EOF&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;REM End of main.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;&lt;/font&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;REM Start of function PrLog&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;:PRLOG&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;echo %*&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;echo %* &amp;gt;&amp;gt; %OUTP%&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;goto :EOF&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;REM End of function PrLog&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Note that the batch processor treats the &lt;font face="Courier New"&gt;:PRLOG&lt;/font&gt; as its own batch context, meaning when you &lt;font face="Courier New" color="#0000a0"&gt;goto :EOF&lt;/font&gt; at the end of that function, you don't go to the end of the current batch file, but you simple exit the function's batch context, which essentially means a function return.&amp;nbsp; You can also do an &lt;font face="Courier New" color="#0000a0"&gt;exit /b&lt;/font&gt; from the function if you need to return a meaningful return value to the caller signifying success or fail.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-4365974120273074784?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/4365974120273074784/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=4365974120273074784' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/4365974120273074784'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/4365974120273074784'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2007/07/function-call-in-batch.html' title='Function Call In Batch'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-8706428545084784011</id><published>2007-06-29T17:58:00.001-07:00</published><updated>2007-06-29T17:58:56.477-07:00</updated><title type='text'>Robocopy</title><content type='html'>&lt;p&gt;One other&amp;nbsp;utility&amp;nbsp;that Vista comes with which is way better than previous Windows is the &lt;font face="Courier New" color="#0000a0"&gt;robocopy&lt;/font&gt; utility.&amp;nbsp; It's got a lot of options and features, but one that I find very useful is the mirroring option.&lt;/p&gt; &lt;p&gt;With the mirroring option you can create exact copy of the source, meaning that if there are files in the source that are different from the destination, they will be copied, if there are extra files already in the destination that don't exist in the source, they will be deleted.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;robocopy /MIR source destination&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Try it out.&amp;nbsp; Play with it.&amp;nbsp; You'll like it.&lt;/p&gt; &lt;p&gt;One thing you want to watch out about &lt;font face="Courier New" color="#0000a0"&gt;robocopy&lt;/font&gt; however, is the error code it returns when it exits.&amp;nbsp; It's not the straightforward zero == success and non-zero == fail.&amp;nbsp; Oh, no.&amp;nbsp; That would be too easy.&amp;nbsp; So here is a list of the various error codes&amp;nbsp;that &lt;font face="Courier New" color="#0000a0"&gt;robocopy&lt;/font&gt; gives out.&lt;/p&gt; &lt;table cellspacing="0" cellpadding="2" width="359" border="0" unselectable="on"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" align="middle" width="113"&gt;&lt;font color="#0000a0"&gt;Error code&lt;/font&gt;&lt;/td&gt; &lt;td valign="top" align="middle" width="244"&gt;&lt;font color="#0000a0"&gt;Meaning&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="middle" width="113"&gt;0&lt;/td&gt; &lt;td valign="top" width="244"&gt;No change&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="middle" width="113"&gt;1&lt;/td&gt; &lt;td valign="top" width="244"&gt;Files were copies successfully&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="middle" width="113"&gt;2&lt;/td&gt; &lt;td valign="top" width="244"&gt;Extra files deleted from destination&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="middle" width="113"&gt;4&lt;/td&gt; &lt;td valign="top" width="244"&gt;Some mismatched files detected&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="middle" width="113"&gt;8&lt;/td&gt; &lt;td valign="top" width="244"&gt;Some files could not be copied&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="middle" width="113"&gt;16&lt;/td&gt; &lt;td valign="top" width="244"&gt;Fatal error&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;The error codes form a bit field, though.&amp;nbsp; So 3 really means 2+1, meaning there are extra files but copy was performed successfully.&amp;nbsp; That means actual failure is anything greater than or equal to error code 8.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;robocopy /MIR source destination&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;if %errorlevel% geq 8 echo FAIL!&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Once you know that, it's a sweet utility to have around.&amp;nbsp; If you're not on Vista, it is included in the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=9d467a69-57ff-4ae7-96ee-b18c4790cffd&amp;amp;DisplayLang=en"&gt;Win2k3 Resource Kit Tools&lt;/a&gt; which you can download.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-8706428545084784011?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/8706428545084784011/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=8706428545084784011' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/8706428545084784011'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/8706428545084784011'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2007/06/robocopy.html' title='Robocopy'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-5783006974450591794</id><published>2007-06-29T17:15:00.001-07:00</published><updated>2007-06-29T18:00:11.472-07:00</updated><title type='text'>Symbolic Links</title><content type='html'>&lt;p&gt;Symbolic links have existed for ages in UNIX, but Windows have not had any built in support for symbolic links until Vista.&amp;nbsp; Vista has a utility called &lt;font face="Courier New" color="#0000a0"&gt;mklink&lt;/font&gt;, which allows you to create symbolic links for files and directories.&amp;nbsp; Just be mindful that it requires admin privileges to run.&lt;/p&gt; &lt;p&gt;Symbolic links is useful for creating aliases for files or directories.&amp;nbsp; Say you do a daily build of something.&amp;nbsp; And you want to create an alias directory called &lt;font face="Courier New" color="#0000a0"&gt;current&lt;/font&gt; to point to the latest build you did.&amp;nbsp; For simplicity, let's assume your build&amp;nbsp;version is stored in some file called buildver.txt.&amp;nbsp; You increment that every time you do a build.&amp;nbsp; You create a directory named after the build version, and you create a &lt;font face="Courier New" color="#0000a0"&gt;current&lt;/font&gt; directory pointing to that.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;if not exist buildver.txt echo 0 &amp;gt; buildver.txt&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;set /P CURRBUILD=&amp;lt;buildver.txt&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;set /A CURRBUILD=%CURRBUILD% +&amp;nbsp;1&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;md %CURRBUILD%&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;pushd %CURRBUILD%&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;REM the following assumes you have build.bat in your path that will create your directory content&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;call build.bat&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;popd&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;mklink /D current %CURRBUILD%&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;This way a script that wants to access the current build can just always hit current without trying to figure out what the latest build version is.&lt;/p&gt; &lt;p&gt;If you want to delete it, you can safely use the usual &lt;font face="Courier New" color="#0000a0"&gt;rd&lt;/font&gt; command to remove directory.&amp;nbsp; This will only delete the link, not the actual directory it points to.&amp;nbsp; The same goes for file symbolic links.&amp;nbsp; To remove it you use the &lt;font face="Courier New" color="#0000a0"&gt;del&lt;/font&gt; command and it will delete the link, not the file.&lt;/p&gt; &lt;p&gt;You can find out if a file is a link or not when you do a &lt;font face="Courier New" color="#0000a0"&gt;dir&lt;/font&gt; in a directory by the &amp;lt;&lt;font face="Courier New" color="#0000a0"&gt;SYMLINK&amp;gt;&lt;/font&gt; or &amp;lt;&lt;font face="Courier New" color="#0000a0"&gt;SYMLINKD&amp;gt;&lt;/font&gt; type it shows you.&lt;/p&gt; &lt;p&gt;For XP and Win2003, you can use a &lt;a href="http://www.microsoft.com/technet/sysinternals/default.mspx"&gt;Sysinternals&lt;/a&gt; utility&amp;nbsp;called &lt;a href="http://www.microsoft.com/technet/sysinternals/FileAndDisk/Junction.mspx"&gt;Junction&lt;/a&gt; to create NTFS&amp;nbsp;reparse point&amp;nbsp;that will do similar job as a symbolic link.&amp;nbsp; However unlike symbolic links which will work on files too, junctions only work for directories.&lt;/p&gt; &lt;p&gt;Another tool that can create junctions is the &lt;font face="Courier New" color="#0000a0"&gt;linkd&lt;/font&gt; utility from &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=9d467a69-57ff-4ae7-96ee-b18c4790cffd&amp;amp;DisplayLang=en"&gt;Win2k3 Resource Kit Tool&lt;/a&gt; which you can download.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-5783006974450591794?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/5783006974450591794/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=5783006974450591794' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/5783006974450591794'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/5783006974450591794'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2007/06/symbolic-links.html' title='Symbolic Links'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-1450925143507068295</id><published>2007-06-28T05:47:00.001-07:00</published><updated>2007-06-28T05:47:56.698-07:00</updated><title type='text'>Setting Variable Value From File</title><content type='html'>&lt;p&gt;Let's say you have file containing some string, and you want to get that string and assign it to an environment variable.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;echo&amp;nbsp;Hello&amp;nbsp;World &amp;gt; foo.txt&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;There are two ways you can assign the content of that file to an environment variable.&amp;nbsp; One is to use redirection.&amp;nbsp; To do this, you need to make the &lt;font face="Courier New" color="#0000a0"&gt;set&lt;/font&gt; command interactive by using the &lt;font face="Courier New" color="#0000a0"&gt;/P&lt;/font&gt; switch.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;set /P BAR=&amp;lt;foo.txt&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;echo %BAR%&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;If you have more than one lines in the file, this will set the variable value to the &lt;em&gt;first&lt;/em&gt; line in the file.&lt;/p&gt; &lt;p&gt;The other method is using the for loop, telling it to read from the file.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;for /F "tokens=*" %x in (foo.txt) do (&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;&amp;nbsp; set BAR=%x&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;)&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The &lt;font face="Courier New" color="#0000a0"&gt;"tokens=*"&lt;/font&gt; option tells it to consume the whole line, so that if you have any white spaces in&amp;nbsp;the line, it will not&amp;nbsp;pick up the first word only. &amp;nbsp;If you use this approach and there are more than one lines in your file, your&amp;nbsp;variable&amp;nbsp;will end up with&amp;nbsp;the &lt;em&gt;last&lt;/em&gt; line as its value.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-1450925143507068295?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/1450925143507068295/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=1450925143507068295' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/1450925143507068295'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/1450925143507068295'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2007/06/setting-variable-value-from-file.html' title='Setting Variable Value From File'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-9126180886260580210</id><published>2007-06-27T12:57:00.001-07:00</published><updated>2007-06-27T12:57:43.939-07:00</updated><title type='text'>Printing Date and Time</title><content type='html'>&lt;p&gt;What's this, you say?&amp;nbsp; We're getting down to such dumb topics after only a few posts?&amp;nbsp; Well, it might be dumb, but it's kind of useful.&amp;nbsp; Say you want to print the date and the time.&amp;nbsp; You would use the &lt;font face="Courier New" color="#0000a0"&gt;date&lt;/font&gt; and &lt;font face="Courier New" color="#0000a0"&gt;time&lt;/font&gt; command, obviously.&amp;nbsp; And they have the &lt;font face="Courier New" color="#0000a0"&gt;/t&lt;/font&gt; switch to allow no interaction which is nice for batch files.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;date /t&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;time /t&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Excellent.&amp;nbsp; Marvelous.&amp;nbsp; Jolly good.&amp;nbsp; But what if you want to put both of them on the same line?&amp;nbsp; Like if you want to create a log trace where you put date and time at the beginning of each line?&amp;nbsp; Well, the date and time commands won't really work well because they will put the date and time on different lines.&amp;nbsp; Luckily there is an alternative.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;echo %DATE% %TIME% - Log message goes here.&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;This will print out the date, time and log message on one line.&amp;nbsp; Ideal for logging traces.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-9126180886260580210?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/9126180886260580210/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=9126180886260580210' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/9126180886260580210'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/9126180886260580210'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2007/06/printing-date-and-time.html' title='Printing Date and Time'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-2228046605811835255</id><published>2007-06-27T10:49:00.001-07:00</published><updated>2007-06-27T10:53:30.736-07:00</updated><title type='text'>Random Number Generation</title><content type='html'>&lt;p&gt;If you ever need to get a random number while writing a Windows batch script, you can use Windows command's handy little %RANDOM% environment variable.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;echo %RANDOM%&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;And if you want to generate a random number within a range of values, all you have to do is perform some simple command line math.&amp;nbsp; Say you want to generate a random number between 50 and 150.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;set MIN=50&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;set RANGE=100&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" color="#0000a0"&gt;set /A RN=%RANDOM% % %RANGE% + %MIN%&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;That should do it.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-2228046605811835255?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/2228046605811835255/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=2228046605811835255' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/2228046605811835255'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/2228046605811835255'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2007/06/random-number-generation.html' title='Random Number Generation'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-5558529211329850018</id><published>2007-06-26T11:47:00.000-07:00</published><updated>2007-06-26T13:32:58.608-07:00</updated><title type='text'>How To ENABLEDELAYEDEXPANSION</title><content type='html'>&lt;p&gt;ENABLEDELAYEDEXPANSION is a useful property that allow you to do what you think should happen when you write a &lt;span style="color: #000099; font-family: courier new"&gt;for&lt;/span&gt; loop or an &lt;span style="color: #000099; font-family: courier new"&gt;if&lt;/span&gt; block. Consider this example.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;set COUNT=0&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;&lt;/span&gt;&lt;span style="color: #000099; font-family: courier new"&gt;for %%var in (1 2 3 4) do (&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;&lt;/span&gt;&lt;span style="color: #000099; font-family: courier new"&gt;&amp;nbsp; set /A COUNT=%COUNT% + 1&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;&lt;/span&gt;&lt;span style="color: #000099; font-family: courier new"&gt;&amp;nbsp; echo %COUNT%&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;&lt;/span&gt;&lt;span style="color: #000099; font-family: courier new"&gt;)&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;&lt;/span&gt;Now in any other scripting or programming language, this would be just fine. Not so in windows batch. Since batch processor treats the whole &lt;span style="color: #000099; font-family: courier new"&gt;for&lt;/span&gt; loop as one command, it expands the variables once and only once, before it executes the loop. So you end up with &lt;span style="color: #000099; font-family: courier new"&gt;%COUNT%&lt;/span&gt; being expanded to its value, which is &lt;span style="color: #000099; font-family: courier new"&gt;0&lt;/span&gt;, before you start the loop, and you end up printing &lt;span style="color: #000099; font-family: courier new"&gt;0&lt;/span&gt; four times in a row.&lt;/p&gt; &lt;p&gt;That's where delayed expansion comes in. As the name suggests, delayed expansion makes batch processor delay expanding the variable to its value until it actually loops through it.&lt;/p&gt; &lt;p&gt;But to make that happen, you need to do two things.&lt;br&gt;&lt;br&gt;1. Enable delayed expansion. You can do this by doing &lt;span style="color: #000099; font-family: courier new"&gt;setlocal ENABLEDELAYEDEXPANSION&lt;/span&gt; at the beginning of your script.&lt;/p&gt; &lt;p&gt;2. Use &lt;span style="color: #000099; font-family: courier new"&gt;!&lt;/span&gt; instead of &lt;span style="color: #000099"&gt;%&lt;/span&gt; to expand environment variable value.&lt;/p&gt; &lt;p&gt;Now here's that example again using delayed expansion:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;setlocal ENABLEDELAYEDEXPANSION&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;set COUNT=0&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;for %%var in (1 2 3 4) do (&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;&amp;nbsp; set /A COUNT=!COUNT! + 1&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;&amp;nbsp; echo !COUNT!&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;)&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;&lt;/span&gt;This time you will see 1 2 3 4 being printed, as you expect.&lt;/p&gt; &lt;p&gt;Another way of turning on delayed expansion is through the registry. You can go and add it manually through regedt32.exe, or you can load a registry file like the one shown here:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;Windows Registry Editor Version 5.00[HKEY_CURRENT_USER\Software\Microsoft\Command Processor]&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;&lt;/span&gt;&lt;span style="color: #000099; font-family: courier new"&gt;"DelayedExpansion"=dword:00000001&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;&lt;/span&gt;Just save it to a file called enabledelayedexpansion.reg or something, and just invoke that file from the command line.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;enabledelayedexpansion.reg&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;&lt;/span&gt;This will enable delayed expansion for current user. You can do the same for &lt;span style="color: #000099; font-family: courier new"&gt;HKEY_LOCAL_MACHINE&lt;/span&gt;.&lt;br&gt;You need to start a new console window to see its effect. To check, simply do&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;echo !COMPUTERNAME!&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;&lt;/span&gt;in the new command console. If it prints your computername, then it recognizes the &lt;span style="color: #000099; font-family: courier new"&gt;!&lt;/span&gt; variable expansion, which means delayed expansion is enabled.&lt;br&gt;This way you don't have to do &lt;span style="color: #000099; font-family: courier new"&gt;setlocal ENABLEDELAYEDEXPANSION&lt;/span&gt;. But watch out, you need to make sure this thing is enabled if you are planning on skipping &lt;span style="color: #000099; font-family: courier new"&gt;setlocal ENABLEDELAYEDEXPANSION&lt;/span&gt; in your script.&lt;/p&gt; &lt;p&gt;I'll get into how to check for this from your script some other time.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-5558529211329850018?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/5558529211329850018/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=5558529211329850018' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/5558529211329850018'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/5558529211329850018'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2007/06/how-to-enabledelayedexpansion.html' title='How To ENABLEDELAYEDEXPANSION'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-2858085442188253924</id><published>2007-06-26T08:50:00.000-07:00</published><updated>2007-06-26T13:35:54.773-07:00</updated><title type='text'>The Little Pipe That Could</title><content type='html'>&lt;p&gt;So pipes can be bad at times (see my last post), but pipes can be really good for a lot of things too. I won't go and say a lot about the goodness of pipes.&lt;br&gt;Here I just want to give an example of how pipe can be used to get you through some of those old fashioned commands that just refuse to be invoked without user interaction.&lt;/p&gt; &lt;p&gt;In windows, comp.exe is one of those things. It's similar to diff, which is not a standard Windows utility. You invoke comp.exe by giving it two file names to compare. But after it compares the files, it will ask you if you want to compare any more files. It ALWAYS asks you that. There is no way to turn it off by passing some command line switch.&lt;/p&gt; &lt;p&gt;So what do you do? Well, one thing you can do feed it a file containing the letter "N" through it's input redirection.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;echo N &amp;gt; answer.txt&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;&lt;/span&gt;&lt;span style="color: #000099; font-family: courier new"&gt;comp file1.txt file2.txt &lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;&lt;/span&gt;This works well.&amp;nbsp; But what if you don't want to create a temporary file just for answering that? You can use pipe of course. And since you need comp.exe to consume the answer, you just need it at the end of the pipe.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;/span&gt;&lt;span style="color: #000099; font-family: courier new"&gt;echo N ¦ comp file1.txt file2.txt&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;span style="color: #000099; font-family: courier new"&gt;&lt;/span&gt;Nice and simple. And like I mentioned in previous post, this will get you the exit code of comp.exe itself if you decide to check for errorlevel afterwards.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-2858085442188253924?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/2858085442188253924/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=2858085442188253924' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/2858085442188253924'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/2858085442188253924'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2007/06/little-pipe-that-could.html' title='The Little Pipe That Could'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6454686814995217416.post-8004286027953623317</id><published>2007-06-25T08:28:00.000-07:00</published><updated>2007-06-26T13:34:55.855-07:00</updated><title type='text'>Hidden Danger of Pipes</title><content type='html'>&lt;p&gt;OK, this is my first post, so I figure I need to explain a bit what I intend this blog is about. Batch. That's what I intend to write. Specifically, tips, tricks and pitfalls of windows batch file.&lt;/p&gt; &lt;p&gt;Now that we have that out of the way, let's take a look at the first of such batch quirk.&lt;/p&gt; &lt;p&gt;When you are using pipes to do some chained processing, just remember that the exit code of the last command in the pipe is the one that prevails.&lt;br&gt;I've seen this bitten a lot of people:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;span style="color: #000099"&gt;&lt;span style="font-family: courier new"&gt;test.bat ¦ tee.exe outputfile.log&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #000099"&gt;&lt;span style="font-family: courier new"&gt;&lt;/span&gt;&lt;span style="font-family: courier new"&gt;exit /b %errorlevel%&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;span style="color: #000099"&gt;&lt;span style="font-family: courier new"&gt;&lt;/span&gt;&lt;/span&gt;The intention here is to exit with whatever the exit code of test.bat is, when in fact you're capturing exit code of tee.exe, which will most likely be zero.&lt;br&gt;You'll then end up masking the test.bat exit code. If this is in some pre-checkin test script, that usually ends up with bad codes sneaking in.&lt;br&gt;So save yourself some time, and output to a file instead, and post process the output.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;span style="color: #000099"&gt;&lt;span style="font-family: courier new"&gt;test.bat &amp;gt; outputfile.log&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #000099"&gt;&lt;span style="font-family: courier new"&gt;&lt;/span&gt;&lt;span style="font-family: courier new"&gt;set EXITCODE =%errorlevel%&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="color: #000099"&gt;&lt;span style="font-family: courier new"&gt;&lt;/span&gt;&lt;span style="font-family: courier new"&gt;type outputfile.log&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;span style="color: #000099"&gt;&lt;span style="font-family: courier new"&gt;&lt;/span&gt;&lt;/span&gt;This captures your intent just the same (well, almost the same).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6454686814995217416-8004286027953623317?l=batcheero.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://batcheero.blogspot.com/feeds/8004286027953623317/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6454686814995217416&amp;postID=8004286027953623317' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/8004286027953623317'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6454686814995217416/posts/default/8004286027953623317'/><link rel='alternate' type='text/html' href='http://batcheero.blogspot.com/2007/06/hidden-danger-of-pipes.html' title='Hidden Danger of Pipes'/><author><name>Arif Sukoco</name><uri>http://www.blogger.com/profile/02253016747219807790</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry></feed>
