Asset compiler crashes when using `System.Windows.Forms`
Release Type: GitHub
Version: main branch
Platform(s): Windows
Describe the bug We have troubles building our solution with latest Stride source builds as the asset compiler crashes during the build. This crash wasn't present before and seems to be have introduced by https://github.com/stride3d/stride/pull/2082.
To Reproduce Steps to reproduce the behavior:
- Start Game Studio from current main branch
- Create a new game using Windows as platform
- Add a public class which inherits from
System.Windows.Forms.Control, for example
using System.Windows.Forms;
namespace GameUsingWindowsForms
{
public class SomeControl : Control
{
}
}
- Build the game
Expected behavior It shouldn't crash.
Screenshots
I cannot reproduce. I added a Forms to the project, it compiled correctly and I could run the Game.
It worked both with the Form added to the Windows app project or to the Game project.
However, you shouldn't add a form to the Game project. It isn't meant to have platform-specific code (that project is supposed to be shared between multiple platforms). In fact, I think the templates are kind of incorrect to set the target framework to net8.0-windowsfor that project as it should be net-8.0.
Can you try again after cleaning up any previous build artifacts (e.g. running git clean -xfd) or share your code somehow?
Our setup is far more complex than just a game project and a platform specific project. I was only using this simple setup to illustrate the issue. Getting rid of the platform specific thing would be nice but unfortunately not realistic in all the scenarios we're usually in.
I'll try your suggestions later the day and upload my example project.
- Updated VS 2022 to latest and made sure all prerequisites are present (which they were)
- Repaired VS 2022 (just to be sure)
- Removed all USER.nuget\packages\Stride* (just to be sure)
- Opened developer command prompt for VS2022
- cd stride
- git clean -xfd
- cd build
- dotnet restore Stride.sln
- msbuild Stride.sln
- cd USER\GameUsingWindowsForms
- dotnet build
- All good :)
Went back to our solution, dotnet build, and also all good. Jesus. Thanks for your help!
Sorry, wait, I did all that with releases/4.2.0.2067
Ok, now did all the steps from above (except the VS update) with master branch and the result is sadly what I initially posted: asset compiler crashes with a type load exception not finding System.Windows.Forms
Attached you find the test project I was using: GameUsingWindowsForms.zip
In a quick test I modified the crashing RegisterCompilersFromAssembly method like this and it compiled fine:
private void RegisterCompilersFromAssembly(Assembly assembly)
{
// Process Asset types.
foreach (var type in GetSuccesfullyLoadedTypes(assembly))
{
// Only process Asset types
if (!typeof(IAssetCompiler).IsAssignableFrom(type) || !type.IsClass)
continue;
// Asset compiler
var compilerAttribute = type.GetCustomAttribute<AssetCompilerAttribute>();
if (compilerAttribute == null) // no compiler attribute in this asset
continue;
try
{
ProcessAttribute(compilerAttribute, type);
}
catch (Exception ex)
{
log.Error($"Unable to instantiate compiler [{compilerAttribute.TypeName}]", ex);
}
}
// Taken from https://stackoverflow.com/questions/7889228/how-to-prevent-reflectiontypeloadexception-when-calling-assembly-gettypes
[DebuggerNonUserCode]
static IEnumerable<Type> GetSuccesfullyLoadedTypes(Assembly assembly)
{
try
{
return assembly.GetTypes();
}
catch (ReflectionTypeLoadException e)
{
// If some types can't be loaded, this exception is thrown.
// The [DebuggerNonUserCode] makes sure these exceptions are not thrown in the developers
// face when they have "Just My Code" turned on in their debugging settings.
return e.Types.Where(t => t != null);
}
}
}
Is the IAssetCompiler interface intended to be implemented by user assemblies? If not, wouldn't it be ok to suppress the error like above?
Thanks for the small project. I can reproduce now.
~~@azeno silly question, but how did you manage to break inside the Assets.CompilerApp? I launched the GameStudio with he debugger attached but it didn't break on that exception.~~
edit: I managed to do it.
IAssetCompiler is supposed to be available to user assemblies to be able to design custom assets. However that scenario is not fully tested (and probably missing some parts to work entirely). It will be revisited once we have proper cross-platform support and start working on the plugin system for the editor.
I think your proposed change is a good workaround for the time being.
Note for later: if the same issue arise again after the proposed quick fix, another solution would be to multi-target Stride.Core.Assets.CompilerApp to both $(StrideXplatEditorTargetFramework);$(StrideEditorTargetFramework) and adapt Stride.Core.Assets.CompilerApp.targets to call the right version depending of the user project target.
Linking to #2034 to keep track.