Get ApplicationIcon from Code in NET Core 3.0 - c#

In the .csproj I assign an icon to my .NET Core 3.0 application:
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<ApplicationIcon>C:\temp\myicon.ico</ApplicationIcon>
</PropertyGroup>
</Project>
The icon gets set for the generated exe file and shown in task-manager/file explorer.
How can I access this icon from code? I don't want to extract it from generated exe or add an additional resource icon.

you can extract like this
using System;
using System.Drawing; //For Icon
using System.Reflection; //For Assembly
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
try
{
//Gets the icon associated with the currently executing assembly
//(or pass a different file path and name for a different executable)
Icon appIcon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);
}
catch(ArgumentException ae)
{
//handle
}
}
}
}

//We can use this statement.
using System.Drawing;
using System.Reflection;
static void Main(string[] args)
{
try
{
Icon appIcon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);
}
catch(ArgumentException ae)
{
//handle
}

Related

Roslyn fails to compile a trivial project

I am trying to use Roslyn to compile a trivial project but it fails.
Consider the following setup (assuming c:\temp exists and you have .NET 6 installed):
mkdir c:\temp\TestLib
notepad c:\temp\TestLib\TestLib.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
notepad c:\temp\TestLib\SomeClass.cs
namespace TestLib
{
public class SomeClass
{
void DoThings()
{
Console.WriteLine("Things!");
}
}
}
cd c:\temp\TestLib
dotnet build
Result: Build succeeded
mkdir c:\temp\RoslynTrouble
notepad c:\temp\RoslynTrouble\RoslynTrouble.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Build.Locator" Version="1.5.5" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.8.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="3.8.0" />
</ItemGroup>
</Project>
notepad c:\temp\RoslynTrouble\Program.cs
using Microsoft.Build.Locator;
using Microsoft.CodeAnalysis.MSBuild;
class TestProgram
{
public static async Task Main(string[] args)
{
string csprojPath = args[0];
var instance = MSBuildLocator.RegisterDefaults();
Console.WriteLine(instance.Name + ": " + instance.Version);
var workspace = MSBuildWorkspace.Create();
var project = await workspace.OpenProjectAsync(csprojPath);
var compilation = await project.GetCompilationAsync();
if (compilation == null)
{
Console.WriteLine("Error: unexpected null compilation");
return;
}
foreach (var diagnostic in compilation.GetDiagnostics())
{
Console.WriteLine(diagnostic);
}
}
}
cd c:\temp\RoslynTrouble
dotnet run c:\temp\TestLib\TestLib.csproj
Expected result: no errors
Actual result: lots of compilation errors:
.NET Core SDK: 6.0.203
c:\open\prototypes\TestLib\obj\Debug\net6.0\TestLib.GlobalUsings.g.cs(2,1): error CS0116: A namespace cannot directly contain members such as fields or methods
c:\open\prototypes\TestLib\obj\Debug\net6.0\TestLib.GlobalUsings.g.cs(3,1): error CS0116: A namespace cannot directly contain members such as fields or methods
c:\open\prototypes\TestLib\obj\Debug\net6.0\TestLib.GlobalUsings.g.cs(4,1): error CS0116: A namespace cannot directly contain members such as fields or methods
c:\open\prototypes\TestLib\obj\Debug\net6.0\TestLib.GlobalUsings.g.cs(5,1): error CS0116: A namespace cannot directly contain members such as fields or methods
c:\open\prototypes\TestLib\obj\Debug\net6.0\TestLib.GlobalUsings.g.cs(6,1): error CS0116: A namespace cannot directly contain members such as fields or methods
c:\open\prototypes\TestLib\obj\Debug\net6.0\TestLib.GlobalUsings.g.cs(7,1): error CS0116: A namespace cannot directly contain members such as fields or methods
c:\open\prototypes\TestLib\obj\Debug\net6.0\TestLib.GlobalUsings.g.cs(8,1): error CS0116: A namespace cannot directly contain members such as fields or methods
c:\open\prototypes\TestLib\SomeClass.cs(7,13): error CS0103: The name 'Console' does not exist in the current context
c:\open\prototypes\TestLib\obj\Debug\net6.0\TestLib.GlobalUsings.g.cs(2,8): hidden CS8019: Unnecessary using directive.
c:\open\prototypes\TestLib\obj\Debug\net6.0\TestLib.GlobalUsings.g.cs(8,8): hidden CS8019: Unnecessary using directive.
c:\open\prototypes\TestLib\obj\Debug\net6.0\TestLib.AssemblyInfo.cs(11,1): hidden CS8019: Unnecessary using directive.
c:\open\prototypes\TestLib\obj\Debug\net6.0\TestLib.GlobalUsings.g.cs(7,8): hidden CS8019: Unnecessary using directive.
c:\open\prototypes\TestLib\obj\Debug\net6.0\TestLib.GlobalUsings.g.cs(6,8): hidden CS8019: Unnecessary using directive.
c:\open\prototypes\TestLib\obj\Debug\net6.0\.NETCoreApp,Version=v6.0.AssemblyAttributes.cs(2,1): hidden CS8019: Unnecessary using directive.
c:\open\prototypes\TestLib\obj\Debug\net6.0\TestLib.GlobalUsings.g.cs(3,8): hidden CS8019: Unnecessary using directive.
c:\open\prototypes\TestLib\obj\Debug\net6.0\TestLib.AssemblyInfo.cs(12,1): hidden CS8019: Unnecessary using directive.
c:\open\prototypes\TestLib\obj\Debug\net6.0\TestLib.GlobalUsings.g.cs(4,8): hidden CS8019: Unnecessary using directive.
c:\open\prototypes\TestLib\obj\Debug\net6.0\TestLib.GlobalUsings.g.cs(5,8): hidden CS8019: Unnecessary using directive.
c:\open\prototypes\TestLib\obj\Debug\net6.0\.NETCoreApp,Version=v6.0.AssemblyAttributes.cs(3,1): hidden CS8019: Unnecessary using directive.
What am I missing and how can I fix those errors?
Below you'll find the modifications described in a Note. Try the following:
mkdir c:\temp\TestLib
notepad c:\temp\TestLib\TestLib.csproj
Click Yes
TestLib.csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
Save As (save with "UTF-8" encoding)
notepad c:\temp\TestLib\SomeClass.cs
Click Yes
SomeClass.cs:
Note: Made the method public - not much point in having a class with one method and making it private.
namespace TestLib
{
public class SomeClass
{
public void DoThings()
{
Console.WriteLine("Things!");
}
}
}
Save As (save with "UTF-8" encoding)
mkdir c:\temp\RoslynTrouble
notepad c:\temp\RoslynTrouble\RoslynTrouble.csproj
Click Yes
RoslynTrouble.csproj:
Note: Use version 4.4.0 for Microsoft.CodeAnalysis.CSharp.Workspaces and Microsoft.CodeAnalysis.Workspaces.MSBuild.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Build.Locator" Version="1.5.5" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.4.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="4.4.0" />
</ItemGroup>
</Project>
Save As (save with "UTF-8" encoding)
notepad c:\temp\RoslynTrouble\Program.cs
Click Yes
Program.cs:
Note: Added namespace RoslynTrouble. Changed class name to Program to match the filename (Program.cs).
using Microsoft.Build.Locator;
using Microsoft.CodeAnalysis.MSBuild;
namespace RoslynTrouble
{
public class Program
{
public static async Task Main(string[] args)
{
string csprojPath = args[0];
var instance = MSBuildLocator.RegisterDefaults();
Console.WriteLine(instance.Name + ": " + instance.Version);
var workspace = MSBuildWorkspace.Create();
var project = await workspace.OpenProjectAsync(csprojPath);
var compilation = await project.GetCompilationAsync();
if (compilation == null)
{
Console.WriteLine("Error: unexpected null compilation");
return;
}
foreach (var diagnostic in compilation.GetDiagnostics())
{
Console.WriteLine(diagnostic);
}
}
}
}
Save As (save with "UTF-8" encoding)
cd c:\temp\RoslynTrouble
dotnet run "C:\temp\TestLib\TestLib.csproj"
Note: The double-quotes in the command above are optional since there aren't any spaces in the path.
Result:
Note: The result has warnings, but no errors.
.NET Core SDK: 6.0.301
C:\temp\TestLib\obj\Debug\net6.0\.NETCoreApp,Version=v6.0.AssemblyAttributes.cs(2,7): hidden CS8933: The using directive for 'System' appeared previously as global using
C:\temp\TestLib\obj\Debug\net6.0\TestLib.AssemblyInfo.cs(10,7): hidden CS8933: The using directive for 'System' appeared previously as global using
C:\temp\TestLib\obj\Debug\net6.0\TestLib.GlobalUsings.g.cs(5,1): hidden CS8019: Unnecessary using directive.
C:\temp\TestLib\obj\Debug\net6.0\TestLib.GlobalUsings.g.cs(3,1): hidden CS8019: Unnecessary using directive.
C:\temp\TestLib\obj\Debug\net6.0\TestLib.GlobalUsings.g.cs(4,1): hidden CS8019: Unnecessary using directive.
C:\temp\TestLib\obj\Debug\net6.0\TestLib.AssemblyInfo.cs(11,1): hidden CS8019: Unnecessary using directive.
C:\temp\TestLib\obj\Debug\net6.0\.NETCoreApp,Version=v6.0.AssemblyAttributes.cs(2,1): hidden CS8019: Unnecessary using directive.
C:\temp\TestLib\obj\Debug\net6.0\TestLib.GlobalUsings.g.cs(8,1): hidden CS8019: Unnecessary using directive.
C:\temp\TestLib\obj\Debug\net6.0\.NETCoreApp,Version=v6.0.AssemblyAttributes.cs(3,1): hidden CS8019: Unnecessary using directive.
C:\temp\TestLib\obj\Debug\net6.0\TestLib.AssemblyInfo.cs(10,1): hidden CS8019: Unnecessary using directive.
C:\temp\TestLib\obj\Debug\net6.0\TestLib.GlobalUsings.g.cs(7,1): hidden CS8019: Unnecessary using directive.
C:\temp\TestLib\obj\Debug\net6.0\TestLib.GlobalUsings.g.cs(6,1): hidden CS8019: Unnecessary using directive.
If one would like to avoid displaying warnings, one could use the following alternative code for Program.cs:
using Microsoft.Build.Locator;
using Microsoft.CodeAnalysis.MSBuild;
namespace RoslynTrouble
{
public class Program
{
public static async Task Main(string[] args)
{
bool errorsExist = false;
string csprojPath = args[0];
var instance = MSBuildLocator.RegisterDefaults();
Console.WriteLine(instance.Name + ": " + instance.Version);
var workspace = MSBuildWorkspace.Create();
var project = await workspace.OpenProjectAsync(csprojPath);
var compilation = await project.GetCompilationAsync();
if (compilation == null)
{
Console.WriteLine("Error: unexpected null compilation");
return;
}
foreach (Microsoft.CodeAnalysis.Diagnostic diagnostic in compilation.GetDiagnostics())
{
if (diagnostic.Severity != Microsoft.CodeAnalysis.DiagnosticSeverity.Hidden &&
diagnostic.Severity != Microsoft.CodeAnalysis.DiagnosticSeverity.Warning)
{
Console.WriteLine(diagnostic);
errorsExist = true;
}
}
if (!errorsExist)
Console.WriteLine($"Successfully compiled '{args[0]}'.");
}
}
}
Resources:
Roslyn Code Analysis returns false build errors from an error free solution

Edit and Continue doesn't work with Roslyn compiled class library

Background
I'm trying to get Edit and Continue to work with a class library I'm compiling at runtime using Roslyn. This is for adding modding support to a game I'm developing.
Breakdown of problem
I have one class library project (A) with source files (.cs)
I have another console application project (B) in another solution that does the following:
Compiles all of project A's source files
Emits a dll and pdb
Loads the emitted dll and pdb via an assembly context
Calls a static method defined within project B
My desire is to be able to attach a debugger to a running process of project B in an instance of VS with project A loaded and be able to break, edit project A's code, and continue with my changes being executed
Currently, I am only able to break and continue
Any edits lead to the following notification:
This source file has changed. It no longer matches the version of the file used to build the application being debugged.
Source
Project A: DebuggableClassLibrary.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
</Project>
Project A: Test.cs
using System;
namespace DebuggableClassLibrary
{
public class Test
{
public static int Ct = 0;
public static void SayHello()
{
Ct++;
Console.WriteLine("Hello World");
}
}
}
Project B: DynamicLoading.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0" />
</ItemGroup>
</Project>
Project B: Program.cs
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using System.Text;
namespace DynamicLoading
{
class Program
{
static void Main(string[] args)
{
var references = new MetadataReference[]
{
MetadataReference.CreateFromFile(Assembly.Load("System.Runtime").Location),
MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
MetadataReference.CreateFromFile(typeof(Console).Assembly.Location)
};
var files = Directory.GetFiles(#"C:\Users\mrbri\source\repos\DebuggableClassLibrary\DebuggableClassLibrary", "*.cs");
var assemblyName = "DebuggableClassLibrary.dll";
var debug = true;
var allowUnsafe = false;
var outputDirectory = #"C:\Users\mrbri\Documents\Test";
var preprocessorSymbols = debug ? new string[] { "DEBUG" } : new string[] { };
var parseOptions = new CSharpParseOptions(LanguageVersion.Latest, preprocessorSymbols: preprocessorSymbols);
var compilation = CSharpCompilation.Create(
assemblyName: assemblyName,
syntaxTrees: files.Select(f => SyntaxFactory.ParseSyntaxTree(File.ReadAllText(f), parseOptions, f, Encoding.UTF8)),
references: references,
options: new CSharpCompilationOptions(
OutputKind.DynamicallyLinkedLibrary,
assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default,
optimizationLevel: debug ? OptimizationLevel.Debug : OptimizationLevel.Release,
allowUnsafe: allowUnsafe
));
var pePath = Path.Combine(outputDirectory, assemblyName);
var pdbPath = Path.Combine(outputDirectory, Path.ChangeExtension(assemblyName, ".pdb"));
using (var peStream = new FileStream(pePath, FileMode.Create))
using (var pdbStream = new FileStream(pdbPath, FileMode.Create))
{
var results = compilation.Emit(
peStream: peStream,
pdbStream: pdbStream,
options: new EmitOptions(debugInformationFormat: DebugInformationFormat.PortablePdb)
);
}
var assemblyLoadContext = new SimpleUnloadableAssemblyLoadContext();
var assembly = assemblyLoadContext.LoadFromStream(File.OpenRead(pePath), File.OpenRead(pdbPath));
var type = assembly.GetTypes().First();
var method = type.GetMethod("SayHello");
while (true)
{
method.Invoke(null, null);
}
}
}
internal class SimpleUnloadableAssemblyLoadContext : AssemblyLoadContext
{
public SimpleUnloadableAssemblyLoadContext(): base(true) { }
protected override Assembly Load(AssemblyName assemblyName) => null;
}
}
Attempts at solutions and observations
Compiling project A manually through VS and loading the generated pdb and dll exactly as I do for the Roslyn compiled one does allow for Edit and Continue
Comparing project A's dlls generated via Roslyn and VS in JetBrains dotPeek did yield some interesting differences that stem from the compilation time generated .NETCoreApp,Version=v5.0.AssemblyAttributes.cs and DebuggableClassLibrary.AssemblyInfo.cs that I do not include when I compile in project B
Going through the trouble of compiling project A via a MSBuildWorkspace Project did not allow Edit and Continue, although did include .NETCoreApp,Version=v5.0.AssemblyAttributes.cs and DebuggableClassLibrary.AssemblyInfo.cs
Alternatives
I am open to Roslyn alternatives/wrappers that do have Edit and Continue support.
Edit and Continue does not support this scenario. The project for the library being edited needs to be loaded in VS (in the current solution) and the program needs to be launched with the debugger attached.

Cannot see the Image type in System.Drawing namespace in .NET

I'm trying to write a program that sorts images in specific folder by ther dimensions and moves little images to another folder via simple .NET console application. I decided to use System.Drawing.Image class to get the image dimentions from an image file. But I face following error:
The type or namespace name 'Image' could not be found (are you missing
a using directive or an assembly referrence?)
What exactly did I do wrong and why it doesn't see this class?
Here are the complete code of my program:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Drawing;
namespace ImageSort
{
class Program
{
static void Main(string[] args)
{
string targetPath = #"d:\SmallImages";
string[] files = Directory.GetFiles(#"d:\Images");
foreach (string path in files)
{
if (File.Exists(path))
{
Image newImage = Image.FromFile(path);
var Width = (int)(newImage.Width);
var Height = (int)(newImage.Height);
if (Width * Height < 660000) {
System.IO.File.Move(path, targetPath);
}
}
}
}
}
}
You need to add a reference : System.Drawing.dll.
In Solution Explorer, right-click on the References node and choose Add Reference and find System.Drawing.dll.
The answer to this issue for .NET Core 3.1 is to simply install System.Drawing.Common from NuGet.

How can i get lines of code / fetch declaration in c#? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
Hi can anyone tell me that how can I fetch lines of code from C# code.
For example, I have following code in c#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyCodeHelp
{
class MultiplicationProgram
{
public int Multiplication(int Firstnumber, int SecondNumber)
{
int Result = (Firstnumber * SecondNumber);
return Result;
}
}
}
So please tell me how can I fetch the following code from the code above and display it in a label or panel?
public int Multiplication(int Firstnumber, int SecondNumber)
{
int Result = (Firstnumber * SecondNumber);
return Result;
}
Get your panel/label name and just do this:
labelName.Text = Result.ToString();
You cannot get the code from the compiled dll, you have to include the code as a resource or as loose files. One way to do this is to add an MSBuild step that causes all Compile items to be embedded as EmbeddedResources.
In your .csproj file, add the below to the end:
Before:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- ... -->
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
After:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- ... -->
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="CodeAsResource" BeforeTargets="BeforeBuild">
<ItemGroup>
<EmbeddedResource Include="#(Compile)" />
</ItemGroup>
</Target>
</Project>
Then you can access it as a resource:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Resources;
using System.Text;
using System.Threading.Tasks;
namespace Codeception
{
class Program
{
static void Main(string[] args)
{
var code = getcode("Program.cs");
Console.WriteLine(code);
}
private static string getcode(string filename)
{
using (var sr = new StreamReader(typeof(Program).Assembly.GetManifestResourceStream("Codeception." + filename)))
{
return sr.ReadToEnd();
}
}
}
}
Here is an example:
private void Form1_Load(object sender, EventArgs e)
{
string filePath = #"";
using (var sr = new StreamReader(filePath))
{
string line;
while ((line = sr.ReadLine()) != null)
{
label1.Text += "\n" + line;
}
}
}
Well, I imagine you want to fetch some lines from the source code you wrote, right?
First of all, you need to ship your code (or a text copy of your code) with your binaries, and put it in a known path.
Then, you can Open the file with File.OpenText method (example in https://msdn.microsoft.com/en-us/library/system.io.file.opentext(v=vs.110).aspx ).
To get specific content from the file (which is the StreamReader you received as return from OpenText method), you can call ReadLine method (example in https://msdn.microsoft.com/en-us/library/system.io.streamreader.readline(v=vs.110).aspx) and search wit String compares (https://msdn.microsoft.com/en-us/library/system.string.compare(v=vs.110).aspx) if you found the piece of code you are looking for.
If you are thinking of changing the code later, I recommend you put the code you would like to share inside a "region" tag (https://msdn.microsoft.com/en-us/library/9a1ybwek.aspx). This way you can look for that region specifically, and you don't need to worry about changing your code.
I hope I could help you.

Roslyn CTP - How to Write Changes To File System

I created an empty Visual Studio Solution called Solution.sln which I load into the workspace int the first line. Then I add a project to the solution, and update the workspace to the latest solution which should now contain a project. How do I write out the files for the new stuff I added to the empty solution?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Roslyn.Compilers;
using Roslyn.Compilers.CSharp;
using Roslyn.Services;
namespace RoslynMainApp
{
class Program
{
static void Main(string[] args)
{
IWorkspace workspace = Workspace.LoadSolution(#"C:\RoslynSolutions\Solution.sln");
ProjectId projectId;
ISolution solution = Solution.Create(SolutionId.CreateNewId("Solution"));
solution.AddCSharpProject("Project1.dll", "Project1", out projectId);
var success = workspace.ApplyChanges(workspace.CurrentSolution, solution);
if(success)
{
//How do I write out all the stuff I just added to Solution.sln to the directory RoslynSolutions?
}
}
}
}
Thanks in advance,
Bob
The act of calling ApplyChanges should write the changes to disk. However, note that in CTP1, only a small set of the changes you can apply to solutions are actually implemented.

Categories