November 3, 2010

Is a File Ready? Waiting for a File Process to Complete.

Filed under: Automation, Scripting — Marcus Tettmar @ 4:11 pm

In the comments to my last post Richard asked how we can wait for a process to finish updating a file.

In my reply to Richard I point out that most of the time we can use a visual cue. Where possible this is the approach I would use. Usually an application would present some kind of visual cue when the file operation finishes. A dialog box might appear, or disappear, an object may become enabled or disabled, some text may appear on the screen, etc. We might be able to use commands such as WaitWindowOpen, WaitWindowClosed, WaitWindowChanged, WaitScreenText, WaitScreenImage, WaitCursorChanged, WaitPixelColor, or WaitRectChanged. Or we might even create our own wait loop which checks for some value or property. I mention this approach in Top Tips for Reliable Macros.

Unfortunately there are sometimes scenarios where there is no visual cue and we have nothing we can “see” which tells us the file operation has completed.

If the file is locked by the application that is writing to it, we could create a wait loop which checks to see if the file is still locked or not.

How might we achieve that? Well, why not just try to read from the file. If the file is locked we’re not going to be able to read it right? So we could just do:

Label>wait_file
ReadLn>file,1,res
Pos>##ERR##,res,1,pErr
If>pErr>0
  Wait>0.2
  Goto>wait_file
Endif

This will work for any kind of file.

Of course this assumes that the file is locked for reading by other processes.

It’s possible that the application locks the file only for writing. In that situation we could use WriteLn to attempt to write an empty string to the file:

Let>WLN_NOCRLF=1
Label>wait_file
WriteLn>file,res,{""}
If>RES<>0
  Wait>0.2
  Goto>wait_file
Endif

But that’s a bit invasive in the instance that the file IS available as although we’re writing nothing, we’re still modifying it so updating it’s timestamp.

We can get a bit more control over this with VBScript where we can attempt to open a file for appending without actually modifying it:

VBSTART
Function TestFile(filename)
   Set oFSO = CreateObject("Scripting.FileSystemObject") 
   On Error Resume Next 
   Set f = oFSO.OpenTextFile(filename, 8, True)
   TestFile = Err.Number 
End Function
VBEND

Let>file=C:\files\bmp.bmp

Label>wait_file
VBEval>TestFile("%file%"),fRes
If>fRes<>0
  Wait>0.2
  Goto>wait_file
Endif

All the TestFile function does is try to open the file for appending, and if an error occurs it returns the error code. So if we get zero back, there’s no error and the file must be available for writing and therefore not locked.

Don’t be put off by the fact that this uses the OpenTextFile method. It will still work with any kind of file. We’re not actually going to attempt to modify it. We’re just trying to see if we can open it. So the file type is unimportant.

Note that in these samples I haven’t checked for any specific error code nor have I checked for the existence of the file first – I’m assuming any error means the file isn’t available. An error will also be returned if the file does not exist, so you’d probably want to use IfFileExists first. You might even want to put FileExists in a loop so that you can wait until it exists.

Note also the small wait in each loop. This is just to make sure the loop isn’t so tight that it hogs CPU. Better to be nice to the system and give other processes a chance to breathe.

November 2, 2010

Waiting for the Clipboard

Filed under: Automation, Scripting — Marcus Tettmar @ 2:58 pm

Today I was helping someone who was wanting to write a script to take screen-shots from one application and then paste those screen-shots into Microsoft Excel.

Initially things weren’t working reliably because the script didn’t factor in the time taken for the large bitmap of a screen-shot to exist in the clipboard after pressing the print screen button, before attempting to paste into Excel. E.g. consider:

Press Print Screen
SetFocus>Microsoft - Excel*
Press CTRL
Send>v
Release CTRL

The above is probably going to fail most of the time because a screen shot is a large bitmap and is going to take some time to arrive on the clipboard, but the script above performs a paste in Excel immediately after pressing print screen. The print screen key being depressed and the clipboard containing the bitmap are not the same thing.

While we could have just said “wait 5 seconds” and that would probably have been fine for evermore, it isn’t very sensitive and wouldn’t be ideal for a script that needs to run as fast as possible. Ideally we only want to wait until we know the bitmap is in the clipboard.

Text is usually smaller than a bitmap, but for large text items one way to make things bulletproof is to do something like this:

PutClipBoard>dummy

SetFocus>source_app_title
Press CTRL
Send>c
Release CTRL

Label>wait_for_data
Wait>0.2
GetClipBoard>clipdata
If>clipdata=dummy
  Goto>wait_for_data
Endif

By putting a known value onto the clipboard in the first place we can then have a little loop which keeps checking the clipboard until the returned value is not our known value. We then know our CTRL-V has worked and that we can safely paste to the target application.

But how can we do the same thing when the clipboard data is an image? The above won’t work because GetClipBoard won’t return anything for non-textual data.

Well, Windows has a function called IsClipboardFormatAvailable which will allow us to determine what kind of data is on the clipboard. So we could use this in a similar way to above to see if the clipboard contains a bitmap or not. Like this:

Let>CF_BITMAP=2

Let>haveBMP=0
PutClipBoard>dummy

Press Print Screen

While>haveBMP=0
  LibFunc>user32,IsClipboardFormatAvailable,haveBMP,CF_BITMAP
  Wait>0.2
EndWhile

We could then paste it somewhere:

SetFocus>Document - WordPad
Press CTRL
Send>v
Release CTRL

It’s always nice to wait only as long as we have to and it makes the script more reliable and portable.

October 19, 2010

ClipMagic 4.0 Released

Filed under: Announcements — Marcus Tettmar @ 6:43 pm

ClipMagic - Clipboard Extender Way back in 1998 we released a handy little Windows Clipboard extender and information manager called ClipMagic. It lives over at http://www.clipmagic.com/ where today after far too long a new version was released.

If you’re not already familiar with ClipMagic it is a Windows clipboard monitor/viewer/extender/manager which stores every item you copy to the windows clipboard and allows you to edit clips, organize them, manipulate and filter them, assign hot keys to them, and provides useful features to make it easier to paste clips into other windows. It is also an information manager, as you can create clips manually, assign them to categories and quickly retrieve/paste them using hot keys. Web clips are stored with the URL of the page they came from, allowing you quick access back to the source.

Basically it speeds up your work. The big problem with the native Windows clipboard is that it only stores one item at a time. You know that feeling when you have to copy lots of items from one screen to another and you have to go back and forth? Then a bit later you realise you need an item you copied earlier but it was obliterated by a recent copy? Well ClipMagic removes all that, because ClipMagic remembers every clip and gives you quick ways to paste into the active application.

For those familiar with previous versions of ClipMagic you may not notice any major difference in version 4.0 at first. But the big change is that version 4.0 has a completely new database format which is faster and more reliable. V 4.0 is also fully compatible with Vista and Windows 7 and supports the new Vista/Win7 clipboard monitoring method, so if you’re using Vista/Win7 you can say good bye to the annoying clipboard chain problems.

ClipMagic 4.0 comes in two flavours. As well as the full featured version, with a 30 day trial, there’s also a free Lite version which just keeps a copy of all clips giving you access to them but with no editing, filtering or custom hot key features.

More Info
Downloads

October 18, 2010

Macro Scheduler 12.1.0 Now Available

Filed under: Announcements — Marcus Tettmar @ 12:08 pm

Macro Scheduler 12.1.0 is now available with the following fixes since my last update announcement:

  • Fixed: IGNORESPACES ignoring CRLFs and SPACES when on their own.
  • Fixed: StringReplace crashes if empty string passed in find parameter
  • Fixed: Occassional “cannot write to comdef.ini” error in standalone editor.
  • Fixed: CTRL-V etc not working in Watch List search box
  • Fixed: Some text missing from GetTextInRect / GetWindowTextEx where text overlaps (New Text Capture libs)
  • Added: Full complex expression support to Repeat and While (when expr between curly braces)
  • Added: -KEEPLOGOPEN command line parameter: keeps log file open during script execution (faster for installations with large number of simultaneous running scripts)
  • Change: If insufficient privileges to open a script for exclusive write access (or if script already being edited) will now ask if you want to open it read only

Workflow Designer and the SDK have also been updated to the same MacroScript version.

Registered Downloads/Upgrades | Evaluation Downloads | New License Sales

October 15, 2010

Display an Animated GIF on a Dialog

Filed under: Scripting — Marcus Tettmar @ 8:19 am

Forum regular JRL has come up with yet another great coding example, with a demonstration of how to jazz up your dialogs by displaying an animated image – a great way to represent progress of an activity.

Here it is.

In fact this example shows how any window can be embedded into a dialog by using the SetParent function. Take a look at JRL’s helpful comments to see how this works.

September 23, 2010

Success Story: MacroScript SDK bridges healthcare system boundaries

Filed under: Success Stories — Marcus Tettmar @ 3:56 pm

Are you a developer? Did you know that with our MacroScript SDK you can add the ability to run Macro Scheduler code right from within your own applications? The SDK lets you run Macro Scheduler scripts and code, as well as query Macro Scheduler script variables during code execution. The SDK gives you a more seamless way to run Macro Scheduler code and use Macro Scheduler capabilities within your own applications.

Steen Jakobsen of DM Software recently integrated the SDK into their Dialog Manager software. He kindly agreed to a case study.

Macro Scheduler made it very easy to integrate the SDK. The input parameters for the scripts are completely integrated and direct, and secure and reliable data transfer is being accomplished – all thanks to the brilliant architecture of the MacroScript SDK. …. We’ve saved the doctors and nurses enormous amounts of time, and at the same time, added very valuable and sophisticated calculation and decision support across five systems that otherwise have no link to one another. This can only be done with the unique Windows automation capabilities of Macro Scheduler combined with the tight integration with Dialog Manager.

Steen Jakobsen, DM Software

Read the Case Study here.

September 16, 2010

Making a Dialog or Window Stay On Top

Filed under: Automation, Scripting — Marcus Tettmar @ 1:45 pm

Edit: 23 March 2011. In Version 12 it is possible to make a dialog stay on top simply by setting the dialog’s FormStyle property to fsStayOnTop. The method outlined in this post is not necessary for v12 dialogs but will remain as it can be used for older versions and the same approach can be used for windows belonging to other processes.

A question that comes up every now and then is how to make a custom dialog stay “on top” of other windows even when it loses the focus. There is a way to do this by calling the Windows API function SetWindowPos. There are examples in the forums but for convenience here’s a version of one:

SRT>StayOnTop
  Let>HWND_TOPMOST=-1
  Let>HWND_NOTOPMOST=-2
  Let>SWP_NOSIZE=1
  Let>SWP_NOMOVE=2
  Let>SWP_NOACTIVATE=16
  Let>SWP_SHOWWINDOW=64
  Let>WindowHandle=%StayOnTop_var_1%
  Let>Flags={%SWP_NOACTIVATE% Or %SWP_SHOWWINDOW% Or %SWP_NOMOVE% Or %SWP_NOSIZE%}
  LibFunc>User32,SetWindowPos,swpr,%WindowHandle%,HWND_TOPMOST,0,0,0,0,Flags
END>StayOnTop

This subroutine takes a window handle and modifies the properties of that window to make it stay above other windows.

For example, if we had just opened Notepad and wanted to force it to stay on top we could do:

GetWindowHandle>Untitled - Notepad,hwndNotepad
GoSub>StayOnTop,hwndNotepad

Or to get the handle of the active window use GetActiveWindow with WIN_USEHANDLE set to 1.

To set one of your own custom dialogs to stay on top use:

GoSub>StayOnTop,DialogName.Handle

Don’t forget that we are at the mercy of Windows here (and possibly the developers of the app we’re trying to force to the top). It’s a bit rude to have a window floating around on top of other windows. And consider what would happen if another window is opened which is also set to stay on top in the same way? You can’t have two windows on top. So multiple “stay on top” windows will still overlap each other depending on which one has the focus. In short you can’t really guarantee that a window will always be on top.

September 15, 2010

Macro Scheduler 12.0.8 Update Available

Filed under: Announcements — Marcus Tettmar @ 10:07 am

Macro Scheduler 12.0.8 is now available with the following fixes since my last update announcement:

  • Fixed: SCRIPT_FILE / SCRIPT_DIR returning exename/dir when queried in macro called by compiled macro
  • Fixed: Variable Breakpoints not being recognised inside dialog event handler subroutines
  • Fixed: LDblClick / RDblClick not independent of left hand/right hand mouse settings (LDblCLick should always do primary button function)
  • Fixed: XLSetCell example in help file has missing Sheet name
  • Fixed: HTTPPost using multipart/form-data and binary encoding for all form data. Should be application/x-www-form-urlencoded unless sending files
  • Fixed: SK_IGNORECAPS incorrectly causing non alphabetic characters to be “shifted”
  • Fixed: Dialog Designer – sometimes changing property selection to dialog’s properties unexpectedly
  • Fixed: List out of bounds error when trying to edit a script which is already open in another editor or being edited by another user.
  • Fixed: Long delay when updating very long dialogs
  • Fixed: Exit command not returning specified exit code (always returning zero) in compiled macros
  • Fixed: Imported DLLs being unloaded at the end of a dialog event handler subroutine
  • Change: RunProgram now returning error code if an error occured instead of just -1 (now returns -1:errcode)
  • Added: possible workaround for Win7 regional settings bug which occurs on some systems

Workflow Designer and the SDK have also been updated to the same MacroScript version.

Registered Downloads/Upgrades | Evaluation Downloads | New License Sales

Accessing 64 bit System Folders – Turn off File System Redirection

Filed under: Automation, General — Marcus Tettmar @ 8:50 am

If you need to run a 64 bit system command, or a system command that requires access to the 64 bit system folders you may need to turn off File System Redirection.

To turn off File System Redirection call the snappily named Wow64DisableWow64FsRedirection function and remember to turn it back on with the equally memorable function Wow64RevertWow64FsRedirection.

For example:

//turn off File System Redirection
LibFunc>kernel32,Wow64DisableWow64FsRedirection,result,0

Let>RP_ADMIN=1
let>RP_WAIT=1
DeleteFile>%TEMP_DIR%\vss.txt
Run>"cmd.exe" /c vssadmin list shadowstorage  >> "%TEMP_DIR%\vss.txt"
ReadFile>%TEMP_DIR%\vss.txt,vss
MessageModal>vss

//revert File System Redirection
LibFunc>kernel32,Wow64RevertWow64FsRedirection,result,0

Recently someone running the 64 bit version of XP was having a problem running this innocuous looking code:

Run>c:\windows\system32\mstsc.exe

mstsc.exe is the remote desktop client. Macro Scheduler returned an error saying that c:\windows\system32\mstsc.exe could not be found, yet using Windows Explorer we could see mstsc.exe clearly in the system32 folder. The same code worked perfectly fine on a Win7 x64 system.

Eventually I realised what was happening. Because the OS was 64 bit and Macro Scheduler is 32 bit, Windows was redirecting “c:\windows\system32\” to “c:\windows\syswow64” – the 32 bit system folder. There should be a 32 bit version of mstsc.exe in there, but on this particular system it was missing (it may be that earlier versions of Remote Desktop on x64 did not install a 32 bit version). Hence the error that Macro Scheduler could not find the file. We quickly resolved this by turning off File System Redirection using the code above.

Although the current 32 bit version of Macro Scheduler runs on and is compatible with all 64 bit versions of Windows, a 64 bit version of Macro Scheduler is in the pipeline. Until then calling some system level functions may need the above treatment if those commands need to access the 64 bit subsystem. Macro Scheduler can happily execute and interact with 64 bit applications, but Windows will redirect references to some locations such as system32 unless File System Redirection is disabled.

September 14, 2010