UE4 文件选择框OpenFileDialog在Shipping环境下崩溃报错

**解决方案:**需要把依赖developer的三个模块(DesktopPlatformDirectoryWatcherSlateFileDialogs)源码拷贝到项目中,重新编译即可。

具体步骤:

  • 新建一个Plugin

  • 把developer路径(UE_4.26\Engine\Source\Developer)里的目录(DesktopPlatform、DirectoryWatcher、SlateFileDialogs)拷贝到Plugin的Source路径下

  • 修改目录文件名为(MyDesktopPlatform、MyDirectoryWatcher、MySlateFileDialogs),对应的Build.cs也需要改名字

  • 修改每个模块的Build.cs
    Build.cs 里涉及到这三个库的路径和名称全改成“Myxxxxxx”,

MySlateFileDialogs:

public class MySlateFileDialogs : ModuleRules
{
    public MySlateFileDialogs(ReadOnlyTargetRules Target) : base(Target)
    {
        PrivateDependencyModuleNames.AddRange(
            new string[] {
                "Core",
                "CoreUObject",
                "InputCore",
                "Slate",
                "SlateCore",
                "MyDirectoryWatcher",
            }
        );
    
        PrivateIncludePaths.AddRange(
            new string[] {
                "MySlateFileDialogs/Private",  
            }
        );

        PrivateIncludePathModuleNames.Add("TargetPlatform");
    }
}

MyDesktopPlatform:

public class MyDesktopPlatform : ModuleRules
{
	public MyDesktopPlatform(ReadOnlyTargetRules Target) : base(Target)
	{
		PrivateIncludePaths.Add("MyDesktopPlatform/Private");

		PrivateDependencyModuleNames.AddRange(
			new string[] {
				"Core",
				"ApplicationCore",
				"Json",
			}
		);

		if (Target.IsInPlatformGroup(UnrealPlatformGroup.Linux))
		{
			PrivateIncludePathModuleNames.AddRange(
				new string[] {
					"MySlateFileDialogs",
				}
			);

			DynamicallyLoadedModuleNames.AddRange(
				new string[] {
					"MySlateFileDialogs",
				}
			);

			AddEngineThirdPartyPrivateStaticDependencies(Target, "SDL2");
		}
	}
}

MyDirectoryWatcher:

public class MyDirectoryWatcher : ModuleRules
{
	public MyDirectoryWatcher(ReadOnlyTargetRules Target) : base(Target)
	{
		PrivateIncludePaths.Add("MyDirectoryWatcher/Private");

		PrivateDependencyModuleNames.Add("Core");
	}
}
  • 修改Plugin的uplugin文件
"Modules": [
		{
			"Name": "WinSelectedDialog",
			"Type": "Runtime",
			"LoadingPhase": "PreLoadingScreen",
			"WhitelistPlatforms": [
				"Win32",
				"Win64"
			]
		},
		{
			"Name": "MyDesktopPlatform",
			"Type": "Runtime",
			"LoadingPhase": "Default",
			"WhitelistPlatforms": [
				"Win32",
				"Win64"
			]
		},
		{
			"Name": "MySlateFileDialogs",
			"Type": "Runtime",
			"LoadingPhase": "Default",
			"WhitelistPlatforms": [
				"Win32",
				"Win64"
			]
		},
		{
			"Name": "MyDirectoryWatcher",
			"Type": "Runtime",
			"LoadingPhase": "Default",
			"WhitelistPlatforms": [
				"Win32",
				"Win64"
			]
		}
	]
  • 修复编译错误
  1. 去掉像DESKTOPPLATFORM_API这样的宏
  2. 修改模块实现的模块名称 (可全项目搜索IMPLEMENT_MODULE)
    IMPLEMENT_MODULE( FDirectoryWatcherModule, MyDirectoryWatcher );
    IMPLEMENT_MODULE(FSlateFileDialogsModule, MySlateFileDialogs);
    IMPLEMENT_MODULE( FDesktopPlatformModule, MyDesktopPlatform );
  • 弹窗代码实现
FString UMySelectedDialogBPLibrary::OpenFileDialog()
{
	void* ParentWindowPtr = FSlateApplication::Get().GetActiveTopLevelWindow()->GetNativeWindow()->GetOSWindowHandle();
	IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get();

	TArray<FString> OutFileNames;

	if (DesktopPlatform)
	{
		EFileDialogFlags::Type SelectionFlag = EFileDialogFlags::None;
		DesktopPlatform->OpenFileDialog(ParentWindowPtr,
			TEXT("请选择资源"),
			TEXT("/"),
			TEXT(""),
			TEXT("(Image Files)|*.BMP;*.JPG;*.PNG;*.JPEG;)"),
			//LOCTEXT("Image Files", "Stats files (*.BMP)|*.BMP;*.JPEG|Raw Stats files (*.PNG)|*.PNG").ToString(),
			SelectionFlag,
			OutFileNames);
	}

	if (OutFileNames.Num() > 0)
	{
		return FString(OutFileNames[0]);
	}
	else
	{
		return TEXT("");
	}
}
  • 打包shipping测试

下面链接可以下载打包好的:https://download.csdn.net/download/killfunst/20322471