Autor |
Beitrag |
MCPC10
Beiträge: 35
Win 10, Win Server 2016
C# (VS 2015, VS2017, VS2019), Assembler (Atmel Studio 7.0)
|
Verfasst: So 02.08.20 15:36
Hallo liebe Community,
Ich hätte wieder mal eine Frage .
Ich wollte mal von euch wissen ob dieser Code den so gut ist oder ob dieser noch verbessert werden kann/es eine bessere Methode gibt.
Ich danke für jede konstruktive Antwort .
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50:
| public unsafe void ChangeFailureActions(TimeSpan resetPeriod, string rebootMessage, string command, IReadOnlyList<Win32ScAction> actions) { int size = 0; Win32ScAction** ptr = null; if (actions != null) { size = actions.Count; ptr = (Win32ScAction**) Marshal.AllocHGlobal(Marshal.SizeOf<Win32ScAction>() * size); }
try { if (ptr != null) { for (int i = 0; i < actions.Count; i++) Marshal.StructureToPtr(actions[i], (IntPtr)ptr[i], false); }
Win32ServiceFailureActions serviceFailureActions = new Win32ServiceFailureActions(resetPeriod, rebootMessage, command, size, ptr != null ? (IntPtr)ptr : IntPtr.Zero); IntPtr ptrServiceFailureActions = Marshal.AllocHGlobal(Marshal.SizeOf(serviceFailureActions)); try { Marshal.StructureToPtr(serviceFailureActions, ptrServiceFailureActions, false); try { if (!ChangeServiceConfig2W(this, Win32ServiceConfigInfoLevel.SERVICE_CONFIG_FAILURE_ACTIONS, ptrServiceFailureActions)) throw new Win32Exception(Marshal.GetLastWin32Error()); } finally { Marshal.DestroyStructure<Win32ServiceFailureActions>(ptrServiceFailureActions); } } finally { Marshal.FreeHGlobal(ptrServiceFailureActions); } } finally { if (ptr != null) { for (int i = 0; i < actions.Count; i++) Marshal.DestroyStructure<Win32ScAction>((IntPtr)ptr[i]);
Marshal.FreeHGlobal((IntPtr)ptr); } } } |
Mit freundlichen Grüßen
MCPC10 Moderiert von Th69: Topic aus C# - Die Sprache verschoben am Mo 03.08.2020 um 08:47
|
|
Th69
Beiträge: 4784
Erhaltene Danke: 1055
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mo 03.08.20 08:46
So ganz verstehe ich deinen Code und die verwendeten Datentypen nicht.
Welchen Datentyp verlangt denn die ChangeServiceConfig2W-Funktion: Win32ScAction* (Zeiger auf Strukturen) oder Win32ScAction** (Zeiger auf Zeiger auf Struktur)?
Bei
C#-Quelltext 1:
| ptr = (Win32ScAction**) Marshal.AllocHGlobal(Marshal.SizeOf<Win32ScAction>() * size); |
müßte doch als Datentyp Win32ScAction* verwendet werden (da du die Größe der Struktur und nicht eines Zeigers angibst).
Funktioniert denn dein Code so zur Laufzeit oder erhältst du einen Laufzeitfehler?
Für das Marshallen eines Arrays schau dir auch mal die letzten Beispiele " TestArrayOfStructs/2" in Marshallen verschiedener Typen von Arrays an.
Für diesen Beitrag haben gedankt: MCPC10
|
|
MCPC10
Beiträge: 35
Win 10, Win Server 2016
C# (VS 2015, VS2017, VS2019), Assembler (Atmel Studio 7.0)
|
Verfasst: Mo 03.08.20 20:52
Hallo,
Erstmal Danke für deine Antwort.
Hast natürlich völlig Recht aber gibt es ne schönere Methode direkt die richtige menge Speicher zu zuweisen ohne mehrfach Marshal.AllocHGlobal aufzurufen (außer dieser hier xD)?
Hier ist der verbessert Code (funktioniert so auch, hab den Code etwas geändert da ich ihn zum testen in meine bestehende App eingebaut habe):
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60:
| public unsafe void ChangeFailureActions2(Advapi32.ServiceFailureActions failureActions) { int size = 0; Advapi32.ScAction* ptr = null; if (failureActions.Actions != null) { size = failureActions.Actions.Count; ptr = (Advapi32.ScAction*) Marshal.AllocHGlobal(Marshal.SizeOf<Advapi32.ScAction>() * size); }
try { if (ptr != null) { for (int i = 0; i < size; i++) Marshal.StructureToPtr(failureActions.Actions[i], new IntPtr(&ptr[i]), false); }
Advapi32.ServiceConfigFailureActions serviceConfigFailureActions = new Advapi32.ServiceConfigFailureActions { resetPeriode = (uint)Math.Round(failureActions.ResetPeriode.TotalSeconds), rebootMessage = failureActions.RebootMessage, command = failureActions.Command, actionsLength = (uint)size, actions = (IntPtr)ptr };
IntPtr ptrServiceFailureActions = Marshal.AllocHGlobal(Marshal.SizeOf<Advapi32.ServiceConfigFailureActions>()); try { Marshal.StructureToPtr(serviceConfigFailureActions, ptrServiceFailureActions, false); try { if (!Advapi32.ChangeServiceConfig2(this, Advapi32.ServiceInfoLevel.FailureActions, ptrServiceFailureActions)) throw new Win32Exception(Marshal.GetLastWin32Error()); } finally { Marshal.DestroyStructure<Advapi32.ServiceConfigFailureActions>(ptrServiceFailureActions); } } finally { Marshal.FreeHGlobal(ptrServiceFailureActions); } } finally { if (ptr != null) { for (int i = 0; i < size; i++) Marshal.DestroyStructure<Advapi32.ScAction>(new IntPtr(&ptr[i]));
Marshal.FreeHGlobal((IntPtr)ptr); } } } |
_________________ Mit freundlichen Grüßen
MCPC10
|
|
jfheins
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Mo 03.08.20 22:36
Ich habe schon lange nichts mehr mit P/invoke gemacht, aber müsste man nicht auch das Array so anlegen und dann pinnen können?
Also statt ein neues Array aufzumachen, einfach das vorhandene nehmen?
|
|
MCPC10
Beiträge: 35
Win 10, Win Server 2016
C# (VS 2015, VS2017, VS2019), Assembler (Atmel Studio 7.0)
|
Verfasst: Di 04.08.20 19:39
Hallo,
Werden Strukturen nicht mit GCHandle.Alloc kopiert?
Moderiert von Th69: C#-Tags hinzugefügt
_________________ Mit freundlichen Grüßen
MCPC10
|
|
jfheins
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Mi 05.08.20 08:33
MCPC10 hat folgendes geschrieben : | Werden Strukturen nicht mit GCHandle.Alloc kopiert? |
Also soweit ich weiß (/gelesen habe), erzeugt GCHandle.Alloc ein neues Handle, sodass der GC den struct nicht abräumt. Der struct selbst bleibt aber an der Stelle und wird nicht kopiert.
Ich glaube das Problem wird eher, dass du kein Array hast sondern nur eine IReadOnlyList, die ihr Array nicht offen legt.
|
|
MCPC10
Beiträge: 35
Win 10, Win Server 2016
C# (VS 2015, VS2017, VS2019), Assembler (Atmel Studio 7.0)
|
Verfasst: Fr 07.08.20 20:35
In diesem Fall würde es funktionieren (wenn es ein Array wäre), weil hier keine Non-Blittable typen zum Einsatz kommen oder lieg ich falsch?
_________________ Mit freundlichen Grüßen
MCPC10
|
|
jfheins
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: So 09.08.20 19:55
|
|
|