vb.netwinformsconsole

How to know if application was run from console or explorer?


I'm writing a small application that should run both as winform mode or console mode. The problem is that I don't know how my application was started-up. If it was started-up using console it should do some stuff, otherwise it should display a winform.

Friend NotInheritable Class Program
    Shared Sub Main()

        If The application was run in console mode then
            'Run console processes
        Else
            'Open winform
            Application.Run(New Form1)
        End If
    End Sub
End Class

What can I try to resolve this?


Solution

  • I found an answer for what you need, but it's in C#. You can simply use a C# to VB.net converter if you don't know C#, or convert it manually

    Found from a similar question: https://stackoverflow.com/a/3346055/1388267

    /// <summary>
    /// A utility class to determine a process parent.
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct ParentProcessUtilities
    {
        // These members must match PROCESS_BASIC_INFORMATION
        internal IntPtr Reserved1;
        internal IntPtr PebBaseAddress;
        internal IntPtr Reserved2_0;
        internal IntPtr Reserved2_1;
        internal IntPtr UniqueProcessId;
        internal IntPtr InheritedFromUniqueProcessId;
    
        [DllImport("ntdll.dll")]
        private static extern int NtQueryInformationProcess(IntPtr processHandle, int processInformationClass, ref ParentProcessUtilities processInformation, int processInformationLength, out int returnLength);
    
        /// <summary>
        /// Gets the parent process of the current process.
        /// </summary>
        /// <returns>An instance of the Process class.</returns>
        public static Process GetParentProcess()
        {
            return GetParentProcess(Process.GetCurrentProcess().Handle);
        }
    
        /// <summary>
        /// Gets the parent process of specified process.
        /// </summary>
        /// <param name="id">The process id.</param>
        /// <returns>An instance of the Process class.</returns>
        public static Process GetParentProcess(int id)
        {
            Process process = Process.GetProcessById(id);
            return GetParentProcess(process.Handle);
        }
    
        /// <summary>
        /// Gets the parent process of a specified process.
        /// </summary>
        /// <param name="handle">The process handle.</param>
        /// <returns>An instance of the Process class.</returns>
        public static Process GetParentProcess(IntPtr handle)
        {
            ParentProcessUtilities pbi = new ParentProcessUtilities();
            int returnLength;
            int status = NtQueryInformationProcess(handle, 0, ref pbi, Marshal.SizeOf(pbi), out returnLength);
            if (status != 0)
                throw new Win32Exception(status);
    
            try
            {
                return Process.GetProcessById(pbi.InheritedFromUniqueProcessId.ToInt32());
            }
            catch (ArgumentException)
            {
                // not found
                return null;
            }
        }
    }
    

    You can get the handle of the parent process, then check its name to know whether it's explorer or command prompt

    EDIT: Just got it converted to VB.net so you can use it directly:

    ''' <summary>
    ''' A utility class to determine a process parent.
    ''' </summary>
    <StructLayout(LayoutKind.Sequential)> _
    Public Structure ParentProcessUtilities
        ' These members must match PROCESS_BASIC_INFORMATION
        Friend Reserved1 As IntPtr
        Friend PebBaseAddress As IntPtr
        Friend Reserved2_0 As IntPtr
        Friend Reserved2_1 As IntPtr
        Friend UniqueProcessId As IntPtr
        Friend InheritedFromUniqueProcessId As IntPtr
    
        <DllImport("ntdll.dll")> _
        Private Shared Function NtQueryInformationProcess(processHandle As IntPtr, processInformationClass As Integer, ByRef processInformation As ParentProcessUtilities, processInformationLength As Integer, ByRef returnLength As Integer) As Integer
        End Function
    
        ''' <summary>
        ''' Gets the parent process of the current process.
        ''' </summary>
        ''' <returns>An instance of the Process class.</returns>
        Public Shared Function GetParentProcess() As Process
            Return GetParentProcess(Process.GetCurrentProcess().Handle)
        End Function
    
        ''' <summary>
        ''' Gets the parent process of specified process.
        ''' </summary>
        ''' <param name="id">The process id.</param>
        ''' <returns>An instance of the Process class.</returns>
        Public Shared Function GetParentProcess(id As Integer) As Process
            Dim process__1 As Process = Process.GetProcessById(id)
            Return GetParentProcess(process__1.Handle)
        End Function
    
        ''' <summary>
        ''' Gets the parent process of a specified process.
        ''' </summary>
        ''' <param name="handle">The process handle.</param>
        ''' <returns>An instance of the Process class.</returns>
        Public Shared Function GetParentProcess(handle As IntPtr) As Process
            Dim pbi As New ParentProcessUtilities()
            Dim returnLength As Integer
            Dim status As Integer = NtQueryInformationProcess(handle, 0, pbi, Marshal.SizeOf(pbi), returnLength)
            If status <> 0 Then
                Throw New Win32Exception(status)
            End If
    
            Try
                Return Process.GetProcessById(pbi.InheritedFromUniqueProcessId.ToInt32())
            Catch generatedExceptionName As ArgumentException
                ' not found
                Return Nothing
            End Try
        End Function
    End Structure