* tests if the definition of reg free servers in an executable propagates
* throughout the entire process
* 2 servers are created, TestLibHW and TestLibW
* TestLibHW is dependent on TestLibW, and the executable depends on TestLibHW
* the registration of the 2 servers is made only in the executable manifest
* although TestLibHW instantiates a class of TestLibW, it uses the declaration
* of the executable manifest
LOCAL Source AS String
LOCAL Manifest AS String
LOCAL SafetyStatus AS String
LOCAL DefaultStatus AS String
LOCAL TempDir AS String
LOCAL DLLFullPath AS String
m.DefaultStatus = SET("Directory")
m.SafetyStatus = SET("Safety")
SET SAFETY OFF
* the folder can be safely emptied afterwards
m.TempDir = ADDBS(SYS(2023)) + "thread-dll-manifests"
IF !DIRECTORY(m.TempDir)
MKDIR (m.TempDir)
ENDIF
SET DEFAULT TO (m.TempDir)
* the executable main (and single) program source
TEXT TO m.Source NOSHOW
LOCAL Test AS TestLibHW.TestClass
m.Test = CREATEOBJECT("TestLibHW.TestClass")
MESSAGEBOX(m.Test.HelloWorld())
ENDTEXT
STRTOFILE(m.Source, "testexe.prg", 0)
* the first DLL class source
TEXT TO m.Source NOSHOW
DEFINE CLASS TestClass AS Session OLEPUBLIC
FUNCTION HelloWorld
LOCAL Test AS TestLibW.TestClass
m.Test = CREATEOBJECT("TestLibW.TestClass")
RETURN "Hello, " + m.Test.World() + "!"
ENDFUNC
ENDDEFINE
ENDTEXT
STRTOFILE(m.Source, "testlib-hw.prg", 0)
* build a project for it, and then the DLL itself
BUILD PROJECT "TestLibHW" FROM "testlib-hw.prg"
m.DLLFullPath = ADDBS(m.TempDir) + "testlibhw.dll"
BUILD DLL (m.DLLFullPath) FROM "TestLibHW" RECOMPILE
* unregister, to make sure we don't have it available in the registry
RUN REGSVR32 /u &DLLFullPath
* now, do the same for the second DLL
TEXT TO m.Source NOSHOW
DEFINE CLASS TestClass AS Session OLEPUBLIC
FUNCTION World
RETURN "World"
ENDFUNC
ENDDEFINE
ENDTEXT
STRTOFILE(m.Source, "testlib-w.prg", 0)
BUILD PROJECT "TestLibW" FROM "testlib-w.prg"
m.DLLFullPath = ADDBS(m.TempDir) + "testlibw.dll"
BUILD DLL (m.DLLFullPath) FROM "TestLibW" RECOMPILE
RUN REGSVR32 /u &DLLFullPath
* create the manifest
TEXT TO m.Manifest TEXTMERGE NOSHOW
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
type="win32"
name="Testing with reg free servers"
processorArchitecture="x86"
/>
<file name="testlibhw.dll">
<comClass clsid="{<<STREXTRACT(FILETOSTR("testlibhw.vbr"), "\CLSID = {", "}")>>}"
threadingModel="Apartment"
progid="testlibhw.testclass"
description="testlibhw.testclass" />
</file>
<file name="testlibw.dll">
<comClass clsid="{<<STREXTRACT(FILETOSTR("testlibw.vbr"), "\CLSID = {", "}")>>}"
threadingModel="Apartment"
progid="testlibw.testclass"
description="testlibw.testclass" />
</file>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" />
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
language="*"
processorArchitecture="x86"
publicKeyToken="6595b64144ccf1df"
/>
</dependentAssembly>
</dependency>
</assembly>
ENDTEXT
STRTOFILE(m.Manifest, "testexe.exe.manifest", 0)
BUILD PROJECT "TestExe" FROM "testexe.prg"
BUILD EXE TestExe.exe FROM TestExe RECOMPILE
* run as an independent process, the SxS on the manifest will be used
RUN TestExe.exe
LOCAL LaunchError AS Exception
* try to run in the VFP9 IDE process, the manifest won't be honored and the classes won't be found
TRY
DO TestExe.exe
CATCH TO m.LaunchError
MESSAGEBOX("Executable could not be launched from the IDE. Reported: " + m.LaunchError.Message)
ENDTRY
SET DEFAULT TO (m.DefaultStatus)
IF m.SafetyStatus == "ON"
SET SAFETY ON
ENDIF