The way to restrict a ruby program to just once occurrence on a windows box?

I'm rewriting a vb app to ruby (in about a quarter of the code!). If I ran
the same ruby program twice in parallel, the second instance should exit.

In VB6 I could do this:

             If App.PrevInstance Then Exit Sub

Any ideas how this is done in ruby?

Ta muchly

Never mind, solved it (unless anybody knows a better way).

It's a windows app, so:

require 'Win32API'

SW_HIDE = 0
WS_OVERLAPPED = 0
WS_DISABLED = 0x08000000
WS_MINIMIZED = 0x20000000

  def already_running

···

#
    # Not sure of any other way to do this.
    # Create a window with the title "i4FileProcessorHiddenWindow".
When we come to run this program again,
    # if there is already a window called
"i4FileProcessorHiddenWindow" then abort that instance.
    # In this way, only one instance of the script should run.
    #

    findwindow = Win32API.new('user32','FindWindow', ['p','p'], 'L')
    return true if findwindow.call("STATIC", "i4FileProcessorHiddenWindow") != 0

    createwindow = Win32API.new('user32', 'CreateWindowEx', ['l', 'p',
'p', 'l', 'i', 'i', 'i', 'i', 'l', 'l', 'l', 'P'], 'l')
    dwStyle = (WS_DISABLED | WS_MINIMIZED)
    cw = createwindow.call( WS_OVERLAPPED, 'STATIC',
'i4FileProcessorHiddenWindow', dwStyle, 0, 0, 0, 0, 0, 0, 0, 0 )
    show = Win32API.new('user32', 'ShowWindow', ['L', 'L'], 'L')
    show.call(cw, SW_HIDE)

    return false
  end

On 07/11/06, Glenn Smith <glenn.ruby@gmail.com> wrote:

I'm rewriting a vb app to ruby (in about a quarter of the code!). If I ran
the same ruby program twice in parallel, the second instance should exit.

In VB6 I could do this:

             If App.PrevInstance Then Exit Sub

Any ideas how this is done in ruby?

Ta muchly

--

All the best
Glenn
Aylesbury, UK

Glenn Smith wrote:

I'm rewriting a vb app to ruby (in about a quarter of the code!). If I ran
the same ruby program twice in parallel, the second instance should exit.

In VB6 I could do this:

             If App.PrevInstance Then Exit Sub

Any ideas how this is done in ruby?

Ta muchly

------=_Part_1672_14945421.1162889756916--

Though not very "elegant", here's one approach...

When the script starts up, run the following line of code, within the
BEGIN block of a BEGIN...RESCUE...ENSURE construct.

def main()

  begin
    lockFile = File.new("semaphore.lck", File::CREAT|File::EXCL)

  rescue Errno::EEXIST
    puts("Script is already running")

  rescue Exception => ex
    puts(ex.message())

  ensure
    unless lockFile.nil?
      lockFile.close()
      File.delete("semaphore.lck")
    end

  end

end

main()

The first instance of the script will create and open the
"semaphore.lck" file. Running another instance of the script will cause
the preceeding line of code to throw a Errno::EEXIST error, which is
easy enough to trap. In that case, display a message to the user. The
ENSURE block will need to close and delete the semaphore file so that,
in the case of an abend, the file is not left hanging out there.
Otherwise, this will prevent the script from running again until
someone manually deletes the file.

Is it some kind of GUI app? I don't know what toolkit you are using, but I
do remember from my days as a wxPython jockey that the wxWidgets toolkit
came with a api for doing exactly this: wx.SingleInstanceChecker. I imagine
that there's a win32 API that is used to do it, and that should be available
to most other toolkits you might be using (e.g. I'm sure Java Swing has
something similar).

I imagine that such an API should be available even if it isn't a GUI app
(perhaps through Win32API) and I imagine that using this would be slightly
cleaner than doing your own version.

Admittedly this isn't much use as all I'm saying is, "yeah, there is a way
to do this" without providing much details...

Sorry

Muz

···

On 07/11/06, Glenn Smith <glenn.ruby@gmail.com> wrote:

Never mind, solved it (unless anybody knows a better way).

It's a windows app, so:

require 'Win32API'

SW_HIDE = 0
WS_OVERLAPPED = 0
WS_DISABLED = 0x08000000
WS_MINIMIZED = 0x20000000

  def already_running
    #
    # Not sure of any other way to do this.
    # Create a window with the title "i4FileProcessorHiddenWindow".
When we come to run this program again,
    # if there is already a window called
"i4FileProcessorHiddenWindow" then abort that instance.
    # In this way, only one instance of the script should run.
    #

    findwindow = Win32API.new('user32','FindWindow', ['p','p'], 'L')
    return true if findwindow.call("STATIC",
"i4FileProcessorHiddenWindow") != 0

    createwindow = Win32API.new('user32', 'CreateWindowEx', ['l', 'p',
'p', 'l', 'i', 'i', 'i', 'i', 'l', 'l', 'l', 'P'], 'l')
    dwStyle = (WS_DISABLED | WS_MINIMIZED)
    cw = createwindow.call( WS_OVERLAPPED, 'STATIC',
'i4FileProcessorHiddenWindow', dwStyle, 0, 0, 0, 0, 0, 0, 0, 0 )
    show = Win32API.new('user32', 'ShowWindow', ['L', 'L'], 'L')
    show.call(cw, SW_HIDE)

    return false
  end

On 07/11/06, Glenn Smith <glenn.ruby@gmail.com> wrote:
> I'm rewriting a vb app to ruby (in about a quarter of the code!). If I
ran
> the same ruby program twice in parallel, the second instance should
exit.
>
> In VB6 I could do this:
>
> If App.PrevInstance Then Exit Sub
>
> Any ideas how this is done in ruby?
>
> Ta muchly
>

--

All the best
Glenn
Aylesbury, UK

You could also take a leaf out of unix tradition and simply write a
small file containing the current process ID into a temporary
directory. When your program starts, it checks for this file, and if a
corresponding running Ruby process is found then it can exit (perhaps
with a log message or something). If not, then the starting instance
would seem to be the only one.

- james

···

On 11/7/06, Murray Steele <murray.steele@gmail.com> wrote:

Is it some kind of GUI app? I don't know what toolkit you are using, but I
do remember from my days as a wxPython jockey that the wxWidgets toolkit
came with a api for doing exactly this: wx.SingleInstanceChecker. I imagine
that there's a win32 API that is used to do it, and that should be available
to most other toolkits you might be using (e.g. I'm sure Java Swing has
something similar).

I imagine that such an API should be available even if it isn't a GUI app
(perhaps through Win32API) and I imagine that using this would be slightly
cleaner than doing your own version.

Admittedly this isn't much use as all I'm saying is, "yeah, there is a way
to do this" without providing much details...

Sorry

Muz

On 07/11/06, Glenn Smith <glenn.ruby@gmail.com> wrote:
>
> Never mind, solved it (unless anybody knows a better way).
>
> It's a windows app, so:
>
> require 'Win32API'
>
> SW_HIDE = 0
> WS_OVERLAPPED = 0
> WS_DISABLED = 0x08000000
> WS_MINIMIZED = 0x20000000
>
> def already_running
> #
> # Not sure of any other way to do this.
> # Create a window with the title "i4FileProcessorHiddenWindow".
> When we come to run this program again,
> # if there is already a window called
> "i4FileProcessorHiddenWindow" then abort that instance.
> # In this way, only one instance of the script should run.
> #
>
> findwindow = Win32API.new('user32','FindWindow', ['p','p'], 'L')
> return true if findwindow.call("STATIC",
> "i4FileProcessorHiddenWindow") != 0
>
> createwindow = Win32API.new('user32', 'CreateWindowEx', ['l', 'p',
> 'p', 'l', 'i', 'i', 'i', 'i', 'l', 'l', 'l', 'P'], 'l')
> dwStyle = (WS_DISABLED | WS_MINIMIZED)
> cw = createwindow.call( WS_OVERLAPPED, 'STATIC',
> 'i4FileProcessorHiddenWindow', dwStyle, 0, 0, 0, 0, 0, 0, 0, 0 )
> show = Win32API.new('user32', 'ShowWindow', ['L', 'L'], 'L')
> show.call(cw, SW_HIDE)
>
> return false
> end
>
> On 07/11/06, Glenn Smith <glenn.ruby@gmail.com> wrote:
> > I'm rewriting a vb app to ruby (in about a quarter of the code!). If I
> ran
> > the same ruby program twice in parallel, the second instance should
> exit.
> >
> > In VB6 I could do this:
> >
> > If App.PrevInstance Then Exit Sub
> >
> > Any ideas how this is done in ruby?
> >
> > Ta muchly
> >
>
> --
>
> All the best
> Glenn
> Aylesbury, UK
>

--
* J *
  ~

I thought that, the problem being what if the other ruby program crashed
without removing the file? I guessed the file would remain. I suppose the
check against whether or not the existing pid was a ruby program would
mostly remove this problem, but it seemed imperfect. Then again, who's to
say my solution is...!

···

On 07/11/06, James Adam <james.adam@gmail.com> wrote:

You could also take a leaf out of unix tradition and simply write a
small file containing the current process ID into a temporary
directory. When your program starts, it checks for this file, and if a
corresponding running Ruby process is found then it can exit (perhaps
with a log message or something). If not, then the starting instance
would seem to be the only one.

- james

On 11/7/06, Murray Steele <murray.steele@gmail.com> wrote:
> Is it some kind of GUI app? I don't know what toolkit you are using,
but I
> do remember from my days as a wxPython jockey that the
wxWidgets toolkit
> came with a api for doing exactly this: wx.SingleInstanceChecker. I
imagine
> that there's a win32 API that is used to do it, and that should be
available
> to most other toolkits you might be using (e.g. I'm sure Java Swing has
> something similar).
>
> I imagine that such an API should be available even if it isn't a GUI
app
> (perhaps through Win32API) and I imagine that using this would be
slightly
> cleaner than doing your own version.
>
> Admittedly this isn't much use as all I'm saying is, "yeah, there is a
way
> to do this" without providing much details...
>
> Sorry
>
> Muz
>
> On 07/11/06, Glenn Smith <glenn.ruby@gmail.com> wrote:
> >
> > Never mind, solved it (unless anybody knows a better way).
> >
> > It's a windows app, so:
> >
> > require 'Win32API'
> >
> > SW_HIDE = 0
> > WS_OVERLAPPED = 0
> > WS_DISABLED = 0x08000000
> > WS_MINIMIZED = 0x20000000
> >
> > def already_running
> > #
> > # Not sure of any other way to do this.
> > # Create a window with the title "i4FileProcessorHiddenWindow".
> > When we come to run this program again,
> > # if there is already a window called
> > "i4FileProcessorHiddenWindow" then abort that instance.
> > # In this way, only one instance of the script should run.
> > #
> >
> > findwindow = Win32API.new('user32','FindWindow', ['p','p'], 'L')
> > return true if findwindow.call("STATIC",
> > "i4FileProcessorHiddenWindow") != 0
> >
> > createwindow = Win32API.new('user32', 'CreateWindowEx', ['l', 'p',
> > 'p', 'l', 'i', 'i', 'i', 'i', 'l', 'l', 'l', 'P'], 'l')
> > dwStyle = (WS_DISABLED | WS_MINIMIZED)
> > cw = createwindow.call( WS_OVERLAPPED, 'STATIC',
> > 'i4FileProcessorHiddenWindow', dwStyle, 0, 0, 0, 0, 0, 0, 0, 0 )
> > show = Win32API.new('user32', 'ShowWindow', ['L', 'L'], 'L')
> > show.call(cw, SW_HIDE)
> >
> > return false
> > end
> >
> > On 07/11/06, Glenn Smith <glenn.ruby@gmail.com> wrote:
> > > I'm rewriting a vb app to ruby (in about a quarter of the
code!). If I
> > ran
> > > the same ruby program twice in parallel, the second instance should
> > exit.
> > >
> > > In VB6 I could do this:
> > >
> > > If App.PrevInstance Then Exit Sub
> > >
> > > Any ideas how this is done in ruby?
> > >
> > > Ta muchly
> > >
> >
> > --
> >
> > All the best
> > Glenn
> > Aylesbury, UK
> >
>

--
* J *
  ~

--

All the best
Glenn
Aylesbury, UK