以下是适用于我的本地Windows 8和VS .NET 2015环境的控制台应用程序的C#代码段。当我在本地Windows 8计算机上的管理员DOS / CMD窗口中运行控制台应用程序时,它也可以工作。
使用Windows远程桌面连接到Windows 2012 R2服务器时,控制台应用程序(以管理员身份打开的DOS / CMD窗口)不接受ESC键。
do
{
while (!Console.KeyAvailable)
{
// Do nothing while waiting for input
}
} while (Console.ReadKey(true).Key != ConsoleKey.Escape);
我知道Windows 2012 R2在使用远程桌面时具有特殊命令的特殊键,但是,这是ESC键不能与远程桌面一起使用到Windows 2012 R2 在DOS / CMD窗口。< / p>
我知道我可以使用不同的键(或其他组合),但我想知道为什么在这种情况下DOS /控制台窗口没有“接受”ESC键。
[编辑]: 好的,我需要在这里更具体。
我真的试图将EXE作为控制台应用程序运行。我发布的代码在Windows 2008中工作,但等待还有更多!在将结果输出到CMD / DOS提示符之前,我必须首先附加到现有的Parent CMD窗口。我正在使用以下URL中的代码来创建新的AllocConsole()或AttachConsole()。 http://www.jankowskimichal.pl/en/2011/12/wpf-hybrid-application-with-parameters/
在Windows Server 2008和Windows Server 2012上,它始终使用Console.Write ....编写我编码的所有内容。
但是,在Windows Server 2012中,此代码不再使用ReadKey()或上面最初发布的代码来输入。
代码片段(bool“show”= true会附加到控制台; false分离)。同样,在所有情况下都可以输出,但是没有在Console.ReadKey()中输入我的输入。
//Declarations area
[DllImport("kernel32.dll",
EntryPoint = "AllocConsole",
SetLastError = true,
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern bool AllocConsole();
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool FreeConsole();
[DllImport("kernel32", SetLastError = true)]
private static extern bool AttachConsole(int dwProcessId);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", SetLastError = true)]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
private enum ConsoleCtrlEvent
{
CTRL_C = 0,
CTRL_BREAK = 1,
CTRL_CLOSE = 2,
CTRL_LOGOFF = 5,
CTRL_SHUTDOWN = 6
}
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool GenerateConsoleCtrlEvent(ConsoleCtrlEvent sigevent, int dwProcessGroupId);
[DllImport("User32.Dll", EntryPoint = "PostMessageA")]
private static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
[SNIP]
//Caller:
//Attach or create a console window to display information to the user
DoConsoleWindow(true);
//Determine if user has administrator privileges
if (UserHasAdminPrivileges(args))
{
//Write information to the console
HandleCommandArgs(args);
}
DoConsoleWindow(false);
[SNIP]
private static void DoConsoleWindow(bool show)
{
if (show == true)
{
ptr = GetForegroundWindow();
int u;
GetWindowThreadProcessId(ptr, out u);
process = Process.GetProcessById(u);
if (process.ProcessName == "cmd") //Is the uppermost window a cmd process?
{
AttachConsole(process.Id);
attachedExisting = true;
}
else
{
//no console AND we're in console mode ... create a new console.
AllocConsole();
}
}
else
{
try
{
//Must pause for 2 seconds to allow display of data to catch up?
Thread.Sleep(2000);
//Send the {ENTER} Key to the console.
PostMessage(ptr, WM_KEYDOWN, VK_RETURN, 0);
FreeConsole();
if (process != null)
{
if (attachedExisting != true)
{
process.Close();
}
}
}
catch (Exception ex)
{
Logger.Log(TraceEventType.Error,
string.Format("{0} failed handling console close", serviceName),
string.Format("{0} failed handling console close: {1}",
serviceName, ex.ToString()),
serviceLogContext);
}
}
}
答案 0 :(得分:0)
让我们来看看你的代码
do
{
while (!Console.KeyAvailable)
{
// Do nothing while waiting for input
}
} while (Console.ReadKey(true).Key != ConsoleKey.Escape);
部分
while (!Console.KeyAvailable)
是一个热循环。一个CPU核心将在100%轮询KeyAvailable附近运行。在我的8核机器上,代码仍然响应,并在按下ConsoleKey.Escape时终止。但是,这是不必要的低效率,如果您只有一个或有限的CPU核心,可能会导致错过按键事件。
重写为更高效的
do
{
} while (Console.ReadKey(true).Key != ConsoleKey.Escape);
并查看问题是否消失。
我在通过远程桌面访问的Windows 2012 R2服务器上运行了原始代码和我的原始代码。两种变体都有效。我在该服务器上有几个可用的CPU内核,其中一个确实使用您的代码100%。