OpenGL4Net System.BadImageFormatException - c#

A follow up to:
OpenGL4Net WM_PAINT does not exist?
I am still closely following: https://sourceforge.net/p/ogl4net/wiki/Tutorials
The program as it currently stands:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Forms;
using OpenGL4NET;
namespace pads2
{
class Program : Form
{
private const int WM_PAINT = 15;
RenderingContext rc;
static void Main(string[] args)
{
Program program = new Program();
program.Init();
Application.Run(program);
}
// required for open GL
void Init()
{
rc = RenderingContext.CreateContext(this);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
}
void Render()
{
gl.Clear(GL.COLOR_BUFFER_BIT);
// here is the right place to draw all your scene
rc.SwapBuffers();
}
// change window size
protected override void OnSizeChanged(EventArgs e)
{
gl.Viewport(0, 0, ClientSize.Width, ClientSize.Height);
// projection matrix may also need adjusting
}
// required for open GL
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_PAINT: Render(); break;
default: base.WndProc(ref m); break;
}
}
}
}
Q: Provided that I'm implementing the tutorial correctly, what can I do about the error System.BadImageFormatException on line program.Init();?
Additionally:
Additional information: Could not load file or assembly 'OpenGL4Net,
Version=4.3.37.24, Culture=neutral, PublicKeyToken=null' or one of its
dependencies. An attempt was made to load a program with an incorrect
format.
This could be due to the warning:
There was a mismatch between the processor architecture of the project
being built "MSIL" and the processor architecture of the reference
"OpenGL4Net", "AMD64". This mismatch may cause runtime failures.
Please consider changing the targeted processor architecture of your
project through the Configuration Manager so as to align the processor
architectures between your project and references, or take a
dependency on references with a processor architecture that matches
the targeted processor architecture of your project.
However according to:
How do I fix the Visual Studio compile error, "mismatch between processor architecture"?
This should not be an issue. There is only the option of (32 or 64) bit when downloading the OpenGL4Net DLL.
Given that Microsoft Intermediate Language is not the same as a processor, I tried running in release mode instead of debug mode, but it makes no difference.

What build configuration do you use when compiling? And what version of OpenGL4Net did you download? The 32 or 64 bit version?
Try setting the build configuration to match the intended target cpu of the referenced assembly (so, either 32 or 64 bit, depending on the download of OpenGL4Net).
See C# compiling for 32/64 bit, or for any cpu? for a detailed explanation.

Related

The type name 'SerialPort' could not be found in the namespace 'System.IO.Ports'

I am using Visual Studio Community 2019 to write a new serial port downloader program. I am relatively new to C# but have had to maintain a large-ish c# application that also uses the serial port to configure an embedded device.
Problematic (new) code is below. The "System.IO.Ports" using statement has no effect (is greyed out) and the issue is that the compiler has no clue what a "SerialPort" is (see the error after the code).
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.IO.Ports;
using System.Drawing;
namespace PangeaUpdater
{
class Download
{
const byte STX_CHAR = (byte)'\x2';
const byte ETX_CHAR = (byte)'\x3';
const byte DLE_CHAR = (byte)'\x10';
const int MAX_DATA_PACKET_LEN = 128;
private BinaryReader pkgStream = null;
public SerialPort serialPort;
private void Create(String comPort, String baudrate,
System.Windows.Forms.RichTextBox msgListBox,
System.Windows.Forms.ProgressBar progressBar)
{
//Lots of stuff should be configurable but is not (yet)
serialPort = new SerialPort(comPort,
Convert.ToInt32(baudrate),
Parity.None,
8,
StopBits.One);
serialPort.Handshake = Handshake.None;
serialPort.Open();
serialPort.ReadTimeout = 1000;
progBar = progressBar;
messages = msgListBox;
}
public Download(String comPort,
String baudrate,
//String Product,
System.Windows.Forms.RichTextBox msgListBox,
System.Windows.Forms.ProgressBar progressBar)
{
Create(comPort, baudrate, /*Product,*/ msgListBox, progressBar);
}
}
}
C:...\Download.cs(20,16,20,26): error CS1069: The type name 'SerialPort' could not be found in the namespace 'System.IO.Ports'. This type has been forwarded to assembly 'System.IO.Ports, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' Consider adding a reference to that assembly.
I have checked against the app that I maintain and which compiles and runs fine. The old app has a set of References, but the new app has just a set of dependencies, but I gather these are very similar or the same?
I suspect adding a reference is what is required but I have no clue what is needed. When I try to add a Reference in the new app I see nothing except for COM assemblies. There are loads but there is no clue as to which might be needed for serial port stuff. The old config app does not give any clue as the where it finds a reference for the SerialPort type.
Does anyone have a clue what I may have missed?
You probably need to add a reference to System.ComponentModel.Component.
See: https://learn.microsoft.com/en-us/dotnet/api/system.io.ports.serialport?view=netframework-4.8
If its a .NET 6 application you probably need VS2022 and a NuGet package:
https://www.nuget.org/packages/System.IO.Ports/
(.NET 6 is not supported in VS2019)
I found the problem. It was that I had inadvertently chosen a framework "core" project as the template. As a newbie to Visual Studio C#, I don't understand why there are so many templates. It seems to be a confusing array of project types with no explanation of the subtle differences between them.
Anyway, thanks for the suggestions. I think that I focussed to closely on the actual error message and not enough on the other symptoms of this problem, like most of the components in the toolbox being missing!

NullReferenceException while creating a SpeechRecognitionEngine object

I'm currently trying to implement some speech recognition in one of my c# project, and so I found this library :
https://learn.microsoft.com/en-us/dotnet/api/system.speech.recognition.speechrecognitionengine?view=netframework-4.8
Providing this code as an example :
using System;
using System.Speech.Recognition;
namespace SpeechRecognitionApp
{
class Program
{
static void Main(string[] args)
{
// Create an in-process speech recognizer for the en-US locale.
using (
SpeechRecognitionEngine recognizer =
new SpeechRecognitionEngine(
new System.Globalization.CultureInfo("en-US")))
{
// Create and load a dictation grammar.
recognizer.LoadGrammar(new DictationGrammar());
// Add a handler for the speech recognized event.
recognizer.SpeechRecognized +=
new EventHandler<SpeechRecognizedEventArgs>(recognizer_SpeechRecognized);
// Configure input to the speech recognizer.
recognizer.SetInputToDefaultAudioDevice();
// Start asynchronous, continuous speech recognition.
recognizer.RecognizeAsync(RecognizeMode.Multiple);
// Keep the console window open.
while (true)
{
Console.ReadLine();
}
}
}
// Handle the SpeechRecognized event.
static void recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
Console.WriteLine("Recognized text: " + e.Result.Text);
}
}
}
Which should do exactly what I need.
So I created a new project in Visual Studio, copy-pasted the code, and run it.
There is no compilation error, but the constructor of SpeechRecognitionEngine, taking a non-null CultureInfo object as an argument, throws a System.NullReferenceException in System.Speech.dll.
To try to debug this, I made sure
new System.Globalization.CultureInfo("en-US")
returns a non-null object, and that this culture was installed.
I also updated my framework to 4.8, and run the project both as administrator and normal user.
I'm also using a x64 CPU platform, as the build fails with an ANY CPU platform.
It seems to me like I misconfigured something somewhere, as the code itself shouldn't be wrong.
Do you have any idea how to solve my problem ?
Thank you for your help.
EDIT : this may be linked to this problem, though I don't know if it's of any help :
NullReferenceException when starting recognizer with RecognizeAsync
I had the same error, but found the issue on my end. If you have the same issue as me, it may be that your project is using System.Speech.dll from an older framework, which I believe was causing my error. Or it may have been incompatibility between my target framework the dll?
I used NuGet to add System.Speech by Microsoft to my project. It added System.Speech (6.0.0) to the project references. This removed the null exception I was getting.
For information only, I initially added a reference to v3.0 framework, and that was causing my issue.

CSCore: access violation when listening to audio session events

I'm just getting started with CSCore, and getting back to C# after a lot of C++. Here's a test program that enumerates the audio sessions of the default audio session manager, and attaches an empty event handler to each one:
using System;
using CSCore.CoreAudioAPI;
class Program
{
static void Main(string[] args)
{
using (var enumerator = new MMDeviceEnumerator())
using (var device = enumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia))
using (var sessionManager = AudioSessionManager2.FromMMDevice(device))
using (var sessionEnumerator = sessionManager.GetSessionEnumerator())
{
foreach (var control in sessionEnumerator)
{
var control2 = control.QueryInterface<AudioSessionControl2>();
RegisterAudioSession(control2);
}
}
Console.WriteLine("Waiting...");
Console.ReadKey();
}
static void RegisterAudioSession(AudioSessionControl2 session)
{
if (session.Process != null)
{
var events = new AudioSessionEvents();
session.RegisterAudioSessionNotification(events);
}
}
}
I would expect to be able to change the volume of my computer while this program is running without any problems. If you try this, however, the program crashes with an access violation in native code. Here's the stack trace:
> AudioSes.dll!CLockedList<ATL::CComPtr<IAudioSessionEvents>,0,1>::ForEachEntry() Unknown
AudioSes.dll!CAudioSessionControl::OnAudioSessionEvent() Unknown
AudioSes.dll!CAudioSessionControl::CAudioSessionNotificationDelegator::OnMediaNotification(struct MEDIA_NOTIFICATION_BLOCK *) Unknown
MMDevAPI.dll!CMediaNotifications::OnMediaNotificationWorkerHandler(struct _TP_CALLBACK_INSTANCE *) Unknown
MMDevAPI.dll!CMediaNotifications::MediaNotificationWorkerHandler(struct _TP_CALLBACK_INSTANCE *,void *) Unknown
ntdll.dll!TppSimplepExecuteCallback() Unknown
ntdll.dll!TppWorkerThread() Unknown
kernel32.dll!#BaseThreadInitThunk#12() Unknown
ntdll.dll!__RtlUserThreadStart() Unknown
ntdll.dll!__RtlUserThreadStart#8() Unknown
The crash does not occur if you remove the call to RegisterAudioSessionNotification.
The crash still occurs if you register a non-empty event handler.
I tried moving Console.ReadKey(); into the using block in case a necessary resource was being disposed, but the failure persisted.
I searched all over the place for an explanation and solution. There are no relevant open issues on CSCore's github page. I read somewhere that crashes in native code are often caused by incorrect signatures in wrapper assemblies. I compared all of the methods on CSCore's IAudioSessionEvents to the native IAudioSessionEvents methods (enumerated here) but found no obvious discrepancies.
This Firefox bug is the only reference I found online to this particular stack trace, and it has been resolved. Apparently it was resolved in Flash Player 19.0.0.159, but as far as I know that source isn't available for perusal.
Am I overlooking an error in my code, or is this a bug in CSCore?
Turns out this crash occurs if the target platform is 32-bit (or in my case, "Any CPU" but running in the 32-bit VS process). Switching to a 64-bit target platform fixed it for me

My x64 WPF app needs x32 DLLs for Microsoft.Lifecam.*.dll integration. Any ideas for allowing both?

I'm trying to integrate my Microsoft LifeCam Studio into a 64bit C# application but I can't find 64 bit dlls.
1. Does anyone know where I can find 64 bit versions of:
Microsoft.LifeCam.Camera.dll
Microsoft.LifeCam.Framework.dll
Microsoft.LifeCam.Streamer.dll
2. Is there a way to import and use the above 32 bit DLLs in a 64 bit WPF app? When I try to reference and use them, I get the following compile warnings and then related runtime errors.
Warning 1 There was a mismatch between the processor architecture of the project being built "AMD64" and the processor architecture of the
reference "Microsoft.LifeCam.Camera, Version=4.25.512.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35,
processorArchitecture=x86", "x86". This mismatch may cause runtime
failures. Please consider changing the targeted processor architecture
of your project through the Configuration Manager so as to align the
processor architectures between your project and references, or take a
dependency on references with a processor architecture that matches
the targeted processor architecture of your project.
I wrote the following application to demonstrate my issue. This compiles and runs great in 32 bit mode. As soon as I switch the compiler to target x64, I get expected errors.
New WPF Application
Add References:
Microsoft.LifeCam.Camera.dll
Microsoft.LifeCam.Framework.dll
Microsoft.LifeCam.Streamer.dll
MainWindow.xaml.cs
using System;
using System.Windows;
using Microsoft.LifeCam;
namespace LifecamTest32Bit
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
try
{
CameraList cameras = new CameraList();
if (cameras.Count < 1)
{
MessageBox.Show("No imaging device found.", "No Camera", MessageBoxButton.OK, MessageBoxImage.Exclamation);
return;
}
Camera cam = (Camera)cameras[0];
Streamer streamer = new Streamer(cam, previewControl, false);
streamer.CurrentVideoResolutionIndex = 1; //selecting a resolution.
streamer.Start();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + Environment.NewLine + ex.StackTrace);
}
}
}
}
MainWindow.xaml
<!-- language-all: lang-xaml -->
<Window x:Class='LifecamTest32Bit.MainWindow'
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:strm="clr-namespace:Microsoft.LifeCam;assembly=Microsoft.LifeCam.Streamer"
Title="MainWindow" Height="350" Width="525"
Loaded="Window_Loaded">
<Grid>
<strm:PreviewView Name="previewControl" />
</Grid>
</Window>
Microsoft never released an SDK for LifeCam, those DLLs are not APIs. They are part of the software, and it is very unlikely you will get Microsoft to write a 64 bit version for the software.
What you want to do with undocumented DLls anyway? Microsoft has no code contract with you to keep the interface working. In fact Microsoft could push an update to the software next Tuesday to remove the dll altogether.
If you want to work with webcams, work with official APIs like DirectShow or Media Foundation. See How to stream Webcam in WPF? and Video preview in C# for suggestions.

Using Reflection to use a namespace on certain OSs

I'm creating a program that uses the CodeProject CoreAudioApi (pretty popular framework for manipulating audio), but the problem is the CoreAudioApi uses system calls that aren't available in any versions of Windows earlier than Vista. If I run a program with CoreAudioApi compiled with it (using a using statement as normal), the program will crash on anything earlier than Vista.
I've created this function to get the version number of the current environment:
win_version = Environment.OSVersion.Version.Major;
That returns the major version number I need. '6' is Vista/7, anything else is not, which is all I need to determine. Utilizing this, I need to determine whether or not to include the CoreAudioApi namespace if the OS is over or equal to '6'. From research, usings need to be compiled with the program, but I've also read about something called Reflection - which might be what I need.
Once I get the CoreAudioApi namespace using'd (sorry for the lack of terminology), the rest is easy. How can I do this?
TL;DR
I need some form of code that would effectively do this:
using System;
using System.Text;
//etc
if(currentWindowsVersion>=6) using CoreAudioApi;
Except control structures won't work outside of a class, and all namespaces are compiled with the program, not controlled individually.
Thanks!
EDIT: So far, I'm using this to load the CoreAudioApi namespace as a compiled assembly:
if(win_version>=6){
CoreAudioApi = Assembly.LoadFrom("CoreAudio.dll");
CoreAudioApi.GetLoadedModules();
CoreAudioApi.GetTypes();
MessageBox.Show("Loaded CoreAudioApi");
}
From here, what I need to do is actually use the types, and methods from the API. My code that works on Windows Vista/7 is this:
public static MMDeviceEnumerator devEnum;
public static MMDevice defaultDevice;
//later in a mute method:
defaultDevice.AudioEndpointVolume.Mute = true/false;
I don't even really need devEnum AFAIK, so really the only important lines are the last two (besides the comment).
I've just tried the following:
Create a new console application project
Add the CoreAudioApi project from CodeProject to the solution
Add a project reference to CoreAudioApi in my console app
Create the following classes:
interface IAudio { void SetVolume(float level); }
class XpAudio : IAudio {
public void SetVolume(float level) {
// I do nothing, but this is where your old-style code would go
}
}
class VistaAudio : IAudio {
public void SetVolume(float level) {
MMDeviceEnumerator devEnum = new MMDeviceEnumerator();
MMDevice defaultDevice = devEnum
.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);
defaultDevice.AudioEndpointVolume.MasterVolumeLevel = level;
}
}
class Program {
static void Main(string[] args) {
IAudio setter = Environment.OSVersion.Version.Major >= 6
? (IAudio)new VistaAudio()
: (IAudio)new XpAudio();
float val = float.Parse(Console.ReadLine());
setter.SetVolume(val);
Console.ReadLine();
}
}
This runs on both my server (~ Windows 7) and local (Windows XP) machines. On my XP machine it'll happily take in a value and ignore it; on my server, it throws an exception, (presumably because I don't have a sound output). If I make my XP machine run the CoreAudioApi, I get an exception when I input a value, not before.
The question is, what are you doing differently to make your application break? Are you using CoreAudioApi code at startup?
EDIT: After seeing your edit, if you do this, you shouldn't need to mess about with Assembly.LoadFrom at all. The framework should dynamically load that assembly if (and only if) and when it needs to.
COREAUDIOAPI.dll does not work on XP or earlier, because they cant handle MMDEVICE API (Device Enumeration). I dont know about Vista.

Categories