How do you programmatically setup the GLWpfControl? - c#

I've been playing around with OpenTK and it's been great following along the examples/tutorials.
I really want to have the OpenGL render in a smaller portion of the Window so I've been trying to use GLWpfControl, and I want to do it without XAML but I can't get it running properly.
I've been trying to get it to run through dotnet CLI from a console template. Here is my code:
using System;
using System.Windows;
using OpenTK.Wpf;
using OpenTK.Graphics.OpenGL;
namespace Test {
public class MyWindow : Window {
[STAThread]
public static void Main() {
Application app = new Application();
app.Run(new MyWindow());
}
public MyWindow() {
GLWpfControl wpfControl = new GLWpfControl();
wpfControl.Render += GLWpfOnRender;
this.Content = wpfControl;
var settings = new GLWpfControlSettings();
wpfControl.Start(settings);
}
void GLWpfOnRender(TimeSpan delta) {
Console.WriteLine(delta.TotalMilliseconds);
GL.ClearColor(1.0f, 0.0f, 0.0f, 1.0f);
GL.Clear(ClearBufferMask.ColorBufferBit);
}
}
}
I'm expecting the control to be rendered with a red color, however it is black. It isn't black without the call to Start() and GLWpfOnRender is being called repeatedly after the call to Start().
Here is the .csproj file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<RootNamespace>test_2</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="OpenTK" Version="4.7.4" />
<PackageReference Include="OpenTK.GLWpfControl" Version="4.2.2" />
</ItemGroup>
</Project>
I think I'm missing something that might be done when you call InitializeComponent() while using XAML. I've been doing a lot of reading but I'm stumped.
here's a link to what I'm trying to replicate:
https://github.com/opentk/GLWpfControl/tree/aefe945f65e4659bd6f9f82083a4a746c2fb03fc/src
Edit:
I've inherited and overriden GLWpfControl, and able to use the DrawingContext to print text and do all sorts of stuff. So GL is not working with the control for whatever reason?

Okay I got it working. Turns out there are some known issues with two graphics cards / Intel HD graphics. I had my GPU disabled. Enabled, it works fine. My own fault for not checking issues tab on github in the first place.

Related

BenchmarkDotNet InProcessEmitToolchain Complete Sample

I'm looking at BenchmarkDotNet and benchmarking in general for the first time ever. I appear to be unable to run benchmarks using the normal BenchmarkRunner because of antivirus restrictions on our work laptops so I'm trying to use InProcessEmitToolchain, as documented here. However, in those samples and the ones listed here I see no entry point for the application that will actually trigger the benchmarks and I've gotten nowhere useful reading through the documentation.
Can anyone point me at a complete sample of how to use the InProcessEmitToolchain and/or jobs that explains how to use jobs in conjunction with an application entry point to run the tests?
I was facing the same problem with antivirus (Windows Defender) blocking BenchmarkDotNet. I was able to figure out how to change the toolchain setup, though I had to use InProcessNoEmitToolchain since InProcessEmitToolchain was also blocked.
The example below did not actually trigger the antivirus, but it shows how to define which toolchain to use:
[Program.cs]
using BenchmarkDotNet.Running;
using Benchmarks;
_ = BenchmarkRunner.Run<MaterializeTest>();
[MaterializeTest.cs]
using BenchmarkDotNet.Attributes;
namespace Benchmarks;
[Config(typeof(AntiVirusFriendlyConfig))]
[MemoryDiagnoser]
public class MaterializeTest
{
IEnumerable<int> _sequence;
[Params(10, 100, 1000, 10000)]
public int _size;
[GlobalSetup]
public void Setup()
{
_sequence = Enumerable.Range(0, _size).Select(i => Random.Shared.Next());
}
[Benchmark]
public IReadOnlyList<int> ToList() => _sequence.ToList();
[Benchmark]
public IReadOnlyList<int> ToArray() => _sequence.ToArray();
}
[AntiVirusFriendlyConfig.cs]
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Toolchains.InProcess.NoEmit;
namespace Benchmarks;
public class AntiVirusFriendlyConfig : ManualConfig
{
public AntiVirusFriendlyConfig()
{
AddJob(Job.MediumRun
.WithToolchain(InProcessNoEmitToolchain.Instance));
}
}
[Benchmarks.csproj]
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.2" />
</ItemGroup>
</Project>
I ended up being unable to solve this even using the InProcesNoEmitToolchain - our AV software was too persistent. I solved it by getting our IT folks to give us a folder whitelist entry in the AV software where we could run benchmarking.
You can tweak the configuration with the toolchains you like:
var config = DefaultConfig.Instance
.AddJob(Job
.MediumRun
.WithLaunchCount(1)
.WithToolchain(InProcessEmitToolchain.Instance));
Or alternatively
var config = DefaultConfig.Instance
.AddJob(Job
.MediumRun
.WithLaunchCount(1)
.WithToolchain(InProcessNoEmitToolchain.Instance));
And pass it to the Run method (building on the program from Andreas Warberg)
_ = BenchmarkRunner.Run<MaterializeTest>(config);

MessageBox in .net core 5

From what I read System.Windows.MessageBox is available in .net core 5
links:
https://learn.microsoft.com/en-us/dotnet/api/system.windows.messagebox?view=net-5.0
Similar method to messageBox in .NET core
However when I try to use System.Windows.MessageBox I get the error:
The type or namespace name 'MessageBox' does not exist in the namespace 'System.Windows'
Am I missing a setting?
Assuming you want to use WPF, your csproj file has to look like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWPF>true</UseWPF> <!-- this adds support for the GUI stuff like MessageBox -->
</PropertyGroup>
</Project>
Then you should be able to do something like this in MainWindow.xaml.cs:
using System.Windows;
namespace messagebox
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MessageBox.Show("Hello World!");
}
}
}

Auto-generate main method from referenced assembly

I am editing my question I think it is a little confusing and it does not explain what my intent is.
Edit:
My goal is that when my HelloWorld application references MyClassLibrary my code does not compile so that I ensure to initialize some code prior to running the main method. Kind of like a constructor of a class. When I reference MyClassLibrary I will like to run some code in there before running the main method of my HelloWorld application. NUnit has a similar functionality. When my HelloWorld application references NUnit I get the error: Error CS0017 Program has more than one entry point defined. Compile with /main to specify the type that contains the entry point. As #Alex pointed out that Main method that NUnit creates is auto-generated. I will like to auto-generate a main method with some custom code. How can I do that from MyClassLibrary without doing anything on my HelloWorld application just like NUnit does it?
OLD Question:
I want to perform the same behavior that NUnit tests perform that it prevents using a Main method. In this case the error that I need is a good thing. Let me explain what I mean.
I create a hello world application targeting the .net core
Project file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
</Project>
Code file: (default hello world c# code)
If I then run that application it runs fine
Add a reference to NUnit and my project file now contains.
.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
</ItemGroup>
</Project>
When I try to compile the project I get the error:
Error CS0017 Program has more than one entry point defined. Compile with /main to specify the type that contains the entry point.
That means that there is another Main method. That method is probably located on the NUnit nuget package I am referencing. This is the error I am trying to replicate!.
Now this is how I try to replicate the same error:
I remove the NUnit nugget package having no references to NUnit on my hello world application.
Create a Project ClassLibrary1 with the following code:
.
public class MyLib
{
static void Main()
{
Console.WriteLine("fooooo");
// do something
}
}
Have my hello world application reference that project:
When I compile I get no errors even though there are 2 Main methods!
How does NUnit manages to prevent using a Main method? How can I replicate the same behavior? I want to create an assembly that when referenced it prevents executing the Main method.
It's just Microsoft.NET.Test.Sdk making build fail.
Adding <GenerateProgramFile>false</GenerateProgramFile> into <PropertyGroup> makes it compile and work anyway.
But adding another class with static void Main to the application makes build fail again regardless <GenerateProgramFile>.
In your example build fails because Microsoft.NET.Test.Sdk adds some auto-generated code to your application before compilation. That code is in ...\.nuget\packages\microsoft.net.test.sdk\16.2.0\build\netcoreapp1.0\Microsoft.NET.Test.Sdk.Program.cs. It's a class with another Main:
// <auto-generated> This file has been auto generated. </auto-generated>
using System;
[Microsoft.VisualStudio.TestPlatform.TestSDKAutoGeneratedCode]
class AutoGeneratedProgram {static void Main(string[] args){}}
BTW: it's absolutely legal to have Main method in another assembly. You just cannot have 2 Mains in one exe. But you can have any number of them in dll like this:
public class Class1
{
public static void Main() { }
public static void Main(string[] args) { }
}
public class Class2
{
public static void Main() { }
public static void Main(string[] args) { }
}
It compiles.
Update:
I found the solution. It's all about installing nuget, not just adding a reference.
Create a .NET Core Class Library and name it MyCoreLib.
Add MyCoreClass.
namespace MyCoreLib
{
public static class MyCoreClass
{
public static void Initialize()
{
System.Console.WriteLine("Initialized from 'MyCoreLib'");
}
}
}
Build the library.
Create the following file structure:
├───nuget
└───src
│ MyCoreLib.nuspec
│
├───build
│ └───netcoreapp2.1
│ ForcedEntryPoint.cs
│ MyCoreLib.targets
│
└───lib
└───netcoreapp2.1
MyCoreLib.dll
MyCoreLib.nuspec
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
<id>MyCoreLib</id>
<version>1.0.0</version>
<authors>MyCoreLib</authors>
<owners>MyCoreLib</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Some description here</description>
<dependencies>
<group targetFramework=".NETCoreApp2.1" />
</dependencies>
</metadata>
</package>
ForcedEntryPoint.cs
//╔════════════════════════════════════╗
//║ This code was added automatically. ║
//║ Do not change or remove it. ║
//╚════════════════════════════════════╝
public static class ForcedEntryPoint
{
public static void Main(string[] args)
{
MyCoreLib.MyCoreClass.Initialize();
}
}
MyCoreLib.targets
<Project InitialTargets="ForceEntryPoint" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<OutputType>Exe</OutputType>
</PropertyGroup>
<PropertyGroup>
<ForcedEntryPoint Condition="'$(ForcedEntryPoint)' == ''">$(MSBuildThisFileDirectory)ForcedEntryPoint$(DefaultLanguageSourceExtension)</ForcedEntryPoint>
<ForceEntryPoint Condition="'$(ForceEntryPoint)' == ''">true</ForceEntryPoint>
</PropertyGroup>
<Target Name="ForceEntryPoint" Condition="'$(ForceEntryPoint)' == 'true'">
<ItemGroup>
<Compile Include="$(ForcedEntryPoint)"/>
</ItemGroup>
</Target>
</Project>
Use NuGet Commandline to build a package like this:
D:\nugetwalkthrough\nuget>D:\nugetwalkthrough\nuget.exe pack D:\nugetwalkthrough\src\MyCoreLib.nuspec
Create a .NET Core Console App and make sure it works.
Install the created package.
Try to run the application and get error:
CS0017 Program has more than one entry point defined. Compile with /main to specify the type that contains the entry point.
Remove the Main method from the application, run it and see it prints Initialized from 'MyCoreLib'.
Put the Main method back to the application and change the project file so that <PropertyGroup> contains <ForceEntryPoint>false</ForceEntryPoint>
Now it compiles and prints Hello World! from its own Main method.
Changing <ForceEntryPoint> to true makes it use another entry point (not that one of the application) again.
I think you should learn how to make multiple project under same solution.
So helloworld is main project.
Then create new test project helloworld.test as test project use Add a reference to NUnit there.
now all will work fine you can change your start up project to helloworld.test and debug or run it from visual studio or command line.
Anyway I never saw a test project inside main project in professional coding. May be for testing we comment main method and run test case.
Test project is also Executable.

MvvmCross.Exceptions.MvxException: Failed to create setup instance

I'm upgrading from MvvMCross 5.7 to 6.0.0.
When I try to run the app, it shows the splash screen and just after that, vs2017 gives me the following error:
MvvmCross.Exceptions.MvxException: Failed to create setup instance
The error always is in the same line, no matter which file I set as mainlauncher.
Example:
using Android.App;
using Android.OS;
using MvvmCross.Droid.Support.V7.AppCompat;
using MvvmCross.Platforms.Android.Views;
namespace ClaveiSGApp.Droid.Views
{
[Activity(Label = "App", MainLauncher = true)]
public class MainView : MvxAppCompatActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.MainView);
}
}
}
The error always is in base.OnCreate(bundle);
Do you have any ideas?
(Let me know if you need more info/code about something)
From the error you're getting, it looks like something bad is happening in CreateSetup method in MvxSetupSingleton (GitHub). I'm guessing here a bit, but I would assume that there's something wrong with how the RegisterSetupType<TMvxSetup> is being called (or it's not being called at all) - you can find this method in MvxSetup (GitHub). Tracking down where the registration happens, it gave me two possible places: MvxSplashScreenActivity<TMvxAndroidSetup, TApplication> and MvxAndroidApplication<TMvxAndroidSetup, TApplication>.
Going forward with this thinking, and assuming you do use SplashScreen in your app. I would suggest updating your SplashScreen activity to inherit from MvxSplashScreenActivity<TMvxAndroidSetup, TApplication> and check if that helps - you would also need to make your SplashScreen is MainLauncher. Your code could look like this:
[Activity(Label = "FirstDemo.Forms.Splash", Theme = "#style/MainTheme", MainLauncher = true, NoHistory = true)]
public class SplashScreen : MvxFormsSplashScreenAppCompatActivity<MvxFormsAndroidSetup<Core.App, App>, Core.App, App>
{
public SplashScreen()
: base(Resource.Layout.SplashScreen)
{
}
protected override void RunAppStart(Bundle bundle)
{
StartActivity(typeof(MainActivity));
base.RunAppStart(bundle);
}
}
If the above is not clear, check out blog post by Nick Randolph (a contributor to MvvmCross), that writes about setting up a brand new project with MvvmCross v6. I know you're upgrading - so it's not the same, but you can at least check if you have made all the changes that are required to run the app. Here's his GitHub repo, with the sample code that I pasted in
After I few days, searching, seeing gihub files and talking with Nick Randolph as #Ale_lipa suggested.
I noticed that the problem was on the .csproj file under the .Droid project. It was trying to compile files that I manually removed from the project and didn't even exist.
I changed it to match the file that Nick has in his repository.
This is the final look:
<ItemGroup>
<Compile Include="SplashScreen.cs" />
<Compile Include="MainApplication.cs" />
<Compile Include="Resources\Resource.Designer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Views\FirstView.cs" />
</ItemGroup>
Now everything works fine.
I followed the exact steps on the blog post series by Nick Randolph referenced in other answers, and received the same problem as the question specifies [Failed to create setup instance] but in the Xamarin.Forms article. This was due to mixing code from a different part of the example. My specific issue was because the ActivityAttribute that declared MainLauncher=true derived from MvxFormsAppCompatActivity<TViewModel> instead of MvxFormsAppCompatActivity<TMvxAndroidSetup, TApplication, TFormsApplication, TViewModel> Looks like the OP #Brugui sample code may have had the same flaw.

Get Assembly From C# Project File

I am trying to make a simple WinForm tool to assist with code generation, and I was wondering if it was possible to get the Assembly of one project into a different one that presides in a different solution. I want the form to show all of the classes and then properties for each class, and the easiest/best way I can think of doing that is like:
private Type[] GetTypesInNamespace(Assembly assembly, string nameSpace)
{
return assembly.GetTypes().Where(t => String.Equals(t.Namespace, nameSpace, StringComparison.Ordinal)).ToArray();
}
If the user selects a .csproj file, is it possible to get the Assembly? Or is there a different way to get the classes/properties without recursively searching the project folder and parsing the files?
The csproj file will contain the assembly name and the output directory.
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<AssemblyName>MyAppAssemblyNameOnly</AssemblyName>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
</PropertyGroup>
</Project>
You'll have to add .dll suffix to it to get the actual file name.
The Output Path can be found in the different Configuration <PropertyGroup> nodes.
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>x86</PlatformTarget>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
</PropertyGroup>
There's a couple of problems I can think of right off the bat.
The DLL may not be built and so it won't exist.
There are many different configurations with there being Debug and Release by default. You'll have to decide which one to look for.
For ease, you may just want to make the user feed you a DLL if the project is not part of the solution and you don't actually need anything else.
You can also look into Roslyn and parse the files with Roslyn to get you all of the information you need too.
Here's an example straight from their page. Seems super simple and straightforward. Kind of larger than I want, but don't want to just give a single link-only suggestion.
class Program
{
static void Main(string[] args)
{
SyntaxTree tree = CSharpSyntaxTree.ParseText(
#"using System;
using System.Collections;
using System.Linq;
using System.Text;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(""Hello, World!"");
}
}
}");
var root = (CompilationUnitSyntax)tree.GetRoot();
var firstMember = root.Members[0];
var helloWorldDeclaration = (NamespaceDeclarationSyntax)firstMember;
var programDeclaration = (ClassDeclarationSyntax)helloWorldDeclaration.Members[0];
var mainDeclaration = (MethodDeclarationSyntax)programDeclaration.Members[0];
var argsParameter = mainDeclaration.ParameterList.Parameters[0];
}
}

Categories