#!ruby # -*- mode: ruby; coding: utf-8 -*- # Last updated: <2022/08/17 02:06:52 +0900> # # ffi sample. use mutex. # # 二重起動の防止(1) - Advanced HSP # http://chokuto.ifdef.jp/advanced/singleton1.html # # Windows10 x64 21H2 + Ruby 2.6.10 p210 i386-mingw32 + ffi 1.15.5 x86-mingw32 # # not work Ruby 1.9.3 p551 i386-mingw32 + ffi 1.9.14 x86-mingw32 require "rubygems" require "ffi" module WinKernel extend FFI::Library ffi_lib :kernel32 ffi_convention :stdcall attach_function :CreateMutexW, [:long, :bool, :pointer], :ulong attach_function :ReleaseMutex, [:ulong], :bool attach_function :CloseHandle, [:ulong], :long # attach_function :GetLastError, [], :ulong end mutex_name = "rubyffimutexsample" ERROR_ALREADY_EXISTS = 183 mutex = WinKernel.CreateMutexW(0, false, mutex_name.encode("UTF-16LE")) # Add API.last_error #55 - Github Lab # https://githublab.com/repository/issues/cosmo0920/win32-api/55 # # GetLastError() is reset when calling Win32 API from Ruby. # FFI::LastError.winapi_error" is a good choice. begin # err = WinKernel.GetLastError # err = FFI::LastError.error err = FFI::LastError.winapi_error rescue => e puts "Error : This version of ffi does not support FFI::LastError.winapi_error." if mutex != 0 WinKernel.ReleaseMutex(mutex) WininKernel.CloseHandle(mutex) end exit end puts "Mutex : #{mutex}" puts "GetLastError : #{err}" if mutex == 0 or err == ERROR_ALREADY_EXISTS puts "already exists" exit else 10.times do |i| puts i sleep 1 end end if mutex != 0 WinKernel.ReleaseMutex(mutex) WinKernel.CloseHandle(mutex) end