递归搜索指定后缀集合的文件

// Fill out your copyright notice in the Description page of Project Settings.

using System.IO;
using System.Collections.Generic;
using UnrealBuildTool;

namespace UnrealBuildTool.Rules
{
#if WITH_FORWARDED_MODULE_RULES_CTOR
    using zTargetInfo = ReadOnlyTargetRules;
#else
    using zTargetInfo = TargetInfo;
#endif

    public class HeXrTransceiverLib : ModuleRules
    {
        public HeXrTransceiverLib(zTargetInfo Target)
#if WITH_FORWARDED_MODULE_RULES_CTOR
            : base(Target)
#endif
        {
            Type = ModuleType.External;

            PublicIncludePaths.AddRange(
                    new string[] {
                        // ... add public include paths required here ...
                        Path.Combine(ModuleDirectory, "include"),
                    }
                );

            // Add the import library
            //PublicLibraryPaths.Add(Path.Combine(ModuleDirectory, "lib"));
            PublicAdditionalLibraries.Add(Path.Combine(ModuleDirectory, "lib", "HeXrTransceiver.lib"));

            // Delay-load the DLL, so we can load it from the right place first
            PublicDelayLoadDLLs.Add("HeXrTransceiver.dll");

            string dll_folder_path = Path.Combine(ModuleDirectory, "dll");
            string[] dlls_fullpath = DFS_GetFilesRecursively(dll_folder_path, new string[] { ".dll" });
            // Runtime Dependencies for Project Package
            foreach(string dll in dlls_fullpath)
	    {
                 string target_output_path = "$(TargetOutputDir)/dll".Replace("dll", Path.GetFileName(dll));
                 RuntimeDependencies.Add(target_output_path, dll); // copy
                 // PublicDelayLoadDLLs.Add(Path.GetFileName(dll));
		 RuntimeDependencies.Add(target_output_path, StagedFileType.NonUFS);
	    }
        }

        /*
         * Root: folder full path
         * FileExts: dll,jpg,txt,etc.
         * Return full path of files.
         */
        public string[] DFS_GetFilesRecursively(string Root, string[] FileExts)
        {
            List<string> Ret = new List<string>();

            DirectoryInfo DI = new DirectoryInfo(Root);
            foreach(FileInfo FI in DI.GetFiles())
            {
                //System.Console.WriteLine("FI.Extension={0} FI.FullName={1}", FI.Extension, FI.FullName);
                foreach(string Ext in FileExts)
                {
                    if (Ext.Equals(FI.Extension, System.StringComparison.OrdinalIgnoreCase))
                    {
                        Ret.Add(FI.FullName);
                        break;
                    }
                }
            }

            foreach(DirectoryInfo SubDI in DI.GetDirectories())
            {
                Ret.AddRange(DFS_GetFilesRecursively(SubDI.FullName, FileExts));
            }

            return Ret.ToArray();
        }

        /**
         * Root: folder full path
         * FileExts: dll,jpg,txt,etc.
         * Return full path of files.
         */
        public string[] GetFiles_NoRecur(string Root, string[] FileExts)
        {
            List<string> Ret = new List<string>();
    
            DirectoryInfo DI = new DirectoryInfo(Root);
            foreach (FileInfo FI in DI.GetFiles())
            {
                //System.Console.WriteLine("FI.Extension={0} FI.FullName={1}", FI.Extension, FI.FullName);
                foreach (string Ext in FileExts)
                {
                    if (Ext.Equals(FI.Extension, System.StringComparison.OrdinalIgnoreCase))
                    {
                        Ret.Add(FI.FullName);
                        break;
                    }
                }
            }
    
            return Ret.ToArray();
        }
    }
}

UE4插件简单正确加载插件的方法

#include "Interfaces/IPluginManager.h"
#include "HAL/FileManager.h"

bool FSURAPluginRuntimeModule::LoadHeXrDependency( )
{
	// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
	// Get the base directory of this plugin
	FString BaseDir = IPluginManager::Get( ).FindPlugin( "SURAPlugin" )->GetBaseDir( );

	// Add on the relative location of the third party dll and load it
	FString DllFolder(FPaths::Combine(*BaseDir, TEXT("Source/ThirdParty/HeXrTransceiverLib/dll")));
	FPlatformProcess::AddDllDirectory(*DllFolder);

	IFileManager::Get().IterateDirectoryRecursively(*DllFolder, [&](const TCHAR* Node, bool IsDir) -> bool
	{
		if (IsDir)
		{
			FPlatformProcess::AddDllDirectory(Node);
		}
		return true;
	});

	FString LibraryPath;
#if PLATFORM_WINDOWS
	LibraryPath = FPaths::Combine(*DllFolder, TEXT("HeXrTransceiver.dll"));
#endif // PLATFORM_WINDOWS

	HeXr_LIB_HANDLE = !LibraryPath.IsEmpty( ) ? FPlatformProcess::GetDllHandle( *LibraryPath ) : nullptr;

	return HeXr_LIB_HANDLE != nullptr;
}

RuntimeDependencies

If you want to have the DLL copied to the same output directory as the executable at build time, you do so via an overload of the RuntimeDependencies.Add method:
 RuntimeDependencies.Add("$(TargetOutputDir)/Foo.dll", Path.Combine(PluginDirectory, "Source/ThirdParty/bin/Foo.dll"));
Other variables can be used for output paths of the DLL:
$(EngineDir) The engine directory
$(ProjectDir) Directory containing the project file
$(ModuleDir) Directory containing the .build.cs file
$(PluginDir) Directory containing the .uplugin file
$(BinaryOutputDir) Directory containing the binary that this module is compiled into (for example, the path to the DLL for editor builds, and path to the executable (EXE) for packaged builds)
$(TargetOutputDir) Directory containing the executable (including in editor builds)