rt
发现前面一些句柄的文本能正常获取,到了某个句柄那里,程序自动退出    
class Program
    {
        public delegate bool CallBack(int hwnd, int lParam);
        [DllImport("user32")]
        public static extern int EnumWindows(CallBack x, int y);
        [DllImport("user32")]
        public extern static int GetWindowText(int hWnd, StringBuilder lpString, int nMaxCount);
        static void Main(string[] args)
        {
            CallBack myCallBack = new CallBack(Report);
            EnumWindows(myCallBack, 0);
            Console.ReadKey();
        }        public static bool Report(int hwnd, int lParam)
        {
            string name = "";
            StringBuilder windowname = new StringBuilder();
            if (GetWindowText(hwnd, windowname, 5000) > 0)
            {
                name = windowname.ToString();
            }
            Console.Write("Window handle is :"+hwnd+"名字为"+name+"\n");
            return true;        }
    }
上面是控制台应用程序
是写的有问题还是Windows有句柄不让获取name的,把GetWindowText(hwnd, windowname, 5000)去掉,可以正常获取所有句柄。但获取name就有问题了

解决方案 »

  1.   

    你在调用GetWindowText时指出了接收缓冲区的容量为5000,那你就要分配5000长度的缓冲区:
    StringBuilder windowname = new StringBuilder(5000);
      

  2.   

    如果把 if (GetWindowText(hwnd, windowname, 5000) > 0)里的5000改成50 也可以运行。请问是不是StringBuilder()有个默认长度的缓冲区 
      

  3.   

    StringBuilder不是固定长度的,它有个属性Capacity,是“可包含在当前实例所分配的内存中的最大字符数”,默认容量是 16,当字符数超过这个数时,.Net会以当前容量的2倍增加,即增加为32.
    所以,问题可能处在你那5000是否设得过大了。或者像4楼那样,初始化的时候指定Capacity为5000,虽然有点浪费。
      

  4.   

    看看我的猜想对否,当新建立一个stringbuilder时,是在.net的clr上建立的,所以在.net下,不管赋值有多长,.net都会帮你自动扩充内存。但是当直接调用GetWindowText(hwnd, windowname, 5000)时,不在clr上,所以GetwindowText会越过clr直接访问内存,而初始内存只有4个字节,并且跳过了clr,内存不会自动扩充了。所以有些text超过4个字节的窗口就没有办法赋值给stringbuilder。 新手,瞎猜的。错误的地方还请指教
      

  5.   

    对的。
    准确一点说,建立一个stringbuilder时,是在.net的托管内存上建立的,stringbuilder会自动扩充它内部缓冲区的长度。
    直接调用GetWindowText时,.net会把它复制(marshal)到非托管内存,且不会自动扩充。