Answered by:
Open Process in Minimized State

Question
-
Hello,
I'm trying to open a process (*note that I say process, I'm unable to find the programs titlebar title*) in a minimized state; this is what I've got:
Private Const SW_HIDE = 0 Private Sub Form648_Load(sender As Object, e As EventArgs) Handles MyBase.Load Process.Start("C:\Program Files\Random\Randoms.exe") Dim ClientProcess As Process = Process.GetProcessesByName("RandomSLtF").FirstOrDefault If ClientProcess IsNot Nothing Then SendMessage(ClientProcess.MainWindowHandle, SW_HIDE = 0) End If End Sub
Although this doesn't send an error, it doesn't work either.
If it matters, the window that I'm trying to open in a minimized state is top-most and has no titlebar (which means no manual minimize option)
Thanks for any help!
Thursday, October 26, 2017 9:08 PM
Answers
-
Sending SW_HIDE has no sense...
For example with Notepad :
Dim pr As Process = pr.Start(New ProcessStartInfo("notepad")) pr.WaitForInputIdle() Dim hWndTarget As IntPtr = pr.MainWindowHandle ShowWindow(hWndTarget, SW_SHOWMINIMIZED)
Declarations :
Public Const SW_SHOWMINIMIZED As Integer = 2 <DllImport("User32.dll", EntryPoint:="ShowWindow", SetLastError:=True)> Public Shared Function ShowWindow(ByVal hWnd As IntPtr, nShowCmd As Integer) As Boolean End Function
- Marked as answer by Nem Esised Thursday, October 26, 2017 10:31 PM
Thursday, October 26, 2017 9:45 PM -
The WaitForInputIdle method does not always work and is not really reliable for doing what it says it does. There is also no way to tell how long a process will take to load. It would depend on the process itself and if the system is busy or not at the time the process is starting. Using the Thread.Sleep method would be slightly more reliable but, it has its downfalls too.
Imports System.Runtime.InteropServices Public Class Form1 <DllImport("user32.dll", EntryPoint:="SendMessageW")> Public Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As UInteger, ByVal lParam As Integer) As Integer End Function Private Const WM_SYSCOMMAND As Integer = &H112 Private Const SC_MINIMIZE As Integer = &HF020 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim p As Process = Process.Start("C:\Users\?????\Documents\Visual Studio 2015\Projects\Borderless Test Form\Borderless Test Form\bin\Debug\Borderless Test Form.exe") Threading.Thread.Sleep(1000) 'wait 1 second SendMessageW(p.MainWindowHandle, WM_SYSCOMMAND, SC_MINIMIZE, 0) End Sub End Class
Here is a reliable method to detect when a window has actually been created...
Imports System.ComponentModel Imports System.Runtime.InteropServices Public Class Form1 Private hEventHook As IntPtr Private EventHookDel As New WINEVENTPROC(AddressOf EventCallback) Private Const WINEVENT_OUTOFCONTEXT As Integer = &H0 Private Const EVENT_OBJECT_CREATE As Integer = &H8000 Private Const WM_SYSCOMMAND As Integer = &H112 Private Const SC_MINIMIZE As Integer = &HF020 <DllImport("user32.dll", EntryPoint:="SendMessageW")> Public Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As UInteger, ByVal lParam As Integer) As Integer End Function <DllImport("user32.dll")> Private Shared Function SetWinEventHook(ByVal eventMin As UInteger, ByVal eventMax As UInteger, ByVal hmodWinEventProc As IntPtr, ByVal pfnWinEventProc As WINEVENTPROC, ByVal idProcess As UInteger, ByVal idThread As UInteger, ByVal dwFlags As UInteger) As IntPtr End Function <UnmanagedFunctionPointer(CallingConvention.StdCall)> Private Delegate Sub WINEVENTPROC(ByVal hWinEventHook As IntPtr, ByVal [event] As UInteger, ByVal hwnd As IntPtr, ByVal idObject As Integer, ByVal idChild As Integer, ByVal idEventThread As UInteger, ByVal dwmsEventTime As UInteger) <DllImport("user32.dll")> Private Shared Function UnhookWinEvent(ByVal hWinEventHook As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean End Function Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load hEventHook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE, IntPtr.Zero, EventHookDel, 0, 0, WINEVENT_OUTOFCONTEXT) End Sub Private Sub Form1_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing UnhookWinEvent(hEventHook) End Sub Private Filename As String = "C:\Users\?????\Documents\Visual Studio 2015\Projects\Borderless Test Form\Borderless Test Form\bin\Debug\Borderless Test Form.exe" Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Process.Start(Filename) End Sub Private Sub EventCallback(ByVal hWinEventHook As IntPtr, ByVal [event] As UInteger, ByVal hwnd As IntPtr, ByVal idObject As Integer, ByVal idChild As Integer, ByVal idEventThread As UInteger, ByVal dwmsEventTime As UInteger) If [event] = EVENT_OBJECT_CREATE Then Dim p As Process = Process.GetProcesses.Where(Function(x) x.MainWindowHandle = hwnd AndAlso x.ProcessName.ToLower = IO.Path.GetFileNameWithoutExtension(Filename).ToLower).FirstOrDefault If p IsNot Nothing Then SendMessageW(p.MainWindowHandle, WM_SYSCOMMAND, SC_MINIMIZE, 0) End If End If End Sub End Class
EDIT: Changed code a little. By the way, this editor for the forum SUCKS!!!!
If you say it can`t be done then i`ll try it
- Edited by IronRazerz Thursday, October 26, 2017 10:53 PM
- Marked as answer by Nem Esised Thursday, October 26, 2017 10:56 PM
Thursday, October 26, 2017 10:41 PM
All replies
-
Sending SW_HIDE has no sense...
For example with Notepad :
Dim pr As Process = pr.Start(New ProcessStartInfo("notepad")) pr.WaitForInputIdle() Dim hWndTarget As IntPtr = pr.MainWindowHandle ShowWindow(hWndTarget, SW_SHOWMINIMIZED)
Declarations :
Public Const SW_SHOWMINIMIZED As Integer = 2 <DllImport("User32.dll", EntryPoint:="ShowWindow", SetLastError:=True)> Public Shared Function ShowWindow(ByVal hWnd As IntPtr, nShowCmd As Integer) As Boolean End Function
- Marked as answer by Nem Esised Thursday, October 26, 2017 10:31 PM
Thursday, October 26, 2017 9:45 PM -
Private Const SW_HIDE = 0 Private Sub Form648_Load(sender As Object, e As EventArgs) Handles MyBase.Load Process.Start("C:\Program Files\Random\Randoms.exe") Dim ClientProcess As Process = Process.GetProcessesByName("RandomSLtF").FirstOrDefault If ClientProcess IsNot Nothing Then SendMessage(ClientProcess.MainWindowHandle, SW_HIDE = 0) End If End Sub
You should not use GetProcess to get the process handle of a process that you create. The override of the Process.Start method returns the process object. That object provides the methods needed to manage the process.
https://msdn.microsoft.com/en-us/library/0w4h05yb(v=vs.110).aspxThursday, October 26, 2017 10:03 PM -
As Acamar has pointed out, the StartInfo property should be used. In particular, set the StartInfo property's WindowStyle to Minimized.Thursday, October 26, 2017 10:28 PM
-
Thanks for the help Castorix31, and thanks for everyone's input :)Thursday, October 26, 2017 10:31 PM
-
The WaitForInputIdle method does not always work and is not really reliable for doing what it says it does. There is also no way to tell how long a process will take to load. It would depend on the process itself and if the system is busy or not at the time the process is starting. Using the Thread.Sleep method would be slightly more reliable but, it has its downfalls too.
Imports System.Runtime.InteropServices Public Class Form1 <DllImport("user32.dll", EntryPoint:="SendMessageW")> Public Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As UInteger, ByVal lParam As Integer) As Integer End Function Private Const WM_SYSCOMMAND As Integer = &H112 Private Const SC_MINIMIZE As Integer = &HF020 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim p As Process = Process.Start("C:\Users\?????\Documents\Visual Studio 2015\Projects\Borderless Test Form\Borderless Test Form\bin\Debug\Borderless Test Form.exe") Threading.Thread.Sleep(1000) 'wait 1 second SendMessageW(p.MainWindowHandle, WM_SYSCOMMAND, SC_MINIMIZE, 0) End Sub End Class
Here is a reliable method to detect when a window has actually been created...
Imports System.ComponentModel Imports System.Runtime.InteropServices Public Class Form1 Private hEventHook As IntPtr Private EventHookDel As New WINEVENTPROC(AddressOf EventCallback) Private Const WINEVENT_OUTOFCONTEXT As Integer = &H0 Private Const EVENT_OBJECT_CREATE As Integer = &H8000 Private Const WM_SYSCOMMAND As Integer = &H112 Private Const SC_MINIMIZE As Integer = &HF020 <DllImport("user32.dll", EntryPoint:="SendMessageW")> Public Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As UInteger, ByVal lParam As Integer) As Integer End Function <DllImport("user32.dll")> Private Shared Function SetWinEventHook(ByVal eventMin As UInteger, ByVal eventMax As UInteger, ByVal hmodWinEventProc As IntPtr, ByVal pfnWinEventProc As WINEVENTPROC, ByVal idProcess As UInteger, ByVal idThread As UInteger, ByVal dwFlags As UInteger) As IntPtr End Function <UnmanagedFunctionPointer(CallingConvention.StdCall)> Private Delegate Sub WINEVENTPROC(ByVal hWinEventHook As IntPtr, ByVal [event] As UInteger, ByVal hwnd As IntPtr, ByVal idObject As Integer, ByVal idChild As Integer, ByVal idEventThread As UInteger, ByVal dwmsEventTime As UInteger) <DllImport("user32.dll")> Private Shared Function UnhookWinEvent(ByVal hWinEventHook As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean End Function Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load hEventHook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE, IntPtr.Zero, EventHookDel, 0, 0, WINEVENT_OUTOFCONTEXT) End Sub Private Sub Form1_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing UnhookWinEvent(hEventHook) End Sub Private Filename As String = "C:\Users\?????\Documents\Visual Studio 2015\Projects\Borderless Test Form\Borderless Test Form\bin\Debug\Borderless Test Form.exe" Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Process.Start(Filename) End Sub Private Sub EventCallback(ByVal hWinEventHook As IntPtr, ByVal [event] As UInteger, ByVal hwnd As IntPtr, ByVal idObject As Integer, ByVal idChild As Integer, ByVal idEventThread As UInteger, ByVal dwmsEventTime As UInteger) If [event] = EVENT_OBJECT_CREATE Then Dim p As Process = Process.GetProcesses.Where(Function(x) x.MainWindowHandle = hwnd AndAlso x.ProcessName.ToLower = IO.Path.GetFileNameWithoutExtension(Filename).ToLower).FirstOrDefault If p IsNot Nothing Then SendMessageW(p.MainWindowHandle, WM_SYSCOMMAND, SC_MINIMIZE, 0) End If End If End Sub End Class
EDIT: Changed code a little. By the way, this editor for the forum SUCKS!!!!
If you say it can`t be done then i`ll try it
- Edited by IronRazerz Thursday, October 26, 2017 10:53 PM
- Marked as answer by Nem Esised Thursday, October 26, 2017 10:56 PM
Thursday, October 26, 2017 10:41 PM -
Thank you!Thursday, October 26, 2017 10:56 PM