<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Scripting</title>
	<atom:link href="http://scripting.sovereignmagic.com/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://scripting.sovereignmagic.com</link>
	<description></description>
	<lastBuildDate>Mon, 28 Apr 2008 21:56:29 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Providing Command-Line Help</title>
		<link>http://scripting.sovereignmagic.com/?p=23</link>
		<comments>http://scripting.sovereignmagic.com/?p=23#comments</comments>
		<pubDate>Mon, 28 Apr 2008 21:53:49 +0000</pubDate>
		<dc:creator>Jeremy</dc:creator>
				<category><![CDATA[Batch]]></category>
		<category><![CDATA[Windows 2000]]></category>
		<category><![CDATA[Windows NT 4.0]]></category>
		<category><![CDATA[Windows Vista]]></category>
		<category><![CDATA[Windows XP]]></category>

		<guid isPermaLink="false">http://scripting.sovereignmagic.com/?p=23</guid>
		<description><![CDATA[Most well-written scripts and programs offer the user some assistance with providing command-line variables/options.  Do this in your scripts and you&#8217;ll have thankful users, especially if your script gets used by people other than close friends and co-workers.  I&#8217;ve used many methods over the years of checking for, and branching off and providing [...]]]></description>
			<content:encoded><![CDATA[<p>Most well-written scripts and programs offer the user some assistance with providing command-line variables/options.  Do this in your scripts and you&#8217;ll have thankful users, especially if your script gets used by people other than close friends and co-workers.  I&#8217;ve used many methods over the years of checking for, and branching off and providing help.  My favorite though is just a one-liner that checks for a &#8216;?&#8217; anywhere on the command line.<br />
<span id="more-23"></span></p>
<blockquote><p>
echo.%* | find &#8220;?&#8221;>nul2>nul &#038;&#038; goto :CLHelp
</p></blockquote>
<p>There are a few things going on here, and reasons for all of them.  First is the &#8216;echo&#8217; command, which just spits out some text to StdOut (StdOut is the logical path to get to the screen).  The period &#8216;.&#8217; immediately following tells echo to send whatever follows, verbatim, and not try to interpret it.  This helps in the case that someone just types, &#8216;yourscript /?&#8217;.  If the period was not there, echo would interpret the &#8216;/?&#8217; as a command to itself and would spit out the help for the echo command; not what we&#8217;re looking for here.The percent, asterisk combination &#8216;%*&#8217; returns all of the text on the command line following the name of the script.</p>
<p>So at this point, you have &#8216;echo.%*&#8217;, which just echos the text from the command line back to the screen.  The next character, the pipe &#8216;|&#8217; takes the text that is on its way to the screen, and redirects it to another program.  Here, we&#8217;re redirecting it to the &#8216;find&#8217; command, which is searching the text for a question mark.  When find finishes running, it reports to the computer, a status code for whether it was successful or not in its task.  This is called an errorlevel.  An errorlevel of 0 is success.  Anything else is almost always a failure code, but these are set by the program creator and could mean anything.  As for &#8216;find&#8217;, if it sets an errorlevel of 0, it found the text it was looking for.  If it sets an errorlevel of 1, it did not find it.</p>
<p>In this case, we only want to know if a ? was on the line or not.  We don&#8217;t want to actually see the ? on the screen, so the &#8216;>nul2>nul&#8217; takes all the text destined for the screen and flushes it down the toilet.  Finally, we have the &#8216;&#038;&#038;&#8217;, which reads the most recent errorlevel, and if it is 0, continues with the command following it.  If the errorlevel is 1, it skips the command after it.  So, if find finds a ? on the command line and sets errorlevel 0, then the &#038;&#038; executes the &#8216;goto :CLHelp&#8217; command, which is appropriate.  If the user put a ? on the command line, they want help.  Of course, you still need to write the help that the user will get.  Here is a very short, simple example.</p>
<blockquote><p>
@echo off<br />
echo.%* | find &#8220;?&#8221;>nul2>nul &#038;&#038; goto :CLHelp<br />
echo You don&#8217;t need any help, eh?  KNOW-IT-ALL!!!<br />
goto :EOF<br />
:CLHelp<br />
echo So you can&#8217;t figure this out on your own?  DUMMY!!!
</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://scripting.sovereignmagic.com/?feed=rss2&amp;p=23</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Number Format Conversion &#8211; Decimal to Hexidecimal</title>
		<link>http://scripting.sovereignmagic.com/?p=22</link>
		<comments>http://scripting.sovereignmagic.com/?p=22#comments</comments>
		<pubDate>Wed, 02 Apr 2008 04:02:53 +0000</pubDate>
		<dc:creator>Jeremy</dc:creator>
				<category><![CDATA[Batch]]></category>
		<category><![CDATA[Windows 2000]]></category>
		<category><![CDATA[Windows NT 4.0]]></category>
		<category><![CDATA[Windows Vista]]></category>
		<category><![CDATA[Windows XP]]></category>
		<category><![CDATA[vbs]]></category>

		<guid isPermaLink="false">http://scripting.sovereignmagic.com/?p=22</guid>
		<description><![CDATA[As much as I like batch, it cannot do the simple task of converting a number from decimal to any other format. In my job, I need to convert to hex fairly often. Rather than opening up calc and using it&#8217;s clunky format, I found a bit of vbs code from another site and edited [...]]]></description>
			<content:encoded><![CDATA[<p>As much as I like batch, it cannot do the simple task of converting a number from decimal to any other format. In my job, I need to convert to hex fairly often. Rather than opening up calc and using it&#8217;s clunky format, I found a bit of vbs code from another site and edited it to look good. And since my employer disables running vbs code unless you execute the interpreter, I packaged it up nice and neat in this script.<br />
<span id="more-22"></span><br />
Create a batch script named Dec2Hex.cmd</p>
<blockquote><p>
@cscript //Nologo Dec2Hex.vbs
</p></blockquote>
<p>Create a vbs script named Dec2Hex.vbs</p>
<blockquote><p>
Wscript.StdOut.Write &quot;Enter a decimal number to convert (0 to exit): &quot;<br />
strDecimal = Wscript.StdIn.ReadLine</p>
<p>While strDecimal &lt;&gt; 0<br />
Wscript.StdOut.WriteLine &quot;&quot;<br />
Wscript.StdOut.WriteLine &quot;Decimal: &quot; &amp; strDecimal<br />
Wscript.StdOut.WriteLine &quot;Hex: &quot; &amp; Hex(strDecimal)<br />
Wscript.StdOut.WriteLine &quot;&quot;<br />
Wscript.StdOut.Write &quot;Enter a decimal number to convert (0 to exit): &quot;<br />
strDecimal = Wscript.StdIn.ReadLine<br />
Wend</p></blockquote>
<p>And it looks like this when you&#8217;re done:</p>
<blockquote><p>C:\temp&gt;Dec2Hex.cmd<br />
Enter a decimal number to convert (0 to exit): 255</p>
<p>Decimal: 255<br />
Hex: FF</p>
<p>Enter a decimal number to convert (0 to exit): 16</p>
<p>Decimal: 16<br />
Hex: 10</p>
<p>Enter a decimal number to convert (0 to exit): 65536</p>
<p>Decimal: 65536<br />
Hex: 10000</p>
<p>Enter a decimal number to convert (0 to exit): 0</p>
<p>C:\temp&gt;</p></blockquote>
<p>Enjoy</p>
]]></content:encoded>
			<wfw:commentRss>http://scripting.sovereignmagic.com/?feed=rss2&amp;p=22</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Open a file with its associated program</title>
		<link>http://scripting.sovereignmagic.com/?p=21</link>
		<comments>http://scripting.sovereignmagic.com/?p=21#comments</comments>
		<pubDate>Wed, 02 Apr 2008 03:39:59 +0000</pubDate>
		<dc:creator>Jeremy</dc:creator>
				<category><![CDATA[Site]]></category>

		<guid isPermaLink="false">http://scripting.sovereignmagic.com/?p=21</guid>
		<description><![CDATA[Have you ever noticed that when you double-click an Excel file, and if Excel was already open, the file you clicked opens in the already running instance?  How do you replicate that on the command line?  Running &#8220;Excel.exe MyFile.xls&#8221; opens another instance.  Running &#8220;Start MyFile.xls&#8221; opens another instance of Excel as well. [...]]]></description>
			<content:encoded><![CDATA[<p>Have you ever noticed that when you double-click an Excel file, and if Excel was already open, the file you clicked opens in the already running instance?  How do you replicate that on the command line?  Running &#8220;Excel.exe MyFile.xls&#8221; opens another instance.  Running &#8220;Start MyFile.xls&#8221; opens another instance of Excel as well.  Luckily, Windows exposes the functionality that Explorer uses to start programs, if you only know how to get to it.<br />
<span id="more-21"></span><br />
Start Excel, then open a command prompt to a folder with an xls file you wish to open and run the following command.  Make sure you copy the line exactly.  Capitalization matters here.  Obviously, replace MyExcelFile.xls with the file name you want to open.</p>
<blockquote><p>
rundll32 shell32.dll,ShellExec_RunDLL &#8220;MyExcelFile.xls&#8221;
</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://scripting.sovereignmagic.com/?feed=rss2&amp;p=21</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Loops Part VII &#8211; For /F &#8211; To Create Dynamic Menus</title>
		<link>http://scripting.sovereignmagic.com/?p=20</link>
		<comments>http://scripting.sovereignmagic.com/?p=20#comments</comments>
		<pubDate>Wed, 02 Apr 2008 03:22:27 +0000</pubDate>
		<dc:creator>Jeremy</dc:creator>
				<category><![CDATA[Batch]]></category>
		<category><![CDATA[Windows 2000]]></category>
		<category><![CDATA[Windows NT 4.0]]></category>
		<category><![CDATA[Windows Vista]]></category>
		<category><![CDATA[Windows XP]]></category>

		<guid isPermaLink="false">http://scripting.sovereignmagic.com/?p=20</guid>
		<description><![CDATA[Creating menus in batch usually means lots of echo statements to print out the menu, cluttering up what may have been a clean, easy to read script.  Using &#8216;For /F&#8217;, you can create a dynamic menu with just a few lines.  All you need is a separate file to store the menu options [...]]]></description>
			<content:encoded><![CDATA[<p>Creating menus in batch usually means lots of echo statements to print out the menu, cluttering up what may have been a clean, easy to read script.  Using &#8216;For /F&#8217;, you can create a dynamic menu with just a few lines.  All you need is a separate file to store the menu options in.  This is very handy for menus that you have to change occasionally.  It&#8217;s easier to change them in that text file than finding the menu in the script and inserting it, which may require you to renumber the rest of the menu.<br />
<span id="more-20"></span><br />
To start with, here is a snippet of a script that will print out a menu, and then do something with the user&#8217;s choice.</p>
<blockquote><p>
echo 1.  East Coast<br />
echo 2.  MidWest<br />
echo 3.  South<br />
echo 4.  West Coast<br />
set /p LOCATION=Enter the Location you wish to search:<br />
if &#8220;%LOCATION%&#8221; == &#8220;1&#8243; set SEARCHPATH=c:\locations\east<br />
if &#8220;%LOCATION%&#8221; == &#8220;2&#8243; set SEARCHPATH=c:\locations\midwest<br />
if &#8220;%LOCATION%&#8221; == &#8220;3&#8243; set SEARCHPATH=c:\locations\south<br />
if &#8220;%LOCATION%&#8221; == &#8220;4&#8243; set SEARCHPATH=c:\locations\west
</p></blockquote>
<p>Since this is a simple example, it doesn&#8217;t look too complicated.  Grow your menu to 20 or 30 choices, and this can quickly become a nightmare to keep up to date.  Say you have to add in a new location, &#8220;Central&#8221;.  You might want to insert it between the items currently numbered 3 and 4.  You will have to insert that line as menu item 4, change the old 4 to 5, then add a new line between the if statements for 3 and 4, and change the if statement for the old 4 there as well.  You can see how this could grow to be unmanagable just adding 5 or 10 more menu options (20 to 40 changes to add a new menu item at position 4, when you already have 14 choices).</p>
<p>Try this on for size.  Create this text file first.</p>
<blockquote><p>
East Coast=c:\locations\east<br />
MidWest=c:\locations\midwest<br />
South=c:\locations\south<br />
West Coast=c:\locations\west
</p></blockquote>
<p>Then use this in your script to print the menu and set the LOCATION variable</p>
<blockquote><p>
set MENU=0<br />
for /f &#8220;delims== tokens=1,*&#8221; %%A in (locations.menu) do (<br />
set /a MENU+=1<br />
set MENUITEM.!MENU!.1=%%A<br />
set MENUITEM.!MENU!.2=%%B<br />
echo [!MENU!] &#8212; %%A<br />
)<br />
set /p LOCCHOICE=Enter the Location you wish to search:<br />
for /f %%A in (&#8221;%LOCCHOICE%&#8221;) do set LOCATION=!MENUITEM.%%A.1! &#038; set SEARCHPATH=!MENUITEM.%%A.2!
</p></blockquote>
<p>Now, before you run away, yes, this looks, and admittedly is, more complicated in this small example we&#8217;re dealing with here.  The benefits of using this method for your menu show up when you need to make a change.  To add that new central location, you have to make one, that&#8217;s right, ONE change.  Edit the text file that has the menu options in it, and you&#8217;re done.  Nothing needs changed in the script itself.  Even if you have 100 menu choices and you add one more.  Just add it, wherever you like in the menu text file, then pack up your stuff and go home.  You&#8217;re done for the day.</p>
<p>Some more explanation of what is being done is in order though.</p>
<p>Lines 1 &#8211; 7 do the work to print out the menu.  Look closer, and you will see that they do something else as well.  The &#8217;set&#8217; commands are placing each menu item, and the data after the equal sign into a group of variables.  In fact, they&#8217;re emulating the array structure of more advanced languages.  The menu items are being inserted into a 2-dimensional array.  Consider the following representation of the array after these 7 lines have been executed.</p>
<table cols=3 rows=5 border=1>
<tr>
<td></td>
<td><center><b>1</b></center></td>
<td><center><b>2</b></center></td>
</tr>
<tr>
<td><b>MenuItem.1</b></td>
<td>East Coast</td>
<td>c:\locations\east</td>
</tr>
<tr>
<td><b>MenuItem.2</b></td>
<td>MidWest</td>
<td>c:\locations\midwest</td>
</tr>
<tr>
<td><b>MenuItem.3</b></td>
<td>South</td>
<td>c:\locations\south</td>
</tr>
<tr>
<td><b>MenuItem.4</b></td>
<td>West Coast</td>
<td>c:\locations\west</td>
</tr>
</table>
<p>
Lines 8 and 9 take the number that the user enters, then uses that to look up the appropriate row in the array and assign both values to standard variables.</p>
<p>Adding a few lines makes this a complete script, though it doesn&#8217;t really do anything useful yet:</p>
<blockquote><p>
@echo off<br />
setlocal ENABLEDELAYEDEXPANSION</p>
<p>set MENU=0<br />
for /f &#8220;delims== tokens=1,*&#8221; %%A in (locations.menu) do (<br />
set /a MENU+=1<br />
set MENUITEM.!MENU!.1=%%A<br />
set MENUITEM.!MENU!.2=%%B<br />
echo [!MENU!] &#8212; %%A<br />
)<br />
set /p LOCCHOICE=Enter the Location you wish to search:<br />
for /f %%A in (&#8221;%LOCCHOICE%&#8221;) do set LOCATION=!MENUITEM.%%A.1! &#038; set SEARCHPATH=!MENUITEM.%%A.2!</p>
<p>echo.<br />
echo You entered choice %LOCCHOICE% which is menu item %LOCATION% which searches path %SEARCHPATH%
</p></blockquote>
<p>And here&#8217;s what it looks like when it runs:</p>
<blockquote><p>
C:\temp>locations.cmd<br />
[1] &#8212; East Coast<br />
[2] &#8212; MidWest<br />
[3] &#8212; South<br />
[4] &#8212; West Coast<br />
Enter the Location you wish to search: 2</p>
<p>You entered choice 2 which is menu item MidWest  which searches path c:\locations\midwest
</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://scripting.sovereignmagic.com/?feed=rss2&amp;p=20</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Loops Part VI &#8211; For /F</title>
		<link>http://scripting.sovereignmagic.com/?p=19</link>
		<comments>http://scripting.sovereignmagic.com/?p=19#comments</comments>
		<pubDate>Mon, 08 Oct 2007 22:28:00 +0000</pubDate>
		<dc:creator>Jeremy</dc:creator>
				<category><![CDATA[Batch]]></category>
		<category><![CDATA[Windows 2000]]></category>
		<category><![CDATA[Windows NT 4.0]]></category>
		<category><![CDATA[Windows Vista]]></category>
		<category><![CDATA[Windows XP]]></category>

		<guid isPermaLink="false">http://scripting.sovereignmagic.com/?p=19</guid>
		<description><![CDATA[&#8216;For /F&#8217; is my favorite DOS command of all time.  Its uses are endless.  At it&#8217;s core, the /F switch doesn&#8217;t sound like much.  It reads a file, one line at a time, and assigns the first &#8220;token&#8221; to a variable.  The thing that makes it powerful is modifying how it [...]]]></description>
			<content:encoded><![CDATA[<p>&#8216;For /F&#8217; is my favorite DOS command of all time.  Its uses are endless.  At it&#8217;s core, the /F switch doesn&#8217;t sound like much.  It reads a file, one line at a time, and assigns the first &#8220;token&#8221; to a variable.  The thing that makes it powerful is modifying how it defines a line, token, and how many tokens it should grab.<br />
<span id="more-19"></span><br />
Let&#8217;s start small.  You have a text file that looks something like this.  It&#8217;s your grocery list along with prices, aisles, and a reminder of why you need each item.</p>
<blockquote><p>
Eggs 2.99 7 Big breakfast this weekend<br />
Milk 2.65 9 Only a half gallon left<br />
Bread 1.59 2 Kids out of school next week<br />
Coffee 4.99 4 The only way I&#8217;ll be able to get up<br />
Bacon 4.39 6 Again, the big breakfast
</p></blockquote>
<p>Now, that file has all the information you need to go shopping but you don&#8217;t really care *why* you&#8217;re getting each thing when you&#8217;re walking down each aisle.  I&#8217;ll show you a command to pull just a list of the items you need first.</p>
<blockquote><p>
C:\>for /f %A in (GroceryList.txt) do @echo %A<br />
Eggs<br />
Milk<br />
Bread<br />
Coffee<br />
Bacon
</p></blockquote>
<p>%A is the variable you will store each item in.  GroceryList.txt is the text file with all that extra information.  The &#8216;@&#8217; sign in front of &#8216;echo&#8217; just prevents DOS from showing you the command it&#8217;s running.  Try it without the &#8216;@&#8217;, you&#8217;ll see what I mean.</p>
<p>This is all well and good but you want to know what aisle each item is on as well.  Tell &#8216;For&#8217; that you want the 1st and 3rd item on each line then.</p>
<blockquote><p>
C:\>for /f &#8220;tokens=1,3&#8243; %A in (GroceryList.txt) do @echo %A &#8211; Aisle %B<br />
Eggs &#8211; Aisle 7<br />
Milk &#8211; Aisle 9<br />
Bread &#8211; Aisle 2<br />
Coffee &#8211; Aisle 4<br />
Bacon &#8211; Aisle 6
</p></blockquote>
<p>Here, we inserted &#8220;tokens=1,3&#8243; to grab the 1st and 3rd item on the line.  Note that you don&#8217;t have to specify which variable each token gets assigned to.  It does that automatically just by incrementing the variable you do choose.  If you used the variable %M, then the aisle would be stored in the next letter after M, which would be %N.</p>
<p>The next problem you might run into is what happens when you add a new item to your grocery list, say, &#8220;Fruit Juice&#8221;.  Your output would look like this.</p>
<blockquote><p>
C:\>for /f &#8220;tokens=1,3&#8243; %A in (GroceryList.txt) do @echo %A &#8211; Aisle %B<br />
Eggs &#8211; Aisle 7<br />
Milk &#8211; Aisle 9<br />
Bread &#8211; Aisle 2<br />
Coffee &#8211; Aisle 4<br />
Bacon &#8211; Aisle 6<br />
Fruit &#8211; Aisle 2.39
</p></blockquote>
<p>We don&#8217;t see the word &#8220;Juice&#8221;, and our Aisle is now the price for that item.  Well, that&#8217;s because by default, &#8216;For /F&#8217; uses the space character as the delimiter between tokens.  Let&#8217;s just reformat our list a little bit and add another customization to the for command to fix that.</p>
<p>Here&#8217;s our new text file.</p>
<blockquote><p>
Eggs~2.99~7~Big breakfast this weekend<br />
Milk~2.65~9~Only a half gallon left<br />
Bread~1.59~2~Kids out of school next week<br />
Coffee~4.99~4~The only way I&#8217;ll be able to get up<br />
Bacon~4.39~6~Again, the big breakfast<br />
Fruit Juice~2.39~4~Need some Vitamin C
</p></blockquote>
<p>And our new command.</p>
<blockquote><p>
C:\>for /f &#8220;delims=~ tokens=1,3&#8243; %A in (GroceryList.txt) do @echo %A &#8211; Aisle %B<br />
Eggs &#8211; Aisle 7<br />
Milk &#8211; Aisle 9<br />
Bread &#8211; Aisle 2<br />
Coffee &#8211; Aisle 4<br />
Bacon &#8211; Aisle 6<br />
Fruit Juice &#8211; Aisle 4
</p></blockquote>
<p>Here, we specified that the tilde character &#8220;~&#8221; would separate tokens instead of the default space.</p>
<p>Jumping into a different example, let&#8217;s talk about .ini files.  Some programs use them to hold configuration settings.  The app reads the .ini file when it opens and sets certain defaults.  Doing this with &#8216;For /F&#8217; is easy.  If you have a large complex script that a user might want to change some default values for, create an .ini file and have him change them there, instead of getting in and possibly mucking up your script that you spent so much time and energy getting to run just right.  Of course, even in the .ini file, the user may not know what each item is or what to change it to.  That&#8217;s where the EOL customization comes in.  It tells For that if you see this one specific character, to ignore anything else on that line.  Here&#8217;s an example.  I&#8217;ll use the semi-colon &#8220;;&#8221; as the EOL character.</p>
<blockquote><p>
;Set COLOR to 1 if you want a blue screen, 2, if<br />
;you want a yellow screen, or 3 if you want a<br />
;red screen<br />
COLOR=1<br />
;Set SPEED to &#8220;Slow&#8221; or &#8220;Fast&#8221;<br />
SPEED=Fast<br />
;Set OUTPUT to &#8220;CSV&#8221; or &#8220;TSV&#8221; depending on how you<br />
;would like the results to be formatted<br />
OUTPUT=CSV
</p></blockquote>
<p>In your script, just insert a line similar to this.</p>
<blockquote><p>
C:\>for /f &#8220;delims== tokens=1,* eol=;&#8221; %A in (Config.ini) do set %A=%B</p>
<p>C:\>set COLOR=1</p>
<p>C:\>set SPEED=Fast</p>
<p>C:\>set OUTPUT=CSV
</p></blockquote>
<p>The &#8220;eol=;&#8221; part says to ignore anything after the semicolon, so essentially, those are blank lines as far as &#8216;For&#8217; is concerned.  Another thing you may have noticed is the &#8220;tokens=1,*&#8221;.  Specifying an asterisk instead of a token number tells For to take everything else on that line, ignoring the delimiters, and put it all into one variable.  So we want token 1 put into variable %A and everything else on the line put into variable %B.  I do this in case there is another = sign later in the line that should be included as part of the variable instead of acting like another delimiter.</p>
<p>Remember, when using the &#8216;For&#8217; command in your scripts, you have to double-up the percent signs.  Use %%A instead of %A, etc.</p>
<p>The next post will delve further into For /F, exploring more powerful ways to use it.  Stay Tuned</p>
]]></content:encoded>
			<wfw:commentRss>http://scripting.sovereignmagic.com/?feed=rss2&amp;p=19</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unique &#8211; Remove Duplicates from text list</title>
		<link>http://scripting.sovereignmagic.com/?p=18</link>
		<comments>http://scripting.sovereignmagic.com/?p=18#comments</comments>
		<pubDate>Fri, 20 Jul 2007 11:21:57 +0000</pubDate>
		<dc:creator>Jeremy</dc:creator>
				<category><![CDATA[Batch]]></category>
		<category><![CDATA[Windows 2000]]></category>
		<category><![CDATA[Windows NT 4.0]]></category>
		<category><![CDATA[Windows Vista]]></category>
		<category><![CDATA[Windows XP]]></category>

		<guid isPermaLink="false">http://scripting.sovereignmagic.com/?p=18</guid>
		<description><![CDATA[Search the internet and you&#8217;ll find a lot of talk about how to take a large list of values and remove the duplicates.  Unfortunately, I haven&#8217;t found any good solutions using batch.  I took some time to think about this the other day because I needed the functionality in a larger script.  I came up [...]]]></description>
			<content:encoded><![CDATA[<p>Search the internet and you&#8217;ll find a lot of talk about how to take a large list of values and remove the duplicates.  Unfortunately, I haven&#8217;t found any good solutions using batch.  I took some time to think about this the other day because I needed the functionality in a larger script.  I came up with two ways to do this.</p>
<p><span id="more-18"></span></p>
<p>1) The first solution I came up with works, but is very slow. To process a 1000 line file, it took about one and a half minutes to run on my laptop at work.<br />
Read the text file one line at a time, use find to search the output file for the same value.  If not found, insert the current line into that output file.  If it is found, skip.</p>
<blockquote><p>@echo off<br />
set INFILE=%1<br />
set /p INFILE=Enter the filename of the file to remove duplicates from [%INFILE%]:<br />
set OUTFILE=Unique.txt<br />
copy /y nul %OUTFILE%&gt;nul2&gt;nul<br />
for /f %%A in (%INFILE%) do @type %OUTFILE% | @find /i &#8220;%%A&#8221;&gt;nul || @echo %%A&gt;&gt;%OUTFILE%<br />
type %OUTFILE%</p></blockquote>
<p>2) The second solution is more complicated, but runs . . . get this, 40,500 times faster. It completed the same list in two tenths of a second.<br />
This method works by setting an environment variable named for each line in the file, to itself. When a duplicate entry is found, the environment variable is already set so it doesn&#8217;t enter it into the output file again.</p>
<blockquote><p>@echo off</p>
<p>set INFILE=%1<br />
set /p INFILE=Name of the file to remove duplicates from [%INFILE%]:</p>
<p>set OUTFILE=%infile%.out.txt<br />
if exist &#8220;%OUTFILE%&#8221; del %OUTFILE%</p>
<p>setlocal<br />
setlocal ENABLEDELAYEDEXPANSION</p>
<p>for /f &#8220;delims=&#8221; %%A in (%INFILE%) do (<br />
if not &#8220;!%%A!&#8221; == &#8220;%%A&#8221; echo.%%A&gt;&gt;%OUTFILE%<br />
rem if not &#8220;!%%A!&#8221; == &#8220;%%A&#8221; echo.%%A<br />
if not &#8220;!%%A!&#8221; == &#8220;%%A&#8221; set %%A=%%A<br />
)</p>
<p>type %OUTFILE%</p>
<p>endlocal</p></blockquote>
<p>Good Luck!</p>
]]></content:encoded>
			<wfw:commentRss>http://scripting.sovereignmagic.com/?feed=rss2&amp;p=18</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Random Numbers</title>
		<link>http://scripting.sovereignmagic.com/?p=17</link>
		<comments>http://scripting.sovereignmagic.com/?p=17#comments</comments>
		<pubDate>Wed, 27 Jun 2007 04:54:08 +0000</pubDate>
		<dc:creator>Jeremy</dc:creator>
				<category><![CDATA[Batch]]></category>
		<category><![CDATA[Windows 2000]]></category>
		<category><![CDATA[Windows NT 4.0]]></category>
		<category><![CDATA[Windows Vista]]></category>
		<category><![CDATA[Windows XP]]></category>

		<guid isPermaLink="false">http://scripting.sovereignmagic.com/?p=17</guid>
		<description><![CDATA[Random numbers can be generated in several ways.  Depending on what you&#8217;re using them for, each way has its benefits.  This post will talk about the %RANDOM% variable and using the system clock to generate psuedo-random numbers on the command line.

Using the %RANDOM% variable is good if you&#8217;re making a game or need a number [...]]]></description>
			<content:encoded><![CDATA[<p>Random numbers can be generated in several ways.  Depending on what you&#8217;re using them for, each way has its benefits.  This post will talk about the %RANDOM% variable and using the system clock to generate psuedo-random numbers on the command line.<br />
<span id="more-17"></span><br />
Using the %RANDOM% variable is good if you&#8217;re making a game or need a number just to randomize an event. Although it works fine most of the time to create temp files using a random number in the name, there is the possibility that the random number will be identical to one that has been used before and you&#8217;ll have issues trying to use the filename of a file that already exists. For temp files or reports that need a unique number to set them apart from each other, it&#8217;s a better idea to use a number generated from the date and time. Although not truly random, each number generated will be unique and will avoid any duplicate naming issues.</p>
<p>First, the %RANDOM% variable will always return a random number in the range from 0 to 32767. This is good if you just need to randomize an event. Use the number however you like and be done with it. If however you need a random number that lies in a certain range, say a 6-sided die for instance, there are 32761 numbers that are unusable. The trick is to do a little math with it. Remember back to your elementary school days when you learned about long division and remainders? Let&#8217;s take 69 (our random number) divided by 6 (sides on a die). The answer you would get would be 11, remainder 3. If you forget about the 11, the remainder 3 certainly sounds promising. It turns out, any division you do by 6 will actually have a remainder from 0 to 5. Just add one and you have a mathematical formula to generate a random number from 1 to 6. RemainderOf(RandomNumber / 6) + 1 = RandomNumber(1 &#8211; 6). Getting the remainder of a division problem is easier than it sounds. Just use the &#8216;Mod&#8217; operator, &#8220;%&#8221;, with the Set /A command.</p>
<blockquote><p>C:\&gt;SET /A RESULT=%RANDOM% % 6 + 1<br />
5<br />
C:\&gt;SET /A RESULT=%RANDOM% % 6 + 1<br />
2<br />
C:\&gt;SET /A RESULT=%RANDOM% % 6 + 1<br />
3</p></blockquote>
<p>Now you have a method to generate random numbers in any range you wish. If you need a number from 76 &#8211; 100, Random Mod 25 plus 76 (set /a result=%random% % 25 + 76)</p>
<p>The second method, using timestamps, is just as easy. Basically, we want to create a string of numbers starting with the largest measurement of time ending at the smallest. That would be year, month, day, hour, minute, second, millisecond. The way to do that is to use variable modifiers explained in the &#8220;For&#8221; command help. Type &#8220;for /?&#8221; at the command prompt and look for the section starting with &#8220;%~I&#8221;. To create the string, do the following:</p>
<blockquote><p>set RAND=%DATE:~10,4%%DATE:~4,2%%DATE:~7,2%%TIME:~0,2%%TIME:~3,2%%TIME:~6,2%%TIME:~9,2%</p></blockquote>
<p>The only gotcha here is that the hours from 00:00:00.00 &#8211; 09:59:59.99 will have a space at the beginning of the hour instead of a 0. To work around that, just use a small IF-THEN-ELSE statement:</p>
<blockquote><p>if &#8220;%TIME:~0,1%&#8221; == &#8221; &#8221; (<br />
set RAND=%DATE:~10,4%%DATE:~4,2%%DATE:~7,2%0%TIME:~1,1%%TIME:~3,2%%TIME:~6,2%%TIME:~9,2%<br />
) ELSE (<br />
set RAND=%DATE:~10,4%%DATE:~4,2%%DATE:~7,2%%TIME:~0,2%%TIME:~3,2%%TIME:~6,2%%TIME:~9,2%<br />
)</p>
<p>set RAND<br />
RAND=2007062700074091</p></blockquote>
<p>The plus to using this method is that any files that are named using it will have an easy way of telling exactly when the script was run that generated it. This random number was generated in 2007, in June, on the 27th, at 12:07:40.91 AM.</p>
]]></content:encoded>
			<wfw:commentRss>http://scripting.sovereignmagic.com/?feed=rss2&amp;p=17</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Loops Part V &#8211; For /L</title>
		<link>http://scripting.sovereignmagic.com/?p=16</link>
		<comments>http://scripting.sovereignmagic.com/?p=16#comments</comments>
		<pubDate>Wed, 27 Jun 2007 03:52:01 +0000</pubDate>
		<dc:creator>Jeremy</dc:creator>
				<category><![CDATA[Batch]]></category>
		<category><![CDATA[Windows 2000]]></category>
		<category><![CDATA[Windows NT 4.0]]></category>
		<category><![CDATA[Windows Vista]]></category>
		<category><![CDATA[Windows XP]]></category>

		<guid isPermaLink="false">http://scripting.sovereignmagic.com/?p=16</guid>
		<description><![CDATA[For /L is used for counting. Need to execute a command X number of times, or have a variable number of cases that each need to be dealt with separately? For /L is your pony.

The simplest example of a For /L statement is just to count and echo the number.
C:\&#62;for /l %A in (1,1,5) do [...]]]></description>
			<content:encoded><![CDATA[<p>For /L is used for counting. Need to execute a command X number of times, or have a variable number of cases that each need to be dealt with separately? For /L is your pony.<br />
<span id="more-16"></span><br />
The simplest example of a For /L statement is just to count and echo the number.</p>
<blockquote><p>C:\&gt;for /l %A in (1,1,5) do @echo %A<br />
1<br />
2<br />
3<br />
4<br />
5</p></blockquote>
<p>Looking at the previous example, this statement looks similar to the others, yet has one key difference. The text inside the parentheses is completely different.</p>
<p>The values that go there are, (&lt;Start&gt;,&lt;Increment&gt;,&lt;End&gt;).<br />
&lt;Start&gt; is the number to start with. If this number is not an integer, it will be rounded down.<br />
&lt;Increment&gt; is the quantity to increment the start number by after each loop. This will again be rounded down.<br />
&lt;End&gt; is the number that when it is passed by the Starting number that has been incremented, then loop exits. Again, rounded down if not an int.</p>
<p>The previous example showed the basics of this command, but what can it really do? I&#8217;ve used it to generate an At-A-Glance status of available IP addresses on my DHCP server. It could be used to create temporary user accounts for a new classroom of students. Anything where a process needs to be repeated a specific number of times.</p>
<p>The DHCP status example noted above has some lines that queried the server and generated a list of scopes along with the number of free IP addresses for each one. To avoid that complexity in this example, let&#8217;s just say that those lines created several environment variables called SCOPE_10.1.1.0 through SCOPE_10.1.10.0 with each one holding the number of free IP addresses.</p>
<blockquote><p>C:\&gt;set scope_<br />
SCOPE_10.1.1.0=16<br />
SCOPE_10.1.10.0=8<br />
SCOPE_10.1.2.0=148<br />
SCOPE_10.1.3.0=91<br />
SCOPE_10.1.4.0=215<br />
SCOPE_10.1.5.0=24<br />
SCOPE_10.1.6.0=74<br />
SCOPE_10.1.7.0=10<br />
SCOPE_10.1.8.0=206<br />
SCOPE_10.1.9.0=212</p></blockquote>
<p>I&#8217;m going to use the For /F command in this example which will be explained in more detail in a later post. For now, just know that the text inside the For /F loop will get executed for each of the 10 variables.</p>
<p>IMPORTANT: Also note that instead of % signs around some of the variables, I used ! marks. One trick in using the for statement is dealing with the evaluation time of variables. Using % signs, the variables are evaluated and replaced when the initial for statement is read and before any processing takes place. Using ! marks, each variable is evaluated and replaced each time it is used, thus allowing us to set, and then use that value all inside the same for statement. It&#8217;s important to note that this functionality is not enabled by default. You must start the cmd executable with the &#8220;/v&#8221; switch to enable this. I&#8217;ll post later a snippet that I put in the beginning of my batch files that need this functionality that makes sure it is enabled.</p>
<p>One other thing you may notice is that I used a value of 4 to increment. I used 4 to make sure that the line of text that gets generated will not be longer than 80 characters, the default for a command prompt window.</p>
<blockquote><p>@echo off<br />
for /f &#8220;delims== tokens=1,2&#8243; %%A in (&#8217;set scope_&#8217;) do (<br />
set SCOPE=%%A<br />
set LINE=<br />
for /L %%C in (1,4,%%B) do set LINE=!LINE!*<br />
echo !SCOPE:~6! &#8211; !LINE!<br />
)</p></blockquote>
<p>The output will look something like this. An At-A-Glance look at how many free IP addresses you have on each subnet.</p>
<blockquote><p>C:\&gt;scope<br />
10.1.1.0 &#8211; ****<br />
10.1.10.0 &#8211; **<br />
10.1.2.0 &#8211; *************************************<br />
10.1.3.0 &#8211; ***********************<br />
10.1.4.0 &#8211; ******************************************************<br />
10.1.5.0 &#8211; ******<br />
10.1.6.0 &#8211; *******************<br />
10.1.7.0 &#8211; ***<br />
10.1.8.0 &#8211; ****************************************************<br />
10.1.9.0 &#8211; *****************************************************</p></blockquote>
<p>What else can you do with this? Let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://scripting.sovereignmagic.com/?feed=rss2&amp;p=16</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Loops Part IV &#8211; For /R</title>
		<link>http://scripting.sovereignmagic.com/?p=15</link>
		<comments>http://scripting.sovereignmagic.com/?p=15#comments</comments>
		<pubDate>Sat, 02 Jun 2007 05:35:38 +0000</pubDate>
		<dc:creator>Jeremy</dc:creator>
				<category><![CDATA[Batch]]></category>
		<category><![CDATA[Windows 2000]]></category>
		<category><![CDATA[Windows NT 4.0]]></category>
		<category><![CDATA[Windows Vista]]></category>
		<category><![CDATA[Windows XP]]></category>

		<guid isPermaLink="false">http://scripting.sovereignmagic.com/?p=15</guid>
		<description><![CDATA[This post is fairly short because to tell you the truth, I&#8217;ve never used for /r. The functionality offered by this switch can be duplicated with /f if done correctly. That said, why don&#8217;t you jump in and explore it with me. As I write this post, I&#8217;m thinking about all the things I could [...]]]></description>
			<content:encoded><![CDATA[<p>This post is fairly short because to tell you the truth, I&#8217;ve never used for /r. The functionality offered by this switch can be duplicated with /f if done correctly. That said, why don&#8217;t you jump in and explore it with me. As I write this post, I&#8217;m thinking about all the things I could have used this for rather than the more complex commands that I ended up using.<br />
<span id="more-15"></span><br />
for /r . . . The command line help says this:</p>
<blockquote><p>FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters]</p>
<p>Walks the directory tree rooted at [drive:]path, executing the FOR statement in each directory of the tree. If no directory specification is specified after /R then the current directory is assumed. If set is just a single period (.) character then it will just enumerate the directory tree.</p></blockquote>
<p>In English, it runs your For command, without the /R in every directory under the specified directory.</p>
<p>Going along with the example for /D, let&#8217;s say you want more detail in your folder sizes. You want to know how large every folder is as far down as they go:</p>
<blockquote><p>C:\Batch&gt;for /r c:\batch /d %A in (*.*) do @echo %~fA &amp; @dir /a &#8220;%A&#8221; | @find &#8220;File(s)&#8221; &amp; echo.<br />
c:\Batch\Example1<br />
              13 File(s)         4,048,290 bytes</p>
<p>c:\Batch\Example2<br />
               0 File(s)                 0 bytes</p>
<p>c:\Batch\Example3<br />
               4 File(s)           417,093 bytes</p>
<p>c:\Batch\Example1\Disk1<br />
               5 File(s)         1,293,556 bytes</p>
<p>c:\Batch\Example1\Disk2<br />
               4 File(s)         1,630,021 bytes</p>
<p>c:\Batch\Example1\Disk3<br />
               4 File(s)         1,124,713 bytes</p>
<p>c:\Batch\Example2\Disk1<br />
               0 File(s)                 0 bytes</p>
<p>c:\Batch\Example2\Disk2<br />
               0 File(s)                 0 bytes</p>
<p>c:\Batch\Example2\Disk3<br />
               0 File(s)                 0 bytes</p>
<p>c:\Batch\Example3\Disk1<br />
               4 File(s)           417,093 bytes</p>
<p>c:\Batch\Example3\Disk2<br />
               0 File(s)                 0 bytes</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://scripting.sovereignmagic.com/?feed=rss2&amp;p=15</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Samsung Camcorder software on Windows Vista</title>
		<link>http://scripting.sovereignmagic.com/?p=14</link>
		<comments>http://scripting.sovereignmagic.com/?p=14#comments</comments>
		<pubDate>Tue, 08 May 2007 03:08:14 +0000</pubDate>
		<dc:creator>Jeremy</dc:creator>
				<category><![CDATA[Off-Topic]]></category>
		<category><![CDATA[Windows Vista]]></category>

		<guid isPermaLink="false">http://scripting.sovereignmagic.com/?p=14</guid>
		<description><![CDATA[Have an older Samsung Camcorder that you want to use its Motion Capture software on your new Windows Vista PC?  You guessed it, the driver installation doesn&#8217;t work.  To get my SCL770 to work, I did the following:


Insert the CD that came with the camcorder
Cancel the setup program that wants to open
Plug in the camcorder [...]]]></description>
			<content:encoded><![CDATA[<p>Have an older Samsung Camcorder that you want to use its Motion Capture software on your new Windows Vista PC?  You guessed it, the driver installation doesn&#8217;t work.  To get my SCL770 to work, I did the following:</p>
<p><span id="more-14"></span></p>
<ol>
<li>Insert the CD that came with the camcorder</li>
<li>Cancel the setup program that wants to open</li>
<li>Plug in the camcorder to AC power and plug the USB cable into the camcorder and computer</li>
<li>Vista will open its hardware driver wizard.</li>
<li>Let it try to find the drivers on its own.  It will fail and ask you to help it out.</li>
<li>Tell it to search your CDROM drive (click the Search Subfolders check box)</li>
<li>It should find drivers and tell you it can&#8217;t verify the publisher (Which means this probably won&#8217;t work on Vista 64-bit)</li>
<li>Go ahead and install the driver anyway</li>
<li>Navigate to your CDROM drive\USB Media 2.0 directory and run setup.exe</li>
<li>Finish this setup program and you should be set.  Open the app and it should find the camcorder and start working immediately.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://scripting.sovereignmagic.com/?feed=rss2&amp;p=14</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
