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

如何用C#控制台程序实现记事本打开并自动保存文件?

问题:如何在C#中关闭记事本前自动保存文件?

我已经能通过C#打开并关闭指定的文本文件,代码如下:

using System.Diagnostics; 
class Program { 
    static void Main(string[] args) { 
        // 用记事本打开文件
        Process.Start("notepad.exe", @"myfile.txt"); 
        // 这里需要实现记事本自动保存文件的逻辑
        // 关闭记事本进程
        Process[] proc = Process.GetProcessesByName("notepad"); 
        proc[0].Kill(); 
    } 
}

但尝试发送Ctrl+S按键来实现自动保存时没有效果,请问有没有对应的.NET代码可以实现这个需求?谢谢。


解决方案

你遇到的问题其实挺常见的——直接模拟Ctrl+S经常因为记事本窗口没获得焦点而失效,这里给你两种更可靠的实现方式,尤其是第一种通过Windows API发送保存命令的方法,稳定性会高很多:

方式一:通过Windows API发送保存命令(推荐)

记事本的保存功能是通过窗口消息触发的,对应的是WM_COMMAND消息,命令ID为0x0006(也就是记事本内部的ID_FILE_SAVE)。我们可以直接找到记事本的窗口句柄,发送这个消息来触发保存,完全不需要模拟按键,也就不会有焦点问题。

先把需要的Win32 API导入进来,然后写逻辑:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

class Program
{
    // 导入查找窗口的Win32 API
    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

    // 导入发送消息的API
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

    // 定义需要用到的常量
    private const uint WM_COMMAND = 0x0111;
    private const int ID_FILE_SAVE = 0x0006;

    static void Main(string[] args)
    {
        // 启动记事本并打开目标文件
        var notepadProcess = Process.Start("notepad.exe", @"myfile.txt");
        // 等一等,让记事本窗口完全初始化
        notepadProcess.WaitForInputIdle();

        // 找到记事本的窗口句柄——窗口标题格式是「文件名 - Notepad」
        IntPtr notepadWindow = FindWindow("Notepad", "myfile.txt - Notepad");

        if (notepadWindow != IntPtr.Zero)
        {
            // 发送保存命令的消息
            SendMessage(notepadWindow, WM_COMMAND, (IntPtr)ID_FILE_SAVE, IntPtr.Zero);
            Console.WriteLine("已经触发记事本保存啦");
        }
        else
        {
            Console.WriteLine("没找到对应的记事本窗口哦");
        }

        // 给保存留一点时间,根据文件大小可以调整这个延迟
        System.Threading.Thread.Sleep(1000);

        // 关闭记事本进程
        notepadProcess.Kill();
    }
}

方式二:激活窗口后模拟Ctrl+S按键

如果你还是想用模拟按键的方式,那一定要先把记事本窗口激活到前台,再发送按键。这里用SetForegroundWindow API来激活窗口,然后用SendKeys发送Ctrl+S:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;

class Program
{
    // 导入激活窗口的API
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool SetForegroundWindow(IntPtr hWnd);

    static void Main(string[] args)
    {
        var notepadProcess = Process.Start("notepad.exe", @"myfile.txt");
        notepadProcess.WaitForInputIdle();

        // 把记事本窗口调到前台
        SetForegroundWindow(notepadProcess.MainWindowHandle);
        // 等窗口完全激活
        Thread.Sleep(500);

        // 发送Ctrl+S,^代表Ctrl键
        System.Windows.Forms.SendKeys.SendWait("^s");
        // 等保存完成
        Thread.Sleep(1000);

        // 关闭记事本
        notepadProcess.Kill();
    }
}

注意哦:用SendKeys的话,在.NET Core或者.NET 5+的项目里,需要先安装System.Windows.Forms这个NuGet包才行,框架项目的话直接引用对应的程序集就好。

为什么你之前模拟Ctrl+S没用?

大概率是因为记事本窗口没处于活动状态,SendKeys会把按键发送给当前的前台窗口,而不是记事本。所以要么确保窗口激活,要么直接用窗口消息的方式,后者肯定更靠谱,毕竟不用依赖焦点状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:15:39