2012-01-13 4 views
2

Я записал этот макрос, который прикрепляет к процессу (nunit.exe) для меня. Теперь я хочу нажать кнопку («Run») в окне процесса, к которому я прикрепляюсь, но как? Я записал этот макрос:Как нажимать кнопку на другом процессе (nunit.exe)

Sub DebugNUnit() 
DTE.ExecuteCommand("Tools.ExternalCommand6") 
'need a short delay for nunit process to appear in process list: 
Threading.Thread.Sleep(200) 

Try 

    Dim dbg2 As EnvDTE80.Debugger2 = DTE.Debugger 

    Dim trans As EnvDTE80.Transport = dbg2.Transports.Item("Default") 

    Dim dbgeng(1) As EnvDTE80.Engine 

    dbgeng(0) = trans.Engines.Item("Managed (v4.0)") 

    Dim proc2 As EnvDTE80.Process2 = dbg2.GetProcesses(trans, "myPC").Item("nunit.exe") 

    proc2.Attach2(dbgeng) 

Catch ex As System.Exception 

    MsgBox(ex.Message) 

End Try 
End Sub 

UPDATE: Я скорректировали сценарий на основе этого ответа, как этот

Sub DebugNUnit() 
    DTE.ExecuteCommand("Tools.ExternalCommand6") 
    'need a short delay for nunit process to appear in process list: 
    Threading.Thread.Sleep(200) 

    Try 

     Dim dbg2 As EnvDTE80.Debugger2 = DTE.Debugger 

     Dim trans As EnvDTE80.Transport = dbg2.Transports.Item("Default") 

     Dim dbgeng(1) As EnvDTE80.Engine 

     dbgeng(0) = trans.Engines.Item("Managed (v4.0)") 

     Dim proc2 As EnvDTE80.Process2 = dbg2.GetProcesses(trans, "myPC").Item("nunit.exe") 

     proc2.Attach2(dbgeng) 

     'added this because we may need a short delay for nunit gui to load 
     '(would prefer to replace it with a wait on some loaded event or something) 
     Threading.Thread.Sleep(5000) 

     'use Process.Handle or Process.MainWindowHandle? anyway, both do not seem to work.. are the parameters incorrect? 
     Dim ButtonHandle As IntPtr = FindWindowEx(System.Diagnostics.Process.GetProcessById(proc2.ProcessID).Handle, 0, "Button", "Run") 
     'Dim ButtonHandle As IntPtr = FindWindowEx(System.Diagnostics.Process.GetProcessById(proc2.ProcessID).MainWindowHandle, 0, "Button", "Run") 

     SendMessage(ButtonHandle, &HF5, 0, 0) 

    Catch ex As System.Exception 

     MsgBox(ex.Message) 

    End Try 

End Sub 

но кнопка «Run» на пользовательском NUnit интерфейс, который был запущен (по Tools.ExternalCommand6) все еще не нажата. это имеет смысл, потому что ручка кнопки всегда 0 ... почему? есть ли кто-нибудь там с решением?

UPDATE: Я скорректировали сценарий, основанный на отредактированный ответ, как этот

Option Strict Off 
Option Explicit Off 
Imports System 
Imports EnvDTE 
Imports EnvDTE80 
Imports EnvDTE90 
Imports EnvDTE90a 
Imports EnvDTE100 
Imports System.Diagnostics 
Imports System.Runtime.InteropServices 
Imports System.Windows.Forms 

Public Module RecordingModule 

<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _ 
    Private Function PostMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Boolean 
End Function 

Sub DebugNUnit() 
    DTE.ExecuteCommand("Tools.ExternalCommand6") 
    'need a short delay for nunit processes to appear in process list: 
    Threading.Thread.Sleep(1000) 

    Try 

     Dim dbg2 As EnvDTE80.Debugger2 = DTE.Debugger 
     Dim trans As EnvDTE80.Transport = dbg2.Transports.Item("Default") 
     Dim dbgeng(1) As EnvDTE80.Engine 
     dbgeng(0) = trans.Engines.Item("Managed (v4.0)") 
     Dim proc2nunitagent As EnvDTE80.Process2 = dbg2.GetProcesses(trans, Environment.MachineName).Item("nunit-agent.exe") 
     Dim proc2nunit As EnvDTE80.Process2 = dbg2.GetProcesses(trans, Environment.MachineName).Item("nunit.exe") 
     proc2nunitagent.Attach2(dbgeng) 

     PostMessage(System.Diagnostics.Process.GetProcessById(proc2nunit.ProcessID).MainWindowHandle, &H100, Keys.Alt Or Keys.R, IntPtr.Zero) 

    Catch ex As System.Exception 

     MsgBox(ex.Message + Environment.NewLine + ex.StackTrace) 

    End Try 

End Sub 
End Module 

Я использую NUnit 2.5.7 и для прикрепления и отладки для работы вам необходимо приложить к NUnit агента и нажмите run на nunit gui, для более свежих версий nunit, которые вы можете подключить к nunit gui.

приведенный выше сценарий позволяет отлаживать nunit из среды Visual Studio с помощью только визуальных Studio и двоичных файлов nunit. все, что вам нужно сделать, это установить nunit в качестве внешнего инструмента (с текущим проектом в качестве параметра), создать пользовательскую панель инструментов и добавить кнопку на эту панель инструментов, которая использует вышеупомянутый скрипт. это начнет nunit, прикрепится к нему, начнет выполнение тестов и переломит вашу точку останова.

еще одна вещь: в nunit gui отключить «Сохранить визуальное состояние каждого проекта» в «Инструменты» -> «Настройки» -> «Дисплей дерева» или «nunit gui» запомнят последний тест запуска, что является болью, если это не тот вы хотели отлаживать.

Возможные улучшения: построить перед запуском nunit.

+0

Если вы просто хотите отладить свои модульные тесты, я предлагаю вам получить что-то вроде TestDriven.NET или ReSharper. Оба они позволяют легко отлаживать ваши тесты из Visual Studio. –

+0

Я знаком с этими инструментами, но они не являются бесплатными, а бесплатные инструменты, такие как VisualNUnit, недостаточно надежны. и, кроме того, я почти там .. все, что мне нужно сейчас, это ручка кнопки, и у меня есть собственная настраиваемая панель инструментов с кнопкой, которая запускает NUnit для текущего проекта, присоединяется к нему, запускает тесты и ломается на моей точке останова. – mtijn

+0

Visual NUnit - это открытый исходный код, в отличие от бесплатного; вы всегда можете это исправить ...? –

ответ

4

Попробуйте это:

<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> 
Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr 
End Function 
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> 
Private Shared Function FindWindowEx(ByVal parentHandle As IntPtr, ByVal childAfter As IntPtr, ByVal lclassName As String, ByVal windowTitle As String) As IntPtr 
End Function 

Dim ButtonHandle As IntPtr = FindWindowEx(YOURPROCESS.HANDLE, 0, "Button", "&Run") 
SendMessage(ButtonHandle, &HF5, 0, 0) 

EDIT: Похоже NUint это .NET приложение, которое означает, что вы не можете получить кнопку справиться легко. Вы можете это увидеть сами с помощью Spy ++.

Я заметил, что кнопка Run имеет клавиатуры ярлык ALT + R так что вместо этого вы можете использовать этот код:

<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> 
Private Shared Function PostMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Boolean 
End Function 
PostMessage(MAIN_WINDOW_HANDLE, &H100, Keys.Alt Or Keys.R, IntPtr.Zero) 

Я испытал это и она отлично работает.

+0

это потрясающе, спасибо! но теперь, как мне получить дескриптор процесса для nunit.exe? У меня уже есть объект EnvDTE80.Process2, но это, похоже, не имеет никакого смысла. – mtijn

+0

nunit.exe - это процесс графического интерфейса NUnit. см. мой вопрос, я обновил его с последними результатами. – mtijn

+0

спасибо, что мне нужно, я отправил конечный результат в вопрос. – mtijn

Смежные вопросы