我正在寻找一种方法来执行Steam(Steam.exe)并等待它被加载(不要退出)。
我认为一个好主意是列出所有子句柄并在标题句柄中搜索字符串,因为当蒸汽加载存在一个名为“Friends”的窗口句柄时,但这对我来说很难(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")
更新:
主要问题是如何等待加载X进程,但是当加载Steam时我也注意到了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")
更新2:
我正在尝试通过引用Amegon的解决方案来创建函数,我没有完成代码,因为我在行中出错:
Memory = hprocess.PrivateMemorySize64
但是当我尝试启动一个“大”应用程序(需要很多时间加载像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 :(得分:2)
WaitForInputIdle
方法等待应用程序启动并等待输入
Dim psi As New ProcessStartInfo("fileName", "arguments")
Dim p As New Process
p.StartInfo = psi
p.Start()
p.WaitForInputIdle()
注意:这不适用于服务应用程序。
答案 1 :(得分:1)
更新我已经构建了一个示例程序来显示此内存和cpu观察
要运行它,请创建一个新项目,Windows窗体应用程序,然后打开代码部分并插入以下代码。 - 不需要添加任何控件,我手动将它们添加到代码中。我能够在win8 prof x64-上成功运行VS 2012终极代码:
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时间(与上次相比)的差异。如果满足所有条件(运行,没有cpu总时间更改,没有内存更改),则秒表将计为1500,然后消息框将显示“已完成”
它是脏写的,但我想你了解主要核心(如何在没有任何dll声明方法的情况下找到正确的进程),如何在找到它之后读取该进程的一些信息,以及以何种方式应用条件
等待时间是为了确保纯硬盘驱动器加载时间的第二个不会造成加载完成的错误印象(可能没有内存或CPU更改)。
风险在于......如果页面会自动出现并显示内容/广告,那么可能会经常使用cpu。因此,您只能检查内存更改或您可以从Process访问的任何其他值。
更新更正的代码(修复了错误的数据类型)。现在Option严格并没有抱怨我的代码:)