none
Funktionsproblem mit externen Windows Bibliotheken seit Codeumstellung RRS feed

  • Frage

  • Hallo Leute,

    ich arbeite nun seit knapp einem Jahr mit c# und lerne immer noch fleißig weiter. 

    Nun habe ich vor ein paar Tagen an meinem kleinen Projekt ein paar Codeanpassungen vorgenommen.

    hier erstmal der original code :

    	#region =============================================================================== ARP
    
    		[DllImport("Ws2_32.dll")] //wandelt den angegebenen Ip-String in einen Int32-Wert um
    		static extern Int32 inet_addr(string ip);
    		[DllImport("Iphlpapi.dll")] // Holt die Mac-Adresse der angegebenen Ip-Adresse
    		static extern int SendARP(Int32 dest, Int32 host, ref Int64 mac, ref Int32 len);
    
    		// holt die Mac-Adresse einer angegebenen Ip-Adresse
    		public static Int64 getRemoteMAC(string localIP, string remoteIP)
    		{
    			//Umwandlung der Ip-Adressen in Int32-Werte
    			Int32 ldest = inet_addr(remoteIP);
    			Int32 lhost = inet_addr(localIP);
    
    			try
    			{
    				Int64 macinfo = 0; //Dient zur Speicherung der Mac-Adresse
    				Int32 len = 6; //Länge
    
    				int res = SendARP(ldest, 0, ref macinfo, ref len); //Mac-Adresse holen
    
    				return macinfo; //Int64 mit Mac-Adresse zurückgeben
    			}
    			catch
    			{
    				return 0;
    			}
    		#endregion


    das funktionierte auch problemlos .. 

    nun meckerte aber die Codeanalyse von VS das ich das anders machen solle und daraufhin hab ich Tante google befragt wie man sowas machen sollte. Laut MS Hilfe sollte ich die Verweise in eine eigene externe Klasse packen .. Das Ergebnis sieht bei mir nun wie folgt aus :

    #region
    =============================================================================== ARP
    		// holt die Mac-Adresse einer angegebenen Ip-Adresse
    		public static Int64 getRemoteMAC(string localIP, string remoteIP)
    		{
    			//Umwandlung der Ip-Adressen in Int32-Werte
    			Int32 ldest = SaveNativeMethods.inet_addr(remoteIP);
    			Int32 lhost = SaveNativeMethods.inet_addr(localIP);
    
    			//try
    			{
    				Int64 macinfo = 0; //Dient zur Speicherung der Mac-Adresse
    				Int32 len = 6; //Länge
    
    				int res = SaveNativeMethods.SendARP(ldest, 0, ref macinfo, ref len); //Mac-Adresse holen
    
                    return macinfo; //Int64 mit Mac-Adresse zurückgeben
    			}
    			/*catch
    			{
    				return 0;
    			}*/
    		}
    #endregion
    
    //restlicher code der Form Klasse
    //dann folgende Klassendefinition
    
    [SuppressUnmanagedCodeSecurityAttribute]
    	internal static class SaveNativeMethods
    	{
    		#region Integration von Windowsfunktionen zur Steuerung externer Programme
    
    		[DllImport("User32.dll", SetLastError = true)]
    		internal static extern int SetForegroundWindow(IntPtr hwnd);
    		[DllImport("User32.dll")]
    		internal static extern int ShowWindowAsync(IntPtr hWnd, int nCmdShow);
    		[DllImport("Ws2_32.dll",CharSet = CharSet.Unicode)] //wandelt den angegebenen Ip-String in einen Int32-Wert um
    		internal static extern Int32 inet_addr(string ip);
    		[DllImport("Iphlpapi.dll",CharSet = CharSet.Unicode)] // /Holt die Mac-Adresse der angegebenen Ip-Adresse
    		internal static extern int SendARP(Int32 dest, Int32 host, ref Int64 mac, ref Int32 len);
    		#endregion
    	}
    
    

    Mein Problem ist nun das ich nicht verstehe warum diese Variante nicht funktioniert. Ich bekomme in der ref mac immer als value 0 und ich verstehe nicht warum.

    Die anderen DLL Importe funktionieren so übrigens problemlos.

    Wäre schön wenn mir hier jemand von euch einen heißen Tip geben könnte was ich hier falsch gemacht hab.

    Danke schonmal im Vorraus

    Dienstag, 12. Juni 2018 19:59

Antworten

  • Hallo Dimitar,

    erstmal Danke für deine Antwort.  

    aktuell wird 'len' von 6 auf 0 geändert wenn die Routine aufgerufen wurde, genau wie alle anderen Variablen (bis auf die IP). Die Variante mit dem Byte Aufruf gefällt mir persönlich sogar noch besser als die umständliche Version die ich mir gebastelt hatte ;-). Allerdings habe ich auch hier das gleiche Problem. Alle Werte die zurück geliefert wurden sind 0. 

    Kann es sein das es mit der "Berechtigung"

    [SuppressUnmanagedCodeSecurityAttribute]

    der Routinen zusammen hängt ?

    Und was 'idest' angeht so hat sich am Handling zwischen beiden Codevarianten nichts verändert. Der enthaltene Wert ist abhängig von dem was die Anwendung übergibt ;).

    So richtig verstehen will ich das gerade nicht warum diese Routine auf einmal nichts zurück liefert.

    Gruß

    Daniel

    Nachtrag : SendARP liefert einen int Wert von 1168 zurück .. Nach eingängiger Googlesuche hab ich jetzt mal die Fehlercodes gefunden und eingebunden. Angeblich findet er die IP nicht ... was mich irritiert ist das die Routine zum umwandeln der IP in Int  (inet_addr) bei target und host 16777216 liefert. Ich würde sagen das deutet auf nen Overflow bei der Umrechnung hin.

    Abschließender Hinweis  ..

    Ich habe die Ursache gefunden. VisualStudio hatte mir bei der CodeAnalyse gesagt das ich die 'inet_addr' Routine wegen Laufstabilität mit dem Parameter {, CharSet = CharSet.Unicode} erweitern sollte. Allerdings führte der dazu das diese Routine gar nicht mehr richtig umwandelte. 

    Habe gerade bei der Fehlersuche diese Änderung rückgängig gemacht und siehe da es geht wieder.


    Donnerstag, 14. Juni 2018 16:07

Alle Antworten

  • Hallo Zerstreuter,

    Welchen Wert hat len nach dem Aufruf der Funktion? Gibt es eine Änderung, wenn Du als dritten Parameter einen Bytearray byte[6] anstatt Int64 weitergibst? Sieh Dir folgendes Beispiel an:
    How to get the MAC address prior to connection?

    Hat ldest denselben Wert sowohl im alten, als auch im neuen Codeschnipsel?

    Gruß,
    Dimitar


    Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „IT-Pros helfen IT-Pros“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.

    Mittwoch, 13. Juni 2018 19:54
    Administrator
  • Hallo Dimitar,

    erstmal Danke für deine Antwort.  

    aktuell wird 'len' von 6 auf 0 geändert wenn die Routine aufgerufen wurde, genau wie alle anderen Variablen (bis auf die IP). Die Variante mit dem Byte Aufruf gefällt mir persönlich sogar noch besser als die umständliche Version die ich mir gebastelt hatte ;-). Allerdings habe ich auch hier das gleiche Problem. Alle Werte die zurück geliefert wurden sind 0. 

    Kann es sein das es mit der "Berechtigung"

    [SuppressUnmanagedCodeSecurityAttribute]

    der Routinen zusammen hängt ?

    Und was 'idest' angeht so hat sich am Handling zwischen beiden Codevarianten nichts verändert. Der enthaltene Wert ist abhängig von dem was die Anwendung übergibt ;).

    So richtig verstehen will ich das gerade nicht warum diese Routine auf einmal nichts zurück liefert.

    Gruß

    Daniel

    Nachtrag : SendARP liefert einen int Wert von 1168 zurück .. Nach eingängiger Googlesuche hab ich jetzt mal die Fehlercodes gefunden und eingebunden. Angeblich findet er die IP nicht ... was mich irritiert ist das die Routine zum umwandeln der IP in Int  (inet_addr) bei target und host 16777216 liefert. Ich würde sagen das deutet auf nen Overflow bei der Umrechnung hin.

    Abschließender Hinweis  ..

    Ich habe die Ursache gefunden. VisualStudio hatte mir bei der CodeAnalyse gesagt das ich die 'inet_addr' Routine wegen Laufstabilität mit dem Parameter {, CharSet = CharSet.Unicode} erweitern sollte. Allerdings führte der dazu das diese Routine gar nicht mehr richtig umwandelte. 

    Habe gerade bei der Fehlersuche diese Änderung rückgängig gemacht und siehe da es geht wieder.


    Donnerstag, 14. Juni 2018 16:07