Announcement

Collapse
No announcement yet.

Tip: Prev. inst.and shared mem.

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Tip: Prev. inst.and shared mem.

    Not that i build it but;

    Register a global class and set it's extra bytes to desired length.
    This might be a trick to detect a previous instance and have the ab. to share data.

    I know Windows other than NT will only have 40bytes!
    NT has not this small limmit.

    Maybe a good feature under NT?



    #2
    You want to share data among multiple Windows of the same class in the same thread of the same process? (Is this Win-32?)

    The data are aleady shared. If you need data unique to each Window, that's where you use the WindowExtra field. Any size limitation on the number of extra bytes is easily overcome: just save a (four-byte) pointer to a block you allocate on receipt of the WM_CREATE message.

    MCM
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


      #3
      Here is one sample how it can be done - allowing only one instance to run. The idea has been around some time - make a search in the net. Works under Win9x/NT 4 (at least).

      Lasse Rantanen
      [email protected]

      Code:
      #COMPILE EXE
      #INCLUDE "WIN32API.INC"
       
      %IDCLOSE                = 10000
       
      %PAGE_READONLY          = &H002 ' Defines for these constants are missing from PB/DLL include files.
       
      GLOBAL hFile AS LONG
       
      DECLARE CALLBACK FUNCTION DlgProc
       
      '==============================================================================
      FUNCTION PBMAIN() AS LONG
       
          LOCAL hDlg      AS LONG
          LOCAL szMapName AS ASCIIZ*16
       
          szMapName = "MyAppsName" ' Make sure this is unique
       
          hFile = CreateFileMapping(&HFFFFFFFF, _
                                    BYVAL %NULL, _
                                    %PAGE_READONLY , _
                                    0, _
                                    10, _
                                    szMapName)
       
          IF (hFile > 0) AND (GetLastError() = %ERROR_ALREADY_EXISTS) THEN
              MSGBOX "Only one instance allowed!", _
                      %MB_OK OR %MB_ICONSTOP, _
                      szMapName
              UnmapViewOfFile hFile
              EXIT FUNCTION
          END IF
       
          DIALOG NEW  %HWND_DESKTOP, "Only Allowed Instance", _
                      240, 120, 150, 60, _
                      %WS_CAPTION + %WS_SYSMENU, TO hDlg
       
          CONTROL ADD BUTTON, hDlg, %IDCLOSE, "Close", _
                              35, 40, 80, 14, _
                              %WS_TABSTOP
       
          DIALOG SHOW MODAL hDlg, CALL DlgProc
       
      END FUNCTION
       
      '==============================================================================
      CALLBACK FUNCTION DlgProc
       
          SELECT CASE CBMSG
       
              CASE %WM_COMMAND
       
                  SELECT CASE CBWPARAM
       
                      CASE %IDCLOSE
       
                          IF hFile>0 THEN UnmapViewOfFile hFile
       
                          DIALOG END CBHNDL
       
                   END SELECT
          END SELECT
      END FUNCTION
      ------------------


      [This message has been edited by LRantanen (edited March 05, 2000).]

      Comment


        #4
        Oops - forgot the closing [/code] tag and also noticed that I'm not talking exactly the same thing as E B Knoppert. However, this is also using shared memory and allowing only one instance to run - so maybe this qualify as a branch in this thread.

        Lasse Rantanen
        [email protected]

        ------------------

        Comment


          #5
          Lasse --

          > Oops - forgot the closing [/code] tag

          You can always go back and edit a post that contains an error... just click the little "pencil and paper" icon to the right of the post date/time.

          It's a little tricky sometimes... If the post already contains {code} tags you'll find that you have to remove the html tags (in angle brackets) and re-type the code and /code tags (in square brackets). That's a bug in the UBBS software.

          -- Eric

          ------------------
          Perfect Sync: Perfect Sync Development Tools
          Email: mailto:[email protected][email protected]</A>

          "Not my circus, not my monkeys."

          Comment


            #6
            Thanks Eric,

            went and did that.

            Lasse Rantanen
            [email protected]

            ------------------

            Comment


              #7
              I was thinking about two things in one procedure.

              Creating a global(!) class is noticable from another instance.
              AND, it handles data, why shouldn't i take that opportunity?

              Sure, a dozen diff. methods for this, Mutexes whatever.
              just another tip..


              ------------------

              Comment


                #8
                Sorry E B, at the first reading I misunderstood you. Just after hitting that Submit Reply button I realized I was talking about different thing.

                BTW, what do you mean with a global class? A class registered with CS_GLOBALCLASS style? A class usable by every process? A couple of quotes - first one from a MSDN technical article "Window Classes in Win32" by Kyle Marsh.

                16-BIT versions of Windows such as Windows 3.1 gave real meaning to application global classes. A DLL or application could register an application global class that any other DLL or application on the system could use. Thus, an application global class was a global class registered by an application instead of the system.

                Application global classes are quite different in Win32. An application global class is a class that is available to all parts of a process.
                MS Platform SDK defines

                An application global class is a window class registered by an executable or dynamic-link library (.dll) that is available to all other modules in the process.
                Then documentation describes how under NT you can write a DLL and register it under a certain registry key. Then every process loads that DLL and can use the application global class defined in it. As far as I understand this works only under NT.

                IMHO, using this technique to detect previous instance will work only under NT and will require usage of a DLL and sounds somewhat complicated for this purpose.

                Back to my posting. I realize there are other ways to prevent multiple instances and that what I supplied was just another tip. However, I haven't seen any supplied in these forums so after reading your message I thought to post one, because I thought that was what you were after. If I unintentionally offended you, I apologize.

                Lasse Rantanen
                [email protected]

                ------------------


                [This message has been edited by LRantanen (edited March 05, 2000).]

                Comment


                  #9
                  Lasse,
                  This was written before your last reply;

                  First, i think your solution is much better.
                  Didn't know that it was that easy, never used it before.
                  I was planning to test this soon to increase filereading speed.
                  (Lot's of seeks, ANYONE A SPEEDY SUGGESTION?)

                  But, we both have a problem.

                  If the app crashes, we are stuck with a 'flag' for prev. instance.

                  In win2000, the class remains, even while the DLL/EXE is closed.

                  Filemapping; (MSDN)

                  To fully close a file-mapping object,
                  an application must unmap all mapped views of the
                  file-mapping object by calling UnmapViewOfFile,
                  and close the file-mapping object handle by calling CloseHandle.
                  The order in which these functions are called does not matter.
                  The call to UnmapViewOfFile is necessary because mapped views
                  of a file-mapping object maintain internal open handles to the object,
                  and a file-mapping object will not close until all open handles to it are closed.

                  Note To guard against an access violation,
                  use structured exception handling to protect any code that
                  writes to or reads from a memory mapped view. For more information,
                  see Reading and Writing.

                  Let's forget the global class stuff, it wasn't the best idea.
                  (Therefore i posted it here..)


                  ------------------

                  Comment


                    #10
                    E B,
                    that is a problem when mapping files into memory. You should carefully release/close all handles. In case of crash you are more or less out of luck, AFAIK. You have to try to catch as many errors as you can and close all handles opened so far.

                    Glad there is someone else struggling with this matter

                    Lasse Rantanen
                    [email protected]

                    ------------------

                    Comment


                      #11
                      (Edited by Administrator)

                      Have you thought about this little silly *******?
                      Easy to implement, no sideeffects(?).
                      Your first lines of code in the application will give you
                      a chance to detect another instance of the program.
                      The RegisterWindowMessage function is typically used to
                      register messages for communicating between two cooperating
                      applications.

                      If two different applications register the same message string,
                      the applications return the same message value. The message
                      remains registered until the session ends.
                      <font face="Courier New, Courier" size="3"><pre>
                      IsRunning& = RegisterWindowMessage("SPID_SLAV")
                      If SendMessage(%HWND_BROADCAST,IsRunning&,0&,0&)<> 0 then
                      Quit
                      End if
                      </pre></font>
                      I have not tried it but woud like opinions.
                      Like: Will there be a timout if no-one in the other end?


                      ------------------
                      Fred
                      mailto:[email protected][email protected]</A>
                      http://www.oxenby.se

                      Fred
                      mailto:[email protected][email protected]</A>
                      http://www.oxenby.se

                      Comment


                        #12
                        I like to do
                        Open "Log" For Binary Lock Read Write
                        If, when a program starts, you are not able to open a file - means there is another instance

                        ------------------

                        Comment


                          #13
                          Fred,

                          isn't following what happens:

                          RegisterWindowMessage -> a new message is registered
                          SendMessage(%HWND_BROADCAST,...) -> Window under construction responds to that message, so actually even the first instance does not start.

                          At least following behaves so
                          Code:
                          FUNCTION PBMAIN() AS LONG
                           
                              LOCAL hDlg      AS LONG
                           
                              IsRunning& = RegisterWindowMessage("SPLID_SLAV")
                              IF SendMessage(%HWND_BROADCAST,IsRunning&,0&,0&)<> 0 THEN
                                  MSGBOX "Only one instance allowed!"
                                  EXIT FUNCTION
                              END IF
                           
                              DIALOG NEW  %HWND_DESKTOP, "Only Allowed Instance", _
                                          240, 120, 150, 60, _
                                          %WS_CAPTION + %WS_SYSMENU, TO hDlg
                           
                              DIALOG SHOW MODAL hDlg, CALL DlgProc
                              
                          END FUNCTION
                          I am not so familiar w/ DDT so if I am doing something wrong above, let me know.

                          Lasse Rantanen
                          [email protected]


                          ------------------




                          [This message has been edited by LRantanen (edited March 06, 2000).]

                          Comment


                            #14
                            It was a sloppy suggestion:
                            First: The returnvalue from IsRunning-test should not be
                            False or True. It should be some predefined value.
                            Second: It seems that DDT-engine always return "1"
                            whatever Returnvalue you assign.
                            Third: The methode works. Run one instance in the debugger and set breakpoint in DlgProc.
                            Then start a second instance and you will see that the broadcast
                            is handled. Unfortunatly not in DDT-engine
                            You have no "window" under creation, and your Msg-loop has to
                            be running to respond to this message
                            Code:
                            Your testprog modified
                            #Compile Exe
                            #Include "Win32Api.inc"
                            Global IsRunning&
                            
                            CallBack Function DlgProc
                             If CbMsg = IsRunning& Then
                              Function = 5&:Exit Function
                             End If
                            End Function
                            
                            Function PbMain() As Long
                            
                                Local hDlg      As Long
                            
                                IsRunning& = RegisterWindowMessage("SPLID_SLAV")
                                rc&= SendMessage(%HWND_BROADCAST,IsRunning&,0&,0&)
                                #Debug Print Format$(rc&)
                                If rc& = 5 Then
                                    MsgBox "Only one instance allowed!"
                                    Exit Function
                                End If
                            
                                Dialog New  %HWND_DESKTOP, "First Instance", _
                                            240, 120, 150, 60, _
                                            %WS_CAPTION + %WS_SYSMENU, To hDlg
                            
                                Dialog Show Modal hDlg, Call DlgProc
                            
                            End Function

                            ------------------
                            Fred
                            mailto:[email protected][email protected]</A>
                            http://www.oxenby.se



                            [This message has been edited by Fred Oxenby (edited March 06, 2000).]
                            Fred
                            mailto:[email protected][email protected]</A>
                            http://www.oxenby.se

                            Comment


                              #15
                              RegisterWindowMessage really works, but it's seems to me that it's necessary to write something like this
                              Code:
                              #Compile Exe
                              #Include "Win32Api.inc"
                              Global IsRunning&
                              
                              CallBack Function DlgProc
                               Select Case CbMsg
                                  Case %WM_INITDIALOG
                                     SendMessage %HWND_BROADCAST, IsRunning&, 0&, 0&
                                  Case IsRunning&
                                     PostMessage CbHndl, %WM_USER + 999, 0, 0
                                  Case %WM_USER + 999
                                     Dialog End CbHndl
                                     MsgBox "Only one instance is allowed"
                               End Select
                              End Function
                              
                              Function PbMain() As Long
                                  Local hDlg      As Long
                                  IsRunning& = RegisterWindowMessage("SPLID_SLAV")
                                  Dialog New  %HWND_DESKTOP, "First Instance", _
                                              240, 120, 150, 60, _
                                              %WS_CAPTION + %WS_SYSMENU, To hDlg
                                  Dialog Show Modal hDlg, Call DlgProc
                              End Function

                              ------------------

                              Comment


                                #16
                                RE: RegisterWindowMessage

                                Correct me if I'm wrong but the message registered is valid until
                                the Windows session ends. I don't know if this will cause any problems on
                                systems that are seldom shut down but you should be aware of it.
                                Seems it would be more of an issue on a development systems??

                                James


                                ------------------


                                [This message has been edited by jcfuller (edited March 06, 2000).]

                                Comment


                                  #17
                                  James, the idea is to have someone answering your broadcast.
                                  But it turns out that returnvalue ALWAYS is "1" whether it
                                  is someone handling the message or not.
                                  My assumption it was only the DDT-engine doing this was also
                                  wrong.
                                  The idea was to send this broadcast before you create any
                                  windows, and it fell flat to the ground....
                                  It will work, but you have to create a window,start the message-
                                  loop, register TWO windowmessages (a send and a reply-message)
                                  It will work nicely to communicate beetween two applications
                                  but doesnot seem to qualify as an easy way to detect previous
                                  instances.


                                  ------------------
                                  Fred
                                  mailto:[email protected][email protected]</A>
                                  http://www.oxenby.se

                                  Fred
                                  mailto:[email protected][email protected]</A>
                                  http://www.oxenby.se

                                  Comment


                                    #18
                                    For prev. inst. i do have some VB code to walk through the processes, this might be the best solution..


                                    ------------------

                                    Comment

                                    Working...
                                    X
                                    😀
                                    🥰
                                    🤢
                                    😎
                                    😡
                                    👍
                                    👎