mirror of https://github.com/dahall/Vanara.git
Completed unit tests and fixes for TlHelp32.h
parent
5b4853db7e
commit
0d042532a3
|
@ -1,5 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using Vanara.InteropServices;
|
||||
|
||||
namespace Vanara.PInvoke
|
||||
{
|
||||
|
@ -40,6 +42,7 @@ namespace Vanara.PInvoke
|
|||
TH32CS_INHERIT = 0x80000000,
|
||||
|
||||
/// <summary>Includes all heaps of the process specified in th32ProcessID in the snapshot. To enumerate the heaps, see Heap32ListFirst.</summary>
|
||||
[CorrespondingType(typeof(HEAPLIST32))]
|
||||
TH32CS_SNAPHEAPLIST = 0x00000001,
|
||||
|
||||
/// <summary>
|
||||
|
@ -51,6 +54,7 @@ namespace Vanara.PInvoke
|
|||
/// th32ProcessID from a 64-bit process, use the TH32CS_SNAPMODULE32 flag.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[CorrespondingType(typeof(MODULEENTRY32))]
|
||||
TH32CS_SNAPMODULE = 0x00000008,
|
||||
|
||||
/// <summary>
|
||||
|
@ -58,9 +62,11 @@ namespace Vanara.PInvoke
|
|||
/// flag can be combined with TH32CS_SNAPMODULE or TH32CS_SNAPALL. If the function fails with ERROR_BAD_LENGTH, retry the
|
||||
/// function until it succeeds.
|
||||
/// </summary>
|
||||
[CorrespondingType(typeof(MODULEENTRY32))]
|
||||
TH32CS_SNAPMODULE32 = 0x00000010,
|
||||
|
||||
/// <summary>Includes all processes in the system in the snapshot. To enumerate the processes, see Process32First.</summary>
|
||||
[CorrespondingType(typeof(PROCESSENTRY32))]
|
||||
TH32CS_SNAPPROCESS = 0x00000002,
|
||||
|
||||
/// <summary>
|
||||
|
@ -70,6 +76,7 @@ namespace Vanara.PInvoke
|
|||
/// the THREADENTRY32 structure when enumerating the threads.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[CorrespondingType(typeof(THREADENTRY32))]
|
||||
TH32CS_SNAPTHREAD = 0x00000004,
|
||||
|
||||
/// <summary>
|
||||
|
@ -77,7 +84,7 @@ namespace Vanara.PInvoke
|
|||
/// Equivalent to specifying the TH32CS_SNAPHEAPLIST, TH32CS_SNAPMODULE, TH32CS_SNAPPROCESS, and TH32CS_SNAPTHREAD values
|
||||
/// combined using an OR operation ('|').
|
||||
/// </summary>
|
||||
TH32CS_SNAPALL = (TH32CS_SNAPHEAPLIST | TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD | TH32CS_SNAPMODULE),
|
||||
TH32CS_SNAPALL = TH32CS_SNAPHEAPLIST | TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD | TH32CS_SNAPMODULE,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -193,7 +200,7 @@ namespace Vanara.PInvoke
|
|||
// CreateToolhelp32Snapshot( DWORD dwFlags, DWORD th32ProcessID );
|
||||
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
|
||||
[PInvokeData("tlhelp32.h", MSDNShortId = "df643c25-7558-424c-b187-b3f86ba51358")]
|
||||
public static extern SafeHSNAPSHOT CreateToolhelp32Snapshot(TH32CS dwFlags, uint th32ProcessID);
|
||||
public static extern SafeHSNAPSHOT CreateToolhelp32Snapshot(TH32CS dwFlags, [Optional] uint th32ProcessID);
|
||||
|
||||
/// <summary>
|
||||
/// <para>Retrieves information about the first block of a heap that has been allocated by a process.</para>
|
||||
|
@ -348,7 +355,7 @@ namespace Vanara.PInvoke
|
|||
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
|
||||
[PInvokeData("tlhelp32.h", MSDNShortId = "bb41cab9-13a1-469d-bf76-68c172e982f6")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool Module32First(HSNAPSHOT hSnapshot, out MODULEENTRY32 lpme);
|
||||
public static extern bool Module32First(HSNAPSHOT hSnapshot, ref MODULEENTRY32 lpme);
|
||||
|
||||
/// <summary>
|
||||
/// <para>Retrieves information about the next module associated with a process or thread.</para>
|
||||
|
@ -375,7 +382,7 @@ namespace Vanara.PInvoke
|
|||
[DllImport(Lib.Kernel32, SetLastError = true, CharSet = CharSet.Auto)]
|
||||
[PInvokeData("tlhelp32.h", MSDNShortId = "88ec1af4-bae7-4cd7-b830-97a98fb337f4")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool Module32Next(HSNAPSHOT hSnapshot, out MODULEENTRY32 lpme);
|
||||
public static extern bool Module32Next(HSNAPSHOT hSnapshot, ref MODULEENTRY32 lpme);
|
||||
|
||||
/// <summary>
|
||||
/// <para>Retrieves information about the first process encountered in a system snapshot.</para>
|
||||
|
@ -609,6 +616,9 @@ namespace Vanara.PInvoke
|
|||
/// <para>The heap identifier. This is not a handle, and has meaning only to the tool help functions.</para>
|
||||
/// </summary>
|
||||
public UIntPtr th32HeapID;
|
||||
|
||||
/// <summary>Gets an empty instance with the size value set.</summary>
|
||||
public static readonly HEAPENTRY32 Default = new HEAPENTRY32 { dwSize = (uint)Marshal.SizeOf(typeof(HEAPENTRY32)) };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -652,6 +662,22 @@ namespace Vanara.PInvoke
|
|||
/// </list>
|
||||
/// </summary>
|
||||
public HEAPLIST32_FLAGS dwFlags;
|
||||
|
||||
/// <summary>Gets an empty instance with the size value set.</summary>
|
||||
public static readonly HEAPLIST32 Default = new HEAPLIST32 { dwSize = (uint)Marshal.SizeOf(typeof(HEAPLIST32)) };
|
||||
|
||||
/// <summary>Retrieves information about the blocks of a heap that have been allocated by a process.</summary>
|
||||
/// <returns>A enumeration of <see cref="HEAPENTRY32"/> structures.</returns>
|
||||
public IEnumerable<HEAPENTRY32> EnumHeapEntries()
|
||||
{
|
||||
var pe = HEAPENTRY32.Default;
|
||||
if (!Heap32First(ref pe, th32ProcessID, th32HeapID))
|
||||
throw Win32Error.GetLastError().GetException();
|
||||
do { yield return pe; } while (Heap32Next(ref pe));
|
||||
var err = Win32Error.GetLastError();
|
||||
if (err != Win32Error.ERROR_NO_MORE_FILES)
|
||||
throw err.GetException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Provides a handle to a snapshot.</summary>
|
||||
|
@ -773,6 +799,9 @@ namespace Vanara.PInvoke
|
|||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
|
||||
public string szExePath;
|
||||
|
||||
/// <summary>Gets an empty instance with the size value set.</summary>
|
||||
public static readonly MODULEENTRY32 Default = new MODULEENTRY32 { dwSize = (uint)Marshal.SizeOf(typeof(MODULEENTRY32)) };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -843,6 +872,9 @@ namespace Vanara.PInvoke
|
|||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
|
||||
public string szExeFile;
|
||||
|
||||
/// <summary>Gets an empty instance with the size value set.</summary>
|
||||
public static readonly PROCESSENTRY32 Default = new PROCESSENTRY32 { dwSize = (uint)Marshal.SizeOf(typeof(PROCESSENTRY32)) };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -894,6 +926,9 @@ namespace Vanara.PInvoke
|
|||
/// <para>This member is no longer used and is always set to zero.</para>
|
||||
/// </summary>
|
||||
public uint dwFlags;
|
||||
|
||||
/// <summary>Gets an empty instance with the size value set.</summary>
|
||||
public static readonly THREADENTRY32 Default = new THREADENTRY32 { dwSize = (uint)Marshal.SizeOf(typeof(THREADENTRY32)) };
|
||||
}
|
||||
|
||||
/// <summary>Provides a <see cref="SafeHandle"/> to a snapshot that releases a created HSNAPSHOT instance at disposal using CloseHandle.</summary>
|
||||
|
@ -906,12 +941,43 @@ namespace Vanara.PInvoke
|
|||
/// </param>
|
||||
public SafeHSNAPSHOT(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
|
||||
|
||||
private SafeHSNAPSHOT() : base() { }
|
||||
private SafeHSNAPSHOT() : base()
|
||||
{
|
||||
}
|
||||
|
||||
private delegate bool FirstNext<TStruct>(HSNAPSHOT h, ref TStruct str) where TStruct : struct;
|
||||
|
||||
/// <summary>Performs an implicit conversion from <see cref="SafeHSNAPSHOT"/> to <see cref="HSNAPSHOT"/>.</summary>
|
||||
/// <param name="h">The safe handle instance.</param>
|
||||
/// <returns>The result of the conversion.</returns>
|
||||
public static implicit operator HSNAPSHOT(SafeHSNAPSHOT h) => h.handle;
|
||||
|
||||
/// <summary>Retrieves information about the heaps that have been allocated by a specified process.</summary>
|
||||
/// <returns>A enumeration of <see cref="HEAPLIST32"/> structures.</returns>
|
||||
public IEnumerable<HEAPLIST32> EnumHeap32List() => EnumSnap<HEAPLIST32>(Heap32ListFirst, Heap32ListNext);
|
||||
|
||||
/// <summary>Retrieves information about the modules that are associated with a process.</summary>
|
||||
/// <returns>A enumeration of <see cref="MODULEENTRY32"/> structures.</returns>
|
||||
public IEnumerable<MODULEENTRY32> EnumModule32() => EnumSnap<MODULEENTRY32>(Module32First, Module32Next);
|
||||
|
||||
/// <summary>Retrieves information about the processes encountered in a system snapshot.</summary>
|
||||
/// <returns>A enumeration of <see cref="PROCESSENTRY32"/> structures.</returns>
|
||||
public IEnumerable<PROCESSENTRY32> EnumProcess32() => EnumSnap<PROCESSENTRY32>(Process32First, Process32Next);
|
||||
|
||||
/// <summary>Retrieves information about the threads of any process encountered in a system snapshot.</summary>
|
||||
/// <returns>A enumeration of <see cref="THREADENTRY32"/> structures.</returns>
|
||||
public IEnumerable<THREADENTRY32> EnumThread32() => EnumSnap<THREADENTRY32>(Thread32First, Thread32Next);
|
||||
|
||||
private IEnumerable<TStruct> EnumSnap<TStruct>(FirstNext<TStruct> first, FirstNext<TStruct> next) where TStruct : struct
|
||||
{
|
||||
var pe = Vanara.Extensions.ReflectionExtensions.GetStaticFieldValue<TStruct>("Default");
|
||||
if (!first(handle, ref pe))
|
||||
throw Win32Error.GetLastError().GetException();
|
||||
do { yield return pe; } while (next(handle, ref pe));
|
||||
var err = Win32Error.GetLastError();
|
||||
if (err != Win32Error.ERROR_NO_MORE_FILES)
|
||||
throw err.GetException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using NUnit.Framework;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Linq;
|
||||
using Vanara.Extensions;
|
||||
using static Vanara.PInvoke.Kernel32;
|
||||
|
||||
namespace Vanara.PInvoke.Tests
|
||||
|
@ -7,36 +8,52 @@ namespace Vanara.PInvoke.Tests
|
|||
[TestFixture]
|
||||
public class TLHelp32Tests
|
||||
{
|
||||
private static readonly SafeHSNAPSHOT hsnap = CreateToolhelp32Snapshot(TH32CS.TH32CS_SNAPALL | TH32CS.TH32CS_SNAPMODULE32);
|
||||
|
||||
[Test]
|
||||
public void TestMethod()
|
||||
public void Heap32ListFirstTest()
|
||||
{
|
||||
using (var hsnap = CreateToolhelp32Snapshot(TH32CS.TH32CS_SNAPPROCESS, 0))
|
||||
Assert.That(() =>
|
||||
{
|
||||
if (hsnap.IsInvalid) Assert.Fail(Win32Error.GetLastError().ToString());
|
||||
var pe = new PROCESSENTRY32 { dwSize = (uint)Marshal.SizeOf(typeof(PROCESSENTRY32)) };
|
||||
if (!Process32First(hsnap, ref pe)) Assert.Fail(Win32Error.GetLastError().ToString());
|
||||
do
|
||||
{
|
||||
TestContext.WriteLine("=======================================");
|
||||
TestContext.WriteLine($"PROCESS NAME: {pe.szExeFile}");
|
||||
TestContext.WriteLine("---------------------------------------");
|
||||
var heaplists = hsnap.EnumHeap32List().ToArray();
|
||||
Assert.That(heaplists, Is.Not.Empty);
|
||||
foreach (var h in heaplists)
|
||||
Assert.That(h.EnumHeapEntries().ToArray(), Is.Not.Empty);
|
||||
}, Throws.Nothing);
|
||||
}
|
||||
|
||||
CREATE_PROCESS pClass = 0;
|
||||
using (var hproc = OpenProcess((uint)ProcessAccess.PROCESS_ALL_ACCESS, false, pe.th32ProcessID))
|
||||
{
|
||||
if (!hproc.IsInvalid)
|
||||
pClass = GetPriorityClass(hproc);
|
||||
}
|
||||
[Test]
|
||||
public void Module32FirstTest()
|
||||
{
|
||||
Assert.That(() =>
|
||||
{
|
||||
Assert.That(hsnap.EnumModule32().ToArray(), Is.Not.Empty);
|
||||
}, Throws.Nothing);
|
||||
}
|
||||
|
||||
TestContext.WriteLine($"Process ID: {pe.th32ProcessID}");
|
||||
TestContext.WriteLine($"Thread count: {pe.cntThreads}");
|
||||
TestContext.WriteLine($"Parent process ID: {pe.th32ParentProcessID}");
|
||||
TestContext.WriteLine($"Priority base: {pe.pcPriClassBase}");
|
||||
TestContext.WriteLine($"Priority class: {pClass}");
|
||||
TestContext.WriteLine();
|
||||
[Test]
|
||||
public void Process32FirstTest()
|
||||
{
|
||||
Assert.That(() =>
|
||||
{
|
||||
Assert.That(hsnap.EnumProcess32().ToArray(), Is.Not.Empty);
|
||||
}, Throws.Nothing);
|
||||
}
|
||||
|
||||
} while (Process32Next(hsnap, ref pe));
|
||||
}
|
||||
[Test]
|
||||
public void Thread32FirstTest()
|
||||
{
|
||||
Assert.That(() =>
|
||||
{
|
||||
Assert.That(hsnap.EnumThread32().ToArray(), Is.Not.Empty);
|
||||
}, Throws.Nothing);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Toolhelp32ReadProcessMemoryTest()
|
||||
{
|
||||
throw new System.NotImplementedException("No documentation on how.");
|
||||
//Assert.That(Toolhelp32ReadProcessMemory(), Is.True);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue