Ich arbeite mit einem Hersteller bereitgestellten nicht verwalteten DLL zur Schnittstelle mit einigen benutzerdefinierten Hardware. Leider kann ich den Herstellercode nicht posten, aber hoffentlich wird der untenstehende bereinigte Code genügend Informationen zur Ursache des Problems liefern.Visual Studio 2010 entführt Interop-Callbacks und/oder verbirgt das echte Fensterhandle
Das Hersteller-SDK erfordert die Registrierung einer Rückruffunktion für die Benachrichtigung über Hardwareereignisse. Ich habe ein Dienstprogramm vom Hersteller, um zu bestätigen, dass dies erfolgreich geschieht. Die Hardware sendet benutzerdefinierte WIN32-Nachrichten an das Fenster, und das SDK hängt sich an die Nachrichtenschleife an und ruft die Rückruffunktion auf, sobald eine dieser benutzerdefinierten Nachrichten empfangen wird.
Wenn die App direkt ausgeführt wird, funktioniert alles. Wenn die App in Visual Studio ausgeführt wird, ist die Registrierung erfolgreich, aber Ereignisse werden nicht ausgelöst. Dies gilt für das Ausführen mit oder ohne Debugging (F5/Crlt + F5). Ich habe auch versucht, den Visual Studio-Hosting-Prozess in den Projekteigenschaften zu deaktivieren, und es hat keinen Unterschied gemacht.
In einer C# Klassenbibliothek, habe ich mit dem Verkäufer SDK mit dem folgenden Code eingewickelt:
public class Basic {
private delegate void Callback(UInt32 Event, Byte status, UInt16 type, UInt16 devno);
private Callback mInstance;
public delegate void EventHandler(String message);
public event EventHandler HardwareEvent;
[DllImport("VendorSDK.dll")]
private static extern Int32 Register_Callback(Callback shuttleproc, UInt16 type, UInt16 devno);
[DllImport("VendorSDK.dll")]
private static extern Int32 Unregister_Callback(UInt16 type, UInt16 devno);
public Basic() {
mInstance = new Callback(CallbackHandler);
if (Register_Callback(mInstance, 1, 1) != 0)
throw new Exception("Error registereing");
}
~Basic() {
Unregister_Callback(1, 1);
}
public void CallbackHandler(UInt32 Event, Byte status, UInt16 type, UInt16 devno) {
if (HardwareEvent != null)
HardwareEvent(String.Format("Message: {0}, {1}, {2}, {3}", Event, status, type, devno));
}
}
Dann in einer WPF-Anwendung verwende ich diese Wrapper wie so:
public partial class MainWindow : Window {
Basic hardware;
public MainWindow() {
InitializeComponent();
}
protected override void OnSourceInitialized(EventArgs e) {
base.OnSourceInitialized(e);
hardware = new Basic();
hardware.HardwareEvent += new Basic.EventHandler(HardwareEvent);
}
void HardwareEvent(string message) {
Messages.Dispatcher.Invoke(new Action(() => { Messages.Items.Insert(0, message); }));
}
}
Der Verkäufer Das SDK hat ein nicht verwaltetes Beispiel in C++ bereitgestellt, das dasselbe Problem wie mein verwalteter Wrapper aufweist. Die App funktioniert außerhalb von Visual Studio, wird aber von Visual Studio aus gestartet. Nachrichten werden nicht empfangen.
Ich glaube, das wird von Visual Studio verursacht entweder in den Weg des Rückrufs, oder wahrscheinlicher, wenn die nicht verwaltete Kreditor DLL Zugriff auf das aktuelle Fenster behandeln (HWND) den falschen Wert zurückgegeben wird. Ich bin mir jedoch nicht sicher.
Dies ist nicht zu entgegnen, VS macht solche Dinge nicht. Wenden Sie sich an den Anbieter, um Unterstützung zu erhalten. –
Zeigt die API das HWND an, mit dem sie sich verbunden hat? Wenn ja, würde ich das mit Daten von etwas wie Process Explorer (Sysinternals Tools) vergleichen. IIRC, es gibt auch ein sysinternals-Tool, um die versandten Nachrichten zu überwachen ... wenn es richtig verkabelt ist, sollten Sie in der Lage sein zu sehen, dass die Verkäufer-Nachrichten angezeigt werden. Eine andere Idee: Außerhalb von VS laufen und anhängen? –
@Hans Passant - das ist wiederholbar/außerhalb von Visual Studio läuft es funktioniert, innerhalb von Visual Studio es nicht. Die einzige Änderung ist die Verwendung von Visual Studio. – ViNull