Esempio n. 1
0
        public static Dictionary <string, Type> MyCDEPluginTypes = new Dictionary <string, Type>();       //DIC-Allowed   STRING

        public static int PackagePlugIn(string pluginFilePath, string binDirectoryPath, string storeDirectoryPath, string pPlatform, ILogger logger, bool bDiagnostics, bool bCheckForFileOverwrite, out string error)
        {
            if (!binDirectoryPath.EndsWith(Path.DirectorySeparatorChar.ToString()))// && !binDirectoryPath.EndsWith("."))
            {
                binDirectoryPath += Path.DirectorySeparatorChar;
            }
            if (storeDirectoryPath != null && !storeDirectoryPath.EndsWith(Path.DirectorySeparatorChar.ToString())) // && !storeDirectoryPath.EndsWith("."))
            {
                storeDirectoryPath += Path.DirectorySeparatorChar;
            }


            TheBaseAssets.MyServiceHostInfo = new TheServiceHostInfo(cdeHostType.NOTSET, cdeNodeType.NOTSET, binDirectoryPath)
            {
            };

            cdePlatform tPluginPlatform = cdePlatform.NOTSET;

            if (TheCommonUtils.CInt(pPlatform) > 0)
            {
                Enum.TryParse <cdePlatform>(pPlatform, out tPluginPlatform);
            }
            else
            {
                switch (pPlatform)
                {
                case "net35":
                    tPluginPlatform = cdePlatform.X32_V3;
                    break;

                case "net45":
                    tPluginPlatform = cdePlatform.X64_V3;
                    break;

                case "net40":
                    tPluginPlatform = cdePlatform.NETV4_64;
                    break;

                case "netstandard2.0":
                    tPluginPlatform = cdePlatform.NETSTD_V20;
                    break;
                }
            }

            var packageStr = $"Packaging {pluginFilePath} from {binDirectoryPath}";

            if (!String.IsNullOrEmpty(storeDirectoryPath))
            {
                packageStr += $" to {storeDirectoryPath}";
            }

            logger.WriteLine(packageStr);

            //try
            //{
            //    var workingDirectory = Path.GetDirectoryName(pluginFilePath);
            //    logger.WriteLine($"Setring working directory to {workingDirectory}");

            //    Directory.SetCurrentDirectory(workingDirectory);
            //}
            //catch (Exception e)
            //{
            //    logger.WriteLine($"$Warning: unable to set working directory: {e.ToString()}");
            //}

            if (File.Exists(Path.ChangeExtension(pluginFilePath, ".cdes")))
            {
                pluginFilePath = Path.ChangeExtension(pluginFilePath, ".cdes");
            }

            error = "";
            if (pluginFilePath.ToLower().EndsWith(".cdes"))
            {
                try
                {
                    var tInfo = TheCommonUtils.DeserializeJSONStringToObject <ThePluginInfo>(File.ReadAllText(pluginFilePath));
                    if (tPluginPlatform > 0)
                    {
                        tInfo.Platform = tPluginPlatform;
                    }
                    error = CreateCDEX(storeDirectoryPath, tInfo, logger, bCheckForFileOverwrite, out var cdesPath);
                    if (!String.IsNullOrEmpty(error))
                    {
                        logger.WriteLine($"Error creating package: {error}");
                        return(7);
                    }
                    else
                    {
                        logger.WriteLine($"Created CDES at {cdesPath}");
                    }
                }
                catch (Exception e)
                {
                    logger.WriteLine($"Error packaging CDES file {pluginFilePath}: {e} ");
                    error = e.ToString();
                    return(6);
                }
            }
            else
            {
                try
                {
                    AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += (o, args) =>
                    {
                        string   name = null;
                        Assembly ass  = null;
                        try
                        {
                            name = AppDomain.CurrentDomain.ApplyPolicy(args.Name);
                            try
                            {
                                ass = System.Reflection.Assembly.ReflectionOnlyLoad(name);
                            }
                            catch (Exception e)
                            {
                                var assName = new AssemblyName(name).Name;
                                var assPath = Path.Combine(binDirectoryPath, assName + ".dll");
                                if (bDiagnostics)
                                {
                                    logger.WriteLine($"Error resolving {args.Name} {name}, trying {assPath}: {e.Message}");
                                }
                                ass = System.Reflection.Assembly.ReflectionOnlyLoadFrom(assPath);
                            }
                        }
                        catch (Exception e)
                        {
                            logger.WriteLine($"Error resolving {args.Name} {name}: {e.Message}");
                            throw;
                        }
                        if (bDiagnostics)
                        {
                            logger.WriteLine($"Resolving {args.Name} {name}: {ass.CodeBase}");
                        }
                        return(ass);
                    };
                    Assembly tAss;
                    try
                    {
                        // TODO load for reflection only first (to support cross-platform tooling). But needs to be in separate app domain like in the engine host. For now only do reflection when LoadFrom fails (i.e. native x86 assembly in x64 packager process).
                        tAss = Assembly.LoadFrom(pluginFilePath);
                    }
                    catch
                    {
                        tAss = Assembly.ReflectionOnlyLoadFrom(pluginFilePath);
                    }
                    tPluginPlatform = TheCommonUtils.GetAssemblyPlatformHostAgnostic(tAss, bDiagnostics, out string diagInfo);
                    if (!string.IsNullOrEmpty(diagInfo))
                    {
                        logger.WriteLine(diagInfo);
                    }

                    var CDEPlugins = from t in tAss.GetTypes() //.GetTypes()
                                     let ifs = t.GetInterfaces()
                                               where ifs != null && ifs.Length > 0 && ((ifs.FirstOrDefault(i => i.AssemblyQualifiedName == typeof(ICDEPlugin).AssemblyQualifiedName) != null)
#if CDE_METRO
                                                                                       || ifs.Contains(typeof(ICDEUX))
#endif
                                                                                       )
                                               select new { Type = t, t.Namespace, t.Name, t.FullName };
                    // ReSharper disable once PossibleMultipleEnumeration
                    if (CDEPlugins == null || !CDEPlugins.Any())
                    {
                        string tPls = "";
                        foreach (Type ttt in tAss.GetTypes())
                        {
                            if (tPls.Length > 0)
                            {
                                tPls += ",\n\r";
                            }
                            tPls += ttt.FullName;
                        }
                        error = $"File {pluginFilePath} - found but did not contain C-DEngine Plug-In Interface. Types found: \n\r{tPls}";
                        logger.WriteLine(error);
                        return(2);
                    }
                    else
                    {
                        // ReSharper disable once PossibleMultipleEnumeration
                        foreach (var Plugin in CDEPlugins)
                        {
                            //TheSystemMessageLog.ToCo("Processing Plugin :" + Plugin.FullName);
                            if (Plugin.Type.GetInterfaces().FirstOrDefault(itf => itf.FullName == typeof(ICDEPlugin).FullName) != null)
                            {
                                if (!MyCDEPluginTypes.ContainsKey(Plugin.FullName))
                                {
                                    MyCDEPluginTypes.Add(Plugin.FullName, Plugin.Type);
                                    logger.WriteLine(string.Format("Plugin {1} in file {0} - found and added", pluginFilePath, Plugin.FullName));
                                }
                            }
                        }
                    }
                }
                catch (ReflectionTypeLoadException eeee)
                {
                    Exception[] tEx      = eeee.LoaderExceptions;
                    string      res      = eeee.ToString();
                    bool        bOldICDE = false;
                    foreach (Exception e in tEx)
                    {
                        if (e.Message.Contains("'Init'"))
                        {
                            bOldICDE = true;
                        }
                        res += "</br>Loader Exception: " + e;
                    }
                    logger.WriteLine($"LoadAssembly {pluginFilePath} failed with ReflectionTypeLoadException: {eeee.StackTrace} {eeee.LoaderExceptions.Aggregate("", (s,e) => $"{s}\r\n{e.Message}")}");
                    if (bOldICDE)
                    {
                        error = $"Assembly {pluginFilePath} appears to be a plug-in for an earlier C-DEngine and is no longer supported.";
                        logger.WriteLine(error);
                        return(3);
                    }
                    if (MyCDEPluginTypes.Count == 0)
                    {
                        return(4);
                    }
                }
                catch (Exception eee)
                {
                    error = $"ProcessDirectory:LoadAssembly {pluginFilePath} failed: {eee}";
                    logger.WriteLine(error);
                    return(4);
                }

                foreach (var tType in MyCDEPluginTypes.Values)
                {
                    string cdexPath = "";
                    try
                    {
                        if (tType.IsAbstract)
                        {
                            continue;
                        }
                        var tBase = new ThePackagerBaseEngine();
                        if (!EngineAssetInfoAttribute.ApplyEngineAssetAttributes(tType, tBase))
                        {
                            Assembly tAssRunning = Assembly.LoadFrom(pluginFilePath);
                            var      tIPlugin    = Activator.CreateInstance(tType) as ICDEPlugin;
                            if (tIPlugin == null)
                            {
                                error = "Could not activate Plugin-Service:" + tType;
                                logger.WriteLine(error);
                                return(5);
                            }
                            tIPlugin.InitEngineAssets(tBase);
                        }

                        // Ensure the file list is populate with at least the main module
                        tBase.AddManifestFiles(null);

                        var tInfo = tBase.GetPluginInfo();

                        if (tInfo.CurrentVersion <= 0)
                        {
                            tInfo.CurrentVersion = TheCommonUtils.GetAssemblyVersion(tType);
                        }
                        if (tPluginPlatform != cdePlatform.NOTSET)
                        {
                            tInfo.Platform = tPluginPlatform;
                        }

                        // Multi-platform mapping is now/will be done by the mesh manager, rather than in the packager
                        //if (tInfo.AllPlatforms?.Count > 0)
                        //{
                        //    foreach (var platform in tInfo.AllPlatforms)
                        //    {
                        //        var tInfoClone = tInfo.Clone();
                        //        tInfoClone.Platform = platform;
                        //        var error2 = CreateCDEX(storeDirectoryPath, tInfoClone, out cdexPath);
                        //        if (!string.IsNullOrEmpty(error2))
                        //        {
                        //            if (!string.IsNullOrEmpty(error))
                        //            {
                        //                error += "\r\n";
                        //            }
                        //            error += error2;
                        //        }
                        //    }
                        //}
                        //else
                        {
                            error = CreateCDEX(storeDirectoryPath, tInfo, logger, bCheckForFileOverwrite, out cdexPath);
                        }
                    }
                    catch (Exception e)
                    {
                        error = $"Plugin failed to start: {e}";
                    }
                    if (!String.IsNullOrEmpty(error))
                    {
                        logger.WriteLine($"Error creating package: {error}");
                        return(7);
                    }
                    else
                    {
                        logger.WriteLine($"Created CDEX at {cdexPath}");
                    }
                }
            }

            return(0);
        }