過去の投稿のコードをC# 12 (.NET 8)版に書き換えたものです。nint
やオブジェクト初期化子により少し簡潔になります。
非unsafe
版
using System.ComponentModel; using System.Runtime.InteropServices; [assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32)] // リソースファイルからProgressRingのPNGデータを読み込む。 using var imageResDllMunHandle = SafeLibraryHandle.Load( @"SystemResources\imageres.dll.mun"); var pngData = Utility.LoadResource(imageResDllMunHandle, 5021, "PNG"); // ProgressRingのPNGデータから画像を作成する。 using var pngImage = Utility.CreateImageFromByteArray(pngData); // ProgressRingの画像をフォームへ表示する。 var mainForm = new Form(); mainForm.Controls.Add(new PictureBox() { Image = pngImage, AutoSize = true }); Application.Run(mainForm); static class Utility { /// <summary> /// バイト配列から<c>Image</c>インスタンスを返します。 /// </summary> public static Image CreateImageFromByteArray(byte[] data) { using var stream = new MemoryStream(data, false); return Image.FromStream(stream); } /// <summary> /// モジュールのリソースデータを読み込みます。 /// </summary> /// <remarks> /// モジュールが解放されても使用できるように関数はバイト配列を返します。 /// </remarks> public static byte[] LoadResource(SafeHandle handle, ushort id, string type) { return LoadResource(handle, $"#{id}", type); } /// <summary> /// モジュールのリソースデータを読み込みます。 /// </summary> /// <remarks> /// モジュールが解放されても使用できるように関数はバイト配列を返します。 /// </remarks> public static byte[] LoadResource(SafeHandle handle, string name, string type) { var resInfoHandle = NativeMethods.FindResourceW(handle, name, type); if (resInfoHandle == 0) throw new Win32Exception(); var resDataHandle = NativeMethods.LoadResource(handle, resInfoHandle); if (resDataHandle == 0) throw new Win32Exception(); var resSize = NativeMethods.SizeofResource(handle, resInfoHandle); if (resSize == 0) throw new Win32Exception(); var resPointer = NativeMethods.LockResource(resDataHandle); if (resPointer == 0) throw new Win32Exception(); var buffer = GC.AllocateUninitializedArray<byte>(checked((int)resSize)); Marshal.Copy(resPointer, buffer, 0, buffer.Length); return buffer; } private static class NativeMethods { [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)] public static extern nint FindResourceW(SafeHandle hModule, string lpName, string lpType); [DllImport("kernel32.dll", SetLastError = true)] public static extern nint LoadResource(SafeHandle hModule, nint hResInfo); [DllImport("kernel32.dll", SetLastError = true)] public static extern nint LockResource(nint hResData); [DllImport("kernel32.dll", SetLastError = true)] public static extern uint SizeofResource(SafeHandle hModule, nint hResInfo); } } /// <summary> /// ライブラリハンドルを安全に管理します。 /// </summary> sealed class SafeLibraryHandle : SafeHandle { public SafeLibraryHandle() : base(default, false) { } public SafeLibraryHandle(nint handle, bool ownsHandle) : base(handle, ownsHandle) { } protected override bool ReleaseHandle() { NativeLibrary.Free(handle); return true; } public override bool IsInvalid => handle == default; public static SafeLibraryHandle Load(string? path) { ArgumentNullException.ThrowIfNull(path); nint handle = 0; try { handle = NativeLibrary.Load(path); return new SafeLibraryHandle(handle, true); } catch { NativeLibrary.Free(handle); throw; } } }
unsafe
版
using System.ComponentModel; using System.Runtime.InteropServices; [assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32)] // リソースファイルからProgressRingのPNGイメージを読み込む。 using var imageResDllMunHandle = SafeLibraryHandle.Load( @"SystemResources\imageres.dll.mun"); using var pngImage = Utility.LoadResourceAsImage(imageResDllMunHandle, 5021, "PNG"); // ProgressRingの画像をフォームへ表示する。 var mainForm = new Form(); mainForm.Controls.Add(new PictureBox() { Image = pngImage, AutoSize = true }); Application.Run(mainForm); static class Utility { /// <summary> /// バイト配列から<c>Image</c>インスタンスを返します。 /// </summary> public static Image CreateImageFromByteArray(byte[] data) { using var stream = new MemoryStream(data, false); return Image.FromStream(stream); } /// <summary> /// モジュールのリソースデータを読み込みます。 /// </summary> public static Image LoadResourceAsImage(SafeHandle handle, ushort id, string type) { return LoadResourceAsImage(handle, $"#{id}", type); } /// <summary> /// モジュールのリソースデータを<c>Image</c>として読み込みます。 /// </summary> public static Image LoadResourceAsImage(SafeHandle handle, string name, string type) { var resInfoHandle = NativeMethods.FindResourceW(handle, name, type); if (resInfoHandle == 0) throw new Win32Exception(); var resDataHandle = NativeMethods.LoadResource(handle, resInfoHandle); if (resDataHandle == 0) throw new Win32Exception(); var resSize = NativeMethods.SizeofResource(handle, resInfoHandle); if (resSize == 0) throw new Win32Exception(); var resPointer = NativeMethods.LockResource(resDataHandle); if (resPointer == 0) throw new Win32Exception(); unsafe { using var stream = new UnmanagedMemoryStream((byte*)resPointer, resSize); return Image.FromStream(stream); } } private static class NativeMethods { [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)] public static extern nint FindResourceW(SafeHandle hModule, string lpName, string lpType); [DllImport("kernel32.dll", SetLastError = true)] public static extern nint LoadResource(SafeHandle hModule, nint hResInfo); [DllImport("kernel32.dll", SetLastError = true)] public static extern nint LockResource(nint hResData); [DllImport("kernel32.dll", SetLastError = true)] public static extern uint SizeofResource(SafeHandle hModule, nint hResInfo); } } /// <summary> /// ライブラリハンドルを安全に管理します。 /// </summary> sealed class SafeLibraryHandle : SafeHandle { public SafeLibraryHandle() : base(default, false) { } public SafeLibraryHandle(nint handle, bool ownsHandle) : base(handle, ownsHandle) { } protected override bool ReleaseHandle() { NativeLibrary.Free(handle); return true; } public override bool IsInvalid => handle == default; public static SafeLibraryHandle Load(string? path) { ArgumentNullException.ThrowIfNull(path); nint handle = 0; try { handle = NativeLibrary.Load(path); return new SafeLibraryHandle(handle, true); } catch { NativeLibrary.Free(handle); throw; } } }