Results 1 to 18 of 18

Thread: Communicate between separate program through ini file

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2012
    Posts
    433

    Communicate between separate program through ini file

    I made VB6 program and C# program.
    Those 2 program should communicate with each other through Profile(Ini file).
    Once VB6 write flag(for example "N") in the ini and call C# program, which do something.
    If C# program terminate its work, write flag in the ini file and terminate process by itself.
    While C# do its work, VB6 check if the flag in the ini file become "Y".
    VB6 check this at every 0.5sec in the loop.
    Read/Write of ini is performed by WritePrivateProfileString and GetPrivateProfileString.
    But I'm worring that some kind of concurrent access of ini file by 2 program(VB6 program and C# program), which may generate some undesirable result.
    Can I lock ini file while one process is writting?
    If possible, how could I check if the ini file is locked from the counterpart(another) program?

  2. #2
    PowerPoster dilettante's Avatar
    Join Date
    Feb 2006
    Posts
    24,487

    Re: Communicate between separate program through ini file

    I believe those APIs already do a "hang on locked file, lock, batch update, unlock" on writes and a "hang on locked file, lock, batch read, unlock" on reads.

    That's the main reason INI file performance is so bad when used for normal purposes.


    Why not just use one of the many IPC mechanisms Windows offers instead?

  3. #3

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2012
    Posts
    433

    Re: Communicate between separate program through ini file

    Thanks for answer.
    You mean WritePrivateProfileString and GetPrivateProfileString function already handle locking issue.
    If so, I don't have to worry about any error.
    Do you mean "ini performance is bad " speed is low?
    In this mechanism, speed is not very important.

  4. #4
    PowerPoster dilettante's Avatar
    Join Date
    Feb 2006
    Posts
    24,487

    Re: Communicate between separate program through ini file

    Normally the terrible performance of INI operations doesn't matter, but you said you will be polling for changes.

    You can always run a test and see just how many cycles you will burn doing this.

  5. #5
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,687

    Re: Communicate between separate program through ini file

    Actually, no you DO need to worry about handling it... well, sort of. Locking is implemented by the API, so you don't need to worry about locking the file. What you need to worry about is handling the exception when it occurs... specifically, when one system has the file locked for a write, and the other tries to access it for a read, it will result in a "Unable to open file, it is locked by another process" or something along those lines. If you're checking the file every half-second... then I'd argue speed IS an issue, epecially if it takes longer than that to write the flag back out to the file.


    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  6. #6
    PowerPoster
    Join Date
    Feb 2012
    Location
    West Virginia
    Posts
    14,206

    Re: Communicate between separate program through ini file

    Back in the 90s my company created some programs that needed to talk to one another in a very minor way. We decided to use an INI file for this purpose and it worked just fine. Software has been running at 100s of locations for over 15 years now, not aware of this ever causing a problem.

  7. #7
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: Communicate between separate program through ini file

    Quote Originally Posted by jdy0803 View Post
    VB6 check this at every 0.5sec in the loop.
    Are you using DoEvents inside that loop? If so, I strongly recommend that you avoid that rather inelegant method. Instead, use a Timer or some other means of polling that does not involve loops and DoEvents. As suggested by dilettante, one or more of the IPC mechanisms outlined in Interprocess Communications may be viable for you.
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  8. #8

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2012
    Posts
    433

    Re: Communicate between separate program through ini file

    Quote Originally Posted by Bonnie West View Post
    Are you using DoEvents inside that loop? If so, I strongly recommend that you avoid that rather inelegant method. Instead, use a Timer or some other means of polling that does not involve loops and DoEvents. As suggested by dilettante, one or more of the IPC mechanisms outlined in Interprocess Communications may be viable for you.
    I use Sleep and DoEvents in the loop like this.

    Do
    Sleep 500
    bRet = CheckIniFileStatus 'Check flag written by C# program
    If bRet Then
    Exit Do
    DoEvents
    Loop

    If you don't recommend this way,.....which IPC mechanism would be better in order to communicate between 2 process made by VB6 and C#?

  9. #9
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: Communicate between separate program through ini file

    Quote Originally Posted by jdy0803 View Post
    If you don't recommend this way,.....which IPC mechanism would be better in order to communicate between 2 process made by VB6 and C#?
    Well, you could try either File Mapping or Pipes. You might also want to try one or more of the various Synchronization Functions.

    Can you elaborate on why you need your two programs to communicate with each other?
    Last edited by Bonnie West; Jan 24th, 2014 at 04:44 PM.
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  10. #10
    PowerPoster dilettante's Avatar
    Join Date
    Feb 2006
    Posts
    24,487

    Re: Communicate between separate program through ini file

    The best writeup I've found in the topic of thrashing on INI files is probably:

    INI file handling functions are not thread-safe

    The short answer is that this author recommends that you lock the INI file yourself. Of course he also says:

    Do *NOT* put wrapper functions around WritePrivateProfileString, etc, to lock/unlock before/after each function call to access the INI file.
    Which means adding your own explicit locking doesn't really work well for the case at hand at all.


    Considering that INI thrashing doesn't buy you notification so you have to thrash even harder using some polling technique, you may as well just look elsewhere for a solution.


    The best choice may be to punt and use the least common denominator IPC mechanism: IP. You could use either TCP or UDP, but probably TCP for reliable delivery. No matter what you develop in you almost always have a way to use async TCP/IP sockets.

  11. #11
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,892

    Re: Communicate between separate program through ini file

    First off - I agree with Dilettante that another IPC mechanism would be more appropriate than using an INI.

    That said, I'm curious as to what the reason might be for *NOT* putting a wrapper around INI API calls to lock/unlock access to the file (for example, waiting on a mutex). It's true that such a lock would only be useful against processes that are "playing fair" by respecting the lock, but that would appear to be the case with mechanisms other than system-based exclusive file locking (such as creating a .lock file as proposed in the article).

    In any case, using a file for IPC (INI or otherwise), while perhaps simpler to implement, seems to me to have unnecessarily high overhead, and is possibly more risky (e.g. due to Antivirus scanning interfering with the file locking) than other forms of IPC such as sockets. Of course, with sockets you then have to worry about software firewalls getting in the way, so I'm not sure that there is a perfect solution.

  12. #12
    PowerPoster
    Join Date
    Jun 2012
    Posts
    2,728

    Re: Communicate between separate program through ini file

    Why not just using WM_COPYDATA ?

  13. #13
    PowerPoster dilettante's Avatar
    Join Date
    Feb 2006
    Posts
    24,487

    Re: Communicate between separate program through ini file

    WM_COPYDATA could be an answer, but it means more (and more tricky) code. It also fails when process isolation is involved. Basically the technique is obsolete in the post-XP universe.

    IP sockets do raise firewall issues, but they have good support in almost all development environments.

    The obvious solutions would be Mailslots or Named Pipes, but VB6 doesn't have convenient support for either one. You can use them but it requires a bit of code and you still have to do polling.

  14. #14
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: Communicate between separate program through ini file

    Too bad, the OP didn't explain more clearly what he really needs this for...

    I have a slight suspicion, that it's simply about running (shelling) a C# compiled executable -
    and then just waiting for the completion of this other process (currently in a slow polling-loop).

    In his first post he wrote:
    ..."If C# program terminate its work, write flag in the ini file and terminate process by itself."
    and
    ..."VB6 check if the flag in the ini file become "Y". VB6 check this at every 0.5sec in the loop"

    To me, that seems like a typical use-case for "ShellAndWait" - maybe that's all the OP is looking for.

    Olaf

  15. #15

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2012
    Posts
    433

    Re: Communicate between separate program through ini file

    Quote Originally Posted by Bonnie West View Post
    Well, you could try either File Mapping or Pipes. You might also want to try one or more of the various Synchronization Functions.

    Can you elaborate on why you need your two programs to communicate with each other?
    My existing VB6 program is an imaging software used in the dental industry, which interface with various image sensor and too big to change with .NET language(C#).
    The C# program is a x-ray taking module that interface with image sensor of which manufacturer provide only .NET library.
    I couldn't make wrapper dll which VB6 program can call.
    That's why I made C# program and made interact VB6 and C# program each other.
    I have no idea how to implement File Mapping or Pipe in VB6.
    Can you give me more information regarding that?

  16. #16

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2012
    Posts
    433

    Re: Communicate between separate program through ini file

    Sorry, It seems I didn't explain clearly.
    If I explain again.....

    VB6 set flag in the ini file and generate C# program.
    VB6 wait until some flag is ON.
    C# program do its job and set flag in the ini in order to inform VB6 of some event.
    Actually, C# doesn't be terminated until VB6 kill C# program.
    In most case, VB6 check(read) the flag waiting in the loop.
    C# program write flag when some event occur in order to inform VB6 program.
    Last edited by jdy0803; Jan 27th, 2014 at 02:07 PM.

  17. #17
    PowerPoster
    Join Date
    Jan 2008
    Posts
    11,074

    Re: Communicate between separate program through ini file

    VB6 opens (or creates for first time) INI file and sets a flag in the INI file to OFF (I assume) and then Shells the C# program

    VB6 now enters a loop and reads this INI file looking for the same flag. If still OFF VB continues in loop. If ON VB does something

    Is this correct


    Anything I post is an example only and is not intended to be the only solution, the total solution nor the final solution to your request nor do I claim that it is. If you find it useful then it is entirely up to you to make whatever changes necessary you feel are adequate for your purposes.

  18. #18
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: Communicate between separate program through ini file

    Quote Originally Posted by jdy0803 View Post
    Actually, C# doesn't be terminated until VB6 kill C# program.
    If the C# program immediately terminates after doing its job, then as suggested by Schmidt, a Shell & Wait solution might be more suitable for you. However, if you are saying that the C# program doesn't promptly end when it's finished with its task, then one more approach you might want to try is to notify the VB6 program when the C# program completes its task via a registered Windows message.


    Code for the VB6 program:
    Code:
    Option Explicit     'Example code for a Form
    
    Public Sub Procedure()
        MsgBox "X-ray scanning done!", vbInformation
        Command1.Enabled = True
    End Sub
    
    Private Sub Command1_Click()
        If Subclass(hWnd) Then
            If Shell("C#.exe " & hWnd, vbNormalFocus) Then  'Pass the hWnd of this Form to the shelled app as a command line argument
                Command1.Enabled = False                    'If desired, disable the controls of this Form
            End If
        End If
    End Sub
    
    Private Sub Form_Load()
        Caption = "Click The Button To Shell Worker App"
    End Sub
    Code:
    Option Explicit     'Copy & paste all of this to a standard module named "modSubclass"
    
    'Both VB6 and C# apps must use the same string for RegisterWindowMessage
    'Any string will do just fine, as long as it's unique (like this GUID)
    Private Const MyGUID As String = "{07177563-9906-4116-839A-9ED6FE9A5E0E}"
    
    Private Const MSGFLT_ADD As Long = &H1
    Private Const WM_DESTROY As Long = &H2
    
    Private Declare Function DefSubclassProc Lib "comctl32.dll" Alias "#413" (ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Declare Function SetWindowSubclass Lib "comctl32.dll" Alias "#410" (ByVal hWnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long, Optional ByVal dwRefData As Long) As Long
    Private Declare Function RemoveWindowSubclass Lib "comctl32.dll" Alias "#412" (ByVal hWnd As Long, ByVal pfnSubclass As Long, ByVal uIdSubclass As Long) As Long
    Private Declare Function RegisterWindowMessageW Lib "user32.dll" (ByVal lpString As Long) As Long
    Private Declare Function ChangeWindowMessageFilter Lib "user32.dll" (ByVal Message As Long, ByVal dwFlag As Long) As Long
    
    Public Function Subclass(ByVal hWnd As Long) As Boolean
        Dim WMU_JOB_DONE As Long
    
       'Register a Windows message that this VB6 app will receive from the C# app when it's done
        WMU_JOB_DONE = RegisterWindowMessageW(StrPtr(MyGUID))
    
        If WMU_JOB_DONE Then
           'ChangeWindowMessageFilter API doesn't exist before Vista, so ignore possible errors
            On Error Resume Next
           'Add WMU_JOB_DONE to the User Interface Privilege Isolation (UIPI) message filter
            Subclass = ChangeWindowMessageFilter(WMU_JOB_DONE, MSGFLT_ADD)
            On Error GoTo 0
    
           'Start monitoring for the WMU_JOB_DONE message
            Subclass = SetWindowSubclass(hWnd, AddressOf SubclassProc, AddressOf SubclassProc, WMU_JOB_DONE)
        End If
    
        Debug.Assert Subclass
    End Function
    
    Private Function SubclassProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long, _
                                  ByVal uIdSubclass As Long, ByVal WMU_JOB_DONE As Long) As Long
        Select Case uMsg
            Case WMU_JOB_DONE: 'The C# app has just finished with its task. This app can now do whatever needs to be done next.
                               'But first, subclassing must be deactivated before resuming with the rest of the program.
                                WMU_JOB_DONE = RemoveWindowSubclass(hWnd, uIdSubclass, uIdSubclass):  Debug.Assert WMU_JOB_DONE
                               'The relevant public procedure can now be called here. For example:
                                Call Form1.Procedure
                               'Return a confirmation of successful message receipt (the return value should be a non-zero Long value)
                                SubclassProc = True
                                Exit Function
    
            Case WM_DESTROY:    WMU_JOB_DONE = RemoveWindowSubclass(hWnd, uIdSubclass, uIdSubclass):  Debug.Assert WMU_JOB_DONE
        End Select             'End subclassing if this window is destroyed (just in case the WMU_JOB_DONE was never received)
    
        SubclassProc = DefSubclassProc(hWnd, uMsg, wParam, lParam)
    End Function

    VB6 code that should be converted to C# code. Modify as necessary.
    Code:
    Option Explicit     'Port this VB6 code to C#
    
    'Both VB6 and C# apps must use the same string for RegisterWindowMessage
    'Any string will do just fine, as long as it's unique (like this GUID)
    Private Const MyGUID As String = "{07177563-9906-4116-839A-9ED6FE9A5E0E}"
    
    Private Declare Function RegisterWindowMessageW Lib "user32.dll" (ByVal lpString As Long) As Long
    Private Declare Function SendMessageW Lib "user32.dll" (ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    
    Private Sub Form_Click()
        Dim hWnd As Long, WMU_JOB_DONE As Long
    
       'Register a Windows message that this app will send to its parent VB6 app once it's done
        WMU_JOB_DONE = RegisterWindowMessageW(StrPtr(MyGUID))
    
        If WMU_JOB_DONE Then
           'Try obtaining the parent app's hWnd passed as a command line argument to this app
            On Error Resume Next
            hWnd = CLng(Command$)
            On Error GoTo 0
    
            If hWnd Then
               'Send a notification to the parent app in the form of a Windows message
               'A beep confirms whether the parent app successfully received the message
                If SendMessageW(hWnd, WMU_JOB_DONE, 0&, 0&) Then Beep
            End If
        End If
    End Sub
    
    Private Sub Form_Load()
        Caption = "Click Form To Notify Parent App That The Job Is Done"
    End Sub


    EDIT

    Yet another solution that you might find a lot easier than the subclassing code above was demonstrated in VB - Send a string between VB-created apps without using subclassing. You just need to adapt the technique there to make it work in your situation.
    Last edited by Bonnie West; Aug 1st, 2014 at 03:53 AM.
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width