如何在.NET Core 6中获取错误输出的窗口句柄,与Visual Studio 2022中的.NET Framework相比

p5cysglq  于 2023-11-20  发布在  .NET
关注(0)|答案(1)|浏览(156)

对于上下文:
我负责将一个服务从.NET Framework 4.7.2升级到.NET Core 6。此服务由启动其他服务的主服务调用。此主服务是所有这些子服务的错误处理输出,我的服务也不例外。要获取此输出窗口的句柄以从我的服务写入日志,请使用Win32::GetStdHandle
这在.NET Framework中可以正常工作:当在Visual Studio 2022中启动应用程序进行调试时,所有日志记录信息都会转到Output窗口,当使用主服务启动时,它会记录到主服务控制台窗口。
问题是:在.NET Core 6中,在完全相同的条件下,Win32::GetStdHandle调用返回0,一个无效的句柄。

如何让GetStdHandle调用按预期工作,在.NET Core 6中返回正确的句柄,或任何变通方法来获取启动服务的进程的STD_ERROR_HANDLE?

在.NET Framework 4.7.2或.NET Core 6中可重现的示例:
(Note:将输出到控制台应用程序中的控制台,如果在Windows应用程序中并在Visual Studio中启动,则将输出到Output

  1. internal class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. SafeFileHandle handle;
  6. TestLogHandle test = new TestLogHandle();
  7. test.Init();
  8. test.SendMessage("aaaaaaa");
  9. }
  10. }
  11. class TestLogHandle
  12. {
  13. private SafeFileHandle _handle;
  14. private FileStream _stream;
  15. const int STD_ERROR_HANDLE = -12;
  16. private const int BUFFER_SIZE = 4096;
  17. [DllImport("kernel32.dll", SetLastError = true)]
  18. static extern IntPtr GetStdHandle(int nStdHandle);
  19. internal FileStream Init()
  20. {
  21. IntPtr iStdOut = GetStdHandle(STD_ERROR_HANDLE);
  22. _handle = new SafeFileHandle(iStdOut, true); //returns 0 in .NET Core 6
  23. if (_handle.IsInvalid)
  24. {
  25. throw new Exception("Invalid handle."); //throws in .NET Core 6
  26. }
  27. _stream = new FileStream(_handle, FileAccess.Write, BUFFER_SIZE, false);
  28. return _stream;
  29. }
  30. internal void SendMessage(string message)
  31. {
  32. if (_stream == null) return;
  33. var encoder = new ASCIIEncoding();
  34. byte[] messageBuffer = encoder.GetBytes(string.Format("{0}\r\n", message));
  35. _stream.Write(messageBuffer, 0, messageBuffer.Length);
  36. _stream.Flush();
  37. }
  38. }

字符串

wlp8pajw

wlp8pajw1#

在.NET Core 6中,与标准句柄(例如STD_ERROR_HANDLE)相关的行为已更改。具体而言,在.NET Core中,控制台应用程序默认情况下没有与其关联的控制台窗口。因此,GetStdHandle返回无效句柄。
您可以使用Console.OpenStandardError()来获取表示标准错误句柄的流。

  1. class TestLogHandle
  2. {
  3. private FileStream _stream;
  4. private const int BUFFER_SIZE = 4096;
  5. internal FileStream Init()
  6. {
  7. _stream = Console.OpenStandardError();
  8. if (_stream == null)
  9. {
  10. throw new Exception("Error opening standard error.");
  11. }
  12. return _stream;
  13. }
  14. internal void SendMessage(string message)
  15. {
  16. byte[] bytes = Encoding.UTF8.GetBytes(message);
  17. _stream.Write(bytes, 0, bytes.Length);
  18. }
  19. }

字符串

展开查看全部

相关问题