我正在使用Powershell构建一个小实用程序,并且花了很多时间自学如何使用Powershell构建Windows窗体和控件。 为了使我的部署占用空间较小,我使用第三方实用程序(绿鱼图标编辑器专业版,我强烈推荐(将所有图形图标(.ico(和图像(.bmp(打包到动态链接库(*.dll(中。我现在遇到的问题是我无法加载程序集,因为生成的 *.dll 缺少清单。我已经搜索了所有内容,但找不到有关如何在不使用添加类型 cmdlet 加载 *.dll的情况下访问资源的任何简洁答案。
我能够在 Kazun 对这篇文章的回答中找到一种从 dll 加载图标的方法。 然后利用 technet,我能够在 dll 中找到提取位图的方法的相应入口点。 请参阅下面的脚本,该脚本结合了IconExtractor和我新创建的BitmapExtractor类。
$code = @"
using System;
using System.Drawing;
using System.Runtime.InteropServices;
namespace System {
public class IconExtractor { #Credit to Kazun from https://social.technet.microsoft.com/Forums/windows/en-US/16444c7a-ad61-44a7-8c6f-b8d619381a27/using-icons-in-powershell-scripts?forum=winserverpowershell
public static Icon Extract(string file, int number, bool largeIcon) {
IntPtr large;
IntPtr small;
ExtractIconEx(file, number, out large, out small, 1);
try {
return Icon.FromHandle(largeIcon ? large : small);
} catch {
return null;
}
}
[DllImport("Shell32.dll", EntryPoint = "ExtractIconExW", CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern int ExtractIconEx(string sFile, int iIndex, out IntPtr piLargeVersion, out IntPtr piSmallVersion, int amountIcons);
}
public class BitmapExtractor { #Credit to Chad Estes (chadwestes@gmail.com)
public static Bitmap Extract(string file, string resourceID) {
IntPtr hModule = LoadLibraryEx(file,IntPtr.Zero,0x00000020);
Bitmap bmp = null;
IntPtr hBitmap = IntPtr.Zero;
try {
if (hModule != IntPtr.Zero) {
hBitmap = LoadBitmap(hModule, resourceID);
if (hBitmap != IntPtr.Zero) {
bmp = Bitmap.FromHbitmap(hBitmap);
}
}
} catch {
bmp = null;
} finally {
DeleteObject(hBitmap);
FreeLibrary(hModule);
}
return bmp;
}
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, uint dwFlags);
[DllImport("kernel32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool FreeLibrary(IntPtr hModule);
[DllImport("user32.dll")]
static extern IntPtr LoadBitmap(IntPtr hInstance, string lpBitmapName);
[DllImport("gdi32.dll", EntryPoint="DeleteObject", CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern bool DeleteObject(IntPtr hBitmap);
}
}
"@
Add-Type -TypeDefinition $code -ReferencedAssemblies System.Drawing
$myImage = [System.BitmapExtractor]::Extract("C:SomePathSome.dll", "LOGO")
$myIcon = [System.IconExtractor]::Extract("C:SomePathSome.dll", 1, $true)