How to get JIT output for C# applications on Linux? - c#

Let's say, we have a server with Ubuntu 22.04 and ARM64 architecture. Also, we have the latest dotnet:
$ dotnet --version
7.0.102
I want to view JIT assembly output for a program, for example:
C.CurrentAction()
19fc: 64616572 strbtvs r6, [r1], #-1394 ; 0xfffffa8e
1a00: 6e6f635f mcrvs 3, 3, r6, cr15, cr15, {2}
1a04: 69735f64 ldmdbvs r3!, {r2, r5, r6, r8, r9, sl, fp, ip, lr}^
1a08: 6c616e67 stclvs 14, cr6, [r1], #-412 ; 0xfffffe64
1a0c: 68747000 ldmdavs r4!, {ip, sp, lr}^
1a10: 64616572 strbtvs r6, [r1], #-1394 ; 0xfffffa8e
1a14: 7474615f ldrbtvc r6, [r4], #-351 ; 0xfffffea1
We can do it on https://sharplab.io/, however this website doesn't support ARM64 at the moment. Also, we can do it in Visual studio, using Disassembly window, but we have a server without Visual studio.
I am looking for something similar to PrintAssembly in Java, which allows to get JIT output from command line.

I've found a few things, which could work for you, but it doesn't work for me on Linux (it works in Windows, though):
DOTNET_JitDisasm - https://devblogs.microsoft.com/dotnet/performance_improvements_in_net_7/
Using BenchmarkDotNet to get ASM - https://github.com/dotnet/BenchmarkDotNet/issues/1422

Related

Using Span<T> on ARM gives "System.DataMisalignedException:"

I am trying to read data and convert it from a Modbus RTU sensor using .NET 7. Everything is working on my Linux-x64 machine but not when i try to run it on the RevPi core S linux-arm...
Modbus RTU config
Sensor Instructions
I am using FluentModbus version 5.0.2:
fluentClient = new ModbusRtuClient()
{
BaudRate = 9600,
Parity = Parity.None,
StopBits = StopBits.One
};
fluentClient.Connect("/dev/ttyUSB" + port, ModbusEndianness.LittleEndian);
Console.WriteLine("Reading Calibration");
var calibration = fluentClient.ReadHoldingRegisters(1, 8704, 4);
var hexCalibration = Convert.ToHexString(calibration);
foreach (var item in calibration)
{
Console.Write(item);
}
foreach (var item in hexCalibration)
{
Console.Write(item);
}
//The code below works perfect on my machine running Ubuntu 22.04(linux-x64) but does not work //on RevPi Core running Debian custom Buster image (Linux-arm).
var floatCalibration = fluentClient.ReadHoldingRegisters<float>(1, 8704, 4);
Console.WriteLine("calibration K: " + floatCalibration[0]);
Console.WriteLine("calibration B: " + floatCalibration[1]);
Terminal output My computer:
Reading Calibration
000631541535764
0000003F9A993940
calibration K: 0.5
calibration B: 2.9
Terminal output RevPi Core:
Reading Calibration
000631541535764
0000003F9A993940
Unhandled exception. System.DataMisalignedException: A datatype misalignment was detected in a load or store instruction.
at exsys.Program.Main(String[] args) in /home/user/FunctionTest/Program.cs:line 179
Aborted
And this is line 179: Console.WriteLine("calibration K: " + floatCalibration[0]);
Is it not possible to use .Net7 Span<float> on linux Arm? I have tried different setups, but no luck yet. Maybe someone else have run in to this issue?
Tried dotnet publish to self contained linux-x64 and everything works fine. i only get the error when compiling to linux-arm and running it.
Tried different converting setups but no luck.
I have updated the image on the RevPi Core S released in November 2022, but it did not help.
Tried first running on .NET 6 and now on .NET 7. Same error on both.
FluentModbus is breaking alignment here:
https://github.com/Apollo3zehn/FluentModbus/blob/master/src/FluentModbus/Client/ModbusClient.cs#L155
and then calls MemoryMarshal.Cast which is a problem on ARM, because the documentation says
This method is supported only on platforms that support misaligned memory access or when the memory block is aligned by other means.
ARM is not a platform that supports misaligned memory access.
A good workaround would be to allocate a float[], call the version of ReadHoldingRegisters that returns Span<byte>, and call CopyTo(MemoryMarshal.AsBytes(destFloatArray)).

How can I find the Windows product name in Windows 11?

Windows 11, released yesterday, reports itself as Windows 10.0 just about everywhere - RtlGetVersion says 10.0, and if you ask VerifyVersionInfo if you are 11.0 or greater, it says no.
There seems to be no new GUID to shove into app.manifest to say "hey I support Windows 11" like there was for Windows 7, 8, 8.1, and 10.
Currently I rely on HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName to tell me what the current version of Windows is, but on my machine that I've upgraded, it still says "Windows 10 Enterprise", not "Windows 11 Enterprise".
There appears to only be a single place in the registry that contains the text "Windows 11" and that is the BCD section (boot configuration), which can also be renamed so I don't want to touch that.
So far I have only identified a handful of methods to tell if I am running on Windows 11:
Invoke WMI to query Win32_OperatingSystem and check the Name property, which simply says "Windows 11". This is incomplete (it does not include the SKU such as "Enterprise"), and WMI is relatively slow and slightly brittle, so it's not an acceptable solution for my use-case.
Check the build number to see if it is above 21996 (beta builds) or 22000 (first public release). As above, this won't include the SKU, and would require some manual jiggery-pokery in order to build the full string.
Run sysinfo and parse the output. This is quite slow, and possibly brittle (I haven't checked but the output might be localised into different languages).
winver knows, but it's a GUI application so I can't exactly query it programmatically.
Does anyone have any other ideas on how to get the string "Windows 11 Enterprise" (or "Windows 11 Pro", etc. as the case may be) out of my operating system in a performant and complete manner? Where do WMI, sysinfo, and winver get it from?
I need to do this from a .NET library, but P/Invokes / native function calls are acceptable solutions.
Leaving this here so that I can find it later:
It seems that Windows itself (e.g. winver) gets this information from Windows branding - specifically from the resource table in %WinDir%\Branding\Basebrd\en-US\basebrd.dll.mui.
To access this one could use the private APIs in %WinDir%\System32\winbrand.dll. Specifically, the function BrandingFormatString which accepts a wide string (LPW[C]STR) and returns a wide string.
e.g. BrandingFormatString("%WINDOWS_LONG%") returns "Windows 11 Pro" on my home PC.
I do not know the lifecycle semantics of the resulting string, i.e. if/when/how it should be freed.
The following code serves as a functional proof-of-concept (C# 9.0):
using System;
using System.Runtime.InteropServices;
[DllImport("winbrand.dll", CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
static extern string BrandingFormatString(string format);
Console.WriteLine(BrandingFormatString("Hello World from %WINDOWS_LONG%!"));
tldr - Using the EditionID and the CurrentBuild from the CurrentVersion in the registry seems to be a reliable way to determine Win10 vs Win11 and the "edition" of the software. EditionID is "Professional" on Windows 10 Pro and Windows 11 Pro, and CurrentBuild >= ~22000 tells you if it is 10 or 11.
The collection of registry values in the HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion reveals what feels like a lack of planning on Microsoft's part. There's ReleaseId, which is a number that changed with each Windows 10 release (e.g., 1903, 1909, 2004,...) until its last change for Windows 10 20H2, where it changed to 2009. At the same time, DisplayVersion was added, and was set to 20H2.
Then Windows 10 21H1 released, and ReleaseId inexplicably stayed at 2009.
The fact that both current Windows 10 and Windows 11 releases can have the same DisplayVersion (e.g., 21H2 when Windows 10 21H2 releases soon) and ProductName (e.g., Windows 10 Pro) is really head-scratching. (Thanks #yaakov for catching my mistake saying it was 21H1.)
The following code has been tested on Windows XP, 7, 10, 11. It works on 32 bit and 64 bit operating systems. It works inside 32 bit and 64 bit applications.
The following strings will be generated:
"Microsoft Windows XP, Build 2600, 32 bit"
"Windows 7 Ultimate, Build 7601, 64 bit"
"Windows 10 Enterprise LTSC 2019, Version 1809, Build 17763, 64 bit"
"Windows 10 Pro, Version 1909, Build 18362, 64 bit"
"Windows 11 Professional, Version 21H2, Build 22000, 64 bit"
Put the code into a static constructor so it executes only once and writes the version into a static variable.
static String ms_OperatingSystem;
static Constructor()
{
try
{
String s_KernelPath = Path.Combine(Environment.SystemDirectory,"Kernel32.dll");
FileVersionInfo k_Kernel = FileVersionInfo.GetVersionInfo(s_KernelPath);
// on 32 bit Windows this will read the 32 bit hive instead
using (RegistryKey i_HKLM = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
{
using (RegistryKey i_RegVer = i_HKLM.OpenSubKey(#"Software\Microsoft\Windows NT\CurrentVersion", false))
{
// Kernel32.dll on Windows 11 has Product Version 10.0.22000.120
if (k_Kernel.ProductMajorPart == 10 && k_Kernel.ProductBuildPart >= 22000)
{
ms_OperatingSystem = "Windows 11";
Object o_Edition = i_RegVer.GetValue("EditionID"); // "Professional"
if (o_Edition is String)
ms_OperatingSystem += " " + o_Edition;
}
else
{
// "Microsoft Windows XP"
// "Windows 7 Ultimate"
// "Windows 10 Pro" (same string on Windows 11. Microsoft SUCKS!)
ms_OperatingSystem = (String)i_RegVer.GetValue("ProductName");
}
// See: https://en.wikipedia.org/wiki/Windows_10_version_history
// Windows 10 older releases --> "2009" (invalid if DisplayVersion exists)
Object o_ReleaseID = i_RegVer.GetValue("ReleaseId");
// Windows 10 latest release --> "21H1"
// Windows 11 first release --> "21H2"
Object o_DispVer = i_RegVer.GetValue("DisplayVersion");
// Use ReleaseID ONLY if DisplayVersion does not exist in registry!
if (o_DispVer is String) ms_OperatingSystem += ", Version " + o_DispVer;
else if (o_ReleaseID is String) ms_OperatingSystem += ", Version " + o_ReleaseID;
ms_OperatingSystem += ", Build " + k_Kernel.ProductBuildPart;
if (Environment.Is64BitOperatingSystem) ms_OperatingSystem += ", 64 bit";
else ms_OperatingSystem += ", 32 bit";
}
}
}
catch (Exception Ex)
{
ms_OperatingSystem = Ex.Message;
}
}
I created a remote support tool for desktop admins (see http://www.appslife-rdt.appspot.com) In VB.Dot.Net i used a call to the WMI space Win32_OperatingSystem and got the "Name" value back. This then needs to be split to get the first object which is what you require. i.e.
Dim query2 As New SelectQuery("SELECT * FROM Win32_OperatingSystem")
Dim searcher2 As New ManagementObjectSearcher(objManagementScope2, query2, QueryOptions)
For Each mo As ManagementObject In searcher2.[Get]()
OSname = mo("Name")
Next
Dim array1 As Array = Nothing
array1 = Split(OSname, "|")
OSname = array1(0).ToString
OSname then gives you the "Windows 11 Pro" or "Windows XP Professional" that you require.
I also get the OSVersion with the latest patch update info from registry as follows if needed...
THIS IS FOR CLIENT VERSIONS 10/11 :-
.SetPropertyValue("sSubKeyName", "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Update\TargetingInfo\Installed\Client.OS.rs2.amd64")
.SetPropertyValue("sValueName", "Version")
THIS IS FOR SERVER VERSIONS 2019 :-
.SetPropertyValue("sSubKeyName", "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Update\TargetingInfo\Installed\Server.OS.amd64")
.SetPropertyValue("sValueName", "Version")
Hope this is of help.

Running ReadMe in Pythonnet

Environment :
Pythonnet version: 2.3.0, installed with pip in Amaconda3
Python version: 3.6.6 using with Anaconda
Visual Studio 2017 Community
Operating System: Windows 7, 64 bit
I am running this example from Pythonnet wiki.
using (Py.GIL())
{
dynamic np = Py.Import("numpy");
Console.WriteLine(np.cos(np.pi * 2));
dynamic sin = np.sin;
Console.WriteLine(sin(5));
double c = np.cos(5) + sin(5);
Console.WriteLine(c);
dynamic a = np.array(new List<float> { 1, 2, 3 });
Console.WriteLine(a.dtype);
dynamic b = np.array(new List<float> { 6, 5, 4 }, dtype: np.int32);
Console.WriteLine(b.dtype);
Console.WriteLine(a * b);
Console.ReadKey();
}
result
1.0
-0.9589242746631385
-0.675262089199912
object
error occurs here :
dynamic b = np.array(new List { 6, 5, 4 }, dtype: np.int32);
error message :
Python.Runtime.PythonException: 'TypeError : int() argument must be a string, a bytes-like object or a number, not '0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]''
stack trace :
Python.Runtime.PythonException
HResult=0x80131500
Message=TypeError : int() argument must be a string, a bytes-like object or a number, not '0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'
Source=Python.Runtime
StackTrace:
Tried Solution but no success :
1) https://github.com/pythonnet/pythonnet/issues/249
2) download zip file from master and run from Amaconda prompt
python setup.py bdist_wheel --xplat
pip install dist\pythonnet-2.4.0.dev0-cp36-cp36m-win64.whl
python setup.py bdist_wheel failed because need import error : mt.exe could not be found
I did not restart my pc while installing Visual Studio 2017 Community.
So, i think that Visual Studio 2017 Installer did not install mt.exe for me.
Restart PC is not an option for me.
===
Would Like to know is there any option to solve this issue, Thank You.
According to the developer of Pythonnet, i had tried to
install the master of pythonnet.
After the installation completed, i run ReadMe successfully.

How to recognize dll's target platform [duplicate]

I've got an arbitrary list of .NET assemblies.
I need to programmatically check if each DLL was built for x86 (as opposed to x64 or Any CPU). Is this possible?
Look at System.Reflection.AssemblyName.GetAssemblyName(string assemblyFile).
You can examine assembly metadata from the returned AssemblyName instance:
Using PowerShell:
[36] C:\> [reflection.assemblyname]::GetAssemblyName("${pwd}\Microsoft.GLEE.dll") | fl
Name : Microsoft.GLEE
Version : 1.0.0.0
CultureInfo :
CodeBase : file:///C:/projects/powershell/BuildAnalyzer/...
EscapedCodeBase : file:///C:/projects/powershell/BuildAnalyzer/...
ProcessorArchitecture : MSIL
Flags : PublicKey
HashAlgorithm : SHA1
VersionCompatibility : SameMachine
KeyPair :
FullName : Microsoft.GLEE, Version=1.0.0.0, Culture=neut...
Here, ProcessorArchitecture identifies the target platform.
Amd64: A 64-bit processor based on the x64 architecture.
Arm: An ARM processor.
IA64: A 64-bit Intel Itanium processor only.
MSIL: Neutral with respect to processor and bits-per-word.
X86: A 32-bit Intel processor, either native or in the Windows on Windows environment on a 64-bit platform (WoW64).
None: An unknown or unspecified combination of processor and bits-per-word.
I'm using PowerShell in this example to call the method.
You can use the CorFlags CLI tool (for instance, C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin\CorFlags.exe) to determine the status of an assembly, based on its output and opening an assembly as a binary asset you should be able to determine where you need to seek to determine if the 32BIT flag is set to 1 (x86) or 0 (Any CPU or x64, depending on PE):
Option | PE | 32BIT
----------|-------|---------
x86 | PE32 | 1
Any CPU | PE32 | 0
x64 | PE32+ | 0
The blog post x64 Development with .NET has some information about corflags.
Even better, you can use Module.GetPEKind to determine whether an assembly is PortableExecutableKinds value PE32Plus (64-bit), Required32Bit (32-bit and WoW), or ILOnly (any CPU) along with other attributes.
Just for clarification, CorFlags.exe is part of the .NET Framework SDK. I have the development tools on my machine, and the simplest way for me determine whether a DLL is 32-bit only is to:
Open the Visual Studio Command Prompt (In Windows: menu Start/Programs/Microsoft Visual Studio/Visual Studio Tools/Visual Studio 2008 Command Prompt)
CD to the directory containing the DLL in question
Run corflags like this:
corflags MyAssembly.dll
You will get output something like this:
Microsoft (R) .NET Framework CorFlags Conversion Tool. Version 3.5.21022.8
Copyright (c) Microsoft Corporation. All rights reserved.
Version : v2.0.50727
CLR Header: 2.5
PE : PE32
CorFlags : 3
ILONLY : 1
32BIT : 1
Signed : 0
As per comments the flags above are to be read as following:
Any CPU: PE = PE32 and 32BIT = 0
x86: PE = PE32 and 32BIT = 1
64-bit: PE = PE32+ and 32BIT = 0
Just write your own. The core of the PE architecture hasn't been seriously changed since its implementation in Windows 95.
Here's a C# example:
public static ushort GetPEArchitecture(string pFilePath)
{
ushort architecture = 0;
try
{
using (System.IO.FileStream fStream = new System.IO.FileStream(pFilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
using (System.IO.BinaryReader bReader = new System.IO.BinaryReader(fStream))
{
// Check the MZ signature
if (bReader.ReadUInt16() == 23117)
{
// Seek to e_lfanew.
fStream.Seek(0x3A, System.IO.SeekOrigin.Current);
// Seek to the start of the NT header.
fStream.Seek(bReader.ReadUInt32(), System.IO.SeekOrigin.Begin);
if (bReader.ReadUInt32() == 17744) // Check the PE\0\0 signature.
{
// Seek past the file header,
fStream.Seek(20, System.IO.SeekOrigin.Current);
// Read the magic number of the optional header.
architecture = bReader.ReadUInt16();
}
}
}
}
}
catch (Exception) { /* TODO: Any exception handling you want
to do, personally I just take 0
as a sign of failure */
}
// If architecture returns 0, there has been an error.
return architecture;
}
}
Now the current constants are:
0x10B - PE32 format.
0x20B - PE32+ format.
But with this method it allows for the possibilities of new constants. Just validate the return as you see fit.
DotPeek from JetBrains provides a quick and easy way to see msil (Any CPU), x86, and x64:
Try to use CorFlagsReader from this project at CodePlex. It has no references to other assemblies and it can be used as is.
[TestMethod]
public void EnsureKWLLibrariesAreAll64Bit()
{
var assemblies = Assembly.GetExecutingAssembly().GetReferencedAssemblies().Where(x => x.FullName.StartsWith("YourCommonProjectName")).ToArray();
foreach (var assembly in assemblies)
{
var myAssemblyName = AssemblyName.GetAssemblyName(assembly.FullName.Split(',')[0] + ".dll");
Assert.AreEqual(ProcessorArchitecture.MSIL, myAssemblyName.ProcessorArchitecture);
}
}
Below is a batch file that will run corflags.exe against all DLL files and EXE files in the current working directory and all sub-directories, parse the results and display the target architecture of each.
Depending on the version of corflags.exe that is used, the line items in the output will either include 32BIT, or 32BITREQ (and 32BITPREF). Whichever of these two is included in the output is the critical line item that must be checked to differentiate between Any CPU and x86. If you are using an older version of corflags.exe (pre Windows SDK v8.0A), then only the 32BIT line item will be present in the output, as others have indicated in past answers. Otherwise 32BITREQ and 32BITPREF replace it.
This assumes corflags.exe is in the %PATH%. The simplest way to ensure this is to use a Developer Command Prompt. Alternatively you could copy it from its default location.
If the batch file below is run against an unmanaged DLL or EXE file, it will incorrectly display it as x86, since the actual output from Corflags.exe will be an error message similar to:
corflags : error CF008 : The specified file does not have a valid managed header
#echo off
echo.
echo Target architecture for all exes and dlls:
echo.
REM For each exe and dll in this directory and all subdirectories...
for %%a in (.exe, .dll) do forfiles /s /m *%%a /c "cmd /c echo #relpath" > testfiles.txt
for /f %%b in (testfiles.txt) do (
REM Dump corflags results to a text file
corflags /nologo %%b > corflagsdeets.txt
REM Parse the corflags results to look for key markers
findstr /C:"PE32+">nul .\corflagsdeets.txt && (
REM `PE32+` indicates x64
echo %%~b = x64
) || (
REM pre-v8 Windows SDK listed only "32BIT" line item,
REM newer versions list "32BITREQ" and "32BITPREF" line items
findstr /C:"32BITREQ : 0">nul /C:"32BIT : 0" .\corflagsdeets.txt && (
REM `PE32` and NOT 32bit required indicates Any CPU
echo %%~b = Any CPU
) || (
REM `PE32` and 32bit required indicates x86
echo %%~b = x86
)
)
del corflagsdeets.txt
)
del testfiles.txt
echo.
I've cloned a super handy tool that adds a context menu entry for assemblies in Windows Explorer to show all available information:
Download from Releases · tebjan/AssemblyInformation.
One more way would be to use dumpbin from the Visual Studio tools on the DLL and look for the appropriate output:
dumpbin.exe /HEADERS <your DLL file path>
FILE HEADER VALUE
14C machine (x86)
4 number of sections
5885AC36 time date stamp Mon Jan 23 12:39:42 2017
0 file pointer to symbol table
0 number of symbols
E0 size of optional header
2102 characteristics
Executable
32 bit word machine
DLL
Note: The above output is for a 32-bit DLL file
One more useful option with dumpbin.exe is /EXPORTS. It will show you the function exposed by the DLL file
dumpbin.exe /EXPORTS <PATH OF THE DLL FILE>
A more generic way - use the file structure to determine bitness and image type:
public static CompilationMode GetCompilationMode(this FileInfo info)
{
if (!info.Exists)
throw new ArgumentException($"{info.FullName} does not exist");
var intPtr = IntPtr.Zero;
try
{
uint unmanagedBufferSize = 4096;
intPtr = Marshal.AllocHGlobal((int)unmanagedBufferSize);
using (var stream = File.Open(info.FullName, FileMode.Open, FileAccess.Read))
{
var bytes = new byte[unmanagedBufferSize];
stream.Read(bytes, 0, bytes.Length);
Marshal.Copy(bytes, 0, intPtr, bytes.Length);
}
// Check DOS header magic number
if (Marshal.ReadInt16(intPtr) != 0x5a4d)
return CompilationMode.Invalid;
// This will get the address for the WinNT header
var ntHeaderAddressOffset = Marshal.ReadInt32(intPtr + 60);
// Check WinNT header signature
var signature = Marshal.ReadInt32(intPtr + ntHeaderAddressOffset);
if (signature != 0x4550)
return CompilationMode.Invalid;
// Determine file bitness by reading magic from IMAGE_OPTIONAL_HEADER
var magic = Marshal.ReadInt16(intPtr + ntHeaderAddressOffset + 24);
var result = CompilationMode.Invalid;
uint clrHeaderSize;
if (magic == 0x10b)
{
clrHeaderSize = (uint)Marshal.ReadInt32(intPtr + ntHeaderAddressOffset + 24 + 208 + 4);
result |= CompilationMode.Bit32;
}
else if (magic == 0x20b)
{
clrHeaderSize = (uint)Marshal.ReadInt32(intPtr + ntHeaderAddressOffset + 24 + 224 + 4);
result |= CompilationMode.Bit64;
}
else return CompilationMode.Invalid;
result |= clrHeaderSize != 0
? CompilationMode.CLR
: CompilationMode.Native;
return result;
}
finally
{
if (intPtr != IntPtr.Zero)
Marshal.FreeHGlobal(intPtr);
}
}
Compilation mode enumeration
[Flags]
public enum CompilationMode
{
Invalid = 0,
Native = 0x1,
CLR = Native << 1,
Bit32 = CLR << 1,
Bit64 = Bit32 << 1
}
Source code with explanation is at GitHub.
Another way to check the target platform of a .NET assembly is inspecting the assembly with .NET Reflector...
##~#€~! I've just realized that the new version is not free! So, correction, if you have a free version of .NET reflector, you can use it to check the target platform.
cfeduke notes the possibility of calling GetPEKind. It's potentially interesting to do this from PowerShell.
Here, for example, is code for a cmdlet that could be used: https://stackoverflow.com/a/16181743/64257
Alternatively, at https://stackoverflow.com/a/4719567/64257 it is noted that "there's also the Get-PEHeader cmdlet in the PowerShell Community Extensions that can be used to test for executable images."
A tool is sigcheck:
sigcheck c:\Windows\winhlp32.exe
Output:
Sigcheck v2.71 - File version and signature viewer
Copyright (C) 2004-2018 Mark Russinovich
Sysinternals - www.sysinternals.com
c:\windows\winhlp32.exe:
Verified: Signed
Signing date: 20:05 02.05.2022
Publisher: Microsoft Windows
Company: Microsoft Corporation
Description: Windows Winhlp32 Stub
Product: Microsoft® Windows® Operating System
Prod version: 10.0.19041.1
File version: 10.0.19041.1 (WinBuild.160101.0800)
MachineType: 32-bit
sigcheck -nobanner c:\Windows\HelpPane.exe
Output:
c:\windows\HelpPane.exe:
Verified: Signed
Signing date: 00:42 23.04.2022
Publisher: Microsoft Windows
Company: Microsoft Corporation
Description: Microsoft Help and Support
Product: Microsoft® Windows® Operating System
Prod version: 10.0.19041.1151
File version: 10.0.19041.1151 (WinBuild.160101.0800)
MachineType: 64-bit
An alternative to already mentioned tools is Telerik JustDecompile (free tool) which will display the information next to the assembly name:
I like the ILSpy tool. It shows not only architecture, but the target framework as well:
// linq2db, Version=3.0.0.0, Culture=neutral, PublicKeyToken=e41013125f9e410a
// Global type: <Module>
// Architecture: AnyCPU (64-bit preferred)
// Runtime: v4.0.30319
// This assembly is signed with a strong name key.
// This assembly was compiled using the /deterministic option.
// Hash algorithm: SHA1
So it is possible to determine if it is .NET Core 2.1, .NET Framework 4.6 or any other one:

Azure Compute Emulator does not start. DFAgent crashes with error (continious)

Run in to problem when start default mvc project from visual studio. This question is continuation of: Azure Compute Emulator does not start. DFAgent crashes with error. Also I found this AppCrash log file, that contains information about loaded assemblies but it does not fit to previous question:
Version=1
EventType=APPCRASH
EventTime=129860523658697840
ReportType=2
Consent=1
UploadTime=129860523659217892
ReportIdentifier=8caf429b-c768-11e1-a4ed-6cf04951e202
Response.BucketId=3054088369
Response.BucketTable=1
Response.type=4
Sig[0].Name=Application Name
Sig[0].Value=csrun.exe
Sig[1].Name=Application Version
Sig[1].Value=6.0.6002.18488
Sig[2].Name=Application Timestamp
Sig[2].Value=4fcaabdc
Sig[3].Name=Fault Module Name
Sig[3].Value=KERNELBASE.dll
Sig[4].Name=Fault Module Version
Sig[4].Value=6.1.7600.16850
Sig[5].Name=Fault Module Timestamp
Sig[5].Value=4e21132b
Sig[6].Name=Exception Code
Sig[6].Value=e0434f4d
Sig[7].Name=Exception Offset
Sig[7].Value=00009673
DynamicSig[1].Name=Версия ОС
DynamicSig[1].Value=6.1.7600.2.0.0.256.48
DynamicSig[2].Name=Код языка
DynamicSig[2].Value=1049
UI[2]=C:\Program Files\Microsoft SDKs\Windows Azure\Emulator\csrun.exe
UI[3]=Прекращена работа программы "Windows Azure Simulation Execution Tool"
UI[4]=Windows может провести поиск способа устранения этой ошибки в Интернете.
UI[5]=Искать решение проблемы в Интернете и закрыть программу
UI[6]=Проверить наличие способа исправления ошибки в Интернете позднее и закрыть программу
UI[7]=Закрыть программу
LoadedModule[0]=C:\Program Files\Microsoft SDKs\Windows Azure\Emulator\csrun.exe
LoadedModule[1]=C:\Windows\SYSTEM32\ntdll.dll
LoadedModule[2]=C:\Windows\SYSTEM32\MSCOREE.DLL
LoadedModule[3]=C:\Windows\system32\KERNEL32.dll
LoadedModule[4]=C:\Windows\system32\KERNELBASE.dll
LoadedModule[5]=C:\Windows\system32\ADVAPI32.dll
LoadedModule[6]=C:\Windows\system32\msvcrt.dll
LoadedModule[7]=C:\Windows\SYSTEM32\sechost.dll
LoadedModule[8]=C:\Windows\system32\RPCRT4.dll
LoadedModule[9]=C:\Windows\system32\apphelp.dll
LoadedModule[10]=C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll
LoadedModule[11]=C:\Windows\WinSxS\x86_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.4927_none_d08a205e442db5b5\MSVCR80.dll
LoadedModule[12]=C:\Windows\system32\USER32.dll
LoadedModule[13]=C:\Windows\system32\GDI32.dll
LoadedModule[14]=C:\Windows\system32\LPK.dll
LoadedModule[15]=C:\Windows\system32\USP10.dll
LoadedModule[16]=C:\Windows\system32\SHLWAPI.dll
LoadedModule[17]=C:\Windows\system32\IMM32.DLL
LoadedModule[18]=C:\Windows\system32\MSCTF.dll
LoadedModule[19]=C:\PROGRA~1\KASPER~1\KASPER~1.0FO\adialhk.dll
LoadedModule[20]=C:\PROGRA~1\KASPER~1\KASPER~1.0FO\kloehk.dll
LoadedModule[21]=C:\Windows\system32\shell32.dll
LoadedModule[22]=C:\Windows\system32\ole32.dll
LoadedModule[23]=C:\Windows\system32\profapi.dll
LoadedModule[24]=C:\Windows\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll
LoadedModule[25]=C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorsec.dll
LoadedModule[26]=C:\Windows\system32\WINTRUST.dll
LoadedModule[27]=C:\Windows\system32\CRYPT32.dll
LoadedModule[28]=C:\Windows\system32\MSASN1.dll
LoadedModule[29]=C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82.7600.16661_none_ebfb56996c72aefc\COMCTL32.dll
LoadedModule[30]=C:\Windows\system32\CRYPTSP.dll
LoadedModule[31]=C:\Windows\system32\rsaenh.dll
LoadedModule[32]=C:\Windows\system32\CRYPTBASE.dll
LoadedModule[33]=C:\Windows\system32\imagehlp.dll
LoadedModule[34]=C:\Windows\system32\ncrypt.dll
LoadedModule[35]=C:\Windows\system32\bcrypt.dll
LoadedModule[36]=C:\Windows\system32\bcryptprimitives.dll
LoadedModule[37]=C:\Windows\system32\USERENV.dll
LoadedModule[38]=C:\Windows\system32\GPAPI.dll
LoadedModule[39]=C:\Windows\system32\cryptnet.dll
LoadedModule[40]=C:\Windows\system32\WLDAP32.dll
LoadedModule[41]=C:\Windows\system32\SensApi.dll
LoadedModule[42]=C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorjit.dll
LoadedModule[43]=C:\Windows\assembly\GAC_MSIL\mscorlib.resources\2.0.0.0_ru_b77a5c561934e089\mscorlib.resources.dll
LoadedModule[44]=C:\Windows\system32\VERSION.dll
State[0].Key=Transport.DoneStage1
State[0].Value=1
State[1].Key=DataRequest
State[1].Value=Bucket=-1240878927/nBucketTable=1/nResponse=1/n
FriendlyEventName=APPCRASH
ConsentKey=APPCRASH
AppName=Windows Azure Simulation Execution Tool
AppPath=C:\Program Files\Microsoft SDKs\Windows Azure\Emulator\csrun.exe
ReportDescription=Stopped working
Such problems are mainly caused by one misconfiguration in your machine and it would be very hard to troubleshoot however based on your above info I can see 3 possible reason (there may be more..)
Localization - Try to set the local to US and check if that helps.
Problem with some old .net framework installation - Try to uninstalling all of older .net frameworks in your machine and then install .net 4.0 full and launch CSRUN with Emulator again.
VC++ runtime incompatibility: Try removing VC++ runtime in your machine and then install 64bit VC++ runtime
Try making sure above changes and then check if that resolves the problem.

Categories

Resources