InputSimulator works while debugging but not when program is built - vb.net

In my project im using inputsimulator and it works great when visual studio is ran as an administrator, but when i build it into a .exe it doesn't work even when i run it as administrator. here's my code
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
AutoSaveTimer.Enabled = True
Try
System.Threading.Thread.Sleep(50)
GameConnection.SendKeyTo(Keys.OemSemicolon)
System.Threading.Thread.Sleep(2000)
GameConnection.SendKeyTo(Keys.K)
System.Threading.Thread.Sleep(50)
GameConnection.SendKeyTo(Keys.Enter)
Catch AutoSaveExeption As GameException
If AutoSaveExeption.GameErrorCode = GameError.GAME_ERR_SENDMSG Then
' Send message error - connection to Game lost.
'
MessageBox.Show("cant make a connection.... can't autosave sadly", AppTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
SimConnectionBar.BackColor = Color.Red
End If
End Try
End Sub
it does send focus to the window i specify but it doesn't send the keystrokes

Try using SetForegroundWindow before sending any input to ensure your game does in fact have focus.The call to SetForegroundWindow should be made in your method just before sending the input.
<DllImport("user32.dll")> _
Public Shared Function SetForegroundWindow(hWnd As IntPtr) As Boolean
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click `
AutoSaveTimer.Enabled = True
Try
'Find the handle to the game. This can do it by searching for the process.
Dim p As System.Diagnostics.Process() = System.Diagnostics.Process.GetProcessesByName("notepad")
'search for process notepad
If p.Length > 0 Then
'check if window was found
'bring notepad to foreground
SetForegroundWindow(p(0).MainWindowHandle)
End If
System.Threading.Thread.Sleep(50)
GameConnection.SendKeyTo(Keys.OemSemicolon)
System.Threading.Thread.Sleep(2000)
GameConnection.SendKeyTo(Keys.K)
System.Threading.Thread.Sleep(50)
GameConnection.SendKeyTo(Keys.Enter)
Catch AutoSaveExeption As GameException
If AutoSaveExeption.GameErrorCode = GameError.GAME_ERR_SENDMSG Then
' Send message error - connection to Game lost.
'
MessageBox.Show("cant make a connection.... can't autosave sadly", AppTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
SimConnectionBar.BackColor = Color.Red
End If
End Try
end sub

Related

Unable to run my own created exe inside parrent form (vb.net)

I have been able to run an external program using the following code.
Imports System.Runtime.InteropServices
Public Class Form1
<DllImport("user32.dll")> Public Shared Function SetParent(ByVal hwndChild As IntPtr, ByVal hwndNewParent As IntPtr) As Integer
End Function
Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
Dim PRO As Process = New Process
PRO.StartInfo.FileName = ("notepad.exe")
PRO.Start()
Do Until PRO.WaitForInputIdle = True
'Nothing
Loop
SetParent(PRO.MainWindowHandle, Me.Handle)
PRO.Dispose()
End Sub
This works fine..... (for notepad that is)
However If I swich notepad for my own vb.net application it fails to launch that aplication inside the form but rather runs it outside of the form. I thought that the application I am trying to launch might of had somthing in it so I created a new application with nothing in it (as bare as I could get it) and run that instead of notepad but it also fails to launch within its "parent" form but rather it also triggers outside of the "parent" form insted?
Could someone please help me fix this?
You just need to wait a tiny bit longer for the MainWindowHandle property to be populated.
Here's a kludge that'll do it:
Private Async Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
Dim PRO As Process = New Process
PRO.StartInfo.FileName = ("C:\Users\mikes\Desktop\temp.exe")
PRO.Start()
Await Task.Run(Sub()
PRO.WaitForInputIdle()
While PRO.MainWindowHandle.Equals(IntPtr.Zero)
Threading.Thread.Sleep(10)
End While
End Sub)
SetParent(PRO.MainWindowHandle, Me.Handle)
End Sub
If you want a ten second fail-safe, and exceptions caught, then you could change it up to:
Private Async Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
Try
Dim PRO As Process = New Process
PRO.StartInfo.FileName = ("C:\Users\mikes\Desktop\temp.exe")
PRO.Start()
Await Task.Run(Sub()
Dim timeout As DateTime = DateTime.Now.AddSeconds(10)
While timeout > DateTime.Now AndAlso PRO.MainWindowHandle.Equals(IntPtr.Zero)
Threading.Thread.Sleep(10)
End While
End Sub)
If (Not PRO.MainWindowHandle.Equals(IntPtr.Zero)) Then
SetParent(PRO.MainWindowHandle, Me.Handle)
Else
MessageBox.Show("Timed out waiting for main window handle.", "Failed to Launch External Application")
End If
Catch ex As Exception
MessageBox.Show(ex.ToString, "Failed to Launch External Application")
End Try
End Sub

CheckForDetailedUpdate throws "Cannot bind to deployment that is not installed"

I have a 10 second timer checking for updates. I have tried putting "check for updates" in the timer routine. I tried "checking for updates" in a background worker . I have tried async "checking for updates". All throw "Cannot bind to deployment that is not installed". After that, I get a new exception, "Object reference not set to an instance of an object". The exception is not necessarily on the 1st check for updates. I have had it run for hours before throwing an exception. After that, it will no longer retrieve an update. If I can't fix the issue, I would like to clear the error. Every 10 seconds out of a hat. I write to a log and/or restart the computer on the main thread.
Private Sub tmrAppUpdate_Tick(sender As Object, e As EventArgs) Handles tmrAppUpdate.Tick
If bwAutoUpdates.IsBusy Then Return 'if updates busy...leave
bwAutoUpdates.RunWorkerAsync() 'check for updates
End Sub
''' <summary>check for and get automatic updates</summary>
Private Sub bwAutoUpdates_DoWork(sender As Object, e As DoWorkEventArgs) Handles bwAutoUpdates.DoWork
e.Result = {"ok", ""} 'default message
Try
Dim updateCheck = ApplicationDeployment.CurrentDeployment 'updates
Dim info = updateCheck.CheckForDetailedUpdate() 'get update info
If info.UpdateAvailable Then 'if updates available...
updateCheck.Update() 'download updates
e.Result = {"restart", "Automatic Update ReStart: "} 'error, error message
End If '
Catch ex As InvalidOperationException 'error
e.Result = {"err", "bw ioe: " & ex.Message} 'error, error message
Catch ex As DeploymentDownloadException 'error
e.Result = {"err", "bw dde: " & ex.Message} 'error, error message
Catch ex As InvalidDeploymentException 'error
e.Result = {"err", "bw ide: " & ex.Message} 'error, error message
Catch ex As TrustNotGrantedException 'error
e.Result = {"err", "bw tnge: " & ex.Message} 'error, error message
Catch ex As Exception 'error
e.Result = {"err", "bw ax: " & ex.Message} 'error, error message
End Try '
End Sub
Private Sub bwAutoUpdates_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles bwAutoUpdates.RunWorkerCompleted
Dim result = CType(e.Result, Array).OfType(Of String)
If result(1).Length > 0 Then writeLog(result(1)) 'write to log!
Select Case result(0) 'what are we going to do?
Case "ok" : Return 'everything ok
Case "restart" : Application.Restart() 'restart
Case "err" 'errors
End Select
End Sub
The new code is crashing. In poking around, I discovered that this problem has been lurking for 10 years. I don't know why everyone isn't aware of it.
Microsoft Discussion
"A privilege that the service requires to function properly does not exist in the service account configuration. You may use the Services Microsoft Management Console (MMC) snap-in (services.msc) and the Local Security Settings MMC snap-in (secpol.msc) to view the service configuration and the account configuration. (Exception from HRESULT: 0x80070511)"
For the past couple of weeks I have fooled with automatic updates. It has bugs and fails if your app checks for updates often. I have included a link to the full project. You can download it, run it for a couple of days and watch it fail (usually within a couple of hours). When it fails, there seems to be no way to clear the error without a restarting. I have seen reports of this bug going back 10 years. If you find a fix, please let me know. Thanks Sandy
vb.net AutomaticUpdates
"Improved solution"
Imports System.ComponentModel
Imports System.Deployment.Application
Imports System.Deployment.Application.ApplicationDeployment
Public Class frmMain
Private lngUpdateSize As Long = 0
Dim WithEvents ad As ApplicationDeployment
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
lblRev.Text = getRev()
End Sub
Private Sub UpdateApplication()
If ApplicationDeployment.IsNetworkDeployed Then '
ad = ApplicationDeployment.CurrentDeployment '
ad.CheckForUpdateAsync() 'any updates...anyone?
End If
End Sub
Private Sub adUpdate_CheckForUpdateProgressChanged(ByVal sender As Object, ByVal e As
DeploymentProgressChangedEventArgs) Handles ad.CheckForUpdateProgressChanged
Const fmt = "{0:F1}K of {1:F1}K downloaded." 'string format
txtUpdateStatus.Text = String.Format(fmt, e.BytesCompleted / 1024, e.BytesTotal /
1024)
End Sub
Private Sub adUpdate_CheckForUpdateCompleted(ByVal sender As Object, ByVal e As
CheckForUpdateCompletedEventArgs) Handles ad.CheckForUpdateCompleted
If e.Cancelled Then 'if update canceled
lblMsg.Text = "The update was cancelled." 'display message
Return 'leave
ElseIf e.Error IsNot Nothing Then 'if there was an error
MessageBox.Show("ERROR") 'display message
Return 'leave
End If '
If e.UpdateAvailable Then 'if updates available
lngUpdateSize = e.UpdateSizeBytes 'get download size
Dim msg = "" 'holder for message
If Not e.IsUpdateRequired Then 'update flag set
msg = "Optional update, Installing now!" 'required message
Else 'optional update
msg = "Mandatory update, Installing now!" 'optional message
End If
lblMsg.Text = msg 'display message
lblMsg.Refresh() 'make we see message
Threading.Thread.Sleep(2000) 'give chance to see message
BeginUpdate() '
End If
End Sub
Private Sub BeginUpdate()
ad = ApplicationDeployment.CurrentDeployment '
ad.UpdateAsync() 'we have them...install em
now!!!
End Sub
Private Sub adUpdate_UpdateProgressChanged(ByVal sender As Object, ByVal e As
DeploymentProgressChangedEventArgs) Handles ad.UpdateProgressChanged
Const fmt = "{0:F1}K out of {1:F1}K downloaded - {2:F1}% complete"
Dim strProgress = String.Format(fmt, e.BytesCompleted / 1024, e.BytesTotal / 1024,
e.ProgressPercentage)
txtUpdateStatus.Text = strProgress
End Sub
Private Sub adUpdate_UpdateCompleted(ByVal sender As Object, ByVal e As
AsyncCompletedEventArgs) Handles ad.UpdateCompleted
If e.Cancelled Then 'if update canceled
lblMsg.Text = "The update was cancelled." 'display message
Return 'leave
ElseIf e.Error IsNot Nothing Then 'if there was an error
MessageBox.Show("ERROR") 'display message
Return 'leave
End If '
lblMsg.Text = "App finished updating, Restarting now!" 'display message
lblMsg.Refresh() 'make sure displayed
Threading.Thread.Sleep(2000) 'chance to see the message
Application.Restart() 'kill app and restart
End Sub
Private Sub tmrUpdate_Tick(sender As Object, e As EventArgs) Handles tmrUpdate.Tick
UpdateApplication() 'time to check for updates
End Sub
Function getRev() As String
If IsDebug() Then Return "Debug Mode" 'if debug...return
Return CurrentDeployment.CurrentVersion.ToString 'revision
End Function
Function IsDebug() As Boolean
Return Debugger.IsAttached 'return debug mode
End Function
End Class
I created a solution that might help. Basically I look at the modified date of the posted ".application" file. if the date changes, then updates pending. This example is not ftp or http, local only. It prevents CheckForUpdateAsync() from getting hammered (from what I have read is the cause of the problem). Hopes this helps...Sandy
Private Sub UpdateApplication()
If IsNetworkDeployed = False Then Return 'if not deployed...leave
Dim fName = CurrentDeployment.UpdateLocation.ToString 'full deployment path
fName = Replace(fName, "file:", Nothing) 'remove
Dim modD = CStr(File.GetLastWriteTime(fName)) 'get file modified
If modD = My.Settings.fileModified Then Return 'if files match...leave
My.Settings.fileModified = modD 'save modified date
ad = CurrentDeployment 'get current deployment
ad.CheckForUpdateAsync() 'any updates...anyone?
writeLog("check for updates") 'log it!
End Sub

Unable to dismiss a message box automatically in vb.net

I am trying a simple code in Silk4Net using VB.Net. I have automated launching of a calculator. Before the numbers can be typed, a message box appears. I am unable to find a way to dismiss the message box automatically. I want to be able to recognize the message box and either push it to the back or dismiss it totally.
The code is as below:
<TestMethod()>
Public Sub TestMethod1()
With _desktop.Window("Calculator")
.SetActive()
generateMsg()
.PushButton("Clear").Select()
.PushButton("3").Select()
.PushButton("5").Select()
End With
End Sub
Public Sub generateMsg()
Thread.Sleep(2000)
With _desktop.Window(MsgBox("Test", MsgBoxStyle.Critical, "Test"))
For Each p As Process In Process.GetProcesses
If p.MainWindowTitle.Contains("Test") Then
p.Kill()
End If
Next
'With .Dialog("Test")
' '.PushButton("OK").Select()
'End With
' .Close()
End With
End Sub
Any help would be much appreciated. Thanks.
Updated answer
You could add a timer to the code that uses SendKeys.SendWait - like this - adapting it a little for your test environment as I'm not sure about Silk4Net tbh
Dim WithEvents timer1 As New System.Timers.Timer
timer1.Interval = 5000
timer1.Enabled = True
MsgBox("Hello. I will go bye-bye in 5 seconds.")
timer1.Enabled = False
And as a separate sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles timer1.Elapsed
SendKeys.SendWait("{ENTER}")
End Sub

CATIA and VB.NET detect closing of CATIA in external app

I latched onto the Catia using:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim boolCatAlive As Boolean
boolCatAlive = False
Try
Dim myCatia As INFITF.Application
myCatia = Interaction.GetObject(vbNullString, "CATIA.Application")
boolCatAlive = True
Catch ex As Exception
boolCatAlive = False
End Try
Select Case boolCatAlive
Case True
'continue loading app, do my stuff
Case Else
'end this now
MsgBox("No running CATIA instance detected, please start a new CATIA instance and re-run this program.", MsgBoxStyle.Critical, "Error")
End
End Select
End Sub
So that is a simple boolean switch at the form loading that decides whether the app is going to load or not.
This works ok, but is doing the check only once when the app is started. Is there a way to continually detect CATIA status, so that - if a user exits CATIA in the middle of my app running - app gets notified and realises that the CATIA COM link is no longer alive?
I could also use that to detect selection changes for example?
You can Check it All the time by using a timer.Add a timer and specify the same code in its TICK event.sorry to Post this as an answer.I don't have enough reputation to post comment.
http://vb.net-informations.com/gui/timer-vb.htm
This link will be helpfull to you.
Thanks, it works fine.
I put this code inside Tick event, set timer to enabled, and use 1000ms interval to check every 1 second for CATIA link.
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Dim boolCatAlive As Boolean
boolCatAlive = False
Try
Dim myCatia As INFITF.Application
myCatia = Interaction.GetObject(vbNullString, "CATIA.Application")
boolCatAlive = True
Catch ex As Exception
boolCatAlive = False
End Try
End Sub
I would recommend to ask the actual Catia Object in timer instead of getting new object. Assuming you have Global CatiaApp variable
Put in the timer something like this
Try
If CatiaApp.Name.Length > 0 Then
'catia is alive
End If
Catch ex As Exception
'catia is down
CatiaApp = Nothing
End Try
You get an exception if Name.Length fails which signal that catia is down

Vb.net - Cross-threading exception by closing a form

I'm working on an application to read something from a serial port (COMM-port).
In short, it works like this: when you work in a bar or restaurant, before you can enter something in the register, you have to scan a sort of card. If this card returns a good number, you can enter something.
So, there has to be a form that listens to the serial port and checks whether someone scans a card and if it's a card with good rights.
If the person has the good rights, the form can be closed and another form is called.
Now, in code:
Here, the MenuForm is loaded (the form that has to be accesible after the correct code was read). I call the frmWaiterKey to show up.
Private Sub frmMenu_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim oForm As frmWaiterKey = New frmWaiterKey()
oForm.ShowDialog()
End Sub
The code of the class frmWaiterKey:
Private Sub frmWaiterKey_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
nameArray = SerialPort.GetPortNames
OpenComPort()
AddHandler myComPort.DataReceived, SerialDataReceivedEventHandler1
End Sub
Sub OpenComPort()
Try
' Get the selected COM port's name
' from the combo box.
If Not myComPort.IsOpen Then
myComPort.PortName = _
nameArray(0).ToString()
' Get the selected bit rate from the combo box.
myComPort.BaudRate = CInt(9600)
' Set other port parameters.
myComPort.Parity = Parity.None
myComPort.DataBits = 8
myComPort.StopBits = StopBits.One
myComPort.Handshake = Handshake.None
'myComPort.ReadTimeout = 3000
'myComPort.WriteTimeout = 5000
' Open the port.
myComPort.Open()
End If
Catch ex As InvalidOperationException
MessageBox.Show(ex.Message)
Catch ex As UnauthorizedAccessException
MessageBox.Show(ex.Message)
Catch ex As System.IO.IOException
MessageBox.Show(ex.Message)
End Try
End Sub
Sub CloseComPort()
Using myComPort
If (Not (myComPort Is Nothing)) Then
' The COM port exists.
If myComPort.IsOpen Then
' Wait for the transmit buffer to empty.
Do While (myComPort.BytesToWrite > 0)
Loop
End If
End If
End Using
End Sub
Private SerialDataReceivedEventHandler1 As New SerialDataReceivedEventHandler(AddressOf DataReceived)
' Specify the routine that runs when
' a DataReceived event occurs at myComPort.
' This routine runs when data arrives at myComPort.
Friend Sub DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
Dim newReceivedData As String
' Get data from the COM port.
newReceivedData = myComPort.ReadExisting
newReceivedData = newReceivedData.Trim()
MsgBox(newReceivedData)
If newReceivedData.Equals("00150324294764") Then
CloseComPort()
Me.Close()
End If
End Sub
I get an error in the last line: Me.Close()
I get the point: I call the form frmWaiterKey from the frmMenu and can't close it here...
But I have no idea how to solve this problem.
I hope someone can help me or tell me what I'm doing wrong.
First, you need to make a method like this:
Private Sub CloseMe()
If Me.InvokeRequired Then
Me.Invoke(New MethodInvoker(AddressOf CloseMe))
Exit Sub
End If
Me.Close()
End Sub
Then, close your form by calling that method, like this:
If newReceivedData.Equals("00150324294764") Then
CloseComPort()
CloseMe()
End If
The reason this is necessary is because all UI activity in WinForms must be performed from the same thread. Since the DataReceived method is being called from another thread, it must get back onto the UI thread before it can close the form. The InvokeRequired property returns true if you are on any thread other than the UI thread, and the Invoke method invokes the given method from the UI thread.