Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Lesedauer 6 Min.

Systemdiagnose

Das Steuerelement RegEditCtl wird durch Funktionen zur Systemdiagnose ergänzt.
© dotnetpro
Diese Serie zeigt, wie Sie Kontrollelemente erzeugen, die sich auf die Bearbeitung der Systemregistrierung von Windows verstehen. Die Grundfunktionen sind dabei in den vergangenen Teilen der Serie entstanden. In dieser Folge kommen noch Funktionen zur Systemdiagnose hinzu.Hierzu gehört die Methode ShowLastSystemDiagnosticReport. Sie stellt zwei optionale Parameter bereit. GenerateReport bestimmt, ob ein Bericht anzulegen ist oder nicht. Standardmäßig ist der Wert dieses Parameters auf False gesetzt. Die Berichtsanlage wird dementsprechend standardmäßig unterbunden.Über den zweiten Parameter kann ein Berichtsname ohne Pfadangabe übergeben werden. Der Pfad der Berichte ist
mit PerfLogs\System\Diagnostics\ vom Windows-System fest vorgegeben und befindet sich auf dem Systemlaufwerk, das hier über die benutzerdefinierte Funktion GetSystemDrive ermittelt wird.In der Methode wird zunächst der Berichtspfad in die Variable reportPath übernommen, um dann das Unterverzeichnis für den eigentlichen Bericht zu bestimmen und in die Variable reportSubPath zu übernehmen. Das Unterverzeichnis ist eine Kombination aus Maschinenname (Environment.MachineName) und Datumsinformationen (Jahr, Monat und Tag), die zu einer Zeichenkette verbunden werden (Listing 1). Der Pfadname endet mit einem Bindestrich und wird später mit einer fortlaufenden Tagesnummer verkettet, die über die benutzerdefinierte Funktion GetHighestReportNumberOf-ThisDay ermittelt wird.
Listing 1: Systemdiagnosebericht anlegen und anzeigen
<span class="hljs-keyword">Sub</span> ShowLastSystemDiagnosticReport(<br/>  <span class="hljs-keyword">Optional</span> GenerateReport <span class="hljs-keyword">As</span> <span class="hljs-built_in">Boolean</span> = <span class="hljs-literal">False</span>, <br/>  <span class="hljs-keyword">Optional</span> ReportName <span class="hljs-keyword">As</span> <span class="hljs-built_in">String</span> = <span class="hljs-string">""</span>)<br/> <span class="hljs-keyword">Dim</span> reportPath <span class="hljs-keyword">As</span> <span class="hljs-built_in">String</span> = GetSystemDrive() & <br/>  <span class="hljs-string">"PerfLogs\System\Diagnostics\"</span><br/> <span class="hljs-keyword">Dim</span> reportSubPath <span class="hljs-keyword">As</span> <span class="hljs-built_in">String</span> = <br/>  Environment.MachineName & <span class="hljs-string">"_"</span> & <br/>  Now.Year.ToString & Now.Month.ToString(<span class="hljs-string">"00"</span>) & <br/>  Now.Day.ToString(<span class="hljs-string">"00"</span>) & <span class="hljs-string">"-"</span><br/> <span class="hljs-keyword">If</span> GenerateReport <span class="hljs-keyword">Then</span><br/>  GenerateReportMessageDialog(ReportName)<br/> <span class="hljs-keyword">End</span> <span class="hljs-keyword">If</span><br/> <span class="hljs-keyword">Dim</span> CheckPath <span class="hljs-keyword">As</span> <span class="hljs-built_in">String</span> = reportPath & <br/>  reportSubPath & <br/>  GetHighestReportNumberOfThisDay().ToString(<span class="hljs-string">"000000"</span>)<br/> <span class="hljs-keyword">Dim</span> ReportURL <span class="hljs-keyword">As</span> <span class="hljs-built_in">String</span> = CheckPath & <span class="hljs-string">"\report.html"</span><br/> <span class="hljs-keyword">If</span> File.Exists(ReportURL) <span class="hljs-keyword">Then</span><br/>  <span class="hljs-keyword">Dim</span> frm <span class="hljs-keyword">As</span> <span class="hljs-keyword">New</span> frmBrowser<br/>  frm.Show()<br/>  frm.BrowserCtl.NavigateTo(<span class="hljs-string">"file:///"</span> & ReportURL)<br/> <span class="hljs-keyword">Else</span><br/>  NewMessageDialog(<span class="hljs-string">"Letzten heutigen Bericht zur "</span> &<br/>   <span class="hljs-string">"Systemdiagnose anzeigen"</span>, <br/>   <span class="hljs-string">"Die Berichtsdatei "</span> & ReportURL & <span class="hljs-string">" wurde nicht"</span> &<br/>   <span class="hljs-string">" gefunden!"</span>, eIcons.<span class="hljs-keyword">Error</span>, <br/>   eButtons.OK, <span class="hljs-string">"Systemdiagnose"</span>)<br/> <span class="hljs-keyword">End</span> If<br/>End <span class="hljs-keyword">Sub</span> 
Ist die Reportanlage erwünscht (GenerateReport = True), blendet die Methode mit GenerateReportMessageDialog zunächst einen Dialog mit Fortschrittsanzeige ein. Die aufwendige Pfadanlage und -verwaltung ist erforderlich, da der Name der Berichtsdatei immer (!) report.html lautet. Die Unterverzeichnisse erlauben die Anlage und Verwaltung mehrerer Berichte mit einheitlichem Dateinamen.Für die Neuanlage von Berichten ist jeweils die höchste Berichtsnummer des Tages zu berücksichtigen. Die Berichtsanlage dauert zwischen zehn und 20 Sekunden.Pfad und Dateiname werden in der Variablen ReportURL verkettet, anschließend wird die Datei auf Existenz geprüft. Ist die Datei vorhanden, wird Sie im Dialog des Typs frm­Browser im HTML-Format angezeigt.Das Formular frmBrowser beinhaltet ein Webbrowser-Steuerelement BrowserCtl. Über die zugehörige NavigateTo-Anweisung wird dann zur lokalen HTML-Berichtsdatei navigiert und einhergehend damit der zugehörige Inhalt angezeigt (Bild 1). Existiert die ermittelte Berichtsdatei nicht, wird dies über die Methode NewMessageDialog in einem Meldungsdialog angezeigt.
Für die Ausgabe des Systemdiagnoseberichts kommt das benutzerdefinierte Webbrowser-Steuerelement BrowserCtl der Steuerelementbibliothek ExtendedControlsLib zum Einsatz (Bild 1) © Autor
Die Funktion GetSystemDrive ermittelt über das Windows-Systemverzeichnis WinSysDir das Systemlaufwerk und liefert es als Zeichenkette zurück.

Function GetSystemDrive() As String
  Return WinSysDir.Substring(0, 3)
End Function 
Wie zuvor beschrieben werden Protokollverzeichnisse datumsbasiert im Verbund mit einer fortlaufenden tagesspezifischen Berichtsnummer benannt. Die zu verwendende höchste Berichtsnummer des aktuellen Tages ermittelt die Funk­tion GetHighestReportNumberOfThisDay. Diese liefert den numerischen Wert als Ganzzahl zurück.Zunächst wird das Berichtsverzeichnis reportPath und das tagesspezifische Unterverzeichnis reportSubPath bestimmt, um dann die Berichtsnummern schrittweise hochzuzählen. Die maximale Nummer ist mit 999 999 vorgegeben und wird per For-Next-Schleife schrittweise hochgezählt. Zur aktuell verarbeiteten Nummer wird der zugehörige Verzeichnisname generiert und in die Variable CheckPath übernommen.Existiert der Pfad, ist die höchste Berichtsnummer nicht erreicht, und der Zähler wird um den Wert eins erhöht. Existiert der Pfad aber nicht, ist die höchste Berichtsnummer ermittelt. Dann wird die For-Next-Schleife beendet und der höchste Wert zurückgegeben (Listing 2).
Listing 2: Höchste Berichtsnummer des aktuellen Tages ermitteln
Function GetHighestReportNumberOfThisDay() As Integer<br/> Dim NumberFound As Boolean = False<br/> Dim HighestNumber As Integer = 0<br/> Dim reportPath As String = GetSystemDrive() & <br/>  "PerfLogs\System\Diagnostics\"<br/> Dim reportSubPath As String = <br/>  Environment.MachineName & "_" & <br/>  Now.Year.ToString & Now.Month.ToString("00") & <br/>  Now.Day.ToString("00") & "-"<br/> Dim ReportExist As Boolean = False<br/> For x = 1 To 999999<br/>  Dim CheckPath As String = <br/>   reportPath & reportSubPath & x.ToString("000000")<br/>  If Directory.Exists(CheckPath) Then<br/>   NumberFound = True<br/>   HighestNumber = x<br/>   If Directory.Exists(reportPath & reportSubPath & <br/>    (x + 1).ToString("000000")) = False Then <br/>    Exit For<br/>   End If<br/>  Next<br/> Return HighestNumber <br/>End Function 
Um die Berichtsanlage zu veranschaulichen, wird ein Dialog mit Fortschrittsanzeige angezeigt, der über das Formular frmGenerateReportMessageDialog definiert ist, mit der Methode GenerateReportMessageDialog angezeigt wird und den über den Parameter ReportName übergebenen Berichtsnamen ausgibt. Die Anzeige des Dialoges erfolgt nicht modal. Wird die Berichtsanlage beendet, wird auch der Dialog ausgeblendet.

Sub GenerateReportMessageDialog(ReportName)
  Dim frm As New frmGenerateReportMessageDialog
  frm.ReportFile = ReportName
  frm.ShowDialog()
End Sub 
Mit den Befehl StartSysMonitor starten Sie das Windows-Programm zur Leistungsüberwachung. Dazu übergeben Sie an das Programm perfmon den Parameter /sys.

Sub StartSysMonitor()
  Shell("perfmon /sys", 
    AppWinStyle.NormalFocus)
End Sub 
Windows liefert über die Systemsteuerung themenbasierte Lösungen an, die Sie über die Methode ResolveProblems und die darin angeführte Shell-Anweisung aufrufen. Daraufhin öffnet sich der zugehörige Dialog zu den Einstellungen zur Problembehandlung (Bild 2). Darin wählen Sie bestimmte Themenbereiche an und erhalten weiterführende Hinweise zur Problembehandlung (zum Beispiel Probleme beim Drucken, Lösen von Audioaufzeichnungsproblemen, Wartungsaufgaben durchführen).
Systemfunktionen für Problemlösungen per Systemsteuerung abrufen (Bild 2) © Autor

Sub ResolveProblems()
  Shell("explorer shell:::" & 
    "{C58C4893-3BE0-4B45-ABB5-A63E4B8C8651}", 
    AppWinStyle.NormalFocus)
End Sub 

Systeminterne Diagnose-Tools starten

Die Systemdiagnose-Tools werden über das Dienstprogramm msdt (Microsoft Support-Dia­gnosetool) bereitgestellt und auch im Verbund mit Supportmitarbeitern von Microsoft genutzt. Das Programm erlaubt die gezielte Anwahl von Themen. Jedem Thema ist dabei ein bestimmter Schlüssel zugeordnet, der später beim Programmaufruf als Kommandozeilenschalter übergebbar ist.Geben Sie keinen Schalter an, müssen Sie diesen Hauptschlüssel selbst eintippen. An dieser Stelle werden alle Themen mitsamt den Schlüsseln über den Enumerationsdatentyp DiagnosticTools zusammengefasst:

Enum DiagnosticTools
  AeroDiagnostic
  NetworkDiagnosticsDA
  DeviceDiagnostic
  HomeGroupDiagnostic
  NetworkDiagnosticsInbound
  NetworkDiagnosticsWeb
  IEBrowseWebDiagnostic
  IESecurityDiagnostic
  ...
End Enum 
Um die Diagnose-Tools gezielt zu starten, kommt die Methode StartDiagnosticTool zum Einsatz, der Sie das Schlüsselwort für das zu verwendende Thema über den Parameter Tool übergeben. Über Optionalparameter geben Sie später an, ob mehr (MoreOptions), erweiterte (AdvancedStr) und eigene Optionen anzugeben sind (CustomStr) sowie abschließende Meldungen angezeigt werden sollen. Die Optionalparameter erfordern Zusatzschalter, die intern zwar bereits codiert sind, derzeit aber nicht genutzt werden. Dementsprechend wird der Befehlsaufruf des Programms msdt.exe immer nur mit einem Themenbezeichner verkettet, der selbst über den Schalter /id angegeben wird (Listing 3).
Listing 3: Befehlszuweisung für die Diagnose-Tools
Sub StartDiagnosticTool(ByVal Tool As DiagnosticTools, <br/>  Optional MoreOptions As Boolean = True, <br/>  Optional Advanced As Boolean = True,<br/>  Optional Custom As Boolean = True, <br/>  Optional ShowMessage As Boolean = True)<br/> Dim AdvancedStr As String = ""<br/> Dim CustomStr As String = ""<br/> Dim MoreOptionsStr As String = ""<br/> If MoreOptions Then <br/>  MoreOptionsStr = "/moreoptions true"<br/> If Advanced Then AdvancedStr = " /advanced"<br/> If Custom Then CustomStr = " /custom"<br/> Dim MSDTcommand As String = ""<br/> Select Case Tool<br/>  Case DiagnosticTools.AeroDiagnostic 'nur Windows 7<br/>   MSDTcommand = "msdt.exe /id AeroDiagnostic"<br/>  Case DiagnosticTools.NetworkDiagnosticsDA <br/>   'alle anderen Windows 8 und höher<br/>   MSDTcommand = "msdt.exe /id NetworkDiagnosticsDA"<br/>  Case DiagnosticTools.DeviceDiagnostic<br/>   MSDTcommand = "msdt.exe /id DeviceDiagnostic"<br/>  Case DiagnosticTools.HomeGroupDiagnostic<br/>   MSDTcommand = "msdt.exe /id HomeGroupDiagnostic"<br/>  Case DiagnosticTools.NetworkDiagnosticsInbound<br/>   MSDTcommand = <br/>    "msdt.exe /id NetworkDiagnosticsInbound"<br/>   ...<br/> End Select<br/> ...<br/>End Sub 
Der festgelegte Befehl für den Aufruf einer bestimmten
Diagnosefunktion wird mit der Methode StartDiagnosticTool realisiert (Listing 4) und per Shell-Anweisung im normalen Fenstermodus abgesetzt. Das Ergebnis wird über den Wert result zurückgegeben. Nur wenn der Parameter ShowMessage auf True gesetzt ist, wird der Dialog zur Meldungsausgabe angezeigt. Setzen Sie dShowMessage auf False, können Sie die abschließende Meldungsausgabe unterbinden.
Listing 4: Diagnose-Tools ausführen
Sub StartDiagnosticTool(ByVal Tool As DiagnosticTools, <br/>  Optional MoreOptions As Boolean = True, <br/>  Optional Advanced As Boolean = True,<br/>  Optional Custom As Boolean = True, <br/>  Optional ShowMessage As Boolean = True)<br/> ...<br/> Dim result As Integer = Shell(MSDTcommand, <br/>  AppWinStyle.NormalFocus)<br/> If ShowMessage Then<br/>  Dim msg As String = "Die gewählte Komponente '" & <br/>   Tool.ToString & "' wurde mit folgendem Ergebnis " & <br/>   "ausgeführt: " & vbCrLf<br/>  Select Case result<br/>   Case -1<br/>    msg += "Die Funktion zur Problemsuche und " &<br/>     "-lösung wurde vorzeitig beendet!"<br/>   Case 0<br/>    msg += "Die Funktion wurde erfolgreich " &<br/>     "abgeschlossen und es wurde mindestens " &<br/>     "ein Problem gefunden und behoben!"<br/>   Case 1<br/>    msg += "Die Funktion hat ein oder mehrere " &<br/>     Fehler gefunden, die nicht in der " & <br/>     "Gesamtheit behoben werden konnten!"<br/>   Case 2<br/>    msg += "Die Funktion hat im gewählten " &<br/>     "Funktionsbereich keine Probleme gefunden!"<br/>   Case Else<br/>  End Select<br/>  If result = -1 Or result = 0 Or result = 1 Or <br/>    result = 2 Then<br/>   Dim msgdata As New MessageData<br/>   With msgdata<br/>    .Buttons = eShowButtons.OK<br/>    .MainInstruction = "Probleme suchen und beheben" & <br/>     " [" & Tool.ToString & "]"<br/>    .Icon = eIcons.Information<br/>    .MessageContent = msg<br/>    .WindowTitle = "Windows-Troubleshooting"<br/>   End With<br/>   NewMessageDialog(msgdata)<br/>  End If<br/> End If<br/>End Sub 

ZIP-Archiv zu Diagnoseberichten generieren

Sie können jeden Tag eine Vielzahl an Diagnoseberichten anlegen. Optional lassen sich die generierten Berichte auch in einem ZIP-Archiv sichern. Dafür kommt die benutzerdefinierte Methode GenerateDiagnosticsZIP zum Einsatz. Innerhalb der Routine wird zunächst das Diagnoseberichtsverzeichnis in der Variablen DataPath gesichert, um dann den ZIP-Archivdateinamen Diagnostics.zip zu setzen und in der Variablen ZipArchive zu sichern.Im Anschluss daran wird über den Dialog FolderDlg des Typs FolderBrowserDialog das Zielverzeichnis für dieses Archiv abgefragt. Nur wenn Sie einen Ordner in diesem Dialog auswählen und mit OK bestätigen, wird dieser in die Variable DestinationPath übernommen. Unterscheidet sich dieser Zielordner vom Datenverzeichnis DataPath, wird das ZIP-Archiv zum Datenverzeichnis generiert. Auftretende Fehler und die Archivanlage werden nach Bedarf in Meldungsdialogen angezeigt (Listing 5).
Listing 5: Archiv mit ZIP-Archiven anlegen
Sub GenerateDiagnosticsZIP()<br/> Dim DataPath As String = GetSystemDrive() & <br/>  "PerfLogs\System\Diagnostics"<br/> Dim ZipArchive As String = ""<br/> Dim DestinationPath As String = ""<br/> ZipArchive = DataPath.Substring(<br/>  DataPath.LastIndexOf("\") + 1) & ".zip"<br/> Dim FolderDlg As New FolderBrowserDialog<br/> With FolderDlg<br/>  .ShowNewFolderButton = True<br/>  .Description = "Wählen Sie das Zielverzeichnis " & <br/>   "für das anzulegende Berichtsarchiv mit dem " &<br/>   "Namen '" & ZipArchive & "'aus, in den das " &<br/>   "Berichtsverzeichnis '" & DataPath & <br/>   "' verpackt werden soll!"<br/>  If .ShowDialog = DialogResult.OK And <br/>    .SelectedPath <> "" Then<br/>   DestinationPath = .SelectedPath<br/>  Else<br/>   Exit Sub<br/>  End If<br/> End With<br/> If DestinationPath <> DataPath Then<br/>  Try<br/>   ZipFile.CreateFromDirectory(<br/>    DataPath, DestinationPath & "\" & ZipArchive, <br/>    CompressionLevel.Optimal, False)<br/>  Catch ex As Exception<br/>   NewMessageDialog("Berichtsarchiv anlegen", <br/>    "Das Berichtsarchiv konnte nicht angelegt " &<br/>    "werden! " & ex.Message, <br/>    eIcons.SecurityShieldError, eButtons.OK, <br/>    "Berichtsarchiv")<br/>   Exit Sub<br/>  End Try<br/>  NewMessageDialog("Berichtsarchiv anlegen", <br/>   "Das Berichtsarchiv wurde unter dem Namen '" & <br/>   DestinationPath & "\" & ZipArchive & "' angelegt!", <br/>   eIcons.SecurityShieldBlueBack, <br/>   eButtons.OK, "Berichtsarchiv")<br/> Else<br/>  NewMessageDialog("Berichtsarchiv anlegen", <br/>   "Das Berichtsarchiv kann nicht im zu " &<br/>   "komprimierenden Datenverzeichnis abgelegt " &<br/>   "werden. Wählen Sie für das ZIP-Archiv ein " &<br/>   "anderes Zielverzeichnis aus!", <br/>   eIcons.SecurityShieldError, eButtons.OK, <br/>   "Berichtsarchiv")<br/> End If<br/>End Sub 

Diagnoseberichte löschen

Um angelegte Diagnoseberichte in der Gesamtheit aus dem Datenverzeichnis zu löschen, nutzen Sie die Methode Kill-
DiagnosticReports
. Diese entfernt alle Unterverzeichnisse und Dateien. Gegebenenfalls sollten Sie, um die Daten später wiederherzustellen, vorab die zuvor beschriebene Funktion zur Anlage eines ZIP-Sicherungsverzeichnisses aufrufen. Bevor das Löschen erfolgt, wird zunächst eine entsprechende Sicherheitsabfrage eingeblendet. Bestätigen Sie diese mit OK, erfolgt das Löschen über die Methode Delete des DirectoryInfo-Objekts dInfo, das zum Pfad reportPath angelegt wurde. Das Löschen selbst wird durch eine abschließende Meldung angezeigt (Listing 6).
Listing 6: Diagnoseberichte löschen
Sub KillDiagnosticReports()<br/> Dim msg As New MessageData<br/> With msg<br/>  .Buttons = eShowButtons.YesNo<br/>  .Icon = eIcons.SecurityShieldBlueBack<br/>  .MainInstruction = "Diagnoseberichte löschen"<br/>  .MessageContent = "Wollen Sie jetzt alle " &<br/>   "vorhandenen Diagnoseberichte endgültig " &<br/>   "löschen?" & "Legen Sie sich gegebenenfalls " &<br/>   "für spätere Berichtszugriffe ein " &<br/>   "Sicherungsarchiv an!" <br/>  .WindowTitle = "Windows-System-Diagnoseberichte"<br/> End With<br/> If NewMessageDialog(msg) = eButtons.YES Then<br/>  Dim reportPath As String = GetSystemDrive() & <br/>   "PerfLogs\System\Diagnostics"<br/>  Dim dInfo As New DirectoryInfo(reportPath)<br/>  With dInfo<br/>   For Each dInfoObj In dInfo.EnumerateDirectories<br/>    dInfoObj.Delete(True)<br/>   Next<br/>   NewMessageDialog("Alle Systemdiagnoseberichte " &<br/>    "löschen", "Aus dem Berichtsverzeichnis " &<br/>    "wurden alle Systemdiagnosberichte gelöscht!", <br/>    eIcons.SecurityShieldBlueBack, eButtons.OK, <br/>    "Berichtsarchiv")<br/>  End With<br/> End If<br/>End Sub 

Fazit

Damit sind die Funktionen zur Systemdiagnose, Leistungsüberwachung, Fehlerkennung und Fehlerbehebung codiert. Bleibt noch der Quelltext für das eigentliche RegEditCtl-Steuerelement zu ergänzen. Doch das ist eine Thematik, die in den abschließenden Teilen dieser Serie behandelt wird.
Projektdateien herunterladen

Fussnoten

  1. Andreas Maslo, Controls für die Registry, dotnetpro 2/2023, Seite 122 ff., http://www.dotnetpro.de/A2302Registry

Neueste Beiträge

DWX hakt nach: Wie stellt man Daten besonders lesbar dar?
Dass das Design von Websites maßgeblich für die Lesbarkeit der Inhalte verantwortlich ist, ist klar. Das gleiche gilt aber auch für die Aufbereitung von Daten für Berichte. Worauf besonders zu achten ist, erklären Dr. Ina Humpert und Dr. Julia Norget.
3 Minuten
27. Jun 2025
DWX hakt nach: Wie gestaltet man intuitive User Experiences?
DWX hakt nach: Wie gestaltet man intuitive User Experiences? Intuitive Bedienbarkeit klingt gut – doch wie gelingt sie in der Praxis? UX-Expertin Vicky Pirker verrät auf der Developer Week, worauf es wirklich ankommt. Hier gibt sie vorab einen Einblick in ihre Session.
4 Minuten
27. Jun 2025
„Sieh die KI als Juniorentwickler“
CTO Christian Weyer fühlt sich jung wie schon lange nicht mehr. Woran das liegt und warum er keine Angst um seinen Job hat, erzählt er im dotnetpro-Interview.
15 Minuten
27. Jun 2025
Miscellaneous

Das könnte Dich auch interessieren

UIs für Linux - Bedienoberflächen entwickeln mithilfe von C#, .NET und Avalonia
Es gibt viele UI-Frameworks für .NET, doch nur sehr wenige davon unterstützen Linux. Avalonia schafft als etabliertes Open-Source-Projekt Abhilfe.
16 Minuten
16. Jun 2025
Mythos Motivation - Teamentwicklung
Entwickler bringen Arbeitsfreude und Engagement meist schon von Haus aus mit. Diesen inneren Antrieb zu erhalten sollte für Führungskräfte im Fokus stehen.
13 Minuten
19. Jan 2017
Evolutionäres Prototyping von Business-Apps - Low Code/No Code und KI mit Power Apps
Microsoft baut Power Apps zunehmend mit Features aus, um die Low-Code-/No-Code-Welt mit der KI und der professionellen Programmierung zu verbinden.
19 Minuten
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige