2013-04-09 3 views
0

Я ищу способ выполнить Steam (Steam.exe) и дождаться его загрузки (не выйти).Выполнение приложения и ожидание его загрузки

Я подумал, что хорошая идея - перечислить все дочерние дескрипторы и найти строку в заголовках, потому что когда паровые нагрузки существуют дескриптор окна с именем «Друзья», но это сложно сделать для меня (API) так что, возможно существует простой способ, чтобы ждать программа для загрузки ...

пример того, что я буду делать:

' First process 
Process.start("Process 1.exe") 

' Here will goes an efficient method to wait for application is loaded, 
' not sleeping X seconds measuring the loading time or any of that. 

' Second process 
' Depends on first process fully loaded. 
' If first process is not fully loaded (libraries and that) then this process can't run. 
Process.start("Processs 2.exe") 

UPDATE:

Главный вопрос заключается в том, чтобы ждать, пока процесс X должен быть загружен, но о Steam.exe я заметил тоже, когда пара загружается пытается читать/открыть некоторые REGKEYS:

http://img267.imageshack.us/img267/6599/prtscrcapture4u.jpg

Может быть, я могу сделать что-то с кодом для мониторинга, если один из этих RegKeys будет принят?

Нечто подобное ?:

Dim RegKey = "HKLM\...blablabla" 
Process.start("steam.exe") 

While not Regkey.IsAccessed 
    ' Do nothing and wait 
Loop 

Process.start("Second process.exe") 

UPDATE 2:

Я пытаюсь сделать функцию, принимая по ссылке решение Amegon, я не закончил код потому что я получаю сообщение об ошибке в строке:

Memory = hprocess.PrivateMemorySize64 

enter image description here

Но я получаю сообщение об ошибке при попытке запустить «большое» приложение (приложение, которое требует много времени для загрузки, например, Photoshop), при этом «маленькие» приложения работают хорошо.

Пожалуйста, если кто-то может помочь мне упростить/улучшить решение Amegon, чтобы создать универсальную функцию и исправить ошибку переполнения памяти ... Спасибо!

Это мой код:

' This is the sub that launchs the unfinished function: 
Private Sub Launch_Game() 
    'Wait_For_Application_To_Load("C:\Games\Steam.exe", "-applaunch 0") 
    Wait_For_Application_To_Load("C:\Program Files\Adobe Photoshop CS6 (64 Bit)\Photoshop.exe") 
End Sub 

Private Function Wait_For_Application_To_Load(ByVal APP_Path As String, Optional ByVal APP_Arguments As String = Nothing) 
    Dim File = My.Computer.FileSystem.GetFileInfo(APP_Path) 
    Process.Start(APP_Path, APP_Arguments) 
    Timer_CheckCPU.Tag = File.Name.Substring(0, File.Name.Length - 4) ' Photoshop 
    Timer_CheckCPU.Enabled = True 
End Function 

Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByVal lpBuffer As Integer, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer 
Private WithEvents Timer_CheckCPU As New Timer 

Dim Memory_Value_Changed As Boolean 
Dim CPU_Changed As Boolean 
Dim CPU_Time As Boolean 
Dim Running_Time As Boolean 
Private _desiredTime_ms As Integer = 1500 

Private Sub Timer_CheckCPU_Tick(sender As Object, ev As EventArgs) Handles Timer_CheckCPU.Tick 
    Timer_CheckCPU.Enabled = False 
    Dim pProcess() As Process = System.Diagnostics.Process.GetProcessesByName(Timer_CheckCPU.Tag) 
    Dim hprocess As Process = pProcess(0) 
    If hprocess Is Nothing Then 
     Running = False 
     Timer_CheckCPU.Enabled = True 
     Return 
    End If 
    Running = True 


    ' Here is the error: 
    Memory = hprocess.PrivateMemorySize64 
    ' MsgBox(hprocess.PrivateMemorySize64.ToString) 


    CPUTotal = hprocess.TotalProcessorTime.TotalMilliseconds 

    If AllConditionsGood() Then 
     If Not (_countdown.IsRunning) Then 
      _countdown.Reset() 
      _countdown.Start() 
     End If 
     Dim _elapsed As Integer = _countdown.ElapsedMilliseconds 
     If _elapsed >= _desiredTime_ms Then 
      Me.TopMost = True 
      MsgBox("process loaded") 
      Return 
     End If 
    Else 
     _countdown.Reset() 
    End If 
    Timer_CheckCPU.Enabled = True 
End Sub 

Private Function AllConditionsGood() As Boolean 
    If CPU_Time Then Return False 
    If Memory_Value_Changed Then Return False 
    If Running_Time Then Return False 
    Return True 
End Function 

Private _countdown As New Stopwatch 

Private _Running As Boolean = False 
Public WriteOnly Property Running() As Boolean 
    Set(ByVal value As Boolean) 
     _Running = value 
     If value Then 
      Running_Time = False 
     Else 
      Running_Time = True 
     End If 
    End Set 
End Property 

Private _CPUTotal As Integer 
Public WriteOnly Property CPUTotal() As Integer 
    Set(ByVal value As Integer) 
     CPU = value - _CPUTotal 'used cputime since last check 
     _CPUTotal = value 
    End Set 
End Property 


Private _CPU As Integer 
Public WriteOnly Property CPU() As Integer 
    Set(ByVal value As Integer) 
     If value = 0 Then 
      CPU_Time = False 
     Else 
      CPU_Time = True 
     End If 
     _CPU = value 
    End Set 
End Property 

Private _Memory As Integer 
Public WriteOnly Property Memory() As Integer 
    Set(ByVal value As Integer) 
     MemoryDiff = Math.Abs(value - _Memory) 
     _Memory = value 
    End Set 
End Property 

Private _MemoryDiff As Integer 
Public WriteOnly Property MemoryDiff() As Integer 
    Set(ByVal value As Integer) 
     If value = _MemoryDiff Then 
      Memory_Value_Changed = False 
     Else 
      Memory_Value_Changed = True 
     End If 
     _MemoryDiff = value 
    End Set 
End Property 
+0

Вы проверили метод [GetProcessesByName] (http://msdn.microsoft.com/en-us/library/z3w4xdc9.aspx) класса Process? Просто попробуйте с помощью инструмента ProcessExplorer определить имя процесса ..... – Steve

+0

И что вы видите, если вы нажмете кнопку «Процесс»? Вы ищете процесс, а не окна – Steve

+0

Простите, что это мой первый раз, когда я использовал spy ++, я отредактировал мой вопрос! – ElektroStudios

ответ

1

Update У меня есть построить пример программы, чтобы показать эту память и центральный процессор наблюдения

Чтобы запустить это создать новый проект, окна образуют приложение, затем откройте часть кода и вставьте следующий код. - Не нужно добавлять никаких элементов управления, я добавил их в код вручную. Я в состоянии успешно выполнить код с VS 2012 конечной на win8 проф x64-:

Option Strict On 
Imports System.Runtime.InteropServices 

Public Class Form1 
    Private WithEvents btnStart As New Button 
    Private WithEvents tmrCheckCPU As New Timer 

    Private tbRunning As New TextBox 
    Private tbCPU As New TextBox 
    Private tbMemory As New TextBox 
    Private tbTime As New TextBox 

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load 
     Me.Size = New Size(400, 400) 
     With btnStart 
      '.Text = "Start DxDiag" 
      .Text = "Start Photoshop" 
      Me.Controls.Add(btnStart) 
      .Location = New Point(50, 50) 
      .Size = New Size(200, 50) 
     End With 
     With tmrCheckCPU 
      .Interval = 100 
      .Enabled = False 
     End With 
     With tbRunning 
      Me.Controls.Add(tbRunning) 
      .Location = New Point(50, 110) 
      .Size = New Size(100, 40) 
     End With 
     With tbCPU 
      Me.Controls.Add(tbCPU) 
      .Location = New Point(50, 150) 
      .Size = New Size(100, 40) 
     End With 
     With tbMemory 
      Me.Controls.Add(tbMemory) 
      .Location = New Point(50, 200) 
      .Size = New Size(100, 40) 
     End With 
     With tbTime 
      Me.Controls.Add(tbTime) 
      .Location = New Point(50, 250) 
      .Size = New Size(100, 40) 
     End With 
    End Sub 

    Private Sub btnStart_Clicked(sender As Object, ev As EventArgs) Handles btnStart.Click 
     'start Process 
     'Process.Start("dxdiag.exe", "/whql:on") 
     Process.Start("C:\Program Files\Adobe\Adobe Photoshop CS6 (64 Bit)\Photoshop.exe") 
     'start watching Timer 
     tmrCheckCPU.Enabled = True 
    End Sub 

    Private Function FindProcess(MainWindowTitle As String) As System.Diagnostics.Process 
     For Each ele As System.Diagnostics.Process In Process.GetProcesses 
      If ele.MainWindowTitle = MainWindowTitle Then Return ele 
     Next 
     Return Nothing 
    End Function 

    Private Sub tmrCheckCPU_Tick(sender As Object, ev As EventArgs) Handles tmrCheckCPU.Tick 
     tmrCheckCPU.Enabled = False 
     'Dim name As String = "DirectX Diagnostic Tool" 
     Dim name As String = "Adobe Photoshop CS6 Extended" 
     Dim hprocess As Process = FindProcess(name) 
     If hprocess Is Nothing Then 
      Running = False 
      tmrCheckCPU.Enabled = True 
      Return 
     End If 
     Running = True 
     Memory = hprocess.PrivateMemorySize64 
     CPUTotal = hprocess.TotalProcessorTime.TotalMilliseconds 

     If AllConditionsGood() Then 
      If Not (_countdown.IsRunning) Then 
       _countdown.Reset() 
       _countdown.Start() 
      End If 
      Dim _elapsed As Long = _countdown.ElapsedMilliseconds 
      If _elapsed >= _desiredTime_ms Then 
       tbTime.Text = _desiredTime_ms.ToString 
       tbTime.BackColor = Color.LightGreen 
       Me.TopMost = True 
       Me.Focus() 
       MsgBox("process loaded") 
       Return 
      Else 
       tbTime.Text = _elapsed.ToString 
       tbTime.BackColor = Color.LightGreen 
      End If 
     Else 
      _countdown.Reset() 
     End If 
     tmrCheckCPU.Enabled = True 
    End Sub 

    Private _desiredTime_ms As Integer = 1500 

    Private Function AllConditionsGood() As Boolean 
     If tbCPU.BackColor <> Color.LightGreen Then Return False 
     If tbMemory.BackColor <> Color.LightGreen Then Return False 
     If tbRunning.BackColor <> Color.LightGreen Then Return False 
     Return True 
    End Function 

    Private _countdown As New Stopwatch 

    Private _Running As Boolean = False 
    Public WriteOnly Property Running() As Boolean 
     Set(ByVal value As Boolean) 
      _Running = value 
      If value Then 
       tbRunning.Text = "Running" 
       tbRunning.BackColor = Color.LightGreen 
      Else 
       tbRunning.Text = "Not Running" 
       tbRunning.BackColor = Color.LightPink 
      End If 
     End Set 
    End Property 

    Private _CPUTotal As Double 
    Public WriteOnly Property CPUTotal() As Double 
     Set(ByVal value As Double) 
      CPU = value - _CPUTotal 'used cputime since last check 
      _CPUTotal = value 
     End Set 
    End Property 


    Private _CPU As Double 
    Public WriteOnly Property CPU() As Double 
     Set(ByVal value As Double) 
      If value = 0 Then 
       tbCPU.BackColor = Color.LightGreen 
      Else 
       tbCPU.BackColor = Color.LightPink 
      End If 
      _CPU = value 
      tbCPU.Text = value.ToString 
     End Set 
    End Property 

    Private _Memory As Long 
    Public WriteOnly Property Memory() As Long 
     Set(ByVal value As Long) 
      MemoryDiff = Math.Abs(value - _Memory) 
      _Memory = value 
     End Set 
    End Property 

    Private _MemoryDiff As Long 
    Public WriteOnly Property MemoryDiff() As Long 
     Set(ByVal value As Long) 
      If value = _MemoryDiff Then 
       tbMemory.BackColor = Color.LightGreen 
      Else 
       tbMemory.BackColor = Color.LightPink 
      End If 
      _MemoryDiff = value 
      tbMemory.Text = value.ToString 
     End Set 
    End Property 

End Class 

Если нажать на кнопку, она начнет DXDIAG и показывает изменение памяти и разность общего времени центрального процессора (по сравнению с последним) в текстовых окнах.Если все условия выполнены (работа, общее изменение времени в cpu, изменение памяти не происходит), то секундомер будет считаться до 1500, а затем в окне сообщений будет указано «закончено»

Это грязно написано, но, я думаю, вы понимаете основные (как найти правильный процесс без какого-либо метода объявления dll), как прочитать некоторую информацию об этом процессе после его поиска и каким образом применить условия.

Время ожидания предназначено для обеспечения того, чтобы второе время загрузки чистого жесткого диска не создавало неправильного впечатления о том, что загрузка выполнена (возможно, нет памяти или процессора).

Риск состоит в том, что .. если страница будет автоматически отображаться и показывать контент/рекламу, то, возможно, процессор постоянно используется. поэтому вы можете проверить только на изменение памяти или любое другое значение, которое вы можете получить от Процесса.

Обновление исправленный код (исправлены неправильные типы данных). Теперь Option Strict не жалуется на мой код :)

+0

Спасибо, но потребление памяти может значительно варьировать время загрузки первого процесса (steam.exe), я думаю, что это риск, подобный времени. На самом деле я не понимаю, что вы будете иметь в виду именно с «подпроцессами» (подпотоком steam.exe или автономным исполняемым файлом), но я контролировал исполняемый файл с помощью «Process Monitor» из «sysinternals», а я «я использовал сейчас« Spy ++ »в первый раз, и я не заметил никакого« подпроцесса », но, возможно, я ошибаюсь, потому что я не эксперт. Я обновлю свой вопрос за несколько секунд, загрузив скриншот. – ElektroStudios

+0

Об исчезновении, я запускаю пар с аргументом, чтобы отключить обновление, эта проблема решена. – ElektroStudios

+0

Я также очень новичок в Spy ++, но, работая с sendkeys (пытаясь создать простой бот), я узнал, что иногда для отправки команд требуется доступ к определенной цели. Поэтому с помощью spy ++ полезно проверить, что еще существует как одна запущенная программа. Я не уверен, что он определяется как подпроцесс или подпроцесс. Поскольку пар, вероятно, не отправит сообщение «Я закончил с загрузкой», возможно, вы можете попытаться найти другой под'объект под паром, который существует только при загрузке, например. показывая друзей.В этом случае вы можете постоянно сканировать этот объект и знать, что пар загружается, когда он найден – Amegon

2

Метод WaitForInputIdle ждет, пока приложение не запускается и ожидает ввода

Dim psi As New ProcessStartInfo("fileName", "arguments") 
Dim p As New Process 
p.StartInfo = psi 
p.Start() 
p.WaitForInputIdle() 

Примечание: Это не будет работать для сервисных приложений.

+0

Ожидание ввода будет означать ожидание ввода пользователя? это решение только для приложений CLI? – ElektroStudios

+0

+1 за то, как начать процесс (и сразу же, имея ручку для него, не знал этого). Кроме того, если вы храните дескриптор процесса p и WaitForInputIdle не успешно (например, пар позволяет вводить пользователя, пока он загружает некоторые компоненты, такие как вход в сеть друзей), вы можете использовать .Refresh, чтобы иметь возможность читать последние значения из дескриптор процесса. – Amegon

+0

@Amegon: Да, вы можете называть 'WaitForInputIdle' только один раз! Позже это уже не будет иметь никакого эффекта. Я не знаю, как этот метод работает точно, но я думаю, что он начинает запускать цикл сообщений, т. Е. Вы можете отправить его с помощью 'SendKeys', например, даже если он все еще работает. –

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