MessageBox in .net core 5 - c#

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!");
}
}
}

Related

How do you programmatically setup the GLWpfControl?

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.

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.

How to read/get a PropertyGroup value from a .csproj file using C# in a .NET Core 2 classlib project?

I want to get the value of the element <Location>SourceFiles/ConnectionStrings.json</Location> that is child of <PropertyGroup /> using C#. This is located at the .csproj file for a .NET Core 2 classlib project. The structure is as follow:
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<Location>SharedSettingsProvider.SourceFiles/ConnectionStrings.json</Location>
</PropertyGroup>
Which class can I use from .NET Core libraries to achieve this? (not .NET framework)
Update 1:
I want to read the value when the application (that this .csproj file builds) runs. Both before and after deployment.
Thanks
As has been discussed in comments, csproj content only controls predefined build tasks and aren't available at run-time.
But msbuild is flexible and other methods could be used to persist some values to be available at run time.
One possible approach is to create a custom assembly attribute:
[System.AttributeUsage(System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)]
sealed class ConfigurationLocationAttribute : System.Attribute
{
public string ConfigurationLocation { get; }
public ConfigurationLocationAttribute(string configurationLocation)
{
this.ConfigurationLocation = configurationLocation;
}
}
which can then be used in the auto-generated assembly attributes from inside the csproj file:
<PropertyGroup>
<ConfigurationLocation>https://my-config.service/customer2.json</ConfigurationLocation>
</PropertyGroup>
<ItemGroup>
<AssemblyAttribute Include="An.Example.ConfigurationLocationAttribute">
<_Parameter1>"$(ConfigurationLocation)"</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
And then used at run time in code:
static void Main(string[] args)
{
var configurationLocation = Assembly.GetEntryAssembly()
.GetCustomAttribute<ConfigurationLocationAttribute>()
.ConfigurationLocation;
Console.WriteLine($"Should get config from {configurationLocation}");
}

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];
}
}

How do I use TextWriter.Synchronized in netcoreapp1.1

I want to use TextWriter.Synchronized method in my app. My target framework is: netcoreapp1.1.
This is the program I am trying to compile:
using System;
using System.IO;
namespace program
{
class Program
{
static void Main(string[] args)
{
using (var log = File.CreateText("out.log"))
{
var syncedLog = TextWriter.Synchronized(log);
}
}
}
}
This is my csproj file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>
</Project>
Unfortunatelly, this does not work:
> dotnet run
Program.cs(12,47): error CS0117: 'TextWriter' does not contain a definition for 'Synchronized'
How do I fix this?
Since TextWriter.Synchronized does not exist on .Net Core 1.1, you will have to implement it yourself. As a start, you can use the .Net Core 2.0 implementation. You won't be able to use that code directly, because it extensively uses [MethodImpl(MethodImplOptions.Synchronized)], which is also not supported on .Net Core 1.1. But you can replace that with lock (this) in each such method.

Categories