Also erstmal Danke an ALLE.
Danke für den Hinweis auf die neue Implementierung von Json. Leider ist es auch so, dass man bei einer Google-Suche, auch über Google News nichts dazu findet, dass Newtonsoft Json praktisch Out of Date ist. Ich werde also natürlich die neue Variante nutzen.
Danke auch an thomas.at mit dem Klartext-Hinweis auf "{get; set;}". Da habe ich echt noch Probleme. NewtonSoft war da wohl etwas toleranter was sowas anging.
Was ist an System.Text.Json besser? Irgendwie wird immer auf das Json von Newtonsoft verwiesen. Da finden sich im Zweifel dann für mich als Anfänger sicher auch mehr Hilfe, weil es wohl jeder kennt und verwendet. Hat ja auch knapp 2,89B downloads bei Nu-Get, was wohl im deutschen 2,89 Millliarden? sind.
Ich habe das trotzdem mal probiert und wohl auch die Lösung gefunden, die mit Newtonsoft funktioniert.
Ich habe die Klasse "InventoryResponse" etwas umgeschrieben und die Klasse "Test" gelöscht. (Ist das richtig?)
class InventoryResponse
{
public int id;
}
Damit klappt das nun. (Diese "Test"-Klasse kam mir eh komisch vor, habe mich aber natürlich an das Lernbeispiel aus einem Videokurs orientiert.)
Ich habe dann
InventoryResponse inventoryAPI = JsonConvert.DeserializeObject<InventoryResponse>(response);
auskommentiert und von learn.microsoft.com das Beispiel für "System.Text.Json" versucht umzusetzen. Klappt soweit auch, aber die id ist jetzt "0" (als Zahl, nicht "null")
InventoryResponse? inventoryAPI = JsonSerializer.Deserialize<InventoryResponse>(response);
Was mache ich falsch?
Ich habe folgendes JSON auf meiner Webseite. Der Quelltext gibt das ebenfalls exakt so wieder.:
{"id":15,"hardwareComputerSerial":"1A2B3C4"}
Wenn ich nun folgenden Code schreibe, dann bekomme ich auch ein anständiges JSON zurück:
string requestUrl = "https://api.meineseite.tld/api.php";
HttpClient httpClient = new HttpClient();
var hardwareComputerSerial = "1A2B3C4";
var urlParameter = requestUrl + "?hardwareComputerSerial=" + hardwareComputerSerial;
HttpResponseMessage responseMessage = httpClient.GetAsync(urlParameter).Result;
string response = responseMessage.Content.ReadAsStringAsync().Result;
In "respnse" steht dann folgendes:
{"id":15,"hardwareComputerSerial":"1A2B3C4"}
Sieht also gut aus.
Nun will ich das ganze deserialisieren.
Dazu habe ich zwei neue Klassen erstellt:
class Test
{
public int id;
}
class InventoryResponse
{
public Test id;
}
und dann den Code um eine Zeile erweitert:
InventoryResponse inventoryAPI = JsonConvert.DeserializeObject<InventoryResponse>(response);
Wenn ich das nun ausführe bekomme ich folgenden Fehler zurück:
Newtonsoft.Json.JsonSerializationException: 'Error converting value 15 to type 'SysteminventoryV2.Api+Test'. Path 'id', line 1, position 8.'
Inner Exception
ArgumentException: Could not cast or convert from System.Int64 to SysteminventoryV2.Api+Test.This exception was originally thrown at this call stack:
[External Code]
In "response" eine Zeile drüber also, bei
string response = responseMessage.Content.ReadAsStringAsync().Result;
steht plötzlich der Wert "null", also "response | null"
Ich habe das Ganze auch mit
class Test
{
public string hardwareComputerSerial;
}
class InventoryResponse
{
public Test hardwareComputerSerial;
}
probiert. Passiert genau das Gleiche, nur dass dann der "Exception
Newtonsoft.Json.JsonSerializationException: 'Error converting value "1A2B3C4" to type 'SysteminventoryV2.Api+Test'. Path 'hardwareComputerSerial', line 1, position 43.'
ArgumentException: Could not cast or convert from System.String to SysteminventoryV2.Api+Test.
This exception was originally thrown at this call stack:
[External Code] steht.
Könnt ihr mir bitte sagen, was ich falsch mache und warum eine Zeile weiter unten plötzlich Einfluss auf eine Variable hat, die weiter oben ohne die Zeile weiter unten bereits den richtigen Wert hat, mit der Zeile dann aber nicht mehr?
Danke Abt. Hat geklappt.
Ich habe vor zwei Wochen angefangen mein Projekt auf Github zu laden. Ist aber private.
Nun habe ich weiter gemacht und wollte das Repository aktualisieren. Geht aber nicht, weil angeblich ist mein lokales Repository älter als online Repository auf GitHub. Stimmt aber nicht und selbst wenn wäre mir das egal. Ich kann machen was ich will, ich bekomme es nicht hin das Projekt auf Github zu aktualisieren. Einfach den alten Kram überschreiben. Jemand eine Idee? Kann doch eigentlich nicht so schwer sein? Verwende VS 2022 Community Edition.
Wenn ich erst Pulle gibt es Konflikte. Ich hake dann zwar an, dass ich das eingehende verwenden möchte, kann das aber nirgendwo bestätigen.
Hi,
hast du mal im Debugger per Breakpoint geschaut, was ipv6key zurückgibt?
Ist das wirklich NULL?
Ja, ist "null". (Siehe Anhang) Ich würde es gerne verstehen, unabhängig davon, dass der restliche Code, bzw. Aufbau nicht schön ist. Direkt falsch ist es ja auch nicht.
Folgender Code kommt mir etwas lang vor. Kann man den sinnvoll kürzen?
Außerdem gibt es in Zeile 9 eine NullReferenceException.
Ist auch richtig, denn auf meinem privaten System gibt es den Registry-Eintrag nicht. Aber ich prüfe doch auf "null"? VS sagt aber auch, dass ich nicht prüfe (grün unterstrichen), also prüfe ich offenbar falsch.
Hinzu kommt, dass der gesuchte Schlüssel ein dword ist und keine Zeichenkette. Deswegen muss ich offenbar eine "doppelte Umwandlung" (so nenne ich das mal) vornehmen. Verstehe also nicht, was "(uint)(int)" genau machen.
public static string GetSystemIpv6State()
{
string SystemIpv6State = "";
try
{
using RegistryKey? ipv6 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey(@"SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters");
if (ipv6 != null)
{
object ipv6key = (uint)(int)ipv6.GetValue("DisabledComponents");
if (ipv6key != null)
{
if (ipv6key.ToString() == "4294967295" || ipv6key.ToString() == "255")
{
SystemIpv6State = "Deaktiviert";
}
else
{
SystemIpv6State = "Aktiviert";
}
}
}
else
{
SystemIpv6State = "Undefinierter Zustand";
}
}
catch (Exception)
{
SystemIpv6State = "Fehler";
}
return SystemIpv6State;
}
Wollte mich noch für die Erklärungen bedanken. Hatte sie unterwegs gelesen und dann zu Hause vergessen zu reagieren.
Danke Abt. Du hast mir zwar jetzt den Weg Richtung Lösung gezeigt, aber warum das so ist habe ich trotzdem nicht verstanden.
Ich nutze doch nur eine Abkürzung um die exe aus zu führen und trotzdem ist ein Workingdir notwendig? Was passiert da im Hintergrund?
Ich habe mir ein kleines Tool geschrieben mit dem ich verschiedene cmd-Dateien als Administrator aufrufen kann.
Solange ich die exe aus dem gleichen Verzeichnis starte wo auch die cmd-Dateien liegen funktioniert es. Verwende ich aber die Verknüpfung zur exe werden die cmd-Dateien nicht mehr gefunden. Ich muss die cmd-Dateien dann in das gleiche Verzeichnis wie die Verknüpfung legen. Dann klappt es wieder.
Ich verstehe das nicht. Eine Verknüpfung ist doch nur ein Verweis auf die exe die gestartet wird. Was läuft falsch?
string fileName;
private void BtnMicrosoftSurface_Click(object sender, EventArgs e)
{
try
{
fileName = Path.GetFileName("InstallSurface.cmd");
Process proc = new Process();
proc.StartInfo.FileName = fileName;
proc.StartInfo.UseShellExecute = true;
proc.StartInfo.Verb = "runas";
proc.Start();
Close();
}
catch (Exception)
{
MessageBox.Show("Datei \"InstallSurface.cmd\" nicht gefunden.", "Fehler",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Ist WMI auch als Datenquelle zu sehen oder ist das was anderes? Für mich irgendwie schon, weil ich darüber ja die Informationen beziehe, die ich dann anzeigen lasse.
Ja, das mit der Abhängigkeit habe ich so gemeint, also Abhängigkeit von der Registry, die ja eine Systemkomponente ist. Ist für mich das gleiche. Ist es aber in der Sprache der Programmierung gar nicht und ich vermische etwas? Von WMI als Komponente bin ich ja auch abhängig. Wenn Microsoft da was ändert könnte mein Tool plötzlich andere Informationen ausgeben oder auch gar nicht mehr funktionieren. Ich frage das nur, um mich zukünftig hoffentlich verständlich aus zu drücken.
Die Frage nach "gutem" Code, war so gemeint, ob das Code ist mit dem man durchaus was anfangen kann. Bei dem alten "Spaghetti-Code" den ich an den Tag gelegt habe sind wir uns ja einig, dass man es drehen und wenden kann wie man will: Er funktionierte einfach nur, machte aber schon mein kleines Mini-Tool wahnsinnig unübersichtlich, weil alles in eine einzige Datei geklatscht wurde (Form1.cs) und am Ende über 1.000 Zeilen Code stand. Das war nicht gut.
Ich habe mir das durchgelesen. Bei dem Thema seid ihr ja echt total unterschiedlicher Meinungen.
Für mich als jemand der ohnehin schon stark zu kämpfen hat und ein Fall von "Unbedingt Wollen, aber eigentlich nicht Können" ist, ist das schwer, wenn die beiden aktivsten und hilfsbereitesten Mitglieder jeweils unterschiedliche Meinungen vertreten und man nun nicht so recht weis, was OK ist und was nicht.
Ich nehme jetzt mal mit, dass man die Methodenvarianten in klein gehaltenen Projekten verwenden kann und nicht grundlegend falsch ist, es aber durchaus sinnvoll ist bei größeren Projekten auf die Klassenvariante zu wechseln, bzw. zumindest dann, wenn man sich von einer Drittkomponente (Hier Registry) abhängig macht. Mit hoffentlich fortschreitendem Wissen sollte man dann beide Varianten beherrschen.
Zu definieren wäre dann noch, was als "Drittkomponente" zu definieren ist, weil im Grunde greift man bei WMI-Abfragen ja auch auf eine Drittkomponente (WMI-Klasse) zurück und ist von dieser abhängig.
@Th69: Abt schreibt noch, dass die Methodenvariante (in meiner Vorgehensweise?) das Drei-Schichten-Modell verletzt. Gehst du da mit? Wie handhabst du diese Thematik?
Ich habe das nun probiert, aber leider funktioniert das nicht. Ich habe den kompletten Code in eine eigene Klasse und am ende sogar in ein neues .net Framework 4.8 Projekt kopiert, weil "using Microsoft.WindowsAPICodePack.Resources;" in Version 7 des "Windows-API-CodePack-NET" nicht mehr unterstützt wird und ich dachte es liegt vielleicht daran. Habe deswegen Version 1.1.2 verwendet (das aber nicht .net Core 6 unterstützt) Daran lag es aber am ende nicht.
Fehler ist:
'Der Zugriff auf "PowerManagementNativeMethods" ist aufgrund des Schutzgrads nicht möglich.
Die dekompilierte Datei, bzw. Methode von MessageManager.cs beginnt dann auch mit
internal static class MessageManager
{
}
und logischerweise kann man das nicht mal eben testweise auf public ändern.
Jetzt bin ich überfordert.
Btw: Die Demo-App, basierend auf WPF funktioniert auch nicht. Die lässt sich zwar kompilieren, wirft beim Starten dann aber auch den Fehler im Ereignisprotokoll.
Ebenfalls interessant: Die Methode (GetSystemEnergyState()) aus meiner App die letztens auf meinem Rechner zu Hause noch funktionierte, funktioniert nun nicht mehr, hat dafür aber auf einem meiner Geschäftsrechner wo sie vorher nicht funktionierte plötzlich funktioniert. Muss man das verstehen?
Also um das richtig zu verstehen: Für ein Mini-Tool ist der Code "OK" (Im Sinne von "Kann man so machen und ist nicht falsch"). Nur der Exception-Block ist Müll.
Für größere Projekte ist der Ansatz aber nicht gut und ich sollte auf die von dir vorgeschlagene Variante umschwenken und noch mehr lernen.
Danke Abt. Ich muss den Code jetzt erstmal nachvollziehen und verstehen. Geht noch über meien Wissensstand hinaus. Aber jetzt weiß ich in welche Richtung es gehen soll.
Ich habe mich beim coden an diesem Thread orientiert und mich für die Methodenlösung entschieden. War das falsch?
Ich habe den Code übrigens erstmal nicht in Code-Reviews gepostet, weil ich dachte, dass er gegen Regel 1 verstößt, also direkt kompilierbar sein muss. Weils aber nur eine Methode ist dachte ich, dass es hier falsch ist. Sorry.
Ich habe meinen Code versucht zu optimieren und mir dabei die Nullreferenz-Warnung zunutze gemacht die ja ständig nervt.
Ich würde nun gerne wissen, ob dieser neue Code auch sauber ist oder man das so nicht machen sollte.
Alter Code:
try
{
var findCitrix = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey(@"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\CitrixOnlinePluginPackWeb")?.GetValue("DisplayVersion") ??
RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64).OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CitrixOnlinePluginPackWeb")?.GetValue("DisplayVersion");
if (findCitrix == null)
{
softwareCitrixProgram = "Nicht installiert";
softwareCitrixVersion = "";
}
else
{
softwareCitrixProgram = "";
softwareCitrixVersion = findCitrix.ToString();
}
}
catch (Exception)
{
MessageBox.Show("Problem im Abschnitt Citrix Workspace.");
}
Neuer Code:
public static string GetCitrixWorkspace()
{
string CitrixWorkspace = "";
try
{
var findCitrix = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey(@"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstal\CitrixOnlinePluginPackWeb")?.GetValue("DisplayVersion") ??
RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64).OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CitrixOnlinPluginPackWeb")?.GetValue("DisplayVersion");
CitrixWorkspace = findCitrix?.ToString() ?? "Nicht installiert";
}
catch (Exception)
{
MessageBox.Show("Problem im Abschnitt Citrix Workspace.");
}
return CitrixWorkspace;
}
Danke.
Ich habe das Tool gerade bei meiner zweiten Arbeitsstelle getestet und habe hier das gleiche Problem. Beides Dell-Rechner.
In der einen Arbeitsstelle ist es ein Optiplex 5040 und bei der anderen ein Optiplex 7050. Mittels Dell Command | Update (Sucht automatisch die aktuellen Treiber zum jeweiligen Dell-System) wurde sichergestellt, dass alles auf dem aktuellen Stand ist.
Die Ereignisanzeige sagt folgendes:
Name der fehlerhaften Anwendung: SysteminventoryV2.exe, Version: 1.0.0.0, Zeitstempel: 0x6377dc84
Name des fehlerhaften Moduls: ntdll.dll, Version: 10.0.19041.2130, Zeitstempel: 0xb5ced1c6
Ausnahmecode: 0xc0000374
Fehleroffset: 0x00000000000ff6a9
ID des fehlerhaften Prozesses: 0x3c48
Startzeit der fehlerhaften Anwendung: 0x01d9210924c48852
Pfad der fehlerhaften Anwendung: [..]\SysteminventoryV2\bin\Debug\net6.0-windows\SysteminventoryV2.exe
Pfad des fehlerhaften Moduls: C:\WINDOWS\SYSTEM32\ntdll.dll
Berichtskennung: [...]
Vollständiger Name des fehlerhaften Pakets: <Hier steht nichts>
Anwendungs-ID, die relativ zum fehlerhaften Paket ist:
Ich kann das bis Projekt das bislang gemacht wurde gerne hier reinstellen falls euch das helfen sollte mir zu helfen.
Mein C# Programm funktioniert auf meinem Rechner zu Hause, aber im Geschäft wird die Anwendung in VS mit folgendem Fehler beendet:
Das Programm "[16224] SysteminventoryV2.exe" wurde mit Code 3221226356 (0xc0000374) beendet.
Ursächlich dafür ist folgender Code:
// Use WindowsAPICodePack.
public static string GetSystemEnergyState()
{
string SystemEnergyState = PowerManager.PowerPersonality.ToString();
return SystemEnergyState;
}
lblSystemEnergyState.Text = SystemClass.GetSystemEnergyState(); // Wenn auskommentiert startet das Programm, bzw. bleibt offen
Wenn man Google bemüht finden sich Fehler in Bezug auf C++, zu C# eher weniger und nichts was mir weiterhelfen würde. Rechner wurde bereits neu gestartet. Fehler 0xc0000374 sieht für mich nach einem speicherproblem aus, aber stimmt das überhaupt und wenn ja, wieso?
Ich verwende das WindowsAPICodePack 7.0.1
https://www.nuget.org/packages/WindowsAPICodePack/7.0.1
Danke euch. Auch für das Tool. Direkt runtergeladen.
Einmal mehr ein Dankeschön für dich.
Das löst mein aktuelles Problem, aber wie / wo kann ich nachschlagen, was mir das Pack noch alles so bietet und wie ich es anwende? Ich schätze nicht für alles gibt es eine Demoanwendung? Wie geht man mit Nu-Get Paketen um zu denen sich keine (ausreichende) Dokus finden, bzw. schlecht dokumentiert sind? Ist ja eine ganz allgemeine Sache.
Sorry, wollte nur das ironisch aufgreifen, was man in diversen Foren (so wortwörtlich hier nicht, das stimmt) so unsanft gerne an den Kopf geworfen bekommt.
Sollte echt nicht frustriert klingen und war auch nicht frustriert gemeint. Sollte zum Ausdruck bringen, dass ich mir bereits echt Mühe gegeben habe eine Dokumentation zu finden, zu lesen und zu verstehen.
Ich suche die Dokumentation zum Windows-API-Code-Pack. Ich würde gerne nachlesen, ob es dort eine Funktion gibt, um das Energieschema von Windows auszulesen. Scheinbar gibt es da nämlich was:
https://stackoverflow.com/a/7457150
Auf der verlinkten Seite von Microsoft stehen zwar die Funktionen, aber nicht, wie ich diese anwenden muss. Keine Beispiele, nix.
https://learn.microsoft.com/de-de/windows/win32/power/power-management-functions?redirectedfrom=MSDN
Im Git-Repository gibt es zwar unter anderem eine Demo-App unter source/Samples/PowerMgmtDemo/CS/, aber mit der kann ich nichts anfangen und in der Hilfedatei unter documentation/Windows API Code Pack Help.chm gibt es zwar ein Inhaltsverzeichnis, aber wenn man sich da durch klickt erscheint im rechten Fenster kein Inhalt.
Generell soll das API-Code-Pack mächtig und hilfreich sein, so dass sich das wohl echt lohnt die Funktionen da drin zu kennen und anwenden zu können.
Vielleicht noch als Randnotiz:
Ich habe bereits funktionierenden Code, aber der funktioniert nur, wenn die Anwendung explizit als Administrator aufgerufen wird. (Mit Adminrechten am System angemeldet zu sein reicht nicht. Gbit eine Exception)
public static string GetSystemEnergySettingState()
{
var searcher = new ManagementObjectSearcher(@"\\.\root\cimv2\power", "SELECT * FROM Win32_PowerPlan WHERE IsActive = True");
using ManagementObjectCollection managementObjectCollection = searcher.Get();
ManagementObject managementObject = managementObjectCollection.OfType<ManagementObject>().First();
string SystemEnergySettingState = managementObject["ElementName"].ToString() ?? "Default";
return SystemEnergySettingState;
}
Das gleiche Problem hatte ich mal, als ich auslesen wollte, ob Bitlocker aktiviert ist oder nicht. Damals bin ich dann auf den verlinkten Code, basierend auf dem Windows-API-Code-Pack-1.1 gestoßen, den ich aber nur kopiert habe. Wie hat der damalige Autor rausgefunden, wie er den Code schreiben muss? Wie geht man sowas an?
https://stackoverflow.com/a/41310139
Danke. Das die Variablen außerhalb von if/else nicht mehr gilt war mir gar nicht mehr bewusst. Ich dachte das ist nur bei Methoden und Klassen der Fall.
Ja, das die Eigenschaften gar keinen Verweis mehr haben, habe ich heute im Geschäft gesehen. Dort hatte ich wohl mal die Funktion aktiviert um das zu sehen. Zu Hause hatte ich das noch nicht aktiviert (Jetzt schon 😄)
Ich habe mich letztlich für die Methodenvariante entschieden, einzig weil sie mir besser gefällt. Ob und in welchen praktischen Anwendungsfällen die Klasse besser geeignet ist, habe ich nicht verstanden, aber da das Programm nur Daten ermitteln und übertragen soll und anschließend beendet wird ist es wohl ohnehin egal.
Ich habe da ein Verständnisproblem.
Folgender Code wirft Fehler:
Fehler CS1023 Eine eingebettete Anweisung kann keine Deklaration und keine Anweisung mit Bezeichnung sein.
public string? SystemBitlockerState { get; private set; }
public static string GetSystemBitlockerState()
{
IShellProperty prop = ShellObject.FromParsingName("C:").Properties.GetProperty("System.Volume.BitLockerProtection");
int? bitLockerProtectionStatus = (prop as ShellProperty<int?>)?.Value;
if (bitLockerProtectionStatus.HasValue && (bitLockerProtectionStatus == 1 || bitLockerProtectionStatus == 3 || bitLockerProtectionStatus == 5))
string SystemBitlockerState = "Aktiviert"; // Fehler hier
else
string SystemBitlockerState = "Deaktiviert"; // Fehler hier
return SystemBitlockerState; // Fehler hier
}
// // Lässt man das "string" weg gibt es den Fehler "Fehler CS0120 Für das nicht statische Feld, die Methode oder die Eigenschaft "SystemClass.SystemBitlockerState" ist ein Objektverweis erforderlich."
Folgender Code funktioniert.
public string? SystemBitlockerState { get; private set; }
public static string GetSystemBitlockerState()
{
string SystemBitlockerState; // Variable deklariert
IShellProperty prop = ShellObject.FromParsingName("C:").Properties.GetProperty("System.Volume.BitLockerProtection");
int? bitLockerProtectionStatus = (prop as ShellProperty<int?>)?.Value;
if (bitLockerProtectionStatus.HasValue && (bitLockerProtectionStatus == 1 || bitLockerProtectionStatus == 3 || bitLockerProtectionStatus == 5))
SystemBitlockerState = "Aktiviert";
else
SystemBitlockerState = "Deaktiviert";
return SystemBitlockerState;
}
Ich verstehe den Unterschied nicht? Warum muss ich SystemBitlockerState in dieser Methode erste deklarieren? Vor allem habe ich die Variable doch schon ganz oben (Zeile 1) deklariert?
Wenn ich beispielsweise diese Methode heranziehe, dann ist das nicht notwendig.
public string? SystemComputerName { get; private set; }
public static string GetSystemComputername()
{
var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_ComputerSystem");
using ManagementObjectCollection managementObjectCollection = searcher.Get();
ManagementObject? managementObject = managementObjectCollection.OfType<ManagementObject>().First();
string SystemComputerName = managementObject["Name"].ToString() ?? "Default";
return SystemComputerName;
}
Für mich ist das verwirrend.
OK, codetechnische Umsetzung habe ich kapiert. (Hat etwas gedauert)
Die Frage bleibt aber, wann welche Vorgehensweise sinnvoller ist und ob meine Aufteilung sinnvoll ist.
Um es zu erklären.
In der Datei SystemClass.cs frage ich folgendes ab:
public string? SystemComputerName { get; private set; } public string? SystemOs { get; private set; } public string? SystemLastStart { get; private set; } public string? SystemOsCaption { get; private set; } public string? SystemOsDisplayVersion { get; private set; } public string? SystemLanIpAdress { get; private set; } public string? SystemDhcp { get; private set; } public string? SystemLastWindowsUpdate { get; private set; } public string? SystemOtherMicrosoftUpdates { get; private set; } public string? SystemSpaceCFree { get; private set; } public string? SystemBitlocker { get; private set; } public string? SystemBitockerKey { get; private set; } public string? SystemEnergySetting { get; private set; } public string? SystemWlanSsid { get; private set; } public string? SystemLastUser { get; private set; }
Daneben wird es aber noch andere Dateien geben, beispielsweise eine HardwareClass.cs und dort frage ich dann beispielsweise sowas hier ab:
public string? HardwareLocation { get; private set; } public string? HardwareManufactor { get; private set; } public string? HardwareModel { get; private set; } public string? HardwareType { get; private set; } public string? HardwareSerial { get; private set; } public string? HardwareBios { get; private set; } public string? HardwareCpu { get; private set; } public string? HardwareRamCapacity { get; private set; } public int? HardwareRamSlotsUsed { get; private set; } public int? HardwareRamSlotsAvailable { get; private set; } public string? HardwareMac { get; private set; } public string? HardwareDrive { get; private set; } public string? HardwareSpaceCAvailable { get; private set; } public string? HardwareBatteryCapacity { get; private set; }
Mist, kann nicht mehr editieren.
Gemeint ist "Alle Foren als gelesen markieren" in der Hauptübersicht.
Entweder übersehe ich es dauernd oder es fehlt tatsächlich:
Eine Funktion "Alle Themen als gelesen markieren" wäre schön.
Hallo und Frohes Neues,
ich habe die codetechnische Umsetzung leider nicht ganz verstanden.
Kannst du das anhand eines Beispiels bitte deutlicher machen? Und was ist in welcher Situation der bessere Ansatz?
Wie meinst du das mit dem Assembly? Das scheint sehr interessant zu sein. Vielleicht macht es Sinn auf diesem Ansatz auf zu bauen, weil dann könnte man das ja in anderen Projekten direkt wiederverwenden, oder?
Was die Wiederverwertbarkeit angeht brauche ich diesen Codefetzen nochmal:
var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_ComputerSystem");
using ManagementObjectCollection managementObjectCollection = searcher.Get();
ManagementObject? managementObject = managementObjectCollection.OfType<ManagementObject>().First();
Damit kann ich dann zum Beispiel Hersteller und Typ ermitteln
Wo du aber das Thema "Design" ansprichst. Momentan sieht das Ganze noch so aus. Ich denke das ist nicht ganz richtig. Wenn das Programm mal Formen annimmt werden folgende Bestandteile enthalten sein:
So, mit der Angelegenheit befasst und zumindest das Ergebnis stimmt. Aber ist die Herangehensweise so auch richtig oder gibt es Einwände eurerseits?
Ich bin leider unsicher, bitte seht es mir nach, wenn ich öfters mal nachfrage. Ich denke aber es ist besser als es falsch verstanden zu haben und dann wieder umlernen zu müssen.
SystemClass.cs
namespace SysteminventoryV2
{
class SystemClass
{
// Deklaration
// System
public string? SystemComputerName { get; set; }
public string GetSystemComputername()
{
var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_ComputerSystem");
using ManagementObjectCollection managementObjectCollection = searcher.Get();
ManagementObject? managementObject = managementObjectCollection.OfType<ManagementObject>().First();
this.SystemComputerName = managementObject["Name"].ToString()?.ToLower() ?? "Default";
return SystemComputerName;
}
public SystemClass() // Irgendwie bissel doof, dass das so leer jetzt ist, aber löschen kann man das ja scheinbar auch nicht.
{
}
}
}
Form1.cs
[...]
private void Form1_Load(object sender, EventArgs e)
{
SystemClass test = new SystemClass();
lblSystemComputerName.Text = test.GetSystemComputername();
}
Hmmm, eventuell mache ich gerade den zweiten Schritt vor dem ersten. Wie dem aber auch sei: Ich komme nicht weiter. Ich denke es ist mal wieder eine Kleinigkeit:
Es spielt dabei überhaupt keine Rolle, ob ich die Methode mit oder ohne Überlasung anlage / aufrufe und ob mit oder ohne "return;" Das Ergebnis ist immer gleich.
Also ich habe folgenden beispielhaften Code:
Erstmal die Klasse. Diese ist in eine eigene Klassendateiausgelagert.
SystemClass.cs
namespace SysteminventoryV2
{
class SystemClass
{
// Deklaration
// System
string? systemComputerName;
// Methode
public SystemClass(string systemComputerName) // Egal ob mit oder ohne Paramter
{
var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_ComputerSystem");
using ManagementObjectCollection managementObjectCollection = searcher.Get();
ManagementObject? managementObject = managementObjectCollection.OfType<ManagementObject>().First();
this.systemComputerName = managementObject["Name"].ToString()?.ToLower() ?? "Default";
return; // Egal, ob mit oder ohne. Ergebnis immer gleich
}
}
Form1.cs
namespace SysteminventoryV2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
SystemClass test = new SystemClass("Bla"); // Wenn in der Methode kein Parameter, dann lasse ich das natürlich hier leer)
lblSystemComputerName.Text = test.ToString();
}
}
}
So, dass nun nicht der Name des Computers steht ist mit dem Code ja erstmal logisch. Ich hätte aber zumindest mal erwartet, dass bei "lblSystemComputerName" das Wort "Bla" steht. Stattdessen steht da aber "SysteminventoryV2.SystemClass". Warum? Was läuft falsch?
Ich habe den Code auch immer wieder versucht anzupassen und natürlich mittels Variable an den Computernamen zu kommen, aber von Variablen will der Methodenaufruf überhaupt nichts wissen und gibt nur Fehler zurück.
Könnt ihr mir da bitte weiterhelfen?
Direkt auch die nächste Frage hinterher: Ist der Codeaufbau so überhaupt richtig oder gehe ich hier schon direkt einen falschen Weg? Wie sähe er richtig aus? Am Ende möchte ich ein Programm haben mit dem ich mir Informationen über den Computer anzeigen lassen kann.
Edit: Ergänzung und Rechtschreibfehler behoben.
Ich wollte einfach fragen, ob es möglich ist PowerShell-Befehle direkt in C# auszuführen, bzw. zu verarbeiten? Gibt es da eine Art "Brücke" oder API?
Einfaches Beispiel:
PowerShell:
powercfg /GETACTIVESCHEME
In meinem Fall bekomme ich dann folgende Ausgabe:
PowerShell:
GUID des Energieschemas: 9897998c-92de-4669-853f-b7cd3ecb2790 (AMD Ryzen™ Balanced)
Im Endeffekt würde ich dann in meiner WinForm nur noch "AMD Ryzen™ Balanced" angezeigt bekommen wollen.
Danke für die schnelle Antwort.
Damals war es mir wichtig (schnell) was zu haben mit dem ich arbeiten kann (im Sinne von ich habe die Informationen die ich brauche)
Das habe ich jetzt und nun kann ich mich daran machen das nochmal ordentlich umzusetzen. In Sachen PHP ist das bereits passiert und ich habe neben komplett neuen Code (auf Basis von MVC) auch eine echt schöne GUI zusammengebaut (Die aber noch mit Platzhalterdaten gefüllt ist).
Jetzt ist der C#-Teil dran und da ich was habe das bereits schonmal funktioniert habe ich auch die Zeit und vor allem Ruhe das so anzugehen wie es empfohlen wird. Vor allem habe ich bereits grundlegend funktionierenden Code den ich nun halt so umbauen muss, dass er am Ende immer noch funktioniert. Ich muss mir jedoch keine Gedanken darüber machen, ob ich schon beim Auslesen und ggf. Konvertieren / Formatieren der Werte einen Fehler mache und es deswegen nicht funktioniert, sondern ich weis, dass wenn es nach der Umstellung nicht funktioniert ich die Umsetzung schlicht falsch gemacht habe.
Ich weis, dass das für viele nicht nachvollziehbar ist, aber mir hilft es etwas Schritt für Schritt anzugehen. Etwas von Anfang an "professionell" und "perfekt" lösen zu wollen, damit bin ich in vielen Bereichen (nicht nur in der Programmierung) zu oft auf die Nase gefallen. Deswegen mache ich Dinge inzwischen lieber erstmal rudimentär / provisorisch, sammle Erfahrung und verbessere es dann. Es ist nicht so, dass es länger dauert, sondern es wird überhaupt nur deswegen fertig und ein gutes Ergebnis. (Ist wie beim Führerschein. Anfangs ist man froh, wenn man eine Fahrstunde übersteht ohne den Motor abzuwürgen. Später ist dann selbst das Anfahren an einer Steigung kein Problem mehr.)
@Abt (und alle anderen): Du kennst ja mein Projekt Systeminventory bei dem ich versuche Systeminformationen auszulesen und anzuzeigen.
Ich seh so viel Code pro Woche, wenn Du mir Montags was zeigst weiß ich Dienstagabend nicht mehr wie Dein Code aussah oder worums ging.
Ich merk mir auch nicht jedes Thema, sorry.
OK, dachte das Thema hätte einen bleibenden Eindruck hinterlassen. 😉
Der Code sah seinerzeit so aus: (Auszug, natürlich alles in die Form1.cs geklatscht.)
// Deklaration
string computerCpu;
// Prozessor auslesen
try
{
var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Processor");
using (ManagementObjectCollection managementObjectCollection = searcher.Get())
{
ManagementObject managementObject = managementObjectCollection.OfType<ManagementObject>().FirstOrDefault();
computerCpu = managementObject["name"].ToString();
}
}
catch (Exception)
{
MessageBox.Show("Problem im Abschnitt Prozessor");
}
// Ausfüllen der Label
lblComputerCpu.Text = computerCpu;
So habe ich das im Grunde mit allen Werten gemacht die ich ausgelesen habe. Am Ende hatte ich einen Schlauch von ~700-800 Zeilen Code nur um an die Informationen zu kommen und diese anzuzeigen.
Würde / Sollte man sowas mit get/set und Methoden lösen, bzw. sogar in eine Klasse auslegen (Also Klasse für alle Systemvariablen, Hardwarevariablen, Monitorvariablen, Softwareinformationen, ...)? Der Screenshot oben zeigt ja, dass ich das in entsprechende Bereiche unterteilt habe.
Ich danke euch so weit.
Ich finde das Thema sehr schwierig und habe für mich, bzw. übertragen auf mein Projekt den Nutzen noch nicht so wirklich verstanden, akzeptiere aber, dass es für die Programmierung wichtig ist. Vielleicht liege ich aber auch grundsätzlich falsch und zum Auslesen der verschiedenen Systemvariablen ist das Thema überhaupt nicht wichtig und ich versuche (krampfhaft) etwas auf mein Projekt zu übertragen, was gar keinen Sinn ergeben kann?
@Abt (und alle anderen): Du kennst ja mein Projekt Systeminventory bei dem ich versuche Systeminformationen auszulesen und anzuzeigen. Hat ja in Version 1 dank eurer Hilfe auch geklappt. Kannst du die Frage einfach nur mit "Sinnvoll" oder "Nicht sinnvoll" beantworten ob das Konzept von get und set für diese Sache sinnvoll ist oder ich mich in was verrenne? Wir reden erstmal nur vom auslesen und anzeigen. API zur Übertragung an eine Datenbank oder andere Dinge sind noch kein Thema. V2 startet bei Null auf Basis von .Net 6. Ich habe nochmal ein Screen angehängt.
(Bitte keine Codebeispiele. Wenn es sinnvoll ist will ich von alleine drauf kommen und ggf. dann lieber nochmal nachfragen, ob ich es richtig umgesetzt und damit verstanden habe.)
Ich mache den Kurs jetzt weiter und vielleicht erschließt sich mir das ganze im weiteren Verlauf auch noch. Man merkt hier wirklich, dass ein guter Kurs nicht nur einfach die Grundlagen und Techniken anhand simpler Beispiele erklärt, sondern das Ganze in einem praxisbezogenem Projekt auch angewendet werden muss. Das hat mir bei PHP extrem geholfen und quasi nach ~1,5 Jahrzehnten! zum Durchbruch verholfen, weil der Dozent eines Kurses (Aktualisierte Neuauflage hier) das gemacht hat. (Ein Projekt, das mit fortschreiten des Kurses sich verändert hat und gewachsen ist.)
Ich arbeite gerade einen C#-Kurs durch.
Der Kurs scheint von der Sache her nicht schlecht zu sein und alle wichtigen Themen zu behandeln. Der Dozent bemüht sich auch die Sache zu erklären, verliert sich aber dann, bzw. springt wild hin und her und lässt es an praxisbezogenen Beispielen missen.
Ich habe das mit dem get und set deswegen noch nicht so ganz kapiert und hoffe, dass ihr es besser erklären könnt.
Grundsätzlich auf mein Projekt übertragen in dem Systemvariablen (beispielsweise freier Festplattenspeicher oder verbaute CPU) vom System ausgelesen werden sollen: Brauche ich da jetzt get und set oder nur get? Ich will ja die Systemvariablen bekommen, also "get". Ich will die Variable dann nicht mehr verändern, weil ich ja die Information dann habe die ich brauche. Ich muss die Information aber auch in einer Variablen speichern um den Wert dann anzeigen zu können oder ggf. weiterverarbeiten zu können (beispielsweise in eine Datenbank übertragen). Also brauche ich doch auch "set"? Aber wenn man für sowas schon beides braucht, wofür braucht man dann NUR get und NUR set? Habt ihr mir da bitte praxisnahe Beispiele? Oder habe ich schon wieder überhaupt nix kapiert und für mein Beispiel reicht "get" aus?
Danke euch und Danke Abt für die Verlinkungen.
Ja, in PHP habe ich das MVC-Prinzip bereits umgesetzt. (Damit war ich die letzten Monate beschäftigt) Für die ergänzende Anwendung (ihr erinnert euch an mein Projekt zur Inventarisierung?) will ich das gerade richtig lernen, weil es nun ohne Rest-API nicht mehr gehen wird...
Das hier ist ein Programm, dass ich vor Jahren mal angefangen hatte, dann aber aufgehört habe, weil ich nicht weiter kam und es nun doch vollendet habe.
Es ist nur diese eine Sache übrig geblieben die mich nun stört und beheben will.
Was haltet ihr vom Ansatz in diesem YouTube-Video? (https://www.youtube.com/watch?v=JuIINT41Uf4) Kann man das AUCH so machen, oder sollte ich streng dem Beispielcode im verlinkten Thread folgen?
Ich habe mir eine Anwendung erstellt wo man mittels GridView alle Drucker eintragen kann und beim Start wird direkt geprüft, ob diese Online sind.
Das Problem ist, dass nach dem Doppelklick der EXE das Programm im Hintergrund loslegt, aber nichts darauf hindeutet, dass das Programm bereits arbeitet, weil die GUI erst geladen wird nachdem die komplette Liste durch ist und für alle Einträge das Ergebnis vor liegt. Mit zunehmender Größe der Datenbank dauert das halt immer länger. Ich brauche also einen Splashscreen / Ladebildschirm.
Auf YouTube habe ich leider nur Beispiele gefunden, wo das mit einem timer() gelöst wird, aber so ein "Fakeladebalken" bringt mir ja nichts.
Nun würde ich gerne eine der folgenden Möglichkeiten umsetzen, weis aber nicht wie:
Ladebalken der Durchläuft und den Fortschritt des Scanvorgangs anzeigt. Im laufenden Programm habe ich sowas bereits und wenn man dort auf "Aktualisieren" klickt oder ein festgelegtes Intervall abgelaufen ist klappt das auch.
Momentan ist es noch so, dass das Programm scheinbar einfriert während der Scanvorgang läuft (Egal ob beim Start oder im laufenden Programm getriggert) und dann mit einem Schlag das Ergebnis in allen Zeilen des DataGridView anzeigt. Schöner wäre es, wenn das Ergebnis Zeile für Zeile angezeigt wird sobald es vor liegt. Dann würde das Programm auch nicht "einfrieren".
Anbei mal der Code, wie er jetzt ist und der für die Angelegenheit wohl relevant ist. Ich hoffe, dass nicht alles furchtbar ist und es mit dezenten Verfeinerungen getan ist.
private void Form1_Load(object sender, EventArgs e)
{
// Prüfen ob die Datenbankdatei existiert.
if (File.Exists(dataSource))
{
// Timer starten. Intervall (in Minuten) wird in den Einstellungen festgelegt.
timer1.Interval = Convert.ToInt32(Settings.Default["settingIntervall"]) * 60000;
timer1.Enabled = true;
timer1.Start();
// Konfiguration einlesen
foreach (string? line in deviceFile)
{
string[] tokens = line.Split(',');
comboDevice.Items.Add(tokens[0]);
}
foreach (string? line in departmentFile)
{
string[] tokens = line.Split(',');
comboDepartment.Items.Add(tokens[0]);
}
// Datagrid-Spaltenüberschriften generieren
dataGridView1.Columns.Add("Column", "ID");
dataGridView1.Columns.Add("Column", "Breich");
dataGridView1.Columns.Add("Column", "Raum-Nr");
dataGridView1.Columns.Add("Column", "Raum-Name");
dataGridView1.Columns.Add("Column", "Gerät");
dataGridView1.Columns.Add("Column", "IP");
dataGridView1.Columns.Add("Column", "Bemerkungen");
dataGridView1.Columns.Add("Column", "Status");
// Datenbank auslesen.
ReadDB();
// Funktion ping() ausführen.
Ping();
}
else
{
// Datenbankdatei anlegen
}
}
public void Ping()
{
int online = 0; // Zählt Online
int offline = 0; // Zählt Offline
int notDetermined = 0; // Zählt nicht ermittelte Geräte (Wenn IP nicht gültig)
progressBar1.Value = 0; // Fortschrittsbalken
try
{
// Füllen des Datagrid mit Daten aus der Datenbank.
foreach (DataGridViewRow row in dataGridView1.Rows)
{
// Prüft ob eine IP-Adresse hinterlegt ist und versucht diese an zu pingen.
try
{
if (row.IsNewRow)
{
break; // Die letzte Zeile (die Leer sein wird) im DataGrid nicht durchlaufen.
}
// Ping ausführen. Warte 1,5 Sekunden pro Zeile auf Antwort.
Ping ping = new Ping();
PingReply reply = ping.Send(row.Cells[5].Value.ToString(), 1500);
// Fortschrittsbalken.
progressBar1.Maximum = dataGridView1.Rows.Count;
progressBar1.Value++;
// Wird ausgeführt, wenn die angepingte IP eine Antwort liefert.
if (reply.Status.ToString() == "Success")
{
// Verbindung herstellen
SQLiteConnection dbConnection = new SQLiteConnection("Data Source=" + dataSource + ";Version=3;"); //Create the connection with database
dbConnection.Open();
// Einfügen der Uhrzeit in die Datenbank
string myQuery = "UPDATE printerlist SET online = @_online WHERE id='" + row.Cells[0].Value + "'";
SQLiteCommand command = new SQLiteCommand(myQuery, dbConnection);
command.Parameters.AddWithValue("@_online", DateTime.Now.ToString("yyyy.MM.dd, HH:mm")); // Aktuelles Datum und Uhrzeit.
command.ExecuteNonQuery(); // Update-Befehl ausführen.
dbConnection.Close(); // Verbindung schließen.
// Schriftzug "Online" in Spalte "Online" anzeigen
row.Cells[7].Style = new DataGridViewCellStyle { ForeColor = Color.Green };
row.Cells[7].Value = "Online";
online++; // Zählen wie viele Geräte online sind.
}
else
{
// Datum + Uhrzeit aus der Datenbank auslesen und unter "Online" anzeigen lassen
// SQlite-Verbindung herstellen
SQLiteConnection dbConnection = new SQLiteConnection("Data Source=" + dataSource + ";Version=3;"); //Create the connection with database
dbConnection.Open();
// SQlite-Datenbank auslesen
SQLiteCommand comm = new SQLiteCommand("SELECT online FROM printerlist WHERE id='" + row.Cells[0].Value + "'", dbConnection);
using (SQLiteDataReader read = comm.ExecuteReader())
{
while (read.Read())
{
row.Cells[7].Value = read[0].ToString();
}
}
dbConnection.Close(); // Verbindung schließen.
offline++; // Zählen wie viele Geräte offline sind.
}
}
catch
{
// Fortschrittsbalken.
progressBar1.Maximum = dataGridView1.Rows.Count;
progressBar1.Value++;
// Schriftzug "Nicht ermittelt" in Spalte "Online" anzeigen
row.Cells[7].Value = "Nicht ermittelt";
notDetermined++;
continue;
}
lblOnline.Text = "Online: " + online;
lblOffline.Text = "Offline: " + offline;
lblNotDetermined.Text = "Nicht ermittelt: " + notDetermined;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Ich hatte vor einiger Zeit mal einige Changelogs gesehen, die mit Symbolen, bzw. Zeichen arbeiten, also Beispiel:
[+] = Neue Funktion / neues Feature
[-] = Entfernte Funktion / Entfernte Funktion
[~] = Diverses
usw.
Mir gefällt das System. Ich suche nun die Zeichen für
[] Update Feature / Funktion / Änderung
[] Fix
[] Deprecated
Ich finde zu dieser Art von Changelog schreiben nichts mehr. Ist das komplett out bzw. außerhalb des Standards und man schreibt es normal, also
[Add]
[Remove]
[Update]
[Fix]
usw.
Nur eine Kleinigkeit und im Grunde auch nicht wirklich wichtig:
[Bug] Das Registrierungsdatum ist bei den Mitgliedern auch gleichzeitig das Datum der letzten Aktivität und auch der letzte Beitrag wurde an diesem Datum erstellt.
@Abt: Ja, vielleicht sollte der Thread in den Smaltalk-Bereich. Dabei habe ich doch nur fragen wollen, wie man eigentlich so eine ASP-Anwendung die auf mehrere Frameworks im Hintergrund setzt auf sicheren Stand halten kann und mir ein eigenes Template einbinden kann. Ich dachte wirklich ich hätte da was gefunden was mir hilft und womit ich arbeiten und lernen kann.
Dann wurde mir gesagt, dass ich leider wieder auf dem Holzweg bin. Das ist kein Vorwurf, ganz im Gegenteil. Schlimmer wäre es, wenn ich auf der Basis des Tutorials mein Projekt dann begonnen und die Technik angelernt hätte und man mir dann bei der ersten Frage im Projekt sagt, dass das alles Mist ist. Wenn es jetzt nur ein, zwei kleine Punkte wären, die nicht ideal sind, hätte ich das vielleicht noch übergangen, aber du listest ja jede Menge auf, so dass das halt wirklich keine Basis ist. Aber so nahm der Thread seinen Lauf.
Inzwischen weis ich nicht mehr, woran ich mich orientieren soll. Sagt jetzt bitte nicht die offizielle Doku. Das diese (alleine) mir nicht hilft bzw. ausreicht sollte ja durchgesichert sein.
@Palladin007 und ThomasE: Danke für eure Worte und das eingehen.
Ich programmiere für mich. Von der Firma aus muss ich das nicht. Das ist alleine mein Ding. Es gehört nichtmal zu meinem Arbeitsbereich. (Wäre auch schön blöd mit meinen Fähigkeiten als Programmierer Geld verdienen zu wollen)
Ein Tutorial in Schriftform wäre natürlich auch gut. Aber halt praktisch veranlagt, wo man ein Projekt beginnt und am Ende ein Ergebnis hat. Das Visuelle ist für mich was ganz ganz wichtiges. Wo man sieht wie die Zusammenhänge sind, wie die Rädchen ineinander greifen und wo man das nicht anhand der Theorie erklärt bekommt, womöglich noch mit haufenweise Fachbegriffe. Ich glaube das sind die Worte die es richtig beschreiben. Ich brauche den praktischen Bezug.
Und nein, es ist nicht Faulheit die ich mir eingestehen muss. Bitte unterstelle mir keine Faulheit, das kann ich echt nicht haben und entspricht nicht der Wahrheit. Das ich mich in Sachen Programmierung abmühe ist doch unverkennbar? Die Frage wäre eher, ob ich mir eingestehen müsste, dass ich einfach nicht dafür gemacht bin und in dieser Sache einfach zu dumm bin. Ich weis, dass ich in anderen Bereichen besser bin und auch echt was drauf habe. Das spielt aber hier keine Rolle. Es gibt sicher auch Bereiche wo auch du die Hilfe von anderen brauchst, weil du es alleine nicht kannst. Vielleicht Steuer? Vielleicht Handwerk? Vielleicht KFZ, ... Selbst Albert Einstein war ein miserabler Schüler, gilt zugleich aber als größtes Genie und verstand Dinge die die Wissenschaft selbst heute noch versucht zu begreifen und im Grunde dann nur noch bestätigen kann das er Recht hatte.
Natürlich will ich nicht ohne Doku auskommen. Ich muss die Doku, bzw. was da steht aber erstmal verstehen bevor ich damit arbeiten kann. Vielleicht ist aber auch ein Punkt erreicht, wo es grob gesagt mit "Nachmachen" und "Auswendig lernen" nicht mehr getan ist. Aber das ist nicht Faulheit. Ich kann mir vorstellen, dass es für euch, die ihr es verstanden habt nur schwer vorstellbar ist, wie man das nicht verstehen kann. Ist doch alles logisch. Ich verstehe auch manchmal nicht, wie Leute die einfachsten Dinge am PC nicht hinbekommen und trotz mehrfacher Erklärung spätestens dann wieder hilflos sind, wenn sich auch nur die geringste Kleinigkeit ändert. Aber es ist nunmal so. Deswegen sind die Leute nicht faul, nicht dumm und nicht unwillig. Sie haben ihre Stärken nur woanders.
Es beruhigt mich ja fast, dass Abt schreibt er kennt das Phänomen. Über die 20 Jahre wo ich mich hobbymäßig (mal intensiver und mal gar nicht) mit dem Thema Scripting und Programmierung schon befasse wurde einem immer der Eindruck vermittelt, dass das nur Einbildung ist und gar nicht sein kann und es nur der eigene Unwille wäre sich mit der Thematik richtig zu befassen. Von Abt lese ich zum ersten mal, dass ich scheinbar nicht der Einzige bin der wahnsinnig mit der Theorie hadert. Wenn aber andere das Gleiche sagen und ähnliches berichten muss ja was dran sein, dass es "Theoretiker" und "Praktiker" gibt. Gibt ja schließlich auch Leute, die die Theorie super drauf haben, in der Praxis aber total versagen. Nennen sich dann oftmals Vorstände und Manager 😁
Danke für eure Antworten und das ihr euch die Zeit genommen habt das Tutorial grob durch zu gucken. Ich lerne am besten am praktischen Beispiel. Ich komme mit der Theorie einfach nicht zurecht. Ihr sagt zwar immer ich soll lesen lesen lesen. Das hat bei mir noch nie funktioniert und war auch ein echtes Problem in der Ausbildung, bzw. einer Fortbildung.
Kurzer Abschweifer zu meiner Ausbildungszeit:
Im Theorieunterricht bin ich auch regelmäßig weggedöst bzw. eingeschlafen, weil ichs einfach nicht kapiert und abgeschaltet habe. Das hat(te) mit Desinteresse nichts zu tun. In der Praxis war ich hingegen immer ganz gut. Dementsprechend waren auch die Noten. Ich kann mich noch gut erinnern wie ich im Bereich "Programmierung" (Streng genommen war es damals nur HTML und C++) im theoretischen eine 5 hingelegt habe, im praktischen Teil aber eine glatte 1 hatte, was mir den Hintern gerettet hat, denn ich war drauf und dran raus zu fliegen. Von der Theorie damals im Grunde keinen Plan gehabt, die gestellte Aufgabe mit dem Bau einer HTML-Seite mit allen geforderten Funktionen aber als einer der Wenigen perfekt gelöst. Zugegeben: Wäre im praktischen Teil der Prüfung C++ dran gekommen hätte ich einpacken können. (Das lag aber am Lehrer, denn da waren alle schlecht mit Ausnahme jener die es vorher schon konnten.) Das ganze ließ sich auf ALLE anderen Bereiche übertragen, egal ob Netzwerktechnik, Elektrik, ISDN... mit Ausnahme von AWL/BWL. Da gab es nur Theorie und entsprechend war die Note. Teilweise kann ich das sogar heute noch nachweisen wenn gewünscht. Ich erzähle also keine Ausreden.
Von daher ist es auch wieder ein Stück weit frustrierend, wenn ich nun lesen muss, dass das Tutorial das ich durchgegangen bin für die Tonne war. Das Projekt konnte man soweit ja prima nachbauen und hätte mein bisheriges Frontend, also die Webseite wo ich die Daten anzeige ablösen können. Sah mir also schonmal nach einer guten Basis aus. Im Grunde fehlte ja "nur" noch die Schnittstelle zur Interaktion mit der C#-Anwendung (Rest API / Web API) und vielleicht ein anderes Template was mehr her macht.
Ich weis nun auch nicht mehr weiter... ein klassischer Fall von "wollen", aber nicht" können"?
Ich frag jetzt einfach mal gerade aus: Hat niemand von euch Lust ein vernünftiges deutsches Lerntutorial auf die Beine zu stellen? Das kann dann gerne hinter einer Paywall angeboten werden. Wie gesagt: Mich interessiert das und ich will es können. Dafür bin ich auch bereit im Rahmen meiner Möglichkeiten Geld in die Hand zu nehmen. Hab ja auch einige Udemy-Kurse gekauft, aber wenn ich fürchten muss, dass da einem nur Quatsch erzählt wird und es nicht so ist, wie es sein soll... Das gleiche wird man dann auch bei den Kursen bei Linkedin Learning fürchten müssen.
[1] Sehr theorielastig. Am Ende ein kleines Projekt, aber ohne GUI (ohne Webseite).
[2] Der gleiche Autor wie bei dem Youtube-Tutorial, nur das der Kurs ausführlicher ist. Wenn ihr aber sagt er macht das nicht richtig brauche ich gar nicht anfangen. Schade, weil sein Stil und Aussprache haben mich angesprochen.
[3] Nur mal reingeschaut.
Mir ist klar, dass ihr damit nichts anfangen könnt, weil dazu müsstet ihr die Kurse ja kaufen, bzw. ein Abo haben. Mir gehts nur darum zu zeigen, dass ich Wissen nicht zum Nulltarif erwarte und dann lieber mal in einen Kurs richtig investiere der von einem von euch stammt und man dann auch im Forum auf einer Wellenlänge ist.
Ich arbeite gerade dieses Tutorial durch. Er macht das sehr einsteigerfreundlich und praxisorientiert. Gefällt mir und damit kann man auch echt was anfangen. Ich finde es ja trotzdem wahnsinnig umständlich welche Dateien da alle bearbeitet werden müssen und an was man alles denken muss, nur damit beispielsweise ein weiterer Link bzw. eine weitere Seite hinzugefügt werden kann. Die Zusammenhänge muss man kennen und sind für mich stellenweise logisch nicht herleitbar. Auch wie das alles miteinander verwoben ist finde ich undurchschaubar. Alleine: Keine Chance. Aber so ist das wohl und scheinbar jetzt modern.
Wie auch immer. Der YouTuber erklärt auch, wie man seine fertige ASP.NET-Anwendung am Ende hosten kann. Ich stelle mir jetzt unweigerlich die Frage: Da werden so viele Dateien hochgeladen mit denen man im Grunde nichts am Hut hat, bzw. man weis gar nicht was die machen und ob die aktiv am Projekt beteiligt sind. Was ist eigentlich wenn da eine Sicherheitslücke ist. Log4j lässt ja beispielsweise grüßen. Wie updatet man seine Anwendungen eigentlich und stellt sicher, dass gemachte Einstellungen nicht wieder zurückgesetzt werden und es einem alles zerschießt?
Außerdem habe ich nicht rausbekommen können welche Techniken im Hintergrund alle aktiv sind. Der YouTuber erwähnt irgendwann beispielsweise, dass man das Design mittels Bootstrap-Befehle anpassen kann. Zur Zeit des Videos wurde noch auf Bootstrap 4 gesetzt. Welche Bootstrap-Version kommt in VS2022 zum Einsatz und woher weis man das. Ja, ich habe Google befragt, aber Google weis auch nichts. Welche Techniken und Frameworks sind da im Hintergrund noch so alle integriert?
Mich würde auch interessieren, wie ich ein anderes Template verwenden kann. Kann mir das bitte jemand erklären? Kann man das hier irgendwie integrieren?
Ich bin da jetzt ganz am Anfang und will da auch weitermachen, nur will ich das ja später noch weiter miteinander verweben indem ich eine WebAPI integriere um mit meinen PCs, bzw. einer C#Anwendung interagieren zu können. Das wird ja echt heftig dann. Hab jetzt schon nen kleinen Knoten.
Aber eines muss ich zugeben: Wenn man alles erstmal hergerichtet hat kann man sich wunderbar auf das Design konzentrieren und kann es von der Funktionalität trennen. Das gefällt mir. Aber muss man dafür solche Umstände betreiben?
Einige von euch kennen mein Projekt, wo ich die Inventardaten mit einem C# Programm auslese und mittels FLURL.HTTP in eine Datenbank sende um die Einträge dann auf einer Webseite anzeigen zu lassen. Das haben wir ja über Monate durchgekaut und dank eurer Hilfe habe ich ja auch was Funktionierendes. Darum geht es aber auch -es funktioniert. Mehr aber auch nicht und professionell ist es aber nicht.
Nun will ich mir die Zeit nehmen mein bisheriges Projekt neu und professionell aufsetzen mit allem was dazu gehört. Ich bin dafür auch bereit Geld in die Hand zu nehmen und Zeit zu investieren. Das Problem: Ich weiß überhaupt nicht was ich eigentlich lernen soll, bzw. lernen will. Daher kurz nochmal mein Ziel.
Am Ende will ich
Beim Recherchieren und erste Lernkurse durcharbeiten habe ich aber das Gefühl mich total zu verzetteln. Ich bekomme eine solche Informationsflut, dass ich jetzt gar nicht mehr weiß, welche Techniken für mich schlussendlich von Relevanz sind und welche Techniken am Ende überhaupt miteinander interagieren können / sollen und was ich überhaupt brauche.
Ich lese da von
Bei dem Kurs, den ich gerade durch habe, befindet man sich ständig nur im "Swagger"-Modus. Ich hätte am Ende gerne was fassbares. Der Dozent hat sich mit seinem Kurs zwar echt Mühe gegeben, aber ich habe nicht kapiert, was der da gemacht hat, geschweige wie ich das auf mein Vorhaben übertragen kann.
Danke Abt. Jetzt wo du es schreibst...
Ich habe in eine komplett andere Richtung gedacht und gesucht, nämlich entweder nach einer Einstellung für das Label (Visible brachte nichts) oder einen Befehl.
Das war definitiv "zu einfach", weil "zu kompliziert" gedacht.
Aber wenn ich jetzt eh schon dabei bin mich zu blamieren: Gibt es eine Möglichkeit alle Labels die "label1" heißen auf "" zu setzen? Ich meine das was man bei "Text" einträgt, nicht bei "(Name)".
Nicht "ihr", sondern "du". Ich bastel da alleine in meinem Kämmerlein und bis auf euch und den Rest des Internets habe ich auch niemanden der mir da hilft.
Und ja, mir ging es erstmal darum was funktionierendes zu haben. Das war mir extrem wichtig. Habt ihr sicher auch gemerkt. Das hatten wir (also ich und die Community) ja im letzten halben Jahr erfolgreich hinbekommen. Dafür nochmal Danke an dieser Stelle. Ich bin damit echt schon total glücklich und macht mir die Arbeit angenehmer. Jetzt habe ich den Kopf frei mich darauf zu konzentrieren das Projekt komplett neu und professioneller anzugehen.
Ich migriere das bestehende Projekt auch nicht, sondern habe es komplett neu auf Basis von VS 2022 und .net 6 begonnen. Bislang gibt es nur die GUI. Jetzt sollen Aspekte, wie ihr sie mir schon lange vorgeschlagen habt, mir aber noch zu kompliziert waren, mit einbezogen werden, beispielsweise ASP.NET Core, Rest-API und so. Auch das Web-Backend will ich anders machen und auf Grundlage von Symfony und Bootstrap arbeiten. Jetzt ist es mir auch egal, ob es länger dauert bis ich die neuen Techniken gelernt und (hoffentlich) verstanden habe denn ich habe bereits was mit dem ich arbeiten kann.
Ich habe auch auf Udemy einige Kurse zu den Themen gekauft, die ich durcharbeiten möchte.
Ich gehe vorsorglich schonmal in Deckung, aber ich habe ein ganz dämliches Problem.
Wenn ich die Drucker wie folgt auslese, dann funktioniert das super:
foreach (string printer in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
{
label1.Text += printer + "\n";
}
Nur leider steht vor dem ersten Drucker das "label1.Text". Wie bekomme ich das weg?
Also wie ich die *.cs-Datei erstelle weis ich. Deswegen habe ich nicht nachgefragt.
Ich versuche genauer zu erklären, was ich vor habe.
Mein Systeminventory ist in mehrere Bereiche unterteilt. Hardware, System, Monitor, Software Allgemein und Software Lizenzkontrolle.
Nun könnte ich das alles in der Form.cs abarbeiten und habe am Ende über 1000 Zeilen Code in einer Datei. Ob das mit der kommenden Version besser wird, die komplett anders aufgezogen werden soll wird sich zeigen. Der Plan besteht nun darin für all die einzelnen Bereiche eine eigene *.cs-Datei anzulegen, also beispielsweise hardware.cs, system.cs und so weiter.
Nur mit Datei erstellen und loslegen ist es scheinbar nicht getan. Irgendwie muss ich der Datei noch sagen, dass die Form1.cs die Hauptdatei ist, in der sich u.A. alle Deklarationen, Initialisierungen oder vielleicht auch mal Methoden oder Klassen befinden, also sowas wie
bool isOnline = false;
string hardwareComputerName;
Ich denke dann wirkt alles etwas aufgeräumter und übersichtlicher.