Help getting Dot Net 4 to work in Purebasic

Just starting out? Need help? Post your questions and find answers here.
Project Mayu
User
User
Posts: 20
Joined: Sun Mar 06, 2011 4:58 pm

Re: Help getting Dot Net 4 to work in Purebasic

Post by Project Mayu »

This is not the C++ source that I used, but it also loads Dot Net 4 from C++ http://blogs.msdn.com/b/msdnforum/archi ... ive-c.aspx

With a native exe you can encrypt the Dot Net Metadata into your EXE, or have the rest of the app on the internet, and that means new version each time they load the app. Obviously if you don't encrypt people can look-up the header and extract it, since the header contains the length of the Dot Net Data.

Anyway its more about user friendly checks before app start-up, as it seems to be common for people to un-install components needed by my apps, and if I did not do this, the user is presented with a crash message that is not usefull to them, and causes extra support on me.
User avatar
Rings
Moderator
Moderator
Posts: 1435
Joined: Sat Apr 26, 2003 1:11 am

Re: Help getting Dot Net 4 to work in Purebasic

Post by Rings »

ha, next step reached. the code loads the dll now via the byte-array load_3 method

Code: Select all

Interface ICLRMetaHost
  QueryInterface(a.l, b.l)
  AddRef()
  Release()
  GetRuntime(a.l, b.l, c.l)
  GetVersionFromFile(a.l, b.l, c.l)
  EnumerateInstalledRuntimes(a.l)
  EnumerateLoadedRuntimes(a.l, b.l)
  RequestRuntimeLoadedNotification(a.l)
  QueryLegacyV2RuntimeBinding(a.l, b.l)
  ExitProcess(a.l)
EndInterface

Interface ICLRRuntimeInfo
  QueryInterface(a.l, b.l)
  AddRef()
  Release()
  GetVersionString(a.l, b.l)
  GetRuntimeDirectory(a.l, b.l)
  IsLoaded(a.l, b.l)
  LoadErrorString(a.l, b.l, c.l, d.l)
  LoadLibrary(a.l, b.l)
  GetProcAddress(a.l, b.l)
  GetInterface(a.l, b.l, c.l)
  IsLoadable(a.l)
  SetDefaultStartupFlags(a.l, b.l)
  GetDefaultStartupFlags(a.l, b.l, c.l)
  BindAsLegacyV2Runtime()
  IsStarted(a.l, b.l)
EndInterface

Interface ICorRuntimeHost ; Common Language Runtime Hosting Interface
  QueryInterface(riid.l,ppvObj.l)
  AddRef()
  Release()
  CreateLogicalThreadState()
  DeleteLogicalThreadState()
  SwitchInLogicalThreadState(pFiberCookie.l)
  SwitchOutLogicalThreadState(pFiberCookie.l)
  LocksHeldByLogicalThread(pCount.l)
  MapFile(hFile.l,hMapAddress.l)
  GetConfiguration(pConfiguration.l)
  Start()
  Stop()
  CreateDomain(pwzFriendlyName.p-unicode,*pIdentityArray.IUnknown,pAppDomain.l)
  GetDefaultDomain(pAppDomain.l)
  EnumDomains(hEnum.l)
  NextDomain(hEnum.l,pAppDomain.l)
  CloseEnum(hEnum.l)
  CreateDomainEx(pwzFriendlyName.p-unicode,*pSetup.IUnknown,*pEvidence.IUnknown,pAppDomain.l)
  CreateDomainSetup(pAppDomainSetup.l)
  CreateEvidence(pEvidence.l)
  UnloadDomain(*pAppDomain.IUnknown)
  CurrentDomain(pAppDomain.l)
EndInterface

Interface Int__Assembly
  GetToString()
  Equals(a)
  GetHashCode()
  GetType()
  CodeBase()
  EscapedCodeBase()
  GetName()
  GetName_2(a)
  GetFullName()
  GetEntryPoint()
  GetType_2(a)
  GetType_3(a,b)
  GetExportedTypes()
  GetTypes()
  GetManifestResourceStream(a,b)
  GetManifestResourceStream_2(a)
  GetFile(a)
  GetFiles()
  GetFiles_2(a)
  GetManifestResourceNames()
  GetManifestResourceInfo(a)
  GetLocation()
  GetEvidence()
  GetCustomAttributes(a,b)
  GetCustomAttributes_2(a)
  IsDefined(a,b)
  GetObjectData(a,b)
  add_ModuleResolve(a)
  remove_ModuleResolve(a)
  GetType_4(a,b,c)
  GetSatelliteAssembly(a)
  GetSatelliteAssembly_2(a,b)
  LoadModule(a,b)
  LoadModule_2(a,b,c)
  CreateInstance(a)
  CreateInstance_2(a,b)
  CreateInstance_3(a,b,c,d,e,f,g)
  GetLoadedModules()
  GetLoadedModules_2(a)
  GetModules()
  GetModules_2(a)
  GetModule(a)
  GetReferencedAssemblies()
  GetGlobalAssemblyCache()
EndInterface

Interface Int__AppDomain
  QueryInterface(riid.l,ppvObj.l)
  AddRef()
  Release()
  Hidden1()
  Hidden2()
  Hidden3()
  Hidden4()
  GetToString()
  Equals(a)
  GetHashCode()
  GetType()
  InitializeLifetimeService()
  GetLifetimeService()
  GetEvidence()
  add_DomainUnload(a)
  remove_DomainUnload(a)
  add_AssemblyLoad(a)
  remove_AssemblyLoad(a)
  add_ProcessExit(a)
  remove_ProcessExit(a)
  add_TypeResolve(a)
  remove_TypeResolve(a)
  add_ResourceResolve(a)
  remove_ResourceResolve(a)
  add_AssemblyResolve(a)
  remove_AssemblyResolve(a)
  add_UnhandledException(a)
  remove_UnhandledException(a)
  DefineDynamicAssembly(a,b)
  DefineDynamicAssembly_2(a,b,c)
  DefineDynamicAssembly_3(a,b,c)
  DefineDynamicAssembly_4(a,b,c,d,e)
  DefineDynamicAssembly_5(a,b,c,d)
  DefineDynamicAssembly_6(a,b,c,d,e,f)
  DefineDynamicAssembly_7(a,b,c,d,e,f)
  DefineDynamicAssembly_8(a,b,c,d,e,f,g)
  DefineDynamicAssembly_9(a,b,c,d,e,f,g,h)
  CreateInstance(a,b)
  CreateInstanceFrom(a,b)
  CreateInstance_2(a,b,c)
  CreateInstanceFrom_2(a,b,c)
  CreateInstance_3(a,b,c,d,e,f,g,h,i)
  CreateInstanceFrom_3(a,b,c,d,e,f,g,h,i)
  Load(a)
  Load_2.i(a.p-bstr)
  Load_3(a)
  Load_4(a,b)
  Load_5(a,b,c)
  Load_6(a,b)
  Load_7(a,b)
  ExecuteAssembly(a,b)
  ExecuteAssembly_2(a)
  ExecuteAssembly_3(a,b,c)
  GetFriendlyName()
  GetBaseDirectory$()
  GetRelativeSearchPath()
  GetShadowCopyFiles()
  GetAssemblies()
  AppendPrivatePath(a)
  ClearPrivatePath()
  SetShadowCopyPath(a)
  ClearShadowCopyPath()
  SetCachePath(a)
  SetData(a,b)
  GetData(a)
  SetAppDomainPolicy(a)
  SetThreadPrincipal(a)
  SetPrincipalPolicy(a)
  DoCallBack(a)
  GetDynamicDirectory()
EndInterface

pClrHost.ICLRMetaHost
pRunInfo.ICLRRuntimeInfo
pRuntimeHost.ICorRuntimeHost
pDomain.IUnknown
myAppDomain.Int__AppDomain
loadedAssembly.Int__Assembly

corlib.i = OpenLibrary(#PB_Any, "mscoree.dll")
If corlib <> 0
  MessageRequester("Test","It's Open")
  
;   Ergebnis = ExamineLibraryFunctions(corlib)
;   
;   nochmals:
;   FN.s= LibraryFunctionName()
;   Debug FN
;   n=NextLibraryFunction()
;   If n<>0 
;     Goto nochmals
;   EndIf  
    
;     hr.i = CallFunction(corlib,"GetCORVersion")
;    MessageRequester("CorVersion",Str(hr))
  
  hr.i = CallFunction(corlib,"CLRCreateInstance",?CLSID_CLRMetaHost,?IID_ICLRMetaHost,@pClrHost)
  If hr = #S_OK
    MessageRequester("Text","Bind")
    version.s = "v4.0.30319"
    hr = pClrHost\GetRuntime(@version,?IID_ICLRRuntimeInfo,@pRunInfo)
    If hr = #S_OK
      MessageRequester("Test","Have Runtime")
      fLoadable.l
      hr = pRunInfo\IsLoadable(@fLoadable)
      If hr = #S_OK
        If fLoadable = 1
          hr = pRunInfo\GetInterface(?CLSID_CorRuntimeHost,?IID_ICorRuntimeHost,@pRuntimeHost)
          If hr = #S_OK
            MessageRequester("Test","Runtime loaded")
            hr = pRuntimeHost\Start()
            If hr = #S_OK
              hr = pRuntimeHost\CreateDomain("MyDomain",0,@pDomain)
              If hr = #S_OK
                MessageRequester("Test","Got domain")
                myAppDomain = pDomain
                hr = pDomain\QueryInterface(?IID_AppDomain,@myAppDomain)
                If hr = #S_OK
                  MessageRequester("Test","Got interface to domain")
                  
                  
                  
        
                 
                 temp.s = ".\Test\Test\bin\Release\Test.dll";+Chr(0)+Chr(0)
                 temp.s =GetCurrentDirectory() + "TestDotNet4.dll"
                 Debug "file=" + temp
                 FL=FileSize(Temp)
                 If FL >0
                   Mem=AllocateMemory(FL)
                   ReadFile(10,Temp)
                   ReadData(10,mem,FL)
                   CloseFile(10)
                   Debug FL
                 Else
                   MessageRequester("Test","dotnet dll not found !"  )
                   End
                EndIf  
                
              
                 rgsabound.SAFEARRAYBOUND
                 psa.i;SAFEARRAY PTR
                 rgsabound\lLBound = 0
                 rgsabound\cElements = FL
                 
                 psa = SafeArrayCreate_(#VT_UI1, 1, rgsabound);Create a safearray one dimension, type byte
                 ;Debug "psa="+Str(psa)
                 SafeArrayLock_(psa)
                 ppData.i
                 result=SafeArrayAccessData_(psa, @ppData) ;get a pointer to the data
                 Debug "ppdata="+Str(ppdata)
                 CopyMemory(mem, ppdata, fl); copy the dll bytes into the safearray 
                 
                 loadedAssembly = myAppDomain\Load_3(psa)
                 SafeArrayUnaccessData_(psa)
                
                  If loadedAssembly = #S_OK
                    MessageRequester("Test","ExecuteAssembly")
                    Goto Cleanup
                  Else
                    MessageRequester("Test","Error loading assembly "+Str(hr) + " " + Hex(hr))
                  EndIf
                  Goto Cleanup
                  
      LoadError:
                  MessageRequester("Test", "Load error " + ErrorMessage())
      Cleanup:
                  myAppDomain\Release()
                  myAppDomain = Null
                     
                  SafeArrayUnlock_(psa)
                  SafeArrayDestroy_(psa)
                      
                      
              Else
                      MessageRequester("Test", "Unable to get interface to domain")
                    EndIf
                pDomain\Release()
                pDomain = Null
              EndIf
              pRuntimeHost\Stop()
            EndIf
            pRuntimeHost\Release()
            pRuntimeHost = Null
          EndIf
        Else
          MessageRequester("Test","Dot Net 4.0 can not be loaded")
        EndIf
      EndIf
      pRunInfo\Release()
      pRunInfo = Null
    Else
      MessageRequester("Error",Hex(hr))
    EndIf
    pClrHost\Release()
    pClrHost = Null
  Else
    MessageRequester("Error",Hex(hr))
  EndIf
  CloseLibrary(corlib)
  corlib = Null
Else
  MessageRequester("Test", "Not Open")
EndIf

DataSection
  IID_ICLRMetaHost:
    Data.l $D332DB9E
    Data.w $B9B3, $4125
    Data.b $82, $07, $A1, $48, $84, $F5, $32, $16 
   
  CLSID_CLRMetaHost: 
    Data.l $9280188d
    Data.w $e8e, $4867
    Data.b $b3, $c, $7f, $a8, $38, $84, $e8, $de
   
  IID_ICLRRuntimeInfo:
    Data.l $BD39D1D2
    Data.w $BA2F, $486a
    Data.b $89, $B0, $B4, $B0, $CB, $46, $68, $91
   
  CLSID_CorRuntimeHost:
    Data.l $cb2f6723
    Data.w $ab3a, $11d2
    Data.b $9c, $40, $00, $c0, $4f, $a3, $0a, $3e 

  IID_ICorRuntimeHost:  ; {CB2F6722-AB3A-11D2-9C40-00C04FA30A3E}
    Data.l $CB2F6722
    Data.w $AB3A,$11D2
    Data.b $9C,$40,$0,$C0,$4F,$A3,$A,$3E
   
  IID_AppDomain:  ; {05F696DC-2B29-3663-AD8B-C4389CF2A713}
    Data.l $05F696DC
    Data.w $2B29,$3663
    Data.b $AD,$8B,$C4,$38,$9C,$F2,$A7,$13
   
  CLSID_AppDomain:  ;{5FE0A145-A82B-3D96-94E3-FD214C9D6EB9}
    Data.l $5FE0A145
    Data.w $A82B,$3D96
    Data.b $94,$E3,$FD,$21,$4C,$9D,$6E,$B9
   
  EndDataSection
SPAMINATOR NR.1
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Re: Help getting Dot Net 4 to work in Purebasic

Post by SFSxOI »

Haa HA! so it was something with loading the .dll then, the bstr thing maybe in load_2 ? I saw the absence of the safearray when I looked at the C++ code that was provided, wasn't sure if what was used originally was like that or not.

Rings, I used a different folder, compiled in unicode - definately a unicode critter, and got this so it seemed to get all the way through with no error messages:

Code: Select all

file=J:\PureBasic 4.60\dotnet4\TestDotNet4.dll
11264
ppdata=2215520

which looks like the expcted debugs from the:

Debug "file=" + temp
Debug FL
Debug "ppdata="+Str(ppdata)

which looks like what it was set up to give at those points

then I got the "MessageRequester("Test","ExecuteAssembly")" , so clicked OK and nothing after that, not sure what to expect from it exactly but seemed to get all the way through without error messages. I put in a debug at the 'CloseLibrary' and looks like it got to there OK then ended, no error's

Did you get it to do anything confirmationally useful?
The advantage of a 64 bit operating system over a 32 bit operating system comes down to only being twice the headache.
Project Mayu
User
User
Posts: 20
Joined: Sun Mar 06, 2011 4:58 pm

Re: Help getting Dot Net 4 to work in Purebasic

Post by Project Mayu »

Whats left, is the part I have no idea on how to do in Purebasic, create an instance of the class and execute a method in it.
I am guessing everyone is using the source from the Powerbasic page, so that would be "Class1" and Method "Hello" with a parameter of String "name"
User avatar
Rings
Moderator
Moderator
Posts: 1435
Joined: Sat Apr 26, 2003 1:11 am

Re: Help getting Dot Net 4 to work in Purebasic

Post by Rings »

Yes, Executing the code is the next step.
hopefully we got this running
SPAMINATOR NR.1
Post Reply