Page 3 of 3

Re: OnlyOne Module Crossplattform

Posted: Sat Feb 22, 2014 7:51 pm
by Tenaja
DOH! On writing, not on reading...

Re: OnlyOne Module Crossplattform

Posted: Sat Feb 22, 2014 8:17 pm
by Tenaja
ts-soft wrote:On many windows-machines shortpathnames no more available. the creation is deactivated for performance reason on:
most server, most pcs using ssd, ...

Use

Code: Select all

param.s = #DQUOTE$ + "c:\Program Files\bla.txt" + #DQUOTE$
and not the shortnames.
BTW, that still writes short filenames.

The I believe the fname is getting shortened when you double-click it in the file manager, before it is turned into a parameter, so I do not have the option to "leave" it long.

Re: OnlyOne Module Crossplattform

Posted: Sat Feb 22, 2014 8:25 pm
by Tenaja
Tenaja wrote:DOH! On writing, not on reading...
Seems like that does not work; I had to do it on the reading side regardless if I wrote it in long format or not.

Re: OnlyOne Module Crossplattform

Posted: Mon Feb 24, 2014 5:15 am
by mestnyi
tell me that I should do this module, and it does nothing?

Re: OnlyOne Module Crossplattform

Posted: Mon Feb 24, 2014 3:59 pm
by Tenaja
mestnyi wrote:tell me that I should do this module, and it does nothing?
No, it works perfectly. Just make sure to use your correct Window ID. The only reason I needed to convert to long filename is for display purposes.

Re: OnlyOne Module Crossplattform

Posted: Thu Aug 13, 2015 9:39 pm
by Little John
Hi Thomas,

this module is very useful. Many thanks for sharing!

I included it in a program that I'm currently writing, and calling a new instance of the program seemed to work as expected, i.e.
- command line parameters of a new instance are passed to the original instance of the program
- the original instance is activated
- the new instance is terminated

However, I passed relative filenames as command line parameters to my program, and the program should convert them to absolute filenames, with the help of GetCurrentDirectory(). But that does not work as expected, because the current directory is not necessarily the same for all instances! As far as I found out, when launching a new instance, its current directory has to be passed to the original instance -- the same way as your code already does with the command line parameters. Here is your code with my additions -- maybe it can be improved:

Code: Select all

;======================================================================
; Module:          OnlyOne.pbi
;
; Author:          Thomas (ts-soft) Schulz
; Date:            Aug 13, 2015
; Version:         1.2a
;                  (handling of current directory added by Little John;
;                   tested on Windows 10)
; Target Compiler: PureBasic 5.2+
; Target OS:       All
; License:         Free, unrestricted, no warranty whatsoever
;                  Use at your own risk
; URL:             http://www.purebasic.fr/english/viewtopic.php?p=468905#p468905
;======================================================================


DeclareModule OnlyOne
   EnableExplicit
   
   Declare.i InitOne(wID,                                       ; ID of the main window.
                     OnlyOneName.s,                             ; Unique name for Lockfile.
                     CustomEvent = #PB_Event_FirstCustomValue,  ; User-defined event in which the parameters are processed.
                     TimerID = 1,                               ; TimerID to use.
                     TimeOut = 2000)                            ; Interval in ms, to check the passed parameter queries.
   
   Declare.i ReleaseOne()                                       ; Delete LockFile and removes Timer.
   
   Declare.s GetCurDir()
   
   Declare.s GetParameters()                                    ; The parameter string, separated with #LF$
EndDeclareModule


Module OnlyOne
   Global.i Event, win, timer
   Global.s LockFile, Paras
   
   
   Procedure TimerCB()
      Static oldtime = 0
      If oldtime = 0 : oldtime = Date() : EndIf
      Protected FF, time
      
      If FileSize(LockFile) > 0
         FF = ReadFile(#PB_Any, LockFile)
         If FF
            Paras = ""
            While Not Eof(FF)
               Paras + ReadString(FF) + #LF$
            Wend
            CloseFile(FF)
            FF = CreateFile(#PB_Any, LockFile)
            If FF
               CloseFile(FF)
            EndIf
            PostEvent(Event)
         EndIf
         CompilerSelect #PB_Compiler_OS
            CompilerCase #PB_OS_Windows
            CompilerDefault
            Else
               time = AddDate(oldtime, #PB_Date_Minute, 3)
               If time < Date()
                  oldtime = Date()
                  SetFileDate(LockFile, #PB_Date_Modified, Date())
               EndIf
         CompilerEndSelect
      EndIf
   EndProcedure
   
   
   Procedure.i ReleaseOne()
      RemoveWindowTimer(win, timer)
      UnbindEvent(#PB_Event_Timer, @TimerCB(), win, timer)
      ProcedureReturn DeleteFile(LockFile)
   EndProcedure
   
   
   Procedure.s GetCurDir()
      Protected f.i
      
      f = FindString(Paras, #LF$)
      ProcedureReturn Left(Paras, f-1)
   EndProcedure
   
   
   Procedure.s GetParameters()
      Protected f.i
      
      f = FindString(Paras, #LF$)
      ProcedureReturn Mid(Paras, f+1)
   EndProcedure
   
   
   Procedure InitOne(wID, OnlyOneName.s, CustomEvent = #PB_Event_FirstCustomValue, TimerID = 1, TimeOut = 2000)
      Protected.i FF, i, j, time, result = #False
      
      If Not IsWindow(wID)
         Debug "You have to open a window, before you call this function!"
         ProcedureReturn #False
      EndIf
      win = wID
      timer = TimerID
      Event = CustomEvent
      LockFile = GetTemporaryDirectory() + OnlyOneName
      
      CompilerSelect #PB_Compiler_OS
         CompilerCase #PB_OS_Windows
            Protected Mutex = CreateMutex_(0, 0, OnlyOneName)
            If GetLastError_() = #ERROR_ALREADY_EXISTS
               ReleaseMutex_(Mutex)
               CloseHandle_(Mutex)
            Else
               DeleteFile(LockFile)
            EndIf
         CompilerDefault
            time = AddDate(GetFileDate(LockFile, #PB_Date_Modified), #PB_Date_Minute, 5)
            If time < Date()
               DeleteFile(LockFile)
            EndIf
      CompilerEndSelect
      
      If FileSize(LockFile) = -1
         FF = CreateFile(#PB_Any, LockFile)
         If FF
            CloseFile(FF)
            AddWindowTimer(wID, TimerID, TimeOut)
            BindEvent(#PB_Event_Timer, @TimerCB(), wID, TimerID)
            Paras = ""
            j = CountProgramParameters()
            For i = 0 To j
               Paras + ProgramParameter(i) + #LF$
            Next
            Paras = GetCurrentDirectory() + #LF$ +
                    Left(Paras, Len(Paras) - 1)
            PostEvent(Event)
            HideWindow(wID, #False)
            result = #True
         EndIf
      Else
         FF = OpenFile(#PB_Any, LockFile, #PB_File_Append)
         If FF
            Paras = ""
            j = CountProgramParameters()
            For i = 1 To j
               Paras + ProgramParameter(i-1) + #LF$
            Next
            Paras = GetCurrentDirectory() + #LF$ +
                    Left(Paras, Len(Paras) - 1)
            WriteStringN(FF, Paras)
            CloseFile(FF)
         EndIf
         End
      EndIf
      
      ProcedureReturn result
   EndProcedure
EndModule


CompilerIf #PB_Compiler_IsMainFile
   EnableExplicit
   
   Enumeration #PB_Event_FirstCustomValue
      #Event_NewParams
   EndEnumeration
   
   OpenWindow(0, #PB_Ignore, #PB_Ignore, 640, 480, "Test", #PB_Window_MinimizeGadget|#PB_Window_Invisible)
   ListViewGadget(0, 10, 10, WindowWidth(0) - 20, WindowHeight(0) - 20)
   OnlyOne::InitOne(0, "Example_Application", #Event_NewParams)
   
   Define i, j, paras.s
   
   Repeat
      Select WaitWindowEvent()
         Case #PB_Event_CloseWindow
            OnlyOne::ReleaseOne()
            Break
            
         Case #Event_NewParams
            SetActiveWindow(0)
            CompilerIf #PB_Compiler_OS = #PB_OS_Windows
               ShowWindow_(WindowID(0), #SW_RESTORE)
               SetForegroundWindow_(WindowID(0))
            CompilerEndIf
            AddGadgetItem(0, -1, OnlyOne::GetCurDir())
            paras = OnlyOne::GetParameters()
            j = CountString(paras, #LF$)
            For i = 1 To j
               AddGadgetItem(0, -1, StringField(paras, i, #LF$))
            Next
      EndSelect
   ForEver
CompilerEndIf