Как заставить F12 взломать отладчик на Vista x64 с VS 2008? - PullRequest
5 голосов
/ 03 января 2009

F12 - это чудо для отслеживания операций блокировки пользовательского интерфейса, но я не могу понять, как заставить его работать с VS 2008 и управляемым кодом.

Помощь! Или нет ...

Редактировать: выясняется, что он не работает в VS 2005 на Vista x64, поэтому я предполагаю, что он расширяется или сужается в зависимости от вашей перспективы: (

MSN

Ответы [ 3 ]

1 голос
/ 15 января 2009

Это альтернативное решение, которое сохраняет удобство нажатия F12 в любое время, даже если приложение «кусается», без необходимости переключаться на Visual Studio и вызывать команду «Разбить все» согласно моему первому ответу.

К сожалению, это решение требует добавления дополнительного кода в приложение, которое мы хотим взломать с помощью F12. Этот специальный код отладки может быть условно скомпилирован с использованием, например, Символ отладки, так что функциональность F12 недоступна в сборках релиза.

Решение работает путем создания фонового потока; Затем поток регистрирует глобальный хук клавиатуры и запускает цикл сообщений без формы. Пример приложения ниже создает форму в главном потоке пользовательского интерфейса с помощью единственной кнопки «Спящий режим». При нажатии кнопки основной поток пользовательского интерфейса будет заблокирован в течение 10 секунд в режиме сна (Thread.Sleep) для имитации «кусания» приложения.

Чтобы проверить функциональность F12, сначала нажмите кнопку «Спящий режим», затем нажмите F12 - программа сразу же перейдет в отладчик, даже если основной поток пользовательского интерфейса заблокирован. На следующем снимке экрана показаны текущие потоки на моей машине (Vista x64) после F12:

Активные темы на F12 http://img242.imageshack.us/img242/5189/f12threadsre9.png

Как вы можете видеть, основная программа все еще находится в методе "GoToSleep", в то время как глобальный хук вызывается в фоновом потоке, который мы создали.

Глобальный хук-код основан на статье Стивена Туба .

Теперь реализация:

using System;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;

namespace KeyboardHook
{

    public sealed class SimpleKeyboardHook : IDisposable
    {
        public SimpleKeyboardHook(Action<Keys> handler)
        {
            if (null == handler) { throw new ArgumentNullException("handler"); }
            this._handler = handler;
            var t = new Thread(this.ListenerThread) { IsBackground = true, Name = "KeyboardListener" };
            t.Start();
        }

        public void Dispose()
        {
            if (!this._disposed)
            {
                UnhookWindowsHookEx(this._id);
                this._disposed = true;
                GC.SuppressFinalize(this);
            }
        }

        public static void BreakOnF12(Keys keys)
        {
            if (keys == Keys.F12)
            {
                Debugger.Break();
            }
        }

        private void ListenerThread()
        {
            using (var currentProcess = Process.GetCurrentProcess())
            using (var mainModule = currentProcess.MainModule)
            {
                if (null == mainModule) { throw new InvalidOperationException("Unable to determine main module for the current process"); }

                this._id = SetWindowsHookEx(
                    WH_KEYBOARD_LL,
                    this.HookCallback,
                    GetModuleHandle(mainModule.ModuleName), 0);
            }

            Application.Run();
        }

        private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
            {
                var vkCode = Marshal.ReadInt32(lParam);
                this._handler((Keys)vkCode);
            }
            return CallNextHookEx(this._id, nCode, wParam, lParam);
        }

        private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook,
            LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
            IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);

        private const int WH_KEYBOARD_LL = 13;
        private const int WM_KEYDOWN = 0x0100;
        private IntPtr _id;
        private readonly Action<Keys> _handler;
        private volatile bool _disposed;
    }


    static class Program
    {
        private static void GoToSleep(object sender, EventArgs args)
        {
            Thread.Sleep(10000);
        }

        [STAThread]
        static void Main()
        {
            using (new SimpleKeyboardHook(SimpleKeyboardHook.BreakOnF12))
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);

                var form = new Form { Text = "Sleepy form", Size = new Size(160,80), Padding = new Padding(6) };
                var btn = new Button { Dock = DockStyle.Fill, Text = "Sleep", Location = new Point(10, 10) };
                btn.Click += GoToSleep;
                form.Controls.Add(btn);
                Application.Run(form);
            }
        }
    }
}
0 голосов
/ 26 мая 2013

Я почти уверен, что для этого нужно установить и запустить отладчик режима ядра. Я установил различные версии Visual Studio на множество разных компьютеров, и у меня никогда не было клавиши F12 , которая могла бы сделать что-то особенное. Я не думаю, что это имеет какое-либо отношение к самой VS, вы просто связываете это, потому что у вас также установлен VS на машине.

Я рекомендую загрузить и установить пакет «Средства отладки для Windows», входящий в комплект Windows Software Development Kit (SDK) . (Или, если вы разработчик драйверов, вы можете загрузить Windows Driver Kit (WDK), который также включает эти инструменты.) Убедитесь, что во время установки вы выбрали поле «Средства отладки». Если это единственные инструменты, которые вы хотите установить, вы можете установить этот флажок и снять все остальные; они не являются обязательными компонентами.

Это гарантирует, что на вашем компьютере установлены Kernel Debugger (KD) и вариант NTKD, а также графический интерфейс WinDbg. Все эти инструменты доступны как для процессоров x86, так и для x64.

Подробнее см. Здесь: Отладка Windows .

0 голосов
/ 14 января 2009

Хотя я не знал о функциональности F12 в Windows XP x86, в следующих инструкциях описывается, как я вхожу в уже работающие программы (этот метод работает в операционных системах Windows как x86, так и x64).

Во-первых, запустить Visual Studio (2008, 2005, 2003 ... на самом деле не имеет значения, поскольку все они поддерживают присоединение к запущенным процессам; они наследуют эту функциональность от окончательного отладчика WinDbg, доступного на Средства отладки для Windows )

В меню «Сервис» выберите команду «Присоединить к процессам ...»:

Присоединить к меню процесса http://img297.imageshack.us/img297/2369/attachmenuhe7.png

Я считаю эту функцию настолько полезной, что я даже добавил эту команду на главную панель инструментов Visual Studio:

Присоединить к процессу на панели инструментов http://img440.imageshack.us/img440/1232/vstoolbarmainaw4.png

Откроется диалоговое окно «Присоединить к процессу». В нем будут перечислены все запущенные в данный момент процессы (если вашего процесса нет в списке, попробуйте включить галочки «Показывать процессы от всех пользователей» или «Показывать процессы во всех сеансах» в нижней части диалогового окна). Просто выберите процесс, в который вы хотите перейти, и нажмите кнопку «Присоединить»:

Присоединить к диалоговому окну процесса http://img231.imageshack.us/img231/8415/vsdialogattachoq5.png

Примечание: отладчик может работать в разных режимах, отлаживая собственный код, управляемый код, сценарии (в Internet Explorer) или даже рабочий процесс T-SQL и WF. Независимо от вашего выбора, диалог «прикрепить к процессу» запомнит их при следующем открытии.

После успешного подключения Visual Studio к процессу, в который вы пытаетесь проникнуть, используйте команду Debug -> Break All, чтобы остановить все потоки в этом процессе:

Разбить все меню http://img297.imageshack.us/img297/8579/vsmenubreakallrb1.png

Эта команда также доступна на панели инструментов отладки:

Разбить все на панели инструментов http://img440.imageshack.us/img440/248/vstoolbardebugwt4.png

После разрыва вы можете исследовать все запущенные в настоящий момент потоки, их стеки, память, локальные и глобальные переменные и т. Д. Это должно позволить вам устранять неполадки в длительных операциях даже в операционных системах x64, где использовались функции F12, которые вы использовали недоступен.

...