DEFINE CLASS MyCom AS Session OLEPUBLIC FUNCTION Sayit(MyString as String) As String RETURN MyString ENDFUNC * useful method for reporting on runtime environment FUNCTION ShowEnv() As String LOCAL lcEnv TEXT TO lcEnv TEXTMERGE NOSHOW App Object Name: <<_vfp.Name>> App Object Full Name: <<_vfp.FullName>> COM Server Full Path Name: <<_vfp.ServerName>> App Start Mode: <<THIS.ShowStartMode()>> App Object Process ID: <<_vfp.ProcessId>> Thread ID: <<_vfp.ThreadId>> Automation Server Version: <<_vfp.Version>> VFP Version: <<VERSION()>> Unattended Server Mode: <<THIS.ShowUnattendedMode()>> Current Directory: <<SET("DEFAULT")+SYS(2003)>> Start Directory: <<SYS(2004)>> HOME(0): <<HOME(0)>> HOME(7): <<HOME(7)>> Resource File: <<SYS(2005)>> Config File/Location: <<SYS(2019)>> Temp File Path: <<SYS(2023)>> Path: <<SET("PATH")>> Operating System: <<OS()>> Computer Name/User: <<ID()>> PROGRAM(1): <<PROGRAM(1)>> PROGRAM(2): <<PROGRAM(2)>> ENDTEXT RETURN lcEnv ENDFUNC PROTECTED FUNCTION ShowStartMode() As String LOCAL lnMode, lcShowMode lnMode = _VFP.StartMode DO CASE CASE lnMode = 0 lcShowMode = [None] CASE lnMode = 1 lcShowMode = [Local Server] CASE lnMode = 2 lcShowMode = [Runtime EXE Server] CASE lnMode = 3 lcShowMode = [Runtime DLL Server] CASE lnMode = 4 lcShowMode = [VFP Runtime APP] CASE lnMode = 5 lcShowMode = [Runtime MTDLL Server] OTHERWISE lcShowMode = [] ENDCASE RETURN lcShowMode ENDFUNC PROTECTED FUNCTION ShowUnattendedMode() As String LOCAL lcMode, lcShowMode lcMode = SYS(2335) DO CASE CASE lcMode = "0" lcShowMode = [Enabled - Modal States Prohibited] CASE lcMode = "1" lcShowMode = [Disabled - Modal States Allowed] OTHERWISE lcShowMode = [] ENDCASE RETURN lcShowMode ENDFUNC ENDDEFINEIf you put the code above into a PRG and pull it into a project named comtest, compile it as an MTDLL, then call the ShowEnv() method from inside VFP, you get the same processID and threadID as the instance of VFP you are calling it from (a DLL is an in-process server, right?). Thy this at the command window and compare the ProcessID and ThreadID reported from each instance of the MTDLL to the ones for your instance of VFP:
CLEAR SET MEMOWIDTH TO 120 ? _vfp.ProcessId ? _vfp.ThreadId o=CREATEOBJECT("comtest.MyCom") ? o.ShowEnv() o2=CREATEOBJECT("comtest.MyCom") ? o2.ShowEnv() o=null o2=nullNow, be sure to issue the two lines above to null out the references, and let's try it a different way. If you go to Component Services on your computer and create an empty COM+ Application, add the same COM DLL to that Application as a Component, then call it in two different sessions just like above, you will get both instances with the same processID as each other (but different from the VFP instance, because the DLL is being called by COM+ services) and you will get two completely DIFFERENT threadIDs -- managed for you by COM+ services).