Tag Archives: Windows

Installing OpenCV

So tinkering with OpenCV the past day has been fun.  This past summer, a co-worker and I made an application to crop images and resize them automatically to speed up booking at the jail we work at.

The first problem was face detection.  To create a method, we first invert the image.  Then run a line from left to right until the background color changes.  Do the same thing from right to left and then find the center.  Do that several times through the picture would lead us to a good center location for the face.

The second problem was that we did all this with Windows API/GDI.  These methods were very low level and difficult to run simple methods on.

For some reason, we never found OpenCV until reading a slashdot article last night.  This library is awesome for face detection and other visual work.  I use a Linux box at home and the work computers use Windows, so I like that code can be compiled with only changes to the compiler going between each computer.

Installation

The install in linux was very easy.  Ubuntu has great documentation for installing anything with apt.  Since I’m using Mint 12 (gotta get away from Gnome 3!), I was able to follow this guide.

For Windows, it was a bit more tricky.  I read guides walking me through CMake and such.  Fortunately, I found that OpenCV 2.0’s installer does not need to be compiled, just extracted.  Using this guide I was able to get it work.  To simplify things, I’ve put two zips on my server for anyone to use.

  1. OpenCV_INSTALL.zip has the installer for OpenCV 2.0, CMake guide for those using Visual C++, and a sample codeblocks project.
  2. OpenCV_DONE.zip includes the extracted source and a sample codeblocks project.

Let me know if you have any issues.  Remember, for the codeblocks project to compile, you’ll have to sent compiler search directory to [src]/include/opencv and the linker search directory to [src]/lib

Enjoy!

wxWidgets and ODBC…

Since wxWidgets > 2.8 has dropped wxODBC, I decided to learn how to use sql.h on my own.  I made a simple program to retrieve and print data in C for the command line and everything worked well.  Unfortunately, when I placed this code in my wxWidgets GUI program, it failed.  This was due to wx being unicode, so I had a whole world of learning on how to make sql.h talk with wx.  I’ve outlined the steps to make this work:

With ODBC, sql.h can work with unicode, the functions are the same, but different variables are sent.  WX defines as Unicode (as it’s usually compiled) and ODBC will map the function to the unicode variant.  For example, in a C++ program with #define UNICODE 1, such as WX, SQLDriverConnect will map to SQLDriverConnectW, the unicode variant.  The other option is SQLDriverConnectA which will allow ANSI variables.  Most of the functions you’ll need have an ‘A Variant’, which is what I’ll refer to the functions ending in A.

To Send Data:

  1. Cast your variable as a SQLWCHAR pointer.
  2. Set a string to that pointer, type cast the string too.
  3. Use the functions of ODBC that end with an A.
  4. Send that function a variable type cast as (SQLCHAR*).
SQLWCHAR *connStr;
connStr = (SQLWCHAR*)"DSN=testDB;";
SQLDriverConnectA(dbc, NULL, (SQLCHAR*)connStr, SQL_NTS,
    (SQLCHAR*)outstr, sizeof(outstr), &outstrlen,
     SQL_DRIVER_COMPLETE);

To Return Data:

  1. Do the same steps.
SQLWCHAR colName[256];
SQLDescribeColA(hstmt, i+1, (SQLCHAR*)colName, 255, &colNameLen,
      &dataType, &colSize, &numDecimalDigits, &allowsNullValues);

Convert SQLWCHAR to wxString:

  1. Use wxString’s PrintF() function and interpret the variable with a capital S.
SQLWCHAR colName[256];
wxString test;
test.PrintF(_("Column Name: %S"),colName);

Convert wxString to SQLWCHAR:

  1. Declare your buffer variable as SQLCHAR array.
  2. Cycle through each char in wxString and assign to your SQLCHAR array.
  3. Add a null value on the end (so SQL_NTS knows to stop!)
  4. Typecast the variable as a pointer in send.
wxString send = wxT("SELECT * FROM master");
SQLCHAR sqlTest[1024];
unsigned int j;
for(j=0;j<send.Len();j++) {
sqlTest[j] = send[j];
}
sqlTest[send.Len()] = _T('\0');

SQLPrepareA(hstmt, (SQLCHAR*)sqlTest, SQL_NTS);

VBA – User Defined Type

As much as I do not like VBA, I do like the “User Defined Types” which, from a C/C++ programmer’s prospective, this is a lot like using structs.  And for data management, which is probably 90% of what VBA is used for, it makes a lot of since.  How do we define a User Defined Type?

Private Type dict
    a As Integer
    b As String
    c As String
    d As Integer
End Type

Once Defined, we need an initialization function to store the struct.

Private Function defineDict() As dict
    defineDict.a = 1
    defineDict.b = "two"
    defineDict.c = "three"
    defineDict.d = 4
End Function

At this point, we can use the same calling to to that ‘struct’ to change the variables as needed.

Sub testType()
    Dim t As dict       ' Set the variable
    t = defineDict      ' Initialize
    Debug.Print t.b     ' Prints >> "two"
    t.b = "no more"     ' Change a variable
    Debug.Print t.b     ' Prints >> "no more"
End Sub

Minesweeper Guide

So the classic game of Minesweeper is a great waste of my time.  I’ve found though, the secret to being successful is understanding the 2’s.  I’ll demonstrate with a series of screenshots.  I’ll remind my readers that the Minesweeper I use is Linux based, and Windows’ Minesweeper is somewhat different.  For example, the version I’m using will always have the upper left corner free and there is always a solution through logic.  Unfortunately, in Windows, there are times when no logic will fix it.

Now, I’ve created a program to solve the puzzles, but it’s no where near as fun.  For the cheat program (for Windows XP version) check out my tutorial.  It’s a good read on using C in Windows to pull information about a program, or hooking, as it is better known.

The key for all the graphics is:

  • RED = MINE
  • YELLOW = MAYBE
  • GREEN = CLEAR

The first three graphics will show a common pattern with a 5 and some a row including 2’s.  When 2’s are in a row, you can start eliminating.

EDIT: I plan to continue updating this, but for now I’ll post as is.

NCOER Spreadsheet – Done

Okay, so I’ve updated my code and I’m ready to release to the world my NCOER speardsheet.  Here’s a quick tutorial on how to use it.

  1. Download the Excel 2007 or Excel 2003 version. (Right Click and Save As)
  2. Ensure that you have enabled macros [ Office 2007 ] or [ Office 2003 ] for your MS Excel.
  3. Open the file you downloaded.
  4. Enter the unit you need the report for in the textbox on the left.
  5. Click Update
  6. It will prompt you for your AKO Username/Password to access the data.
  7. Wait a short time and it will automatically load and filter.
  8. Print or export the data as needed.

And that’s it.  I know military types read this blog (proven through the Open XFDL project) so please comment and let me know your opinion!

Microsoft Access : XFDL Viewer – Introduction

I know, I said it yesterday that it is rare that I develop on Windows, but this is a long promised application.  In 2007, my unit administrator (in the U.S. Army Reserves) suggested code that would allow batch loading XFDL forms from MS Access.  Due to the scope of the Apps 4 The Army project, I was limited to using a web application.  Now that the project is submitted and done, I am free to do my original plan, which is code to do the same process in MS Access.

Starting this today, I realized how much I hate doing Visual Basic.  Particularly, VBA is very painful!!  It’s not that the language is bad but it just always feels bulky and pieced together to me.  It seems to lack the professionalism of C/C++ and the flow of Python.  But, I may be alone in that.

I have a question for my readers though. Would anyone have an interest in seeing this project on SourceForge?  The Apps 4 the Army project is no longer my intellectual right, but a desktop application, a MS Office Plugin, etc… that’s all good to make public.  So let me know, if I get readers saying we’d like to help; then I will happily move this project to SourceForge!

Fern Screensaver : Part 3

Today, I had no Mac with me to work on my screensaver in Objective-C.  As you can see in my previous post, I used my python program and wrote it in C for SDL that works on either Windows or Linux.  Now, the basic principle is the same, I just need to output that location to the correct pixel plot method to use other systems.  I thought, since I was on Windows all day, I might as well use that to make the screensaver using Windows API.

I’ve had some use of Window’s API before to make a Breakout game for my children.  It is rustic at times but works.  I decided to not mess with OpenGL today and just use Win32 API and GDI methods.  Below you will find my complete source code and a link to download this screensaver.  Once downloaded, save it in C:\WINDOWS\System32\ and it will appear on your personalization menu.

A quick note before the code, for those unfamiliar with Windows API… there’s a lot of goobly gook here that looks scary.  It’s really not that bad but here’s the meat of the project:

  • Lines 8-34 are the same variables we’ve seen before.
  • Lines 36-40 are a ‘dot()’ method I made to clean the code (slightly).
  • After Line 42:
    • WM_CREATE is called on the start of the program.
    • WM_DESTROY is called on the completion of the program.
    • WM_PAINT is used to paint to the screen.
      • Here you see the same math as before until lines 78-82.
      • At Lines 78-82, I’m using Win32 API to create a color brush and paint it with the dot method.
    • WM_TIMER is called every millisecond in this program, it keeps the loop going.
      • InvalidateRect() will force a WM_PAINT message.
  • Everything that follows is not really applicable as it just meets the demands of the Screensaver library.

If you would like to try out this screen saver, download from this link and save the file to your C:/WINDOWS/system32/ folder.  Let me know how it works for you!

#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>
#include <scrnsave.h>

#define TIMER 1

// VARIABLES
float mat[4][7] = {
    {0.0,0.0,0.0,0.16,0.0,0.0,0.01},
    {0.85,0.04,-0.04,0.85,0.0,1.6,0.85},
    {0.2,-0.25,0.23,0.22,0.0,1.6,0.07},
    {-0.15,0.28,0.26,0.24,0.0,0.44,0.07}
};
// constant sets
float xa = -5.5;
float xb = 6.5;
float ya = -0.5;
float yb = 10.5;
// x and y to be altered
float x = 0.0;
float y = 0.0;
// screen/image size
int imgx = 128;
int imgy = 128;
// floats for math fulction
float p = 0.0;
float x0 = 0;
float jx = 0;
float jy = 0;
// variables to control function
int i = 0;
int k = 1;
int end = imgx*imgy;
int done = 0;

void dot(HDC hdc, HBRUSH whtBr, int x, int y) {
        SelectObject(hdc, whtBr);
            Rectangle(hdc, x-2, y-2, x+1, y+1);
        DeleteObject(whtBr);
}

LRESULT WINAPI ScreenSaverProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
    static HDC hdc;
    //static HGLRC hrc;
    PAINTSTRUCT ps;
    HBRUSH whtBr;
    static RECT rect;
    switch(message) {
        case WM_CREATE:
            GetClientRect(hwnd,&rect);
            imgx = rect.right;
            imgy = rect.bottom;
            int ret = SetTimer(hwnd, TIMER, 1, NULL);
            if(ret == 0)
                MessageBox(hwnd, "Could not set Timer", "ERROR", MB_OK);
            break;
        case WM_DESTROY:
            KillTimer(hwnd,TIMER);
            PostQuitMessage(0);
            break;
        case WM_PAINT:
            k++;
            p = (float) rand()/RAND_MAX;
            if(p <= mat[0][6])
                i = 0;
            else if(p <= (mat[0][6]+mat[1][6]))
                i = 1;
            else if(p <= (mat[0][6]+mat[1][6]+mat[2][6]))
                i = 2;
            else
                i = 3;
            x0 = ((x*mat[i][0])+(y*mat[i][1])+mat[i][4]);
            y = (x*mat[i][2]+y*mat[i][3]+mat[i][5]);
            x = x0;
            jx = ((x-xa)/(xb-xa)*(imgx-1));
            jy = (imgy-1)-(y-ya)/(yb-ya)*imgy-1;
            // Paint it
            whtBr = CreateSolidBrush(RGB(255,255,255));
            hdc = BeginPaint(hwnd, &ps);
                dot(hdc, whtBr, (int)jx, (int)jy);
            EndPaint(hwnd, &ps);
            ReleaseDC(hwnd, hdc);
            if(k == end) {
                Sleep(5);
                done = 1;
            }
            break;
        case WM_TIMER:
            if(done == 0)
                InvalidateRect(hwnd, NULL, FALSE);
            else {
                InvalidateRect(hwnd, NULL, TRUE);
                k = 0;
                done = 0;
            }
            break;
        default:
            return DefScreenSaverProc(hwnd, message, wParam, lParam);
        }
    return 0;
}

BOOL WINAPI ScreenSaverConfigureDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
    //return FALSE;}
    switch(message) {
        case WM_INITDIALOG:
            //get configuration from the registry
            return TRUE;
        case WM_COMMAND:
            switch(LOWORD(wParam)) {
                case IDOK:
                    //write configuration
                    EndDialog(hDlg, LOWORD(wParam) == IDOK);
                    return TRUE;
                case IDCANCEL:
                    EndDialog(hDlg, LOWORD(wParam) == IDOK);
                    return TRUE;
            }
    }
    return FALSE;
}

BOOL WINAPI RegisterDialogClasses(HANDLE hInst) {
    return TRUE;
}

Just a note, this is the rare time you will find me messing with Windows.

Custom Brush for SyntaxHighlighter Evolved

Okay, before I get started let me just say that I realize there are several already set-up plugins for the WordPress Plugin, SyntaxHighlighter Evolved to include a brush for the *.batch language.  Also, there is a great article by the Plugin’s author that will guide you through developing a brush.  The reason I am posting mine is to pass a long a few things that went unsaid for the less experienced WordPress Plugin developer, but let me just say that this was much easier both in the plugin development and brush development than I thought it would be.  The reason I made my own brush, it’s just more fun to make my own!

Now, that being said, here we go!   My post for “Violating IT Policy” included a batch script for Cygwin to be portable.  since there was no brush in SyntaxHighlighter Evolved To develop a brush, you will need to set-up a new plugin for word press.  The plugin will be adopted by SyntaxHighlighter Evolved as you will see in a moment.  The structure for this plugin will be:

<root folder>/wp-content/plugins/
                        /plugins/<javascript brush>.js
                        /plugins/<php plugin>.php

For the javascript brush, this does have some tricky elements. but I’ve commented what I’m doing below.

/** shBrushBatch.js **/
/* Declare a new brush with SyntaxHighlighter.brushes.<your name for the brush> */
SyntaxHighlighter.brushes.Batch = function()
{
	/* Declare words that you need highlighted */
	var variable = 'clear cls goto set';
	var constants = 'if or';

	/* This is the heart of your brush, you can use the *.
	/* SyntaxHighlighter.regexLib.* brushes when applicapble. */
	this.regexList = [
		/* You may notice that my comments are looking for a css that does not match. */
		/* I'll explain below the script. */
		// comments
		{ regex: /(^::|rem).*$/gmi,                             css: 'string'},
		// stings
		{ regex: SyntaxHighlighter.regexLib.doubleQuotedString, css: 'comments'},
		{ regex: SyntaxHighlighter.regexLib.singleQuotedString, css: 'comments'},
		{ regex: /echo.*$/gmi,                                  css: 'keyword'},
		// variables
		{ regex: /%w+\1/gmi,                                    css: 'keyword'},
		{ regex: /%\*|%%?~?[fdpnxsatz]*[0-9a-z]\b/gmi,          css: 'keyword'},
		// clear cls keywords
		{ regex: new RegExp(this.getKeywords(variable), 'gmi'), css: 'variable'},
		// if and key words
		{ regex: new RegExp(this.getKeywords(constants), 'gmi'),css: 'constants'},
		// labels
		{ regex: /^:.+$/gmi,                                    css: 'script'}
	];
};

/* Create the highlighter object. */
SyntaxHighlighter.brushes.Batch.prototype = new SyntaxHighlighter.Highlighter();
/* Set the Aliases */
SyntaxHighlighter.brushes.Batch.aliases = ['bat','batch'];

So the reason that my css does not match the actual of what it is would be because the theme does not match my preference.  I perfer comments to be green, so since the string for the RDark format is green, I had to assing my comments to the string.  This was pretty confusing but the way I figured out my color scheme was simple enough.  In <root>/wp-content/plugins/syntaxhighlighter/styles/ you will find all of the css files to coordinate with the theme.  Half way down, you will see “Actual Syntax Highlighter Colors” and it is at this point that you will want to see what all of your options are.  Rather than converting #5CE63B to green, I went and made a sample script once my plugin was complete, I then went and set up a color tester like this, in place of my normal brush file:

/** shBrushBatch.js  - color test version **/
SyntaxHighlighter.brushes.Batch = function()
{
	/* 	set your wordpress to:
			1
			string
			comments
			... continue until the last keyword ...
			color3
			1 I dropped the correct closing in the example for formatting. */
	var string = 'string';
	var comments = 'comments';
	// ... continue to the last keyword ...
	var keyword = 'color3';

	this.regexList = [
		{ regex: new RegExp(this.getKeywords(string), 'gmi'), 	 css: 'string'},
		{ regex: new RegExp(this.getKeywords(comments), 'gmi'),  css: 'comments'},
		// ... continue to the last keyword ...
		{ regex: new RegExp(this.getKeywords(color3), 'gmi'), 	 css: 'color3'}
	];
};

SyntaxHighlighter.brushes.Batch.prototype = new SyntaxHighlighter.Highlighter();
SyntaxHighlighter.brushes.Batch.aliases = ['bat','batch'];

After doing this and seeing the colors, I could then associate which color I wanted for which sets of syntax.

Now, onto making the plugin work.  Obviously, you’ll need both of these files to have any results.  What this does is when you activate this plugin (yes, it does show in your plugins) then SyntaxHighlighter adopts it.  This script is pretty standard from what I saw online and is almost exactly out of the author’s blog post.  The comments at the front are what will appear in your WordPress under Plugins.  I’ve kept the comments mostly the same as the author, as he is describing it better than I could.

<?php
/*
Plugin Name: Batch Brush - SyntaxHighlighter Evolved
Descriptionn:  Adds support for the Batch language to SyntaxHighlighter Evolved.
Author: Zachary D. Skelton
Version: 1.0.2
Author URI: http://www.skeltonnetworks.com/
*/

// SyntaxHighlighter doesn't do anything until early in the "init" hook.
add_action('init','syntaxhighlighter_batch_regscript');

// Tell SyntaxHighlighter about this new brush.
add_filter('syntaxhighlighter_brushes','syntaxhighlighter_batch_addlang');

// Register the brush with WordPress.
function syntaxhighlighter_batch_regscript() {
	wp_register_script('syntaxhighlighter-brush-batch',
		plugins_url('shBrushBatch.js',__FILE__),
		array('syntaxhighlighter-core'),'1.0.2');
	}
// Add alternative names for your brush.
function syntaxhighlighter_batch_addlang($brushes) {
	$brushes['batch'] = 'batch';
	$brushes['bat'] = 'batch';

	return $brushes;
	}
?>

At this point you should be able to load your page.  If it cannot find the brush (you’ll get a dialog to let you know), you could replace plugins_url() in line 19 with a string of a direct path to the file, but there should be no need for it.  The most common reason for this is an error in your javascript brush, so make sure to check that before going to insane.  After this is all done, you may have problems seeing the results.  It took me 5 loads of the correct format before I saw the change, in that case, deactivate the plugin, clear the cache, change the plugin version number in line 6 and re-activate the plugin.  Should not need all of that but some browsers are fussy, and that takes care of any problem with the cache. As I said before, this is well documented and relatively easy to make.  You can see that I made my plugin only apply to my script but it would be easy to add more things to it.  I used a lot of my regex directly from this plugin because that is a skill I’m still working on.  But this was surprisingly simple, and you can find lots of good information on making plugins of your own.  It is surprisingly not too tough!

Complaint

“I’m a PC and Windows 7 was my idea.”

This has been annoying me for the past several months, and since I have a blog, I’m going to complain.  First of all, Windows is proprietary and if it was your idea and they didn’t pay you for it, oh well, that’s business.  Secondly, the crap in Windows 7 isn’t that great; I bought my wife a Dell Mini-10 for her birthday and it came with Windows 7.  I immediately installed Ubuntu 9.10 Netbook Remix and the comparison without even numbers, just general usage, screen real estate and speed, Ubuntu is far superior.  And finally, Ubuntu and Linux itself are open source which means that I can truly say, as a contributer (bug triage):

“”I’m a PC and Ubuntu truly is partly my idea.”

Violating IT Policy!

So, I work as a social worker and we are not expected to do much more than document with our computers. For job security reasons, I use my hobby programming in work to make the workplace more efficient and ensure that I have a job tomorrow! There are some problems with this, most notably, we are not setup to do programming. So I’m going to list my favorite tricks to get setup at work.

First of all, although we work through a company ethernet connection; we do have some flexibility. For one, I read the IT Policy and it specifically states I cannot install an executable onto the harddrive. Well, problem easily solved, I have a flash drive, so in comes a website for portable applications.  Here’s the applications I use the most.

*        GOOGLE CHROME

Google Chrome is a great browser.  It’s ability to interpret javascript leaves IE# in the dust!  As for it’s portability, just like most of these, just run the executable and install it to your flash drive (or if you want a little more speed and less portability, your harddrive).  Now, Google Chrome works great right out of the box, except one thing.  It’s flash needs to be updated.  Fortunately, this is easy to solve and there are only a few steps.

  1. Get FlashPlayer XPI for Windows.
  2. Rename the *.xpi to *.zip and copy flashplayer.xpt and NPSWF32.dll
  3. Paste those two files into <install directory>/App/Chrome-bin/<version>/ directory.  Replace install directory with where you installed the application and version with the folder that is your version number.

**            NOTEPAD++

This stuff is simple, but I thought I’d post a link for the plugins.  These are easy to install, plugins go in the \Plugins\ folder, configuration files go in the \Plugins\Config\ and documentation goes in \Plugins\Doc\. Here are my favorite plugins:

***   BOA CONSTRUCTOR

For this to work, you’ll need Portable Python which installs similar to most things but it altered file associations and so I just extracted it and then it runs fine.  You’ll also want to install wxPython which is a module for python located on the Portable Python Page.  For Boa Constructor, download the file and install it on a computer of your own.  From there it copies onto the flash drive just fine, just make sure to update the settings for your main python exectuable since it won’t be in the computer’s path.

****       CODEBLOCKS

CodeBlocks is another program that will copy straight from the computer to your flash drive to make it portable.  The real trick is getting paths set and configuring WX if you’re interested in rapid development of GUI’s in C.  So here’s the quick run through.  For paths, I struggled with this on my work computer but it will not read paths that have a space.  It sees that space as the end of your path, so when setting a path for a library, for example WX, make sure you store that in a location that does not have a space in the path.  As for configuring WX, here’s what I did.  I went to the WX Pack site and got the package, which is great.  No need to compile or anything, does it all on it’s own with a directory to link your CodeBlocks library to, just be aware, this will take a lot of space on your flash drive, but with all of these things, you can always store them locally if you are daring that much against your local IT Department!

*****          CYGWIN

The biggest pain and the best program to have for avid Linux users.  This site makes a great tutorial on how to do this.  And rather than reiterating this, I’ll add my own changes.  The biggest thing was I changed the startup script and then linked that script on my desktop.  The first thing to do is to install Cygwin on your flash drive, be aware it may not install all the programs you want.  I did it three times before it all worked.  Then you have to mount the drive as you cannot do this or it will write to the registry.  As for my script, here’s what I wrote:

;rem creating a startup script
@echo off
:: clear
cls

:: locate directory
echo Locating directory...
for /F %%A in ('cd') do set WD=%%A
:: create path
echo Setting Path...
set path=%WD%\bin;%path%
set SHELL=/bin/bash
set CYGWIN=codepage:437
set HOME=/home/zbert
:: mount fs
echo Mounting File System...
bin\mount -bfu %WD%/ /
bin\mount -bfu %WD%\bin /usr/bin
bin\mount -bfu %WD%\lib /usr/lib
:: login
echo Logging in...
echo.
echo.

if "%1" == "" GOTO noopt
	if "%1" == "c" goto cmd
	if "%1" == "-c" goto cmd
	if "%1" == "--cmd" goto cmd
	if "%1" == "h" goto help
	if "%1" == "-h" goto help
	if "%1" == "--help" goto help
	echo  [*] ERROR: Unrecognized option.
	goto usage

:usage
echo usage: cygwin [c^|h^|-c^|-h^|--cmd^|--help]
goto help

:help
echo.
echo          Portable Cygwin Loader v1.0
echo.
echo     Commands:            *Run normal with no options.
echo        c ^| -c ^| --cmd     Run in Command Prompt.
echo        h ^| -h ^| --help    Display Help Message
echo.
echo        Copyright Skelton Computers © 2009
echo.
goto end

:cmd
echo cls > bin\bash -l -i
GOTO end

:noopt
bin\bash -l -i
GOTO end

:end
set path=%WD%\bin;%path%
@echo on