Zwei Fragen zu einer Funktion und zu einen StatusStrip!

  • VB.NET
  • .NET (FX) 3.0–3.5

Es gibt 28 Antworten in diesem Thema. Der letzte Beitrag () ist von Cheffboss.

    Zwei Fragen zu einer Funktion und zu einen StatusStrip!

    Moin! :)
    Ich habe mir eine Sub geschrieben diese mir den Freien Arbeitsspeicher anzeigt.
    Nur wenn ich die Variable Prozentram2 mit +1 addiere.
    Kommt der richte Wert raus, warum ist das so?
    Wie kann man das noch verbessern?
    Da ich nicht so viele Beiträge erstellen möchte, habe ich noch eine zweite Frage an euch.
    Ich habe in meinem Projekt ein StatusStrip, und rechts ist ein komisches Dreieck Symbol.
    Kann man diese auch ausblenden?
    Oder gehört es zu diesem Steuerelement einfach dazu?
    Freue mich auf eure Hilfe.
    BIG THX

    VB.NET-Quellcode

    1. Private Function RAM_FreierSpeicherCheck() As ULong
    2. ' Freier RAM ermitteln...
    3. Dim Prozentram As ULong = My.Computer.Info.AvailablePhysicalMemory * 100
    4. Dim Prozentram2 As ULong = (Prozentram / My.Computer.Info.TotalPhysicalMemory)
    5. Dim Ergebnis As ULong = (Prozentram2 + 1)
    6. Return (Ergebnis)
    7. End Function



    Visual Basic.NET 8o
    MS-SQL
    8o

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Cheffboss“ ()

    Cheffboss schrieb:

    Wie kann man das noch verbessern?
    Option Strict On :!:
    Visual Studio - Empfohlene Einstellungen
    Hatten wir das nicht schon mal?
    ====
    Woher hast Du denn den "richtigen" Wert?
    Du rundest hier nämlich auf.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hi @Cheffboss
    du hast geschrieben
    $\frac{available}{total}$*100%


    Das gibt dir den freien Speicher [%]. In dem Kommentar steht aber belegter Speicher ermitteln. Daher fehlt dir 100-, um den belegten Speicher zu ermitteln.



    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Bartosz“ ()

    @an alle
    Vielen Dank, für eure schnelle Antwort.
    Ich habe den Kommentar geändert, ich möchte den freien Arbeitsspeicher ermitteln…
    „Option Strict On“ habe ich nun eingestellt!
    Leider, kommt der gleiche Fehler.
    Zum Beispiel zeigt der Taskmanager an, dass 32% Ram belegt ist.
    Und mein Code zeigt an das 67% frei sind.
    Wenn ich nun 100% - 67% rechne zeigt er mir 33% an.
    Dieser Wert weicht zwischen +1 und -1 aus.
    Woran kann das liegen? ?(
    Ich habe auch den Datentyp von ULong auf Long und Decimal gestellt.
    Könnte es auch sein, dass die Werte im Taskmanager nicht so schnell aktualisiert werden?
    Das Deshalb der Wert um eins höher oder kleiner ist? ?(

    VB.NET-Quellcode

    1. Option Strict On
    2. Public Class Form1
    3. Private Function RAM_FreierSpeicherCheck() As ULong
    4. ' Freier RAM ermitteln...
    5. Dim Prozentram As ULong = CULng(My.Computer.Info.AvailablePhysicalMemory * 100)
    6. Dim Prozentram2 As ULong = CULng((Prozentram / My.Computer.Info.TotalPhysicalMemory))
    7. Dim Ergebnis As ULong = (Prozentram2)
    8. Return (Ergebnis)
    9. End Function
    10. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    11. MessageBox.Show(RAM_FreierSpeicherCheck.ToString)
    12. End Sub
    13. End Class


    Visual Basic.NET 8o
    MS-SQL
    8o

    Cheffboss schrieb:

    Wenn ich nun 100% - 67% rechne zeigt er mir 33% an.
    Dieser Wert weicht zwischen +1 und -1 aus.
    Mir sieht das nach einem RundungsFehler aus.
    RundungsFehler sind unvermeidlich, wenn man Divisions-Ergebnisse in Ganz-Zahlen speichert.

    Vielleicht wirds so bisserl genauer:

    VB.NET-Quellcode

    1. return DirectCast(ULong.Round(My.Computer.Info.AvailablePhysicalMemory * 100 / My.Computer.Info.TotalPhysicalMemory),ULong)
    Vielleicht auch nicht. Die Idee ist jdfs., die verlustbehaftete TypUmwandlung so spät wie möglich durchzuführen.
    Vielleicht mal Doku von CULng lesen, ob das evtl. garnet rundet, sondern immer abschneidet.
    (Übrigens braucht man garkein ULong für eine ProzentZahl - die gehen doch bis max 100.)

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Rechne die Werte ohne Rundung in Excel einzeln aus. Dann vergleiche diese mit den rohen Werten mit denen du rechnest. Dann kannst du nachvollziehen woher die Differenz kommt. Wird nen „Rundungsfehler“ sein...
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    Ich habe deinen Code etwas umgebaut, in der Hoffnung, etwas zu bewirken

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    3. MessageBox.Show(RAM_FreierSpeicherCheck.ToString)
    4. End Sub
    5. Private Function RAM_FreierSpeicherCheck() As ULong
    6. Dim Prozentram As ULong = CULng(Math.Round(My.Computer.Info.AvailablePhysicalMemory / My.Computer.Info.TotalPhysicalMemory * 100.0, 0))
    7. Return Prozentram
    8. End Function
    9. End Class


    Wie @mrMo und @ErfinderDesRades bereits erwähnten, wird das ein Rundungsfehler sein. Ich habe mir als unabhängige Quelle einen Taschenrechner herbeigezogen.

    Er kommt auf 68,89521092 % freier Speicher. Mit Math.Round wird das zu 69%, aber wenigstens gerundet. So wird nicht abgeschnitten auf 68 ;)

    Mein Task-Manager sagt 5,0 ÷ 15,9 * 100% = 31,4465.

    31,4465 % + 68,89521092 % = 100,3417 % hmm naja, aber es geht in die richtige Richtung.



    Wobei man sich jetzt auch wieder fragan kann, warum der Task-Manager 15,9 GB sagt (ich habe 16384 MB, also 16,0 GB)

    Bilder
    • Screenshot 2020-11-02 211901 - Kopie.png

      23,7 kB, 825×634, 71 mal angesehen
    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.
    @Cheffboss Decimal bringt da eher nix.
    Überleg mal, ob Du das ganze in Double rechnest und dann die finale Ausgabe nicht rundest, sondern geeignet formatierst.
    0,1% von viel RAM ist immer noch mehr als wenig. :thumbsup:
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @ErfinderDesRades
    Danke, für deine Antwort. :thumbup:
    Ich vermute auch dass es ein Rundungs-Fehler sein muss.
    Leider hat dein Code genau das gleiche Problem.
    Ich habe nun auch den Datentyp mal auf Long und Integer geändert.
    Ohne Erfolg!

    @mrMo
    Danke für den Tipp, mit Excel. :thumbup:
    Werde ich gleich mal ausprobieren.

    @Bartosz
    Danke, aber leider hat dein Code den gleichen Fehler.
    Manchmal stimmt der Wert, aber oft auch mit Differenzen +1 oder -1.
    Ich hoffe ich finde noch die passende Lösung!

    @Schmittmuthelm
    Super, genau die Eigenschaft habe ich gesucht.
    Danke :thumbup:

    @RodFromGermany
    Ja, stimmt.
    Ich habe einfach aus meiner Verzweiflung, alles was mir eingefallen ist getestet. ^^
    Visual Basic.NET 8o
    MS-SQL
    8o
    Ich habe gerade einen anderen Code gefunden.
    Dieser arbeitet mit einem PerformanceCounter.
    Leider habe ich auch mit diesem den gleichen Fehler.
    Woran kann das nur liegen? ?(

    VB.NET-Quellcode

    1. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    2. Dim ram As Integer = CInt(100 - (PcRam.NextValue / Convert.ToInt32(My.Computer.Info.TotalPhysicalMemory / 1048576)) * 100)
    3. Me.ProgressBar1.Value = ram
    4. Me.Text = Me.ProgressBar1.Value.ToString + "%"
    5. 'PcRam:
    6. '-CategoryName Arbeitsspeicher
    7. '-CounterName: Verfügbare MB
    8. 'Timer1:
    9. '-Interval 500
    10. '-Enabled: True
    11. End Sub
    Visual Basic.NET 8o
    MS-SQL
    8o
    @Cheffboss Es ist hier

    VB.NET-Quellcode

    1. 100 - (PcRam.NextValue / Convert.ToInt32(My.Computer.Info.TotalPhysicalMemory / 1048576)) * 100)

    unnütz, zu int32 zu converten, weil der Slash (/) eine Double-Berechnung durchführt. Das heißt, das gerade zu Int32-Umgewandelte wird eh wieder zu Double. Daher kannst es auch belassen ;)

    Darf ich mal was sagen?

    VB.NET-Quellcode

    1. Me.ProgressBar1.Value = ram
    2. Me.Text = Me.ProgressBar1.Value.ToString + "%"


    Warum nicht

    VB.NET-Quellcode

    1. Me.ProgressBar1.Value = ram
    2. Me.Text = ram.toString & "%"

    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.
    Oh man, du bist sei Jahren dabei, eigentlich recht aktiv, aber was du hier ablieferst, sieht aus, als ob du erst vor zwei Wochen angefangen hast zu programmieren.
    Miese Benamung, unnötige Klammern und vor allem:
    Warum hast du nicht schon längst, deine IDE auf Option Strict On gestellt ?
    Sei es drum !

    Ich halte mich lieber vom My Namespace fern, daher nutze ich, um an Systeminformationen zu kommen, lieber WMI.

    Dazu habe ich mir einen kleinen Wrapper erstellt:

    VB.NET-Quellcode

    1. Imports System.Management
    2. Namespace WMI
    3. Public NotInheritable Class ObjectSearcher
    4. Private Searcher As ManagementObjectSearcher
    5. Sub New(ByVal _scope As String, ByVal _queryString As String)
    6. Searcher = New ManagementObjectSearcher(_scope, _queryString)
    7. End Sub
    8. Public Function GetObject(ByVal _property As String) As Object
    9. For Each queryObject As ManagementObject In Searcher.Get()
    10. Return queryObject(_property)
    11. Next
    12. Return Nothing
    13. End Function
    14. End Class
    15. End Namespace


    Für die Prozent Berechnung habe ich eine Extension:

    VB.NET-Quellcode

    1. Imports System.Runtime.CompilerServices
    2. Public Module DoubleExtensions
    3. <Extension>
    4. Public Function Percentage(ByVal _value As Double, ByVal _from As Double, ByVal Optional _round As Boolean = False) As Double
    5. Dim result As Double = _value / _from * 100
    6. Return If(_round, Math.Round(result), result)
    7. End Function
    8. End Module


    Die Anwendung könnte dann so aussehen:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class FormWMIMemoryInfo
    2. Private OperatingSystem As New WMI.ObjectSearcher(rootCIMV2, SELECT FROM Win32_OperatingSystem)
    3. Private TotalMemory As Double = Convert.ToDouble(OperatingSystem.GetObject(TotalVisibleMemorySize))
    4. Private freePhysicalMemory As Double
    5. Private usedPhysicalMemory As Double
    6. Private Sub FormWMIMemoryInfo_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    7. LabelMemoryTotal.Text = $Total {TotalMemory}
    8. UpdateMemoryInfoLabels()
    9. With TimerUpdateMemoryInfo
    10. .Interval = 500
    11. .Start()
    12. End With
    13. End Sub
    14. Private Sub TimerUpdateMemoryInfo_Tick(sender As Object, e As EventArgs) Handles TimerUpdateMemoryInfo.Tick
    15. UpdateMemoryInfoLabels()
    16. End Sub
    17. Private Sub UpdateMemoryInfoLabels()
    18. freePhysicalMemory = Convert.ToDouble(OperatingSystem.GetObject(FreePhysicalMemory))
    19. usedPhysicalMemory = TotalMemory - freePhysicalMemory
    20. LabelMemoryUsed.Text = $Used {usedPhysicalMemory} ({usedPhysicalMemory.Percentage(TotalMemory, True)}%)
    21. LabelMemoryFree.Text = $Free {freePhysicalMemory} ({freePhysicalMemory.Percentage(TotalMemory, True)}%)
    22. End Sub
    23. End Class


    Viel Spaß damit. :)
    @Bartosz
    Stimmt, dein Code ist leichter zu lesen.
    Das werde ich mir nun merken.
    Danke! :thumbup:

    @FormFollowsFunction
    Vielen Dank, für deinen Code. :thumbup:
    Leider könnte diesen nicht Compilern.
    Genau an dieser Zeile erscheint ein Fehler.
    Ich habe alle Imports gemacht, und das .NET Framework auch auf die neuste Version gesetzt.

    VB.NET-Quellcode

    1. Private OperatingSystem As New WMI.ObjectSearcher(rootCIMV2, SELECT FROM Win32_OperatingSystem)

    Außerdem zickt meine Sicherheitssoftware bei diesem Code rum.
    (Siehe Anhang!)

    @an alle
    Ich habe nun mein Programm etwas verändert.
    Anstatt herauszufinden wieviel Arbeitsspeicher in Prozent frei ist.
    Möchte ich nun nur noch ermitteln wieviel MB noch frei ist.

    VB.NET-Quellcode

    1. Public Function Percent(ByVal CurrVal As Long, ByVal MaxVal As Long) As Integer
    2. Return CInt(Int(CurrVal / MaxVal * 100))
    3. End Function
    4. Private Sub FreierArbeitspecherAnzeigen()
    5. Dim prozentWert As ULong = CULng(Percent(CLng(My.Computer.Info.AvailablePhysicalMemory), CLng(My.Computer.Info.TotalPhysicalMemory)))
    6. ProgressBar1.Value = CInt(prozentWert)
    7. Label1.Text = String.Format("{0} MB freier Arbeitsspeicher", Math.Round(My.Computer.Info.AvailablePhysicalMemory / 1024 / 1024))
    8. End Sub


    Mein Test ergab, dass der Code so funktioniert.
    Kann jemand, dies bitte auch noch schnell testen und mir Bescheid geben? ?(
    Vielen Dank!


    Anhang:
    Visual Basic.NET 8o
    MS-SQL
    8o
    @Cheffboss Das ganze geht auch mit nur einer Konvertierung:

    VB.NET-Quellcode

    1. Public Function Percent(ByVal CurrVal As ULong, ByVal MaxVal As ULong) As ULong
    2. Return CurrVal \ MaxVal * 100UL
    3. End Function
    4. Private Sub FreierArbeitspecherAnzeigen()
    5. Dim prozentWert As ULong = Percent(My.Computer.Info.AvailablePhysicalMemory, My.Computer.Info.TotalPhysicalMemory)
    6. 'ProgressBar1.Value = CInt(prozentWert)
    7. Label1.Text = String.Format("{0} MB freier Arbeitsspeicher", Math.Round(My.Computer.Info.AvailablePhysicalMemory / 1024 / 1024))
    8. Label2.Text = prozentWert.ToString
    9. End Sub
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Cheffboss schrieb:

    Ich habe alle Imports gemacht, ...

    Alle sind aber gar nicht nötig, Imports System.Management reicht vollkommen aus. ;)

    Und was die Schadsoftware-Warnung angeht, wundert mich das nicht, den Kasperski-Paranoier-Suite ist totaler Schrott !
    Windows-Defender reicht vollkommen aus, wenn es nicht sogar allen anderen Sicherheitslösungen überlegen ist.
    @FormFollowsFunction
    Ja, genau diesen Import habe ich gemeint. :thumbup:
    Ich persönlich fühle mich bei Kaspersky sehr wohl.
    Früher habe ich einige Jahre Panda ausprobiert, dies fand ich nicht so gut.
    Avast ist auch ganz gut, dieses verwende ich auf meine Smartphones.
    Beim Windows Defender habe ich, die Befürchtung, dass irgendwann eine Sicherheitslücke erscheint, diese den Defender blockiert!
    Das ist leider nur eine Frage der Zeit…
    Da die Hacker jetzt eher versuchen die Sicherheitssoftware zu knacken diese sehr bekannt ist.
    Was ich an Kasperky gut finde, ist der Webcam-Schutz!
    Falls irgendeine Anwendung meine Webcam gegen meinen Willen starten möchte,
    kann ich dies dann sofort blockieren!
    Und wenn man in Google etwas sucht, sieht man gleich ob der Link sicher ist.
    Ich weiß, diese Funktion hat man auch meistens auch mit kostenlosen Produkten.
    Ich möchte hier keine Diskussion starten, welche Sicherheitssoftware die beste ist.
    Das ist denke, ich alles Ansicht Sache.
    Jeder hat sein Lieblings Hersteller. ^^
    Visual Basic.NET 8o
    MS-SQL
    8o
    Ja, mußt du wissen, was nur nen Anmerkung meinerseits.

    Daß du den code nicht kompilieren kannst, liegt aber nicht am code, da bin ich mir sicher !
    @Cheffboss Häng mal ein Rumpf-Projekt an oder eine einzelne Klasse, die sich nicht compilieren lässt.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!