我注意到一些非常奇怪的事情。我试图将CRT函数称为“putchar”,但无法使其工作。所以我仔细检查了我没有遗漏的东西,我直接从MSDN上的P / Invoke教程复制代码,看看它是否有效。
http://msdn.microsoft.com/en-us/library/aa288468%28VS.71%29.aspx
你会注意到他们导入了“put”。
所以我测试了从MSDN复制的确切代码。它没用!所以现在我感到沮丧。我以前从未遇到过这个问题。
然后我就这样碰巧运行没有调试(点击ctrl + f5),它运作正常!我测试了输出到控制台的其他函数,调试时它们都不起作用,但是在没有调试时都能正常工作。
然后我写了一个简单的C dll,它导出了一个名为“PrintChar(char c)”的函数。当我从C#调用该函数时,即使我正在调试它也没有任何问题。这是什么处理?
答案 0 :(得分:2)
这是一个糟糕的例子,使用C-Runtime Library DLL来调用puts。继续阅读教程,因为那里有很好的信息,但是尝试改为调用Win32 API。
以下是对p / invoke的更好介绍:http://msdn.microsoft.com/en-us/magazine/cc164123.aspx
它已经过时了,但信息仍然很好。
<强>被修改强>
我的解释是错误的。
我去寻找正确的解释,我发现C-Runtime puts方法和.NET Framework Console.Write方法在它们写入控制台的方式上有所不同(Console.Write适用于p / invoke to puts的位置不)。我想也许答案就在那里,所以我掀起了这个示威:
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
class Program
{
public static void Main()
{
int written;
string outputString = "Hello, World!\r\n";
byte[] outputBytes = Encoding.Default.GetBytes(outputString);
//
// This is the way the C-Runtime Library method puts does it
IntPtr conOutHandle = CreateFile("CONOUT$", 0x40000000, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
WriteConsole(conOutHandle, outputBytes, outputString.Length, out written, IntPtr.Zero);
//
// This is the way Console.Write does it
IntPtr stdOutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
WriteFile(stdOutputHandle, outputBytes, outputBytes.Length, out written, IntPtr.Zero);
// Pause if running under debugger
if (Debugger.IsAttached)
{
Console.Write("Press any key to continue . . . ");
Console.ReadKey();
}
}
const int STD_OUTPUT_HANDLE = -11;
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll", SetLastError = true)]
static extern int WriteFile(IntPtr handle, [In] byte[] bytes, int numBytesToWrite, out int numBytesWritten, IntPtr mustBeZero);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr CreateFile(string lpFileName, int dwDesiredAccess, FileShare dwShareMode, IntPtr securityAttrs, FileMode dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
static extern bool WriteConsole(IntPtr hConsoleOutput, [In] byte[] lpBuffer, int nNumberOfCharsToWrite, out int lpNumberOfCharsWritten, IntPtr mustBeZero);
}
这两个都在调试器下成功输出,即使启用了托管过程。所以这是一个死胡同。
我想分享一下,如果它导致别人弄清楚为什么它会发生 - 汉斯?
答案 1 :(得分:2)
Visual Studio托管过程能够将控制台输出重定向到“输出”窗口。究竟是如何设法完成的,根本没有记录,但它会妨碍这里。它拦截WriteFile()调用,该调用生成puts()。
的输出Project + Properties,Debug选项卡,取消选中“启用Visual Studio托管过程”。在同一页面上,启用非托管调试也可以解决问题。