Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Visual studio 如何检测“是否”;按任意键继续&引用;将显示什么?_Visual Studio_Ide_Console Application_Visual Studio Debugging - Fatal编程技术网

Visual studio 如何检测“是否”;按任意键继续&引用;将显示什么?

Visual studio 如何检测“是否”;按任意键继续&引用;将显示什么?,visual-studio,ide,console-application,visual-studio-debugging,Visual Studio,Ide,Console Application,Visual Studio Debugging,在Visual Studio中运行控制台应用程序时,根据您的设置,它将在程序退出后添加提示: 按任意键继续 我已经找到了如何检测我是否在调试器下运行的方法(使用debugger.IsAttached),但它没有帮助。按CTRL-F5启动而不调试将此标志设置为false,但仍显示提示 我想检测到这一点,因为我想显示我自己的消息并等待按键,但不进行双重按键检查 我不想破坏我的Visual Studio常规设置。如果我可以用一种可以签入源代码管理的方式来禁用这个项目,那也可以 使用什么机制附加此提示,

在Visual Studio中运行控制台应用程序时,根据您的设置,它将在程序退出后添加提示:

按任意键继续

我已经找到了如何检测我是否在调试器下运行的方法(使用
debugger.IsAttached
),但它没有帮助。按CTRL-F5启动而不调试将此标志设置为
false
,但仍显示提示

我想检测到这一点,因为我想显示我自己的消息并等待按键,但不进行双重按键检查

我不想破坏我的Visual Studio常规设置。如果我可以用一种可以签入源代码管理的方式来禁用这个项目,那也可以

使用什么机制附加此提示,以及如何检测它


或者如何根据项目禁用它,并将此更改检查到源代码管理中?

听起来此提示是由
暂停
命令提供的。此命令由Visual Studio自动添加

在Visual Studio之外运行项目时,没有理由“检测”此命令。您可以放心地假设它不会添加到您的程序中。这意味着您可以继续添加所需的任何提示,类似于:

Console.WriteLine("Press any key...");
Console.Read();

该消息与您的程序无关。您可以向您的程序中添加任何您喜欢的内容,并且如果您从命令提示符下运行它,它将以相同的方式执行


VisualStudio显示它的目的是向您显示它的执行已完成运行,以便您知道它已正确结束。如果您想跳过它,您可以尝试“不调试运行”(或类似的内容;它就在“使用调试器运行”的下方)。

将以下代码添加到控制台应用程序:

public static class Extensions {
    [DllImport("kernel32.dll")]
    static extern IntPtr OpenThread(uint dwDesiredAccess, bool bInheritHandle, uint dwThreadId);

    [DllImport("kernel32.dll")]
    static extern bool TerminateThread(IntPtr hThread, uint dwExitCode);

    public static Process GetParentProcess(this Process x) {
        return (
            from it in (new ManagementObjectSearcher("root\\CIMV2", "select * from Win32_Process")).Get().Cast<ManagementObject>()
            where (uint)it["ProcessId"]==x.Id
            select Process.GetProcessById((int)(uint)it["ParentProcessId"])
            ).First();
    }

    public static IEnumerable<Process> GetChildProcesses(this Process x) {
        return (
            from it in (new ManagementObjectSearcher("root\\CIMV2", "select * from Win32_Process")).Get().Cast<ManagementObject>()
            where (uint)it["ParentProcessId"]==x.Id
            select Process.GetProcessById((int)(uint)it["ProcessId"])
            );
    }

    public static void Abort(this ProcessThread x) {
        TerminateThread(OpenThread(1, false, (uint)x.Id), 1);
    }
}
公共静态类扩展{
[DllImport(“kernel32.dll”)]
静态外部IntPtr OpenThread(uint-dwDesiredAccess、bool-bInheritHandle、uint-dwThreadId);
[DllImport(“kernel32.dll”)]
静态外部bool TerminateThread(IntPtr hThread,uint dwExitCode);
公共静态进程GetParentProcess(此进程x){
返回(
从(新的ManagementObjectSearcher(“根\\CIMV2”,“从Win32_进程中选择*)).Get().Cast()中的
其中(uint)it[“ProcessId”]==x.Id
选择Process.GetProcessById((int)(uint)it[“ParentProcessId”])
).First();
}
公共静态IEnumerable GetChildProcess(此进程x){
返回(
从(新的ManagementObjectSearcher(“根\\CIMV2”,“从Win32_进程中选择*)).Get().Cast()中的
其中(uint)it[“ParentProcessId”]==x.Id
选择Process.GetProcessById((int)(uint)it[“ProcessId”])
);
}
公共静态无效中止(此ProcessThread x){
TerminateThread(OpenThread(1,false,(uint)x.Id),1);
}
}
然后按如下方式修改代码:

class Program {
    static void Main(String[] args) {
        // ... (your code might goes here)

        try {
            Process.GetCurrentProcess().GetParentProcess().Threads.Cast<ProcessThread>().Single().Abort();
        }
        catch(InvalidOperationException) {
        }

        Console.Write("Press ONLY key to continue . . . ");
        Console.ReadKey(true);
    }
}
类程序{
静态void Main(字符串[]参数){
//…(您的代码可能在这里)
试一试{
Process.GetCurrentProcess().GetParentProcess().Threads.Cast().Single().Abort();
}
捕获(无效操作异常){
}
控制台。写入(“仅按键继续…”);
Console.ReadKey(true);
}
}
所以,我们期待的一切现在都完成了。我认为这是解决问题的办法。它可以在
windowsxpsp3
下工作,我想它可以在较新的Windows操作系统上工作。在VisualStudio下,应用程序始终是一个衍生过程。在旧的Visual C++ 6中,IDE通过调用<代码> VCSPAWN.exe < /C>来生成。在Visual Studio 2010中,应用程序在不进行调试的情况下启动时使用以下命令行运行:

%comspec%/c“您的应用程序文件名”&暂停

因此,以全面管理的方式实现目标是不可能的;因为它不是应用程序域下的

这里我们使用
WMI
的托管方式来枚举进程,并封装非托管的
WINAPI
s来终止
ProcessThread
s,因为
ProcessThread
通常不应该中止;它像只读的东西一样提供

如上所述,应用程序是使用特定的命令行生成的;它需要一个线程创建一个进程签名,因此我们使用
single()
方法检索该线程并终止它

当我们在现有的命令提示符下启动应用程序时,它与启动而不调试的场景完全相同。此外,启动调试时,应用程序进程由
devenv.exe
创建。它有很多线程,我们知道它不会中止任何线程,只需提示并等待按键。这种情况类似于双击或从上下文菜单启动应用程序。通过这种方式,应用程序进程由系统shell创建,通常是
Explorer.exe
,它也有很多线程

事实上,如果我们能够成功中止线程,这意味着我们有权终止父进程。但我们确实不需要这样做。我们只需要中止唯一的线程,当进程没有更多线程时,系统会自动终止进程。通过识别调用进程是
%comspec%
来终止父进程是做同样事情的另一种方法,但这是一个危险的过程。因为生成应用程序的进程可能有其他线程,这些线程的数量可以是任意的,因此创建一个与
%comspec%
匹配的进程。您可能会粗心大意地终止流程中的关键工作,或者只是增加了检查流程是否可以安全终止的复杂性。所以我认为<强>单
class Program
{
    static void Main(string[] args)
    {
        // do your stuff

        if (!WasStartedWithPause())
        {
            Console.WriteLine("Press any key to continue . . . ");
            Console.ReadKey(true);
        }
    }
}

public static bool WasStartedWithPause()
{
    // Here, I reuse my answer at http://stackoverflow.com/questions/394816/how-to-get-parent-process-in-net-in-managed-way
    Process parentProcess = ParentProcessUtilities.GetParentProcess();

    // are we started by cmd.exe ?
    if (string.Compare(parentProcess.MainModule.ModuleName, "cmd.exe", StringComparison.OrdinalIgnoreCase) != 0)
        return false;

    // get cmd.exe command line
    string cmdLine = GetProcessCommandLine(parentProcess);

    // was it started with a pause?
    return cmdLine != null & cmdLine.EndsWith("& pause\"");
}

public static string GetProcessCommandLine(Process process)
{
    if (process == null)
        throw new ArgumentNullException("process");

    // use WMI to query command line
    ManagementObjectCollection moc = new ManagementObjectSearcher("SELECT CommandLine FROM Win32_Process WHERE ProcessId=" + process.Id).Get();
    foreach (ManagementObject mo in moc)
    {
        return (string)mo.Properties["CommandLine"].Value;
    }
    return null;
}
      cout<<"your message here"
      _getch()
if (Debugger.IsAttached)
{
    Console.Write("Press any key to continue . . . ");
    Console.ReadKey();
}