Laden...

Forenbeiträge von hkdd Ingesamt 16 Beiträge

12.06.2023 - 14:43 Uhr

@Abt, RegistryView ⇒

Danke für diesen Hinweis.

Jetzt sieht es so aus und funktioniert mit AnyCPU ...

using Microsoft.Win32;
using System;
using System.Runtime.InteropServices;

namespace WinVerHK
{
    internal class Program
    {
        struct OSVERSIONINFOEXW 
        {
            public int dwOSVersionInfoSize { get; set; }
            public int dwMajorVersion { get; set; }
            public int dwMinorVersion { get; set; }
            public int dwBuildNumber { get; set; }
        }

        [DllImport("ntdll.dll", SetLastError = true)]
        static extern int RtlGetVersion(ref OSVERSIONINFOEXW versionInfo);

        static void Main(string[] args)
        {
            string sWinVer = WinVer();
            Console.ReadLine();
        }

        //===============================================
        // Windows-Version ermitteln
        //===============================================
        private static string WinVer()
        {
            OSVERSIONINFOEXW osv = new OSVERSIONINFOEXW();
            var rcRtl = RtlGetVersion(ref osv);

            if (osv.dwMajorVersion == 10 && osv.dwMinorVersion == 0  && 
                osv.dwBuildNumber  >= 22000) 
            { osv.dwMajorVersion = 11; }
            
            string RtlVers = osv.dwMajorVersion.ToString() + "." +
                             osv.dwMinorVersion.ToString();

            string sVer = "??"; // "XP", "Vista", "7", "8", "8.1", "10", "11"

            switch (RtlVers) 
            {
                case "5.1" : sVer = "XP";    break;
                case "6.0" : sVer = "Vista"; break;
                case "6.1" : sVer = "7";     break;
                case "6.2" : sVer = "8";     break;
                case "6.3" : sVer = "8.1";   break;
                case "10.0": sVer = "10";    break;
                case "11.0": sVer = "11";    break;
            }
            string sCurrentBuild = osv.dwBuildNumber.ToString();

            bool Is64os = System.Environment.Is64BitOperatingSystem;
            string sArchitektur = Is64os ? "x64" : "x86";

            RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
            RegistryKey skey2 = key.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");

            sCurrentBuild = HoleRegValue(skey2, "CurrentBuild");
            string sUBR = HoleRegValue(skey2, "UBR");
            string sDisplayVersion = HoleRegValue(skey2, "DisplayVersion");
            string sEditionID = HoleRegValue(skey2, "EditionID");
            string sRegisteredOwner = HoleRegValue(skey2, "RegisteredOwner");
            string sInstallDate = HoleRegValue(skey2, "InstallDate");

            Console.WriteLine("Windows " + sVer + " Version " + sDisplayVersion +
                              " (Build " + sCurrentBuild + "." + sUBR + ")\n");

            string SysName = "Microsoft Windows " + sVer + " " + sEditionID + " " + sArchitektur;

            Console.WriteLine("Betriebssystemname      " + SysName);
            Console.WriteLine("Installiert am          " + sInstallDate);
            Console.WriteLine("Registrierter Benutzer  " + sRegisteredOwner);

            return sVer; // 10 oder 11 oder 8.1 oder 7 oder XP

        } // private static string WinVer() 

        //=============================================================
        // Angaben zu einem Key aus der Registry holen
        //=============================================================
        private static string HoleRegValue(Microsoft.Win32.RegistryKey skey, string suKey)
        {
            // Problem: Groß- und Kleinschreibung ist nicht immer gleich, bei C# aber relevant

            System.String[] ParaKeys = skey.GetValueNames();
            for (int i = 0; i < ParaKeys.Length; i++)
            {
                if (suKey.ToLower() == ParaKeys[i].ToLower())
                {
                    string rc = skey.GetValue(ParaKeys[i]).ToString(); // Original-Key benutzen

                    if (suKey == "InstallDate") // UNIX-Zeistempel ab dem 01.01.1970 00:00:00
                    {
                        DateTime AnfDate = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
                        var sec = skey.GetValue(ParaKeys[i]);   // UINT32 = Sekunden seit dem 01.01.1970 00:00:00 Uhr
                        DateTime EndDate = AnfDate.AddSeconds((int)sec);
                        rc = EndDate.ToString();
                    }
                    return rc;
                }
            }  // for

            return "";

        } // private static string HoleRegValue
    } // internal class Program
} // namespace WinVerHK
12.06.2023 - 14:28 Uhr

Jetzt habe ich eine Lösung gefunden, das Programm zeigt alles korrekt an in Windows 32 und 64.

Was habe ich gemacht ?

Projekt → Eigenschaften → Build → Zielplattform: Any CPU

Projekt → Eigenschaften → Anwendung → Zielframework: .NET Framework 4 (vorher war 4.8)

Damit funktioniert alles.  Die Merkwürdigkeiten sind offenbar erst nach 4.0 aufgetreten.

Hier das jetzige Programm

using System;
using System.Runtime.InteropServices;

namespace WinVerHK
{
    internal class Program
    {
        struct OSVERSIONINFOEXW 
        {
            public int dwOSVersionInfoSize { get; set; }
            public int dwMajorVersion { get; set; }
            public int dwMinorVersion { get; set; }
            public int dwBuildNumber { get; set; }
        }

        [DllImport("ntdll.dll", SetLastError = true)]
        static extern int RtlGetVersion(ref OSVERSIONINFOEXW versionInfo);

        static void Main(string[] args)
        {
            string sWinVer = WinVer();
            Console.ReadLine();
        }

        //===============================================
        // Windows-Version ermitteln
        //===============================================
        private static string WinVer()
        {
            OSVERSIONINFOEXW osv = new OSVERSIONINFOEXW();
            var rcRtl = RtlGetVersion(ref osv);

            if (osv.dwMajorVersion == 10 && osv.dwMinorVersion == 0  && 
                osv.dwBuildNumber  >= 22000) 
            { osv.dwMajorVersion = 11; }
            
            string RtlVers = osv.dwMajorVersion.ToString() + "." +
                             osv.dwMinorVersion.ToString();

            string sVer = "??"; // "XP", "Vista", "7", "8", "8.1", "10", "11"

            switch (RtlVers) 
            {
                case "5.1" : sVer = "XP";    break;
                case "6.0" : sVer = "Vista"; break;
                case "6.1" : sVer = "7";     break;
                case "6.2" : sVer = "8";     break;
                case "6.3" : sVer = "8.1";   break;
                case "10.0": sVer = "10";    break;
                case "11.0": sVer = "11";    break;
            }
            string sCurrentBuild = osv.dwBuildNumber.ToString();

            bool Is64os = System.Environment.Is64BitOperatingSystem;
            string sArchitektur = Is64os ? "x64" : "x86";

            string subKey2 = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion";
            Microsoft.Win32.RegistryKey skey2 = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(subKey2);

            sCurrentBuild = HoleRegValue(skey2, "CurrentBuild");
            string sUBR = HoleRegValue(skey2, "UBR");
            string sDisplayVersion = HoleRegValue(skey2, "DisplayVersion");
            string sEditionID = HoleRegValue(skey2, "EditionID");
            string sRegisteredOwner = HoleRegValue(skey2, "RegisteredOwner");
            string sInstallDate = HoleRegValue(skey2, "InstallDate");

            Console.WriteLine("Windows " + sVer + " Version " + sDisplayVersion +
                              " (Build " + sCurrentBuild + "." + sUBR + ")\n");

            string SysName = "Microsoft Windows " + sVer + " " + sEditionID + " " + sArchitektur;

            Console.WriteLine("Betriebssystemname      " + SysName);
            Console.WriteLine("Installiert am          " + sInstallDate);
            Console.WriteLine("Registrierter Benutzer  " + sRegisteredOwner);

            return sVer; // 10 oder 11 oder 8.1 oder 7 oder XP

        } // private static string WinVer() 

        //=============================================================
        // Angaben zu einem Key aus der Registry holen
        //=============================================================
        private static string HoleRegValue(Microsoft.Win32.RegistryKey skey, string suKey)
        {
            // Problem: Groß- und Kleinschreibung ist nicht immer gleich, bei C# aber relevant

            System.String[] ParaKeys = skey.GetValueNames();
            for (int i = 0; i < ParaKeys.Length; i++)
            {
                if (suKey.ToLower() == ParaKeys[i].ToLower())
                {
                    string rc = skey.GetValue(ParaKeys[i]).ToString(); // Original-Key benutzen

                    if (suKey == "InstallDate") // UNIX-Zeistempel ab dem 01.01.1970 00:00:00
                    {
                        DateTime AnfDate = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
                        var sec = skey.GetValue(ParaKeys[i]); // UINT32 = Sekunden seit 01.01.1970 00:00:00 Uhr
                        DateTime EndDate = AnfDate.AddSeconds((int)sec);
                        rc = EndDate.ToString();
                    }
                    return rc;
                }
            }  // for

            return "";

        } // private static string HoleRegValue
    } // internal class Program
} // namespace WinVerHK
12.06.2023 - 13:40 Uhr

Mit der RtlGetVersion kann ich die Windows-Version erkennen unabhängig vom Modus X64 oder AnyCPU.

AnyCPU bwirkt m.E., dass das Programm im x86 Modus ausgeführt wird und dass in diesem Fall die für diesen Modus vorhandenen Registry Werte zur Verfügung gestellt werden. Das ist bekannt und OK. Allerdings ist nicht OK, dass die Registry Werte

"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion"

mit denen von

"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion"

nicht übereinstimmen.

Im X64 Modus bekomme ich korrekte Werte, das Programm kann aber nicht in einem Win32 laufen, dort gibt es die beiden unterschiedlichen Werte nicht.

Im AnyCPU Modus funktioniert das Programm in einem Win32, erhält aber im Win-64 falsche Angaben, weil die Angaben bei WOW6432Node unkorrekt sind oder ganz fehlen, wie das Install-Datum.

Für andere Angaben in der Registry habe ich noch nicht auf Abweichungen untersucht.

Mein Ziel deshalb, ich möchte, dass das Programm auch im AnyCPU-Modus  die korrekten Werte erhält.

12.06.2023 - 12:05 Uhr

Ich habe nun allerdings noch ein Problem, auch eine weniger elegante Lösung.

Ich möchte das Programm nicht im X64 Modus ausführen, weil es da z.B. auf meinem Tablet mit Win10-32 nicht funktioniert.

Wenn ich bei VS2022 in den Eigenschaften "Any CPU" statt X64 einstelle, erhalte ich ganz andere Angaben beim Auslesen der Registry.

Da stimmen einigen Angaben nicht oder sind gar nicht vorhanden, z.B. Installations-Zeitpunkt.  Es wird von folgendem Key gelesen

"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion"

anstelle von

"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion"

Mein Lösungsansatz ist folgender: Ich rufe regedit mit folgendem Kommando auf

"%WINDIR%\RegEdit" /a "x:\RegData.TEMP" "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion"

und lese danach die Datei x:\RegData.TEMP ein und hole mir die benötigten Daten heraus. In dieser Datei steht alles so, wie beim X64-Programm.

Meine Frage: Gibt es eine Möglicheit in einem X64-System mit einem AnyCPU-Programm die X64-Angaben mit GetValue auszulesen ?

Jetzt bekomme ich die unkorrekten WOW6432Node Werte.

12.06.2023 - 11:18 Uhr

Th69,

auf meinem Tablet steht dort auch nicht "Windows 10", sondern etwas anderes - ich habe das allerdings nicht selbst eingetragen.

Ich benutze nun Deinen Vorschlag und bekomme damit heraus, um welches Windows es sich handelt

using System;
using System.Runtime.InteropServices;

namespace WinVerHK
{
    internal class Program
    {
        struct OSVERSIONINFOEXW 
        {
            public int dwOSVersionInfoSize { get; set; }
            public int dwMajorVersion { get; set; }
            public int dwMinorVersion { get; set; }
            public int dwBuildNumber { get; set; }
        }

        [DllImport("ntdll.dll", SetLastError = true)]
        static extern int RtlGetVersion(ref OSVERSIONINFOEXW versionInfo);


        static void Main(string[] args)
        {
            string sWinVer = WinVer();
            Console.ReadLine();
        }

        //===============================================
        // Windows-Version ermitteln
        //===============================================
        private static string WinVer()
        {
            OSVERSIONINFOEXW osv = new OSVERSIONINFOEXW();
            var rcRtl = RtlGetVersion(ref osv);

            if (osv.dwMajorVersion == 10 && osv.dwMinorVersion == 0  && 
                osv.dwBuildNumber  >= 22000) 
            { osv.dwMajorVersion = 11; }
            
            string RtlVers = osv.dwMajorVersion.ToString() + "." +
                             osv.dwMinorVersion.ToString();

            string sVer = "??"; // "XP", "7", "8.1", "10", "11"

            switch (RtlVers) 
            {
                case "5.1" : sVer = "XP";    break;
                case "6.0" : sVer = "Vista"; break;
                case "6.1" : sVer = "7";     break;
                case "6.2" : sVer = "8";     break;
                case "6.3" : sVer = "8.1";   break;
                case "10.0": sVer = "10";    break;
                case "11.0": sVer = "11";    break;
            }
12.06.2023 - 08:53 Uhr

@Abt,

ich habe es wie folgt geändert

                    if (suKey == "InstallDate") // UNIX-Zeistempel ab dem 01.01.1970 00:00:00
                    {
                        DateTime AnfDate = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
                        var sec = skey.GetValue(ParaKeys[i]);   // UINT32 = Sekunden seit dem 01.01.1970 00:00:00 Uhr
                        DateTime EndDate = AnfDate.AddSeconds((int)sec);
                        rc = EndDate.ToString();

                    }

Es wird weiterhin 17:24:18 als Uhrzeit der Installation angezeigt.

Windows 10 Version 22H2 (Build 19045.3031)

Betriebssystemname      Microsoft Windows 10 Professional X64
Installiert am          22.10.2022 17:24:18

11.06.2023 - 17:09 Uhr

Muss man bei Windows einstellen, dass man mit der UTC Zeit arbeiten möchte ?

Windowspage - Datum und Uhrzeit - BIOS/CMOS-Zeit als UTC-Zeit festlegen

Bei mir ist diesbezüglich nichts in der Registry eingestellt, meine Uhrzeit läuft als mitteleuropäische Sommerzeit (UTC+2)

Deshalb sind die angezeigten Zeiten immer die zutreffenden Ortszeiten meines ortsfesten PCs.

Nach UTC bzw. nach ISO8601 zu speichern sind jedoch technische Standards - daher auch keine Philosophie.

Der eine macht es so, der andere macht es nicht so. Das ist kein fixer Standard. Windows mit UTC Zeiten haben nur die PCs, bei denen man es so einstellt, ein Standard-Windows benutzt die Ortszeit. Anders ist es ggf. bei einigen Linux-Systemen.

Th69, wieso hat Deine Registry nicht diesen Eintrag ? Bei mir ist der bei allen drei WIndows 10 und 11 PC vorhanden, allerdings nicht bei der Vorgängerversionen XP, 7 und 8.1.

11.06.2023 - 16:48 Uhr

@Abt,

Windows speichert jedoch alle Werte getreu dem ISO-Standard nach UTC.

Meinst Du damit alle Zeiten, also auch den Zeitstempel beim Ändern von Dateien ?

Ich habe gerade einen Ordner angelegt mit dem Namen X162739,

dabei bedeuten die Zahl die Uhrzeit des Anlegens = 16:27:39

Im Directory sieht der Zeitstempel folgendermaßen aus:

000EC0: 58 31 36 32  37 33 39 20  20 20 20 10  00 0D 76 83 :X162739    ...v.:
000ED0: CB 56 CB 56  00 00 77 83  CB 56 C8 02  00 00 00 00 :.V.V..w..V......:
                           -----  -----
                           Time   Date 

TIME: 77 83 = 0x8377 = 1000 0011 0111 0111
                       ------#######++++++
                       Stunde Minute DoppelSek  = 16:27:46
                       10000  011011 10111
                       16     27     23 => *2 = 46

Die Sekunden weichen etwas ab, aber nicht die Stunde.

Das DIR Kommando zeigt es so an, ich kann keine UTC-Zeit erkennen, alle Zeiten sind dresdner Ortszeiten, auch die BIOS/UEFI-Uhr läuft nach unserer Ortszeit:

Microsoft Windows [Version 10.0.19045.3031]
(c) Microsoft Corporation. Alle Rechte vorbehalten.

G:\Test>dir a:
 Datenträger in Laufwerk A: ist AAA
 Volumeseriennummer: EC88-CC58

 Verzeichnis von A:\

08.06.2023  16:02    <DIR>          Bilder
11.06.2023  16:27    <DIR>          X162739
               0 Datei(en),              0 Bytes
               2 Verzeichnis(se),          2.048 Bytes frei

G:\Test>
10.06.2023 - 18:37 Uhr

Ich könnte bei Zeit ja noch den Hinweis "Lokalzeit" ausgeben.

Welche Zeit sollte denn angezeigt werden, um den CODE-FEHLER zu beseitigen ?

Da ja nicht angespeichert ist, wo (an welchem Ort der  Erde) die  Installation stattfand, kann man die Zeit auch nicht korrekt zuordnen. Wurde dieses Windows bei einem fertig-PC/Notebook/Tablet in Mexiko, China oder Indien installiert und war es damals an diesem ort gerade 14°° Uhr Ortszeit, was soll man nun in Deutschlan anzeigen ? Man weiß ja nicht WO bei dem betreffenden Zeitstempel installiert wurde.

Die ZEIT und die ZEITZONE ist m.E. mehr ein philosophisches als ein technisch-mathematisches Problem.

10.06.2023 - 18:32 Uhr

@Abt,
Die absolute Zeit ist doch völlig uninteressant, ob die Installation nun eine Stunde früher oder später war - interessant ist das Datum.
Die Uhrzeit ist trotzdem hilfreich, wenn ich z.B. nachschauen will, ob ich nun zuerst Windows 11 oder 10 auf einem PC installiert habe. Bei mir gibt es beinahe auf jedem PC Win10 und 11 parallel und zusätzlich XP, 7 und 8.1 und Ubuntu als VMs. DOS und Win3.1 habe ich auch noch in der DosBox laufen.

@Th69,
Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters
SrvComment = Windows 10

Aus dieser Angabe ermittle ich, ob es sich um Windows 10 oder 11 handelt, Bei beiden meiner Pro-Versionen gibt es diesen Parameter. Bei Windows 7 und 8.1 gibt es ihn nicht, deshalb frage ich bei diesen Versionen den Parameter nicht ab, Win7 und 8.1 sind bereits an Hand der OSDescription eindeutig zu erkennen. WIn10 und 11 leider nicht.

Wenn bei Dir SrvComment nicht vorhanden ist - dann hast Du sicherlich ein anderes WIndows, das habe ich nicht und konnte es deshalb auch nicht testen.

@Palladin007,
in meinem Programm, wo ich das einsetze, kann man die System-Information abrufen.
Die angezeigten Werte sind weitestgehend identisch mit der System-Info von Windows 10.
Dort hat man (aus gutem Grund ?) die Uhrzeit der Installation weggelassen.

09.06.2023 - 18:35 Uhr

Ich habe jetzt eine Lösung gefunden, da muss man etwas mehr tun, als nur eine Varibale abfragen.

Das Ergenis dieses Test-Konsolenprogrammes sieht so aus:

Windows 10 Version 22H2 (Build 19045.3031)

Betriebssystemname      Microsoft Windows 10 Professional X64
Installiert am          22.10.2022 17:24:18
Registrierter Benutzer  xyz@t-online.de

In den Projekt Eigenschaften von VS2022 muss bei Build als Zielplattform X64 eingestellt sein.

using System;
using System.Runtime.InteropServices;

namespace WinVerHK
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string sWinVer = WinVer();
            Console.ReadLine();
        }

        //===============================================
        // Windows-Version ermitteln
        //===============================================
        private static string WinVer()
        {
            string sCurrentBuild = "";
            string sUBR = "";
            string sDisplayVersion = "";
            string sEditionID = "";
            string sProductName = "";
            string sRegisteredOwner = "";
            string sReleaseId = "";
            string sInstallDate = "";
            string sInstallTime = "";
            string sCurrentMajorVersionNumber = "";
            string sCurrentMinorVersionNumber = "";
            string sCurrentVersion = "";
            string sSrvComment = "";

            string sVer = "XP"; // "XP", "7", "8.1", "10", "11"

            string OSa = RuntimeInformation.OSArchitecture.ToString(); // X64
            string sArchitektur = OSa;

            string osVersion = Environment.OSVersion.ToString();
            // 10: "Microsoft Windows NT 6.2.9200.0"
            // 11: "Microsoft Windows NT 6.2.9200.0"
            // 7 : "Microsoft Windows NT 6.1.7601 Service Pack 1"
            string sOsVersion = osVersion;

            string Version = Environment.Version.ToString();
            // 10: "4.0.30319.42000"
            // 11: "4.0.30319.42000"
            //  7: "4.0.30319.42000"
            string sVersion = Version;

            string OSd = RuntimeInformation.OSDescription;
            // 10 : Microsoft Windows 10.0.19045
            // 11 : Microsoft Windows 10.0.22621 = Build
            // 8.1: Microsoft Windows 6.3.9600 
            // 7  : Microsoft Windows 6.1.7601 S
            string sDescription = OSd;

            sVer = "???";

            if (OSd.StartsWith("Microsoft Windows 6.3.")) { sVer = "8.1"; goto UpNxt; }
            if (OSd.StartsWith("Microsoft Windows 6.1.")) { sVer = "7"; goto UpNxt; }

            string subKey1 = @"SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters";
            Microsoft.Win32.RegistryKey skey1 = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(subKey1);

            sSrvComment = HoleRegValue(skey1, "SrvComment");
            if (sSrvComment.EndsWith("10")) sVer = "10";
            if (sSrvComment.EndsWith("11")) sVer = "11";

          UpNxt:
            string subKey2 = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion";
            Microsoft.Win32.RegistryKey skey2 = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(subKey2);

            sCurrentBuild = HoleRegValue(skey2, "CurrentBuild");
            sUBR = HoleRegValue(skey2, "UBR");
            sDisplayVersion = HoleRegValue(skey2, "DisplayVersion");
            sEditionID = HoleRegValue(skey2, "EditionID");
            sProductName = HoleRegValue(skey2, "ProductName");
            sRegisteredOwner = HoleRegValue(skey2, "RegisteredOwner");
            sReleaseId = HoleRegValue(skey2, "ReleaseId");
            sInstallDate = HoleRegValue(skey2, "InstallDate");
            sInstallTime = HoleRegValue(skey2, "InstallTime");
            sCurrentMajorVersionNumber = HoleRegValue(skey2, "CurrentMajorVersionNumber");
            sCurrentMinorVersionNumber = HoleRegValue(skey2, "CurrentMinorVersionNumber");
            sCurrentVersion = HoleRegValue(skey2, "CurrentVersion");


            Console.WriteLine("Windows " + sVer + " Version " + sDisplayVersion +
                              " (Build " + sCurrentBuild + "." + sUBR + ")\n");
            string SysName = sOsVersion.Substring(0, 18) + sVer + " " + sEditionID + " " + sArchitektur;
            Console.WriteLine("Betriebssystemname      " + SysName);
            Console.WriteLine("Installiert am          " + sInstallDate);
            Console.WriteLine("Registrierter Benutzer  " + sRegisteredOwner);

            return sVer; // 10 oder 11 oder 8.1 oder 7 oder XP

        } // private static string WinVer() 

        //=============================================================
        // Angaben zu einem Key aus der Registry holen
        //=============================================================
        private static string HoleRegValue(Microsoft.Win32.RegistryKey skey, string suKey)
        {
            // Problem: Groß- und Kleinschreibung ist nicht immer gleich, bei C# aber relevant
            System.String[] ParaKeys = skey.GetValueNames();
            for (int i = 0; i < ParaKeys.Length; i++)
            {
                if (suKey.ToLower() == ParaKeys[i].ToLower())
                {
                    string rc = skey.GetValue(ParaKeys[i]).ToString(); // Original-Key benutzen

                    if (suKey == "InstallDate") // UNIX-Zeistempel ab dem 01.01.1970 00:00:00
                    {
                        DateTime AnfDate = new DateTime(1970, 1, 1);
                        var sec = skey.GetValue(ParaKeys[i]);   // UINT32 = Sekunden seit dem 01.01.1970 00:00:00 Uhr
                        DateTime EndDate = AnfDate.AddSeconds((int)sec);
                        rc = EndDate.ToString();
                    }
                    if (suKey == "InstallTime") // Windows-Zeitstempel (?) ab dem 01.01.1600 00:00:00
                    {
                        DateTime MilliSec = new DateTime((long)skey.GetValue(ParaKeys[i]));  // UINT64 = ulong MilliSekunden seit 1600
                        DateTime EndDate = MilliSec.AddYears(1600); // 01.01.1600 dazu zählen
                        rc = EndDate.ToString();
                    }
                    return rc;
                }
            }  // for

            return "";

        } // private static string HoleRegValue
    }
}
24.05.2023 - 12:14 Uhr

Zugriff verweigert kommt nur manchmal, beim zweiten CLEAN klappt es.

22.05.2023 - 12:43 Uhr

Ich möchte in einem Programm ermitteln, ob das Programm unter Windows 10 oder 11 (besser in welchem Windows XP, 7, 8.1. 10, 11) läuft.

Das Programm mache ich mit C# unter VS2022.

Es geht eigentlich ganz einfach mit

string description = RuntimeInformation.OSDescription;

Hier die Ergebnisse:

Windows 10 liefert ⇒ Microsoft Windows 10.0.19045 <= Build

Windows 11 liefert ⇒ Microsoft Windows 10.0.22621 <= Build

Muss man nun abfragen ; Build > 22000 = Win11, ansonsten Win10 ?

21.05.2023 - 11:42 Uhr

Ich vermute, dass der Defender der Blockierer ist.

Bei Win10 und 11 benutze ich jeweils nur den Defender als Virenschutz.

Offenbar arbeiten diese Programme bei Win10 und 11 nicht gleich.

Im abgesicherten Modus ist der Defender nicht aktiv.

Und das passiert bei Windows 10:


Microsoft DiskPart-Version 10.0.19041.964

Copyright (C) Microsoft Corporation.
Auf Computer: R980

DISKPART> list disk

  Datenträger ###  Status         Größe    Frei     Dyn  GPT
  ---------------  -------------  -------  -------  ---  ---
  Datenträger 0    Online         2794 GB  1024 KB        *
  Datenträger 1    Online         1863 GB  1024 KB        *
  Datenträger 2    Online         5589 GB      0 B        *
  Datenträger 3    Online          931 GB  1024 KB        *
  Datenträger 4    Online          931 GB  1024 KB        *
  Datenträger 5    Online          931 GB  1024 KB        *
  Datenträger 6    Online          960 MB      0 B

DISKPART> select disk 6

Datenträger 6 ist jetzt der gewählte Datenträger.

DISKPART> attributes disk
Aktueller schreibgeschützter Zustand: Nein
Schreibgeschützt  : Nein
Startdatenträger  : Nein
Auslagerungsdatei-Datenträger  : Nein
Ruhezustandsdatei-Datenträger  : Nein
Absturzabbild-Datenträger  : Nein
Clusterdatenträger : Nein

DISKPART> clean

Der Datenträger wurde bereinigt.

DISKPART> attributes disk
Aktueller schreibgeschützter Zustand: Nein
Schreibgeschützt  : Nein
Startdatenträger  : Nein
Auslagerungsdatei-Datenträger  : Nein
Ruhezustandsdatei-Datenträger  : Nein
Absturzabbild-Datenträger  : Nein
Clusterdatenträger : Nein

DISKPART>

21.05.2023 - 11:38 Uhr

So sieht es bei Windows 11 aus:


Microsoft DiskPart-Version 10.0.22621.1

Copyright (C) Microsoft Corporation.
Auf Computer: R980

DISKPART> list disk

  Datenträger ###  Status         Größe    Frei     Dyn  GPT
  ---------------  -------------  -------  -------  ---  ---
  Datenträger 0    Online         2794 GB  1024 KB        *
  Datenträger 1    Online         1863 GB  1024 KB        *
  Datenträger 2    Online         5589 GB      0 B        *
  Datenträger 3    Online          931 GB  1024 KB        *
  Datenträger 4    Online          931 GB  1024 KB        *
  Datenträger 5    Online          931 GB  1024 KB        *
  Datenträger 6    Online          960 MB   944 MB

DISKPART> select disk 6

Datenträger 6 ist jetzt der gewählte Datenträger.

DISKPART> attributes disk
Aktueller schreibgeschützter Zustand: Nein
Schreibgeschützt  : Nein
Startdatenträger  : Nein
Auslagerungsdatei-Datenträger  : Nein
Ruhezustandsdatei-Datenträger  : Nein
Absturzabbild-Datenträger  : Nein
Clusterdatenträger : Nein

DISKPART> clean

Fehler in DiskPart: Zugriff verweigert
Weitere Informationen finden Sie im Systemereignisprotokoll.

DISKPART> clean

Der Datenträger wurde bereinigt.

DISKPART> attributes disk
Aktueller schreibgeschützter Zustand: Nein
Schreibgeschützt  : Nein
Startdatenträger  : Nein
Auslagerungsdatei-Datenträger  : Nein
Ruhezustandsdatei-Datenträger  : Nein
Absturzabbild-Datenträger  : Nein
Clusterdatenträger : Nein

DISKPART>
21.05.2023 - 10:12 Uhr

Wenn ich eine byte[] Array auf ein USB-PhysicalDrive ausgeben will, dann bekomme ich von WIndows 10 den Fehler "Der Zugriff auf den Pfad wurde verweigert.". Unter Windows 11 auf dem gleichen PC funktioniert es ohne diesen Fehler. Bei Win10 klappt es auch im abgesicherten Modus.

Ich muss das USB-Gerät (USB-Stick oder SD-Card im CardReader) zuvor mit DiskPart-CLEAN löschen

und mein Programm bzw. VS2022 mit "Als Administrator ausführen" starten.

So sieht das Ergebnis bei WIndows 10 aus:

<CreateFile> des USB-Laufwerkes "\\.\PhysicalDrive6" = OK
<DeviceIoControl FSCTL_LOCK_VOLUME> OK
<DeviceIoControl FSCTL_DISMOUNT_VOLUME> OK
<FileStream(h, FileAccess.Write> OK
<outPutFile.Write> bei Offset 0x0000000000 von Ges = 0x0000F50000

Fehler bei <write>
~~~~~~~~~~~~~~~~<Exception-Anfang>~~~~~~~~~~~~~~~~~~~~~~
System.UnauthorizedAccessException: Der Zugriff auf den Pfad wurde verweigert.
   bei System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   bei System.IO.FileStream.WriteCore(Byte[] buffer, Int32 offset, Int32 count)
   bei System.IO.FileStream.Write(Byte[] array, Int32 offset, Int32 count)
   bei HkDiskette.Form1.WriteUsb2() in V:\#PgmHK\VC20xx\HKcs\HkDiskette\Form1.cs:Zeile 2380.
~~~~~~~~~~~~~~~~~<Exception-Ende>~~~~~~~~~~~~~~~~~~~~~~~

Und so bei Windows 11

<CreateFile> des USB-Laufwerkes "\\.\PhysicalDrive6" = OK
<DeviceIoControl FSCTL_LOCK_VOLUME> OK
<DeviceIoControl FSCTL_DISMOUNT_VOLUME> OK
<FileStream(h, FileAccess.Write> OK
<outPutFile.Write> bei Offset 0x0000000000 von Ges = 0x0000F50000
DeviceIoControl FSCTL_UNLOCK_VOLUME = OK
"\\.\PhysicalDrive6" 0x80070000: handle closed.
Ausgabe fertig

Hier etwas Code

        //#####################################
        // USB ausgeben TEST (2)
        //#####################################
        private void WriteUsb2()
        {
            string deviceId = @"\\.\PhysicalDrive6";
            string DsnEing = @"G:\Test\USB\CF16MB-CARDupd.vhd";
            int intOut = 0;

            int MaxLenPu = 0x7FFFFE00;

            FileInfo f = new FileInfo(DsnEing);
            if (!f.Exists)
            {
                PutLst("Datei " + DsnEing + " existiert nicht\n=> Abbruch");
                return;
            }
            long LenEing = f.Length;
            if (DsnEing.ToLower().EndsWith(".vhd"))
            {
                LenEing -= 512; // Ohne den Fuss-Sektor
            }

            int LenPu = (int)Math.Min(LenEing, MaxLenPu);

            long RestLen = LenEing;

            SafeFileHandle h = CreateFile(deviceId, GENERIC_READ | GENERIC_WRITE, 0,
                                          IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);

            if (h.IsInvalid)
            {
                PutLst("Fehler <IsInvalid == true> bei <CreateFile> des USB-Laufwerkes \"" + deviceId + "\"");
                return;
            }
            PutLst("<CreateFile> des USB-Laufwerkes \""+ deviceId + "\" = OK");

            if (!DeviceIoControl(h, FSCTL_LOCK_VOLUME, null, 0, null, 0, out intOut, IntPtr.Zero))
            {
                PutLst("Fehler DeviceIoControl FSCTL_LOCK_VOLUME");
                CloseHandle(h);
                return;
            }
            PutLst("<DeviceIoControl FSCTL_LOCK_VOLUME> OK");

            if (!DeviceIoControl(h, FSCTL_DISMOUNT_VOLUME, null, 0, null, 0, out intOut, IntPtr.Zero))
            {
                PutLst("Fehler DeviceIoControl FSCTL_DISMOUNT_VOLUME");
                CloseHandle(h);
                return;
            }
            PutLst("<DeviceIoControl FSCTL_DISMOUNT_VOLUME> OK");

            Stream outPutFile = new FileStream(h, FileAccess.Write);
            PutLst("<FileStream(h, FileAccess.Write> OK");

            byte[] ByPu = null;
            int Gelesen = 0;
            long LenAusg = 0;

            using (FileStream ReadVHD = new FileStream(DsnEing, FileMode.Open, FileAccess.Read,
                                FileShare.Read, 4096, FileOptions.SequentialScan))

            {
                while (RestLen > 0)
                {
                    long LeseLen = Math.Min(RestLen, LenPu);
                    ByPu = new byte[LeseLen];

                    try
                    {
                        Gelesen = ReadVHD.Read(ByPu, 0, (int)LeseLen);
                    }
                    catch (Exception ex)
                    {
                        PutLst("Fehler beim Lesen der Datei \"" + DsnEing + "\"");
                        PutLst("~~~~~~~~~~~~~~~~<Exception-Anfang>~~~~~~~~~~~~~~~~~~~~~~");
                        PutLst(ex.ToString());
                        PutLst("~~~~~~~~~~~~~~~~~<Exception-Ende>~~~~~~~~~~~~~~~~~~~~~~~");
                        return;
                    }
                    if (Gelesen != LeseLen) break; // => EOF erreicht

                    try
                    {
                        PutLst("<outPutFile.Write> bei Offset 0x" + LenAusg.ToString("X10")+
                            " von Ges = 0x"+LenEing.ToString("X10"));
                        outPutFile.Write(ByPu, 0, (int)LeseLen);
                        LenAusg += LeseLen;
                        laDiskLw.Text = EdLong(LenAusg, 14) + " / " + EdLong(LenEing, 14) +
                                        " Bytes ausgegeben.";
                        RestLen -= LeseLen;
                        Application.DoEvents();
                    }
                    catch (Exception ex)
                    {
                        PutLst("");
                        PutLst("Fehler bei <write>");
                        PutLst("~~~~~~~~~~~~~~~~<Exception-Anfang>~~~~~~~~~~~~~~~~~~~~~~");
                        PutLst(ex.ToString());
                        PutLst("~~~~~~~~~~~~~~~~~<Exception-Ende>~~~~~~~~~~~~~~~~~~~~~~~");
                        return;
                    }

                } //  while(RestLen > 0) 

            } // using (FileStream ReadVHD 


            if (!DeviceIoControl(h, FSCTL_UNLOCK_VOLUME, null, 0, null, 0, out intOut, IntPtr.Zero))
            { PutLst("Fehler DeviceIoControl FSCTL_UNLOCK_VOLUME"); return; }
            PutLst("DeviceIoControl FSCTL_UNLOCK_VOLUME = OK");

            if (!CloseHandle(h))
            {
                PutLst("\"" + deviceId + "\" 0x" + Marshal.GetHRForLastWin32Error().ToString("X8") + ": close handle error: " +
                       Marshal.GetHRForLastWin32Error().ToString("X8"));
                return;
            }
            PutLst("\"" + deviceId + "\" 0x" + Marshal.GetHRForLastWin32Error().ToString("X8") + ": handle closed."); 
            PutLst("Ausgabe fertig");
            
            
            

        } //   private void WriteUsb2()