### Archive

Archive for the ‘Myoddweb Piger’ Category

## First the basics

am_execute( cmd, args, admin);

The first argument is the command we wish to execute, the second one is the command line argument and the last one is if we wish to run as administrator or not, (with privileged access).

## How to get the arguments?

You have various commands to get the arguments entered.

You can get the ones typed by the user

-- the number of arguments
local sizeOf = am_getCommandCount();

-- argument number 0 is the action itself, (what he user typed in).
local action= am_getCommand( 0 );
...
-- argument number 1
local cmd= am_getCommand( 1 );

Or you can also get the selected folder if there is one

Remember that we could have selected more than one folder

-- do we have a folder?
local thisFolder =  am_getfolder( 0, false );

## Putting it all together

If you have an app like cmder or even the default command line app you can put it all together

-- the location of the cmder.exe if it is not in the path.
local cmderPath = [[c:\path\to\your\cmder\Cmder.exe]];

-- do we have a folder?
local thisFolder =  am_getfolder( 0, false );

-- if we don't have a folder, guess what we are looking for.
if thisFolder == false  then
local sizeOf = am_getCommandCount();
if sizeOf == 0  then
-- no arguments.
am_say( "<i>Going to <b>home</b> drive</i>.", 400, 10  )
am_execute( cmderPath, [[/START %HOMEDRIVE%\]], true );
else
local thisWord = am_getCommand( 1 );
if thisWord == "home" or thisWord == "h" then
am_say( "<i>Going to <b>home</b> drive</i>.", 400, 10  )
am_execute( cmderPath, [[/START %HOMEDRIVE%\]], true );
elseif thisWord == "system" or thisWord == "s" then
am_say( "<i>Going to <b>system</b> drive</i>.", 400, 10  )
am_execute( cmderPath, [[/START %SYSTEMDRIVE%\]], true );
else
am_execute( cmderPath, "", true );
end
end
else
-- go to the selected folder and in case of multiple drives, change the drive letter.
am_say( "<i>Going to <b>".. thisFolder .."</b></i>.", 400, 10  )
am_execute( cmderPath, "/START \"" .. thisFolder .. "\"", true);
end


And save the file and call it “cmder.lua” and save it in your root command folder, (or subdirectory).

Then if the user types

• cmder home – they will go to their home directory
• cmder – they will go to their system drive
• cmder (with the cursor over a folder name) – they will go to that folder.

## More?

Categories: Tags:

## How to compare multiple folders with BeyondCompare 4 and Piger

##### Why?

In some cases you might often need to compare folders using beyond compare and using a Piger command might just do the trick.

The problem is that you might want to open/compare more than one folder at a time, so here is how to do it.

##### How

Open a blank file with your favourite editor, we will create a LUA file in this case.

— the path to the BC4 exe.
local bCompare = [[%ProgramFiles%\Beyond Compare 4\BCompare.exe]];

— compare folder A and folder B
am_execute( bCompare, [[/filters=”-bin\;-*.exe” “c:\folderA” “c:\folderB”]]);

— also compare folder X and folder Y
am_execute( bCompare, [[/filters=”-lib\;-*.user” “c:\folderX” “c:\folderY”]]);

The part “/filter=” contains the files you want to filter out, in the first example, the folder(s) “bin\” will be filtered out as well as files with the executable extension, (*.exe).

Finally, the 2 folders are listed one after the other, I suggest that you add quotes around them, especially if they have spaces, (but do it anyway).

You might not access to all the folders, (for whatever reason), but you might have access as an admin, so, when in doubt, set the admin flag to true, this might help a little.

But it is not generally needed…

am_execute( bCompare, [[/filters=”-lib” “c:\X” “c:\Y”]], true);

##### String in LUA

A small note about the way I escaped the strings in my example.

normally special characters are ‘escaped’ in LUA, (characters like quotes and so on).

local x = “This is how you do it, \”normally\””

but you can use double square brackets to make your life slightly easier, (and more importantly, easier to read).

local x = [[This is how you do it, “normally”]]

##### Finally

Save you file with whatever command you want to call it, for example “compare.lua”, make sure that it has the “.lua” extension.

Move the file to your command folder, ( located in “%appdata%\MyOddWeb\ActionMonitor\RootCommands\” by default).

And your new command should now appear.

Categories: Myoddweb Piger Tags:

When I was working on the next version of Piger I would sometime get an issue when using the this.bye command, (to close Piger).

What happens in the background is I call WM_CLOSE to close the active window, this message is sent to all the windows.

When it is processed by the message pump no other messages are been processed, this is a problem in case some windows are still dishing out messages, (like a fading dialog box in our example).

So remember, once you call WM_CLOSE, all bets are off and your message pump is as good as dead.

Best to have your own ‘Close()’ that does all the housekeeping in the background before you actually post WM_CLOSE to the main thread…

Otherwise your app my appear to hang.

Categories: Tags:

## Preventing embedded python from killing your app

I was looking at a defect in Piger where a Python script could close Piger itself, it wasn’t a crash, but rather a graceful exit.

import am am.say( "Bye", 1, 1 ); exit(1);

The problem was with the way I was calling the script rather than anything wrong with Piger or Python itself.

Somewhere in the Python virtual machine I had something like…
 ... if( -1 == PyRun_SimpleString( ... ) ) { ... } ... 

And, while that works fine in most cases, if I have an exit( xyz ) in my script, piger would close.
So the answer was to replace it with …

 ... PyObject * PyRes = PyRun_String(s, Py_file_input, main_dict, main_dict); PyObject* ex = PyErr_Occurred(); if( NULL != ex) { ... } ... 

The one last problem was, how to tell if the error was because of an exit(…) or because of an error.

 ... PyObject * PyRes = PyRun_String(s, Py_file_input, main_dict, main_dict); PyObject* ex = PyErr_Occurred(); if( NULL != ex) { // if we exit(...) then 'ex' is not NULL, so we must check for that. if (!PyErr_ExceptionMatches(PyExc_SystemExit)) { // this is a real coding error. } } ... 

Now you can catch all the real errors and swallow all the exist code and so on.

See the exceptions handling in Python and embedding in general.

Categories: Tags:

## Released piger 0.3.2

I released the first version of Piger on Github after moving from sourceforge.net

This new release is pretty much the same as the previous one just brought to the 21st century …

The changes are

1. Python 3.5.1
2. Python is not required on the host machine, (something that was causing a break before!)
3. Lua 5.2
4. x64 or x86 build, (not for memory reasons, but for env. variable reasons).
5. Moved from Sourceforge.net, (I added a readme.md to redirect to github). Please Google for some well documented reasons to move away from them…

Please try it and tell me if you see something cool that should be added.

I am also looking for cool scripts to be added to my list, so please, send them my way!

Categories: Myoddweb Piger Tags:

## Embed Python in your C++ application without Python installed on guest machine

For my Piger application, I wanted my C++ app to parse Python scripts but I quickly became aware of the fact that the user must have Python installed on their machine, not only that they needed the same version as mine, (version 3.5).

The normal call would be something like…

But that throws an error when the user does not have Python installed.
And if they have an older version installed, it _might_ work, but the scripts might not work as expected.

The solution is to embed the Python you want to run in your app.

1. Go to the Python website and download the Embeddable zip file for your app, (x64 or x86)
2. Extract the python35.zip located inside that zip file
3. Copy it somewhere where it can be referenced.