none
Open Process in Minimized State RRS feed

  • 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).aspx

    Thursday, 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