Get Application Name From Keyboard Input in VB.net - vb.net

I am making application in vb.net which when ran detects keystrokes from keyboard in any editors. Now I can get keystrokes, thats easy part but I want to know the application name like if user is writing in notepad, then I want that name.
Please can any one suggest any idea.
Thanks

You need to use windows api:
Private Sub Main()
Dim shortName as String = GetShortEXEName(GetForegroundWindow() )
End Sub
' Define other methods and classes here
<DllImport("user32.dll", SetLastError := True)> _
Public Shared Function GetForegroundWindow() As IntPtr
End Function
Public Shared Function GetProcess(hwnd As IntPtr) As Process
Dim intID As Integer = 0
GetWindowThreadProcessId(hwnd, intID)
Return Process.GetProcessById(intID)
End Function
<DllImport("user32.dll", SetLastError := True)> _
Public Shared Function GetWindowThreadProcessId(hwnd As IntPtr, ByRef lpdwProcessId As Integer) As Integer
End Function
Public Shared Function GetShortEXEName(hwnd As IntPtr) As String
' this seems to be better to use than calling GetProcessEXEName and then using substring functions to get the short executable name
' because that function seems to crash when dealing with Windows Explorer windows
Try
Return GetProcess(hwnd).ProcessName
Catch
Return ""
End Try
End Function

Related

How to get rid of the Close Button of a Console Window?

I have a customer who is using some old but still needed 32Bit-Software, which is running in a Console Window. It is necessary to disable the Close button because closing the Console using this button causes some serious problems in this software.
I thought about the following way:
1) Find the handle of the active Console
2) Disable the Close Button with GetSystemMenu function
Maybe I'm completely wrong, but I did not manage to find a way to do that so far.
Edit:
The problem is just the Close Button. Of course users can also quit the program by Alt+F4 or Task Manager, but they don't do that. They do use Close Button, that's why I want to disable it.
Of course the best solution would by to disable all ways to cancel the program, but to disable the Close Button would work.
To start the program inside a Windows Form would by one possible solution, too.
To interact with a foreign Window, you need to find it/verify it exists first.
We have different methods to find a Window. Here I'm considering FindWindowEx and Process.GetProcessesByName().
UI Automation and EnumWindows provide other options, eventually.
Store the CMD Window caption somewhere, e.g., an instance Field (it could be a Project settings or anything else you can access at run-time).
Private cmdWindowTitle As String = "The Window Title"
→ FindWindowEx is more useful if you know exactly what the Window title is and it doesn't change over time.
→ Process.GetProcessesByName() can be used to find a Window using the Process name and then verify whether the Process.MainWindowTitle.Contains() at least a partial known string.
If instead the Console Window belongs to the current Process, you just need:
Process.GetCurrentProcess().MainWindowHandle
' -- If the Console Window belongs to the current Process: --
Dim cmdWindowHandle = Process.GetCurrentProcess().MainWindowHandle
' -----------------------------------------------------------
' -- Find it when the exact Window title is known: --
Dim cmdWindowHandle As IntPtr = NativeMethods.GetCmdWindowByCaption(cmdWindowTitle)
' -----------------------------------------------------------
' -- Find it when only a partial caption is available: --
Dim cmdWindowHandle As IntPtr = IntPtr.Zero
Dim cmdProc = Process.GetProcessesByName("cmd").
FirstOrDefault(Function(p) p.MainWindowTitle.Contains(cmdWindowTitle))
If cmdProc IsNot Nothing Then
cmdWindowHandle = cmdProc.MainWindowHandle
End If
' -----------------------------------------------------------
' Choose one of the above, then, in any case:
If cmdWindowHanle <> IntPtr.Zero Then
NativeMethods.WindowDisableSysMenu(cmdWindowHandle)
End If
Note: Here, I'm assuming the Process Name is cmd and the Window class name is ConsoleWindowClass. It may not be. Change these as required.
Since now the Window has no SystemMenu or Close buttons (we just hid them all), it cannot be closed using ALT+F4 or any other means except using the Task Manager (or wait for it to close naturally).
To close it from your app, send a WM_CLOSE message:
' -- find the Window as described before --
Dim cmdWindowHandle As IntPtr = NativeMethods.GetCmdWindowByCaption(cmdWindowTitle)
If Not cmdWindowHandle.Equals(IntPtr.Zero) Then
NativeMethods.SendCloseMessage(cmdWindowHandle)
End If
NativeMethods declarations:
Public Class NativeMethods
Private Const WM_CLOSE As Integer = &H10
Public Enum WinStyles As UInteger
WS_MAXIMIZE = &H1000000
WS_MAXIMIZEBOX = &H10000
WS_MINIMIZE = &H20000000
WS_MINIMIZEBOX = &H20000
WS_SYSMENU = &H80000
End Enum
Public Enum GWL_Flags As Integer
GWL_STYLE = -16
GWL_EXSTYLE = -20
End Enum
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function SendMessage(hWnd As IntPtr, uMsg As WinMessage, wParam As Integer, lParam As Integer) As Integer
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function FindWindowEx(hwndParent As IntPtr, hwndChildAfter As IntPtr, lpszClass As String, lpszWindow As String) As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function GetWindowLong(hWnd As IntPtr, nIndex As GWL_Flags) As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function SetWindowLong(hWnd As IntPtr, nIndex As GWL_Flags, dwNewLong As IntPtr) As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function GetWindowLongPtr(hWnd As IntPtr, nIndex As GWL_Flags) As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function SetWindowLongPtr(hWnd As IntPtr, nIndex As GWL_Flags, dwNewLong As IntPtr) As IntPtr
End Function
' Public wrappers
Public Shared Function GetWindowLongUni(hWnd As IntPtr, nIndex As GWL_Flags) As Integer
If IntPtr.Size = 8 Then
Return GetWindowLongPtr(hWnd, nIndex).ToInt32()
Else
Return GetWindowLong(hWnd, nIndex).ToInt32()
End If
End Function
Public Shared Function SetWindowLongUni(hWnd As IntPtr, nIndex As GWL_Flags, dwNewLong As Integer) As Integer
If IntPtr.Size = 8 Then
Return SetWindowLongPtr(hWnd, nIndex, New IntPtr(dwNewLong)).ToInt32()
Else
Return SetWindowLong(hWnd, nIndex, New IntPtr(dwNewLong)).ToInt32()
End If
End Function
Public Shared Function GetCmdWindowByCaption(cmdCaption As String) As IntPtr
Return FindWindowEx(IntPtr.Zero, IntPtr.Zero, "ConsoleWindowClass", cmdCaption)
End Function
Public Shared Sub WindowDisableSysMenu(windowHandle As IntPtr)
Dim styles As Integer = GetWindowLongUni(windowHandle, GWL_Flags.GWL_STYLE)
styles = styles And Not CInt(WinStyles.WS_SYSMENU)
SetWindowLongUni(windowHandle, GWL_Flags.GWL_STYLE, styles)
End Sub
Public Shared Sub SendCloseMessage(windowHandle As IntPtr)
SendMessage(windowHandle, WM_CLOSE, 0, 0)
End Sub
End Class

AppHangB1 trying to bring an Outlook.Explorer to the fore

We have an application that may under some circumstances launch Outlook. It gets an Outlook.Explorer object (oWindow As Outlook.Explorer) and calls its .Activate() procedure.
Up to that point all is hunky dory, but then I want to bring the Explorer object to the foreground, and we call this procedure:
Public Shared Sub BringToFore(ByVal oWindow As Object)
Dim oFoo As IOleWindow
Dim hWnd As IntPtr
oFoo = TryCast(oWindow, IOleWindow)
If Not (oFoo Is Nothing) Then
Try
oFoo.GetWindow(hWnd)
Catch ex As Exception
End Try
End If
Try
If hWnd.ToInt32 <> IntPtr.Zero.ToInt32 Then
Try
If IsIconic(hWnd) Then
ShowWindow(hWnd, SW_RESTORE)
End If
SetForegroundWindow(hWnd)
Catch ex As System.Exception
End Try
Else
End If
Catch ex As Exception
End Try
End Sub
IOleWindow is defined as follows:
<ComImport(), Guid("00000114-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
Private Interface IOleWindow
''' <summary>
''' Returns the window handle to one of the windows participating in in-place activation
''' (frame, document, parent, or in-place object window).
''' </summary>
''' <param name="phwnd">Pointer to where to return the window handle.</param>
Sub GetWindow(<System.Runtime.InteropServices.Out()> ByRef phwnd As IntPtr)
''' <summary>
''' Determines whether context-sensitive help mode should be entered during an
''' in-place activation session.
''' </summary>
''' <param name="fEnterMode"><c>true</c> if help mode should be entered;
''' <c>false</c> if it should be exited.</param>
Sub ContextSensitiveHelp(<[In](), MarshalAs(UnmanagedType.Bool)> ByVal fEnterMode As Boolean)
End Interface
and the usual declarations
Private Const SW_RESTORE As Integer = 9
Private Declare Auto Function IsIconic Lib "user32" (ByVal hWnd As IntPtr) As Boolean
Private Declare Auto Function SetForegroundWindow Lib "user32" (ByVal hwnd As IntPtr) As Long
Private Declare Auto Function ShowWindow Lib "user32" (ByVal hWnd As IntPtr, ByVal nCmdShow As Integer) As IntPtr
The BringToFore procedure works fine most of the time. And sometimes the calling application - a WPF application - just hangs. The Event Viewer records an AppHangB1 and the application crashes.
Is there anything I can do in the BringToFore procedure to prevent this happening? Any idea which of these are causing the problem? TryCast(oWindow, IOleWindow), oFoo.GetWindow(hWnd), IsIconic(hWnd), ShowWindow(hWnd, SW_RESTORE) or SetForegroundWindow(hWnd)? (I personally suspect it may be SetForegroundWindow, to be honest). If so, is there anything I can do in the code? Some condition to check? If this condition is true then don't try to do that ..... sort of thing? I'd rather not go as far as just abandoning the idea of setting the Explorer to the foreground; in that circumstance Outlook may appear "behind" my application and some users may just not realise that something has happened.... if you catch my drift.
Thanks
Pino
Windows would prevent you from using SetForegroundWindow if the window belongs to a process other than the active one. You'd need to call AttachThreadInput first. Here is the function (Delphi):
function ForceForegroundWindow(hWnd: THandle): BOOL;
var
hCurWnd: THandle;
begin
hCurWnd := GetForegroundWindow;
AttachThreadInput(
GetWindowThreadProcessId(hCurWnd, nil),
GetCurrentThreadId, True);
Result := SetForegroundWindow(hWnd);
AttachThreadInput(
GetWindowThreadProcessId(hCurWnd, nil),
GetCurrentThreadId, False);
end;
I think this issue would require more debugging. I found a similar issue posted here quite a few years back with a suggestion which might be useful to get to the root cause.

How do I check if a certain process has focus?

I'm trying to check if javaw.exe has focus, then execute certain code if it does.
Previously I had code which would look for the process ID of javaw.exe, then compare it to the process which currently had focus, which worked for awhile, but then I noticed when I had more than one javaw.exe process running, it would only work on one of those processes, while I need it to work when any javaw.exe process has focus.
Is there any way to do this?
You can determine this quite easily using the GetForegroundWindow() and GetWindowThreadProcessId() WinAPI functions.
First call GetForegroundWindow to get the window handle of the currently focused window, then call GetWindowThreadProcessId in order to retrieve the process id of that window. Finally get it as a Process class instance by calling Process.GetProcessById()
Public NotInheritable Class ProcessHelper
Private Sub New() 'Make no instances of this class.
End Sub
<DllImport("user32.dll", SetLastError:=True)> _
Private Shared Function GetForegroundWindow() As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True)> _
Private Shared Function GetWindowThreadProcessId(ByVal hWnd As IntPtr, ByRef lpdwProcessId As UInteger) As Integer
End Function
Public Shared Function GetActiveProcess() As Process
Dim FocusedWindow As IntPtr = GetForegroundWindow()
If FocusedWindow = IntPtr.Zero Then Return Nothing
Dim FocusedWindowProcessId As UInteger = 0
GetWindowThreadProcessId(FocusedWindow, FocusedWindowProcessId)
If FocusedWindowProcessId = 0 Then Return Nothing
Return Process.GetProcessById(CType(FocusedWindowProcessId, Integer))
End Function
End Class
Usage example:
Dim ActiveProcess As Process = ProcessHelper.GetActiveProcess()
If ActiveProcess IsNot Nothing AndAlso _
String.Equals(ActiveProcess.ProcessName, "javaw", StringComparison.OrdinalIgnoreCase) Then
MessageBox.Show("A 'javaw.exe' process has focus!")
End If
Hope this helps!

Monitor turn on or wake up command in windows 7 SP1 x64

I have the code below, that does successfully "wake up" a sleeping monitor, but it only momentarily wakes it up, it flashes on and then back off. I've tried various timers and loops to reissue the command, but its hard on the cpu by the look of it, does anyone have any ideas on how to get it to turn on the screen for say 10 minutes, or even just turn it on and wait for the OS to turn it off again later?
Ive also looked into the whole send keys thing, but that didnt seem to do anything in windows 7, An important note to make, the dredit for this code in the most part is thanks to the members of StackOverflow! Cheers
Here is the code:
Public Class MonitorHelper
Private Const WM_SYSCOMMAND As Integer = &H112
Private SC_MONITORPOWER As New IntPtr(&HF170)
Private HWND_BROADCAST As Integer = (&HFFFF&)
Private MONITOR_ON As New IntPtr(-1)
Private MONITOR_OFF As New IntPtr(2)
Public Sub TurnOnScreen(ByVal form As Form)
NativeMethods.PostMessage(New HandleRef(Me, HWND_BROADCAST), WM_SYSCOMMAND, SC_MONITORPOWER, MONITOR_ON)
End Sub
<SuppressUnmanagedCodeSecurity()> _
Private Class NativeMethods
<DllImport("user32.dll")> _
Public Shared Function PostMessage( _
ByVal hWnd As HandleRef, _
ByVal message As Integer, _
ByVal lParam As IntPtr, _
ByVal wParam As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
End Class
End Class
public class form3
Private monitorHelper1 As New MonitorHelper
End Class
Calling the monitor to turn on:
monitorHelper1.TurnOnScreen(Me)
SO looking at this from the other direction, not how to turn it on and how to make it not go to sleep in a round about way, I have this working code... Thanks to Hannes Du Preez.
Imports System.Runtime.InteropServices 'APIs
Imports Microsoft.Win32 'For System Events
Public Class frmMonitor
<FlagsAttribute()> _
Public Enum EXECUTION_STATE As UInteger ' Determine Monitor State
ES_AWAYMODE_REQUIRED = &H40
ES_CONTINUOUS = &H80000000UI
ES_DISPLAY_REQUIRED = &H2
ES_SYSTEM_REQUIRED = &H1
' Legacy flag, should not be used.
' ES_USER_PRESENT = 0x00000004
End Enum
'Enables an application to inform the system that it is in use, thereby preventing the system from entering sleep or turning off the display while the application is running.
<DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Private Shared Function SetThreadExecutionState(ByVal esFlags As EXECUTION_STATE) As EXECUTION_STATE
End Function
'This function queries or sets system-wide parameters, and updates the user profile during the process.
<DllImport("user32", EntryPoint:="SystemParametersInfo", CharSet:=CharSet.Auto, SetLastError:=True)> _
Private Shared Function SystemParametersInfo(ByVal uAction As Integer, ByVal uParam As Integer, ByVal lpvParam As String, ByVal fuWinIni As Integer) As Integer
End Function
Private Const SPI_SETSCREENSAVETIMEOUT As Int32 = 15
Public Sub KeepMonitorActive()
SetThreadExecutionState(EXECUTION_STATE.ES_DISPLAY_REQUIRED + EXECUTION_STATE.ES_CONTINUOUS) 'Do not Go To Sleep
End Sub
Public Sub RestoreMonitorSettings()
SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS) 'Restore Previous Settings, ie, Go To Sleep Again
End Sub

Create a service to execute an exe after one screen opens in different exe ( VB.NET)

My question maybe not be very clear, but I just want to know how this process is called or references needed to create something similar, so I can investigate on my own ( but if you have code is welcome.. LOL...)
Basically I have 2 desktop programs ( A and B). For A, I do not have the source code, for B I do. What I need is to create some service/program that after a screen pops up from program A, automatically runs B. IN other words, capture the moment a specific screen is shown in A and execute B.
My real life scenario is that I have a very basic POS where I can't collect customer demographics ( zip code, etc), so I created a second application to capture that but my cashiers are always forgetting to run the program and I need to find a way to run it after a screen is shown ( let's say the "Change Due" in the POS, so they don't forget to run it.
Any pointings will be appreciated!
Thanks
So here's a very quick example of how you can do this with VB which should be very easy to convert to C# if needed. The code search visible windows by title. If your open window doesn't have a title you'll have to work a little more. You can probably find the title of your main app and just enumerate its child windows.
First, some unmanaged code to talk to Win32 directly:
Option Strict On
Option Explicit On
Imports System.Runtime.InteropServices
Imports System.Text
Public Class Unmanaged
<DllImport("user32.dll")>
Public Shared Function EnumWindows(ByVal lpEnumFunc As CallBack, ByVal lParam As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("user32.dll", SetLastError:=True)>
Public Shared Function GetWindowLong(ByVal hWnd As IntPtr, ByVal nIndex As Integer) As Integer
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Public Shared Function GetWindowText(ByVal hwnd As IntPtr, ByVal lpString As StringBuilder, ByVal cch As Integer) As Integer
End Function
<DllImport("user32.dll", SetLastError:=True)> _
Public Shared Function IsWindowVisible(ByVal hWnd As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
Public Const SW_SHOW = 5
Public Const SW_RESTORE = 9
Public Const GW_OWNER = 4
Public Const GWL_HWNDPARENT = (-8)
Public Const GWL_EXSTYLE = (-20)
Public Const WS_EX_TOOLWINDOW = &H80
Public Const WS_EX_APPWINDOW = &H40000
Public Delegate Function CallBack(ByVal hwnd As IntPtr, ByVal lParam As Integer) As Boolean
End Class
Then a non-GUI module which should be set as the startup object:
Option Explicit On
Option Strict On
Module Module1
''//Code loosely base on http://msdntracker.blogspot.com/2008/03/list-currently-opened-windows-with.html
''//This is the title of the window that we are looking for
Public ReadOnly WatchForTitle As String = "About Mozilla Firefox"
''//This is the form that we will show when we find the above
Private MainForm As Form1
<STAThread()>
Public Sub Main()
''//Create the form but don not show it
MainForm = New Form1()
''//Create an infinite loop that checks to see if the target window is open and sleeps for a bit between checks
Do While True
Unmanaged.EnumWindows(AddressOf fEnumWindowsCallBack, IntPtr.Zero)
''//Sleep for a bit
System.Threading.Thread.Sleep(500)
Loop
End Sub
Private Function fEnumWindowsCallBack(ByVal hwnd As IntPtr, ByVal lParam As Integer) As Boolean
''//Ignore our own handle
If hwnd <> Form1.Handle Then
''//Make sure its visible
If Unmanaged.IsWindowVisible(hwnd) Then
Dim lExStyle = Unmanaged.GetWindowLong(hwnd, Unmanaged.GWL_EXSTYLE)
''//We probably want to ignore tool windows, but remove this if needed
If (((lExStyle And Unmanaged.WS_EX_TOOLWINDOW) = 0)) Then
''//Create a buffer to store the title of the window
Dim sWindowText As New System.Text.StringBuilder(256)
''//Get the title of the window
Dim lReturn = Unmanaged.GetWindowText(hwnd, sWindowText, sWindowText.Length - 1)
''//When you are looking for window title uncomment this line
'Trace.WriteLine(sWindowText)
''//Sanity check, make sure we found a window title
If lReturn <> 0 Then
''//See if it matches what we are looking for
If sWindowText.ToString() = WatchForTitle Then
''//If so, show our form
Form1.ShowDialog()
End If
End If
End If
End If
End If
fEnumWindowsCallBack = True
End Function
End Module
Lastly create a regular Windows Form called Form1 (or whatever you want, you'll just need to change it in the Module above).
If you test this it will pop open the form if you go to Firefox's Help->About menu.
I should point out, this is just a start. You'll want to perform better error checking and handle when the program closes or exists or whatever.
It's very unlikely that there is any 'good' way to interact with program A. There won't be a traditional 'event' that fires or anything like that.
Your best bet is going to be looking at some WIN32 API calls. For example, you can use GetPixel() to return the color at a specific location on the screen. So, if program A displays a particular image or screen that is measurably different from any other screen, you can write code that monitors the screen and checks for a match. When the match is found you can execute any code you want, including launching B.