How to Check If the Program Is Run from a Console

How to check if the program is run from a console?

You can use GetConsoleWindow, GetWindowThreadProcessId and GetCurrentProcessId methods.

1) First you must retrieve the current handle of the console window using the GetConsoleWindow function.

2) Then you get the process owner of the handle of the console window.

3) Finally you compare the returned PID against the PID of your application.

Check this sample (VS C++)

#include "stdafx.h"
#include <iostream>
using namespace std;
#if _WIN32_WINNT < 0x0500
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0500
#endif
#include <windows.h>
#include "Wincon.h"

int _tmain(int argc, _TCHAR* argv[])
{
HWND consoleWnd = GetConsoleWindow();
DWORD dwProcessId;
GetWindowThreadProcessId(consoleWnd, &dwProcessId);
if (GetCurrentProcessId()==dwProcessId)
{
cout << "I have my own console, press enter to exit" << endl;
cin.get();
}
else
{
cout << "This Console is not mine, good bye" << endl;
}

return 0;
}

How to check if application runs on the command line?

The console() method of the System class returns a Console object if a console device is present, otherwise it returns null. The expression args.length > 0 checks if the String array args has any elements.

 public static void main(String[] args) {
Console console = System.console();
if (console != null || args.length > 0) {
// The app was started from a terminal
}
}

How to determine whether an console application started from within a console window?

I don't think there a built-in way to find this out. However I think you could look up the parent process and use that as fairly good heuristic. A quick test shows that the parent process is "explorer" when started from Run (Win+R) or double clicking. It would probably be cmd or powershell any other time except when debugging in VS, then devenv will be the parent process. Obviously, if there are scenarios where other tools will start an instance of the process you may want to give a command line parameter to force a particular behavior.

You code would look something like this:

// Note: Adapted from Hans Passant's answer linked above.
private static string GetParentProcessName()
{
var myId = Process.GetCurrentProcess().Id;
var query = string.Format("SELECT ParentProcessId FROM Win32_Process WHERE ProcessId = {0}", myId);
var search = new ManagementObjectSearcher("root\\CIMV2", query);
var queryObj = search.Get().OfType<ManagementBaseObject>().FirstOrDefault();
if (queryObj == null)
{
return null;
}
var parentId = (uint)queryObj["ParentProcessId"];
var parent = Process.GetProcessById((int)parentId);
return parent.ProcessName;
}

static void Main()
{
/*
Program code here.
*/
if (string.Equals(GetParentProcessName(), "explorer", StringComparison.InvariantCultureIgnoreCase))
{
Console.ReadLine();
}
}

How do I know if my app was opened from console or windows in C#

If you really want to know "where" your application has been started you have to know what is your parent process. In order to know your parent process you can read the solution of How to get parent process in .NET in managed way

Then you can for example check if your parent process name is explorer(windows) to open your application as a GUI.

sample code based on the solution provided in How to get parent process in .NET in managed way

namespace ConsoleApp1
{
public static class ProcessExtensions
{
private static string FindIndexedProcessName(int pid)
{
var processName = Process.GetProcessById(pid).ProcessName;
var processesByName = Process.GetProcessesByName(processName);
string processIndexdName = null;

for (var index = 0; index < processesByName.Length; index++)
{
processIndexdName = index == 0 ? processName : processName + "#" + index;
var processId = new PerformanceCounter("Process", "ID Process", processIndexdName);
if ((int)processId.NextValue() == pid)
{
return processIndexdName;
}
}

return processIndexdName;
}
private static Process FindPidFromIndexedProcessName(string indexedProcessName)
{
var parentId = new PerformanceCounter("Process", "Creating Process ID", indexedProcessName);
return Process.GetProcessById((int)parentId.NextValue());
}

public static Process Parent(this Process process)
{
return FindPidFromIndexedProcessName(FindIndexedProcessName(process.Id));
}
}

class Program
{
static void Main(string[] args)
{
Console.WriteLine(Process.GetCurrentProcess().Parent().ProcessName);
Console.ReadKey();
}
}
}

This code will outputs:

  • debug in visual studio: devenv
  • start from windows: explorer
  • start from cmd: cmd
  • start from powershell console: powershell
  • ...

How to check if program is running in local console?

Wouldn't the session number tell you this ?

ProcessIdToSessionId (GetCurrentProcessId(),&dwSessionNum)

You'd have to check the OS version as well, using GetVersionEx: for everything up to XP/Server 2003 session 0 is local (service or interactive console), anything higher is virtual. For Vista/2008 session 0 and 1 are both local (0 is service, 1 is console), everything else is virtual.

I'm guessing your Delphi units would declare the session number as var, so you wouldn't need the ampersand.

Find out if Java program is running from CMD or not

You can use System.console() which returns a console object if there is one attached to the Java Virtual Machine.

The method returns null if there is no console attached. Note that this is not 100% reliable. E.g. the method returns null for the internal console in the Eclipse IDE (which is actually bug #122429). It works with the Windows command line though.

An example could look like this:

public static void main(String[] args)
{
if (System.console() != null)
{
System.out.println("There is a console!");
}
else
{
JFrame frame = new JFrame("There is no console!");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(100, 100);
frame.setVisible(true);
}
}

Running this in the Windows command line with java -jar MyJar.jar will result in

There is a console!

being printed on the console.

Double clicking the .jar-file will show a JFrame.

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

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


Related Topics



Leave a reply



Submit