You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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) # 用类名直接调用静态方法,跳过实例创建步骤
额外优化说明
  1. 路径简化:C#中使用@前缀的逐字字符串时,路径无需双反斜杠转义,@"C:\TestScreenshot.png"即可正常识别。
  2. 引用精简:代码未用到System.Windows.Forms程序集的内容,Add-Type时可移除该引用,仅保留System.Drawing即可。

内容的提问来源于stack exchange,提问作者AnonPowershellGuy1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 21:47:47