PowerShell调用C#封装的PrintWindow报错:ScreenCapture无该方法
错误原因分析
你遇到的报错核心原因是方法调用方式不匹配:
- 你在C#代码中把
PrintWindow(IntPtr hwnd)定义为静态方法(带static关键字),但在PowerShell中却创建了ScreenCapture类的实例$ScreenCapture,试图通过实例对象调用静态方法——这不符合C#的方法调用规则,因此PowerShell提示找不到该方法。
修正方案与代码优化
以下两种方案任选其一即可解决问题,同时附带代码优化说明:
方案1:将静态方法改为实例方法
修改C#代码中的方法定义,去掉static关键字,让方法成为实例可调用的成员:
using System; using System.Runtime.InteropServices; using System.Drawing; using System.Drawing.Imaging; public class ScreenCapture { [DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); [DllImport("user32.dll")] public static extern bool PrintWindow(IntPtr hWnd, IntPtr hdcBlt, int nFlags); // 去掉static关键字,改为实例方法 public Bitmap PrintWindow(IntPtr hwnd) { RECT rc; GetWindowRect(hwnd, out rc); Bitmap bmp = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb); Graphics gfxBmp = Graphics.FromImage(bmp); IntPtr hdcBitmap = gfxBmp.GetHdc(); PrintWindow(hwnd, hdcBitmap, 0); gfxBmp.ReleaseHdc(hdcBitmap); gfxBmp.Dispose(); // 优化路径:逐字字符串(@前缀)无需双反斜杠转义 bmp.Save(@"C:\TestScreenshot.png", ImageFormat.Png); return bmp; } // 以下RECT结构体代码保持不变 [StructLayout(LayoutKind.Sequential)] public struct RECT { private int _Left; private int _Top; private int _Right; private int _Bottom; public RECT(RECT Rectangle) : this(Rectangle.Left, Rectangle.Top, Rectangle.Right, Rectangle.Bottom) { } public RECT(int Left, int Top, int Right, int Bottom) { _Left = Left; _Top = Top; _Right = Right; _Bottom = Bottom; } public int X { get { return _Left; } set { _Left = value; } } public int Y { get { return _Top; } set { _Top = value; } } public int Left { get { return _Left; } set { _Left = value; } } public int Top { get { return _Top; } set { _Top = value; } } public int Right { get { return _Right; } set { _Right = value; } } public int Bottom { get { return _Bottom; } set { _Bottom = value; } } public int Height { get { return _Bottom - _Top; } set { _Bottom = value + _Top; } } public int Width { get { return _Right - _Left; } set { _Right = value + _Left; } } public Point Location { get { return new Point(Left, Top); } set { _Left = value.X; _Top = value.Y; } } public Size Size { get { return new Size(Width, Height); } set { _Right = value.Width + _Left; _Bottom = value.Height + _Top; } } public static implicit operator Rectangle(RECT Rectangle) { return new Rectangle(Rectangle.Left, Rectangle.Top, Rectangle.Width, Rectangle.Height); } public static implicit operator RECT(Rectangle Rectangle) { return new RECT(Rectangle.Left, Rectangle.Top, Rectangle.Right, Rectangle.Bottom); } public static bool operator ==(RECT Rectangle1, RECT Rectangle2) { return Rectangle1.Equals(Rectangle2); } public static bool operator !=(RECT Rectangle1, RECT Rectangle2) { return !Rectangle1.Equals(Rectangle2); } public override string ToString() { return "{Left: " + _Left + "; " + "Top: " + _Top + "; Right: " + _Right + "; Bottom: " + _Bottom + "}"; } public override int GetHashCode() { return ToString().GetHashCode(); } public bool Equals(RECT Rectangle) { return Rectangle.Left == _Left && Rectangle.Top == _Top && Rectangle.Right == _Right && Rectangle.Bottom == _Bottom; } public override bool Equals(object Object) { if (Object is RECT) { return Equals((RECT)Object); } else if (Object is Rectangle) { return Equals(new RECT((Rectangle)Object)); } return false; } } }
对应的PowerShell调用代码无需修改,原有的实例调用逻辑可以正常运行:
Add-type $code -ReferencedAssemblies 'System.Drawing' # 移除未用到的System.Windows.Forms引用 $ScreenCapture = New-Object ScreenCapture $Handle = (Get-Process -Name Notepad).MainWindowHandle $ScreenCapture.PrintWindow($Handle)
方案2:直接调用静态方法(不修改C#代码)
保持原有C#代码不变,在PowerShell中通过类名::静态方法的形式直接调用,无需创建类实例:
Add-type $code -ReferencedAssemblies 'System.Drawing' $Handle = (Get-Process -Name Notepad).MainWindowHandle [ScreenCapture]::PrintWindow($Handle) # 用类名直接调用静态方法,跳过实例创建步骤
额外优化说明
- 路径简化:C#中使用
@前缀的逐字字符串时,路径无需双反斜杠转义,@"C:\TestScreenshot.png"即可正常识别。 - 引用精简:代码未用到
System.Windows.Forms程序集的内容,Add-Type时可移除该引用,仅保留System.Drawing即可。
内容的提问来源于stack exchange,提问作者AnonPowershellGuy1
相关产品推荐
相关产品推荐

