microsoft / MixedReality-QRCode-Sample

A single repository of Mixed Reality samples in Unity.
MIT License
101 stars 30 forks source link

Get a "COMException" error in standalone build #3

Closed liufei2008 closed 3 years ago

liufei2008 commented 3 years ago

Hello, I use Unity 2020.3.14f1 and remoting to Hololens 2 in editor, after fix some missing reference issue, everything is good, I can detect and track QR codes. After I build a windows standalone, I get something like "... cannot find vcruntime140_app.dll ...", then I copy the dlls from Plugins folder to the the same folder of exe and a new error shows, a "COMExcpetion" error:

COMException
  at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR (System.Int32 errorCode) [0x0000a] in <39cd5065f72f426c85b196a374d4b1db>:0 
  at WinRT.Platform.RoGetActivationFactory (System.IntPtr runtimeClassId, System.Guid& iid) [0x0000f] in <8f8054538ba54a4781946220bf85f841>:0 
  at WinRT.WinrtModule.GetActivationFactory (WinRT.HString runtimeClassId) [0x00015] in <8f8054538ba54a4781946220bf85f841>:0 
  at WinRT.ActivationFactory`1[T]..ctor () [0x00098] in <8f8054538ba54a4781946220bf85f841>:0 
  at (wrapper managed-to-native) System.Reflection.MonoCMethod.InternalInvoke(System.Reflection.MonoCMethod,object,object[],System.Exception&)
  at System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[] parameters) [0x00002] in <39cd5065f72f426c85b196a374d4b1db>:0 
Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
  at System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[] parameters) [0x00014] in <39cd5065f72f426c85b196a374d4b1db>:0 
  at System.RuntimeType.CreateInstanceMono (System.Boolean nonPublic) [0x000a8] in <39cd5065f72f426c85b196a374d4b1db>:0 
  at System.RuntimeType.CreateInstanceSlow (System.Boolean publicOnly, System.Boolean skipCheckThis, System.Boolean fillCache, System.Threading.StackCrawlMark& stackMark) [0x00009] in <39cd5065f72f426c85b196a374d4b1db>:0 
  at System.RuntimeType.CreateInstanceDefaultCtor (System.Boolean publicOnly, System.Boolean skipCheckThis, System.Boolean fillCache, System.Threading.StackCrawlMark& stackMark) [0x00027] in <39cd5065f72f426c85b196a374d4b1db>:0 
  at System.Activator.CreateInstance[T] () [0x00021] in <39cd5065f72f426c85b196a374d4b1db>:0 
  at WinRT.WeakLazy`1+<>c[T].<.ctor>b__2_0 () [0x00000] in <8f8054538ba54a4781946220bf85f841>:0 
  at WinRT.WeakLazy`1[T].get_Value () [0x00020] in <8f8054538ba54a4781946220bf85f841>:0 
  at WinRT.ActivationFactory`1[T].As[I] () [0x00000] in <8f8054538ba54a4781946220bf85f841>:0 
  at Microsoft.MixedReality.QR.QRCodeWatcher+Statics..ctor () [0x00000] in <8f8054538ba54a4781946220bf85f841>:0 
  at (wrapper managed-to-native) System.Reflection.MonoCMethod.InternalInvoke(System.Reflection.MonoCMethod,object,object[],System.Exception&)
  at System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[] parameters) [0x00002] in <39cd5065f72f426c85b196a374d4b1db>:0 
Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
  at System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[] parameters) [0x00014] in <39cd5065f72f426c85b196a374d4b1db>:0 
  at System.RuntimeType.CreateInstanceMono (System.Boolean nonPublic) [0x000a8] in <39cd5065f72f426c85b196a374d4b1db>:0 
  at System.RuntimeType.CreateInstanceSlow (System.Boolean publicOnly, System.Boolean skipCheckThis, System.Boolean fillCache, System.Threading.StackCrawlMark& stackMark) [0x00009] in <39cd5065f72f426c85b196a374d4b1db>:0 
  at System.RuntimeType.CreateInstanceDefaultCtor (System.Boolean publicOnly, System.Boolean skipCheckThis, System.Boolean fillCache, System.Threading.StackCrawlMark& stackMark) [0x00027] in <39cd5065f72f426c85b196a374d4b1db>:0 
  at System.Activator.CreateInstance[T] () [0x00021] in <39cd5065f72f426c85b196a374d4b1db>:0 
  at WinRT.WeakLazy`1+<>c[T].<.ctor>b__2_0 () [0x00000] in <8f8054538ba54a4781946220bf85f841>:0 
  at WinRT.WeakLazy`1[T].get_Value () [0x00020] in <8f8054538ba54a4781946220bf85f841>:0 
  at Microsoft.MixedReality.QR.QRCodeWatcher.IsSupported () [0x00000] in <8f8054538ba54a4781946220bf85f841>:0 
  at QRTracking.QRCodesManager+<Start>d__29.MoveNext () [0x0000f] in E:\20210615 EPBS ID4 AR\Projects\Unity_ID4AR\Assets\RemoteQRTrack\Scripts\QRCodesManager.cs:82 
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <39cd5065f72f426c85b196a374d4b1db>:0 
  at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__6_0 (System.Object state) [0x00000] in <39cd5065f72f426c85b196a374d4b1db>:0 
  at UnityEngine.UnitySynchronizationContext+WorkRequest.Invoke () [0x00002] in <1c1473f1ae4d4d669c2e1ef28e35b413>:0 
UnityEngine.DebugLogHandler:Internal_LogException(Exception, Object)
UnityEngine.DebugLogHandler:LogException(Exception, Object)
UnityEngine.Logger:LogException(Exception, Object)
UnityEngine.Debug:LogException(Exception)
UnityEngine.WorkRequest:Invoke()
UnityEngine.UnitySynchronizationContext:Exec()
UnityEngine.UnitySynchronizationContext:ExecuteTasks()

What can I do to solve it?

liufei2008 commented 3 years ago

After a lot of test I success to make it work! Just copy these dlls to same folder of exe file: image

And, I also install "Microsoft.Windows.MixedReality.DotNetWinRT" package from nuget. Then change some code of SpatialGraphCoordinateSystem.cs so that the tracking can work in editor and standalone build:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Microsoft.Windows.Perception.Spatial;
using Microsoft.MixedReality.Toolkit.Utilities;

namespace QRTracking
{
    public class SpatialGraphCoordinateSystem : MonoBehaviour
    {
        private SpatialCoordinateSystem CoordinateSystem = null;
        private System.Guid id;
        public System.Guid Id
        {
            get
            {
                return id;
            }

            set
            {
                id = value;
                CoordinateSystem = Microsoft.Windows.Perception.Spatial.Preview.SpatialGraphInteropPreview.CreateCoordinateSystemForNode(id);
                if (CoordinateSystem == null)
                {
                    Debug.Log("Id= " + id + " Failed to acquire coordinate system");
                }
            }
        }

        void Awake()
        {
        }

        // Use this for initialization
        void Start()
        {
            if (CoordinateSystem == null)
            {
                CoordinateSystem = Microsoft.Windows.Perception.Spatial.Preview.SpatialGraphInteropPreview.CreateCoordinateSystemForNode(id);
                if (CoordinateSystem == null)
                {
                    Debug.Log("Id= " + id + " Failed to acquire coordinate system");
                }
            }
        }

        private void UpdateLocation()
        {
            {
                if (CoordinateSystem == null)
                {
                    CoordinateSystem = Microsoft.Windows.Perception.Spatial.Preview.SpatialGraphInteropPreview.CreateCoordinateSystemForNode(id);

                    if (CoordinateSystem == null)
                    {
                        Debug.Log("Id= " + id + " Failed to acquire coordinate system");
                    }
                }

                if (CoordinateSystem != null)
                {
                    Quaternion rotation = Quaternion.identity;
                    Vector3 translation = new Vector3(0.0f, 0.0f, 0.0f);

                    System.IntPtr rootCoordnateSystemPtr = UnityEngine.XR.WindowsMR.WindowsMREnvironment.OriginSpatialCoordinateSystem;
                    if (rootCoordnateSystemPtr != System.IntPtr.Zero)
                    {
                        var rootSpatialCoordinateSystem = SpatialCoordinateSystem.FromNativePtr(rootCoordnateSystemPtr);

                        // Get the relative transform from the unity origin
                        System.Numerics.Matrix4x4? relativePose = CoordinateSystem.TryGetTransformTo(rootSpatialCoordinateSystem);

                        if (relativePose != null)
                        {
                            System.Numerics.Vector3 scale;
                            System.Numerics.Quaternion rotation1;
                            System.Numerics.Vector3 translation1;

                            System.Numerics.Matrix4x4 newMatrix = relativePose.Value;

                            // Platform coordinates are all right handed and unity uses left handed matrices. so we convert the matrix
                            // from rhs-rhs to lhs-lhs 
                            // Convert from right to left coordinate system
                            newMatrix.M13 = -newMatrix.M13;
                            newMatrix.M23 = -newMatrix.M23;
                            newMatrix.M43 = -newMatrix.M43;

                            newMatrix.M31 = -newMatrix.M31;
                            newMatrix.M32 = -newMatrix.M32;
                            newMatrix.M34 = -newMatrix.M34;

                            System.Numerics.Matrix4x4.Decompose(newMatrix, out scale, out rotation1, out translation1);
                            translation = new Vector3(translation1.X, translation1.Y, translation1.Z);
                            rotation = new Quaternion(rotation1.X, rotation1.Y, rotation1.Z, rotation1.W);
                            Pose pose = new Pose(translation, rotation);

                            // If there is a parent to the camera that means we are using teleport and we should not apply the teleport
                            // to these objects so apply the inverse
                            if (CameraCache.Main.transform.parent != null)
                            {
                                pose = pose.GetTransformedBy(CameraCache.Main.transform.parent);
                            }

                            gameObject.transform.SetPositionAndRotation(pose.position, pose.rotation);
                            //Debug.Log("Id= " + id + " QRPose = " +  pose.position.ToString("F7") + " QRRot = "  +  pose.rotation.ToString("F7"));
                        }
                        else
                        {
                            // Debug.Log("Id= " + id + " Unable to locate qrcode" );
                        }
                    }
                }
                else
                {
                    gameObject.SetActive(false);
                }
            }
        }
        // Update is called once per frame
        void Update()
        {
            UpdateLocation();
        }
    }
}