You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中调用WriteFile()修改文件首字节报错,求助解决方案

问题:C#调用WriteFile修改文件头报错的解决方法

问题背景

我原本用C语言实现了修改转储文件前几个字节的功能,代码如下:

SetFilePointer(hDmpFile, 0, 0, FILE_BEGIN);
WriteFile(hDmpFile, "AA", 2, NULL, NULL);

现在想在C#里实现同样功能,但调用WriteFile时抛出NotImplementedException,我的C#代码片段如下:

public enum EMoveMethod : uint
{
    Begin = 0,
    Current = 1,
    End = 2
}

[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint SetFilePointer(
    [In] SafeFileHandle hFile,
    [In] int lDistanceToMove,
    [Out] out int lpDistanceToMoveHigh,
    [In] EMoveMethod dwMoveMethod);

[DllImport("kernel32.dll", BestFitMapping = true, CharSet = CharSet.Ansi)]
public static extern bool WriteFile(
    IntPtr hFile,
    System.Text.StringBuilder lpBuffer,
    uint nNumberOfBytesToWrite,
    out uint lpNumberOfBytesWritten,
    [In] ref System.Threading.NativeOverlapped lpOverlapped);

// 调用部分
int moveDistanceHighBits = 0;
uint test = SetFilePointer(hDmpFile, 0, out moveDistanceHighBits, EMoveMethod.Begin);
uint test2 = WriteFile(hDmpFile, "AA", 2, null, null);
hDmpFile.Dispose();

报错信息:

Unhandled Exception: System.NotImplementedException: The method or operation is not implemented.
   at Foo.Program.WriteFile(SafeFileHandle hDmpFile, String v1, Int32 v2, Object value1, Object value2)
   at Foo.Program.Execute(String[] args)
   at Foo.Program.Main(String[] args)

注:我完全不懂编程,也从未接触过C#。


错误原因

你的WriteFile调用存在多处参数不匹配问题:

  • 参数类型不匹配:传入的SafeFileHandle和声明的IntPtr不匹配;传入字符串"AA"和声明要求的StringBuilder不匹配;最后两个参数直接传null,但声明要求的是out uint和ref NativeOverlapped,不能直接传空值。
  • 返回值类型不匹配:WriteFile实际返回bool,但你用uint类型接收。

最简单的解决方法(用C#原生API,无需调用Windows底层接口)

对于完全不懂C#的人,直接用C#自带的FileStream类更简单,代码直观且无需处理复杂的API声明:

using System.IO;

// 替换成你的转储文件路径
string filePath = "your_dump_file_path.dmp";

// using块会自动释放文件资源,不用手动处理
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
{
    // 定位到文件开头
    fs.Seek(0, SeekOrigin.Begin);
    // 把"AA"转成ASCII字节(和C代码行为一致)
    byte[] bytes = System.Text.Encoding.ASCII.GetBytes("AA");
    // 写入文件
    fs.Write(bytes, 0, bytes.Length);
}

如果非要用P/Invoke的修复方案

如果坚持要调用Windows底层API,修正后的代码如下:

using System;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32.SafeHandles;

public enum EMoveMethod : uint
{
    Begin = 0,
    Current = 1,
    End = 2
}

[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint SetFilePointer(
    [In] SafeFileHandle hFile,
    [In] int lDistanceToMove,
    [Out] out int lpDistanceToMoveHigh,
    [In] EMoveMethod dwMoveMethod);

// 修正WriteFile的API声明,匹配参数类型
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WriteFile(
    SafeFileHandle hFile,
    byte[] lpBuffer, // 用字节数组直接传递,避免字符串编码问题
    uint nNumberOfBytesToWrite,
    out uint lpNumberOfBytesWritten,
    IntPtr lpOverlapped); // 用IntPtr可以传IntPtr.Zero表示空指针

// 调用部分
int moveDistanceHighBits = 0;
SetFilePointer(hDmpFile, 0, out moveDistanceHighBits, EMoveMethod.Begin);

// 把"AA"转成ASCII字节
byte[] buffer = Encoding.ASCII.GetBytes("AA");
uint bytesWritten;
// 最后一个参数传IntPtr.Zero对应C代码里的NULL
bool writeSuccess = WriteFile(hDmpFile, buffer, 2, out bytesWritten, IntPtr.Zero);

hDmpFile.Dispose();

修复点说明:

  • 将WriteFile的第一个参数改为SafeFileHandle,和你持有的文件句柄类型匹配
  • 用byte[]代替StringBuilder,避免字符串转码的额外问题,和C代码行为一致
  • 最后一个参数改为IntPtr,传IntPtr.Zero即可表示C代码中的NULL
  • 用bool类型接收返回值,符合API实际返回类型
  • 必须声明out uint lpNumberOfBytesWritten变量,不能直接传null

内容的提问来源于stack exchange,提问作者Darktortue

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 09:50:33