簡體   English   中英

確定控制台應用程序是從命令行還是從 Powershell 運行

[英]Determine whether Console Application is run from command line or Powershell

如何確定控制台應用程序是從 Powershell 還是從應用程序內部的標准命令行運行?

像這樣的事情可能比檢查窗口標題更可靠:

using System;
using System.Diagnostics;

Process p = Process.GetCurrentProcess();
PerformanceCounter parent = new PerformanceCounter("Process", "Creating Process ID", p.ProcessName);
int ppid = (int)parent.NextValue();

if (Process.GetProcessById(ppid).ProcessName == "powershell") {
  Console.WriteLine("running in PowerShell");
} else {
  Console.WriteLine("not running in PowerShell");
}

[ 來源]

一種解決方案是測試父進程的名稱,並將其與“cmd”或“powershell”進行比較。 這個線程是關於尋找父進程的。 我擴展了答案之一來回答您的問題。 請調查提供的答案是否是獲取父進程的最有效方法。 此解決方案展示了這種可能性,並不打算成為生產代碼

using System;
using System.Diagnostics;

public class TestPowershell {
    public static void Main() {
        string launcher = Process.GetCurrentProcess().Parent().ProcessName;
        if(launcher == "cmd") {
            Console.WriteLine("I was launched by cmd");
        }else if (launcher == "powershell") {
            Console.WriteLine("I was launched by PowerShell");
        }else {
            Console.WriteLine("not sure who launched me. But his name is: " + launcher);
        }
    }
}


// By Michael Hale: https://stackoverflow.com/questions/394816/how-to-get-parent-process-in-net-in-managed-way
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));
    }

}

// Define other methods and classes here

確定控制台應用程序是從 PowerShell 還是標准命令行運行的更好方法 (IMO) 是P/Invoke GetConsoleProcessList以獲取附加到控制台的進程列表,並使用OpenProcess / QueryFullProcessImageName檢查這些名稱過程。

例如,要確定應用程序是否是從 PowerShell 控制台運行的*:

using System;
using System.Runtime.InteropServices;
using System.Text;

namespace CheckIfRunningFromPowerShell
{
    class Program
    {
        static void Main(string[] args)
        {
            if (PowerShellUtils.IsCurrentProcessRunningFromPowerShellIse())
            {
                Console.WriteLine("PowerShell, yay!");
            }
            else
            {
                Console.WriteLine("NOPE :(");
            }
        }
    }

    public class PowerShellUtils
    {
        public static bool IsCurrentProcessRunningFromPowerShellIse()
        {
            var processList = new uint[1];
            var count = GetConsoleProcessList(processList, 1);
            if (count <= 0)
            {
                return false;
            }

            processList = new uint[count];
            count = GetConsoleProcessList(processList, (uint)processList.Length);
            for (var pid = 0; pid < count; pid++)
            {
                var buffer = new StringBuilder(260);
                var dwSize = (uint) buffer.Capacity;

                var process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, (int) processList[pid]);
                QueryFullProcessImageName(process, 0, buffer, ref dwSize);

                var exeFileName = buffer.ToString(0, (int) dwSize);

                // Name of EXE is PowerShell_ISE.exe or powershell.exe
                if (exeFileName.IndexOf("PowerShell_ISE.exe", StringComparison.OrdinalIgnoreCase) != -1 ||
                    exeFileName.IndexOf("powershell.exe", StringComparison.OrdinalIgnoreCase) != -1)
                {
                    return true;
                }
            }

            return false;
        }

        [DllImport("kernel32.dll", ExactSpelling=true, EntryPoint="QueryFullProcessImageNameW", CharSet = CharSet.Unicode)]
        internal static extern bool QueryFullProcessImageName(IntPtr hProcess, uint dwFlags, StringBuilder lpExeName, ref uint lpdwSize);

        [DllImport("kernel32.dll", ExactSpelling=true)]
        internal static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, int dwProcessId);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern uint GetConsoleProcessList(uint[] processList, uint processCount);

        // ReSharper disable InconsistentNaming
        internal const uint PROCESS_QUERY_LIMITED_INFORMATION = 0x1000;
        // ReSharper restore InconsistentNaming
    }
}

您可以修改上面的代碼來檢查 cmd.exe 等。


但是,如果您要做的只是確定程序退出后控制台是否會繼續存在(例如,以便您可以在程序退出之前提示用戶按Enter ,那么您只需要做的是檢查您的進程是否是唯一附加到控制台的進程。 如果是,那么當您的進程退出時控制台將被銷毀。 如果有其他進程附加到控制台,那么控制台將繼續存在(因為您的程序不會是最后一個)。

例如:

using System;
using System.Runtime.InteropServices;

namespace CheckIfConsoleWillBeDestroyedAtTheEnd
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            // ...

            if (ConsoleWillBeDestroyedAtTheEnd())
            {
                Console.WriteLine("Press any key to continue . . .");
                Console.ReadLine();
            }
        }

        private static bool ConsoleWillBeDestroyedAtTheEnd()
        {
            var processList = new uint[1];
            var processCount = GetConsoleProcessList(processList, 1);
            
            return processCount == 1;
        }

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern uint GetConsoleProcessList(uint[] processList, uint processCount);
    }
}

(*) 改編自此處找到的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM