c# Process.Start()找不到系统文件

本文主要讲述vs1027在X86应用程序下执行报错找不到系统文件的问题。原因是64位Windows为兼容32位程序采用重定向机制。解决办法一是调用API函数禁止系统重定向,网上提到改路径的方法可能需注册表设置,最简单的是将应用程序改为64位。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【参考1】https://www.cnblogs.com/iamlucky/p/5998086.html
【参考2】https://www.bbsmax.com/A/mo5kj04KJw/

问题描述

vs1027在X64应用程序下执行process.start()时,OK;但是在X86应用程序下执行process.start(),报错:找不到系统文件

if (kbpr.HasExited)
{
	kbpr = Process.Start(@"C:\Windows\System32\osk.exe");
}

网上搜索良久,发现原因为:windows重定向搞得鬼

在64位的Windows操作系统中,为了兼容32位程序的运行,64位的Windows操作系统采用重定向机制。目的是为了能让32位程序在64位的操作系统不仅能操作关键文件文夹和关键的注册表并且又要避免与64位程序冲突;因此,32位应用程序的运行是通过WOW64的模拟器来实现的。WOW64 是一个由操作系统提供的兼容性环境,它使得 32 位应用程序能够在 Windows 64 位操作系统上运行,在系统的Windows目录下,存在System32和SysWOW64两个文件夹:

System32文件夹下存放的是64位DLL

SysWOW64文件夹下存放的是32位DLL

因此,如果我们用32位程序去访问c:\windows\system32,不管我们用硬编码还是其它的方式,系统都会自动地给我们转向到C:\windows\syswow64下面。

禁止系统的重定向的解决办法是调用下面的API函数

禁用系统重定向用下面的函数:
BOOL Wow64DisableWow64FsRedirection(PVOID OldValue);
恢复系统重定向用下面的函数:
BOOL Wow64RevertWow64FsRedirection(PVOID OldValue);

解决办法

具体代码如下:

// 关闭64位(文件系统)的操作转向
[DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);
// 开启64位(文件系统)的操作转向
[DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);



IntPtr oldWOW64State = new IntPtr();
Wow64DisableWow64FsRedirection(ref oldWOW64State);   // 关闭64位(文件系统)的操作转向


Wow64RevertWow64FsRedirection(oldWOW64State);        // 开启64位(文件系统)的操作转向

注1

网上还有中办法,将路径c:\windows\system32\改为c:\windows\sysnative\,但是我尝试,好像不管用;可能是需要注册表或者哪里设置过吧

注2

当然最简单的办法,是将应用程序改为64位,就不存在以上问题了。

### 实现C# WinForms中使用`Process.Start`打开TXT文件并读取内容 在C# WinForms应用程序中,可以利用`System.Diagnostics.Process`类来启动外部进程,比如打开一个文本文件。然而,如果目标是在程序内部获取该文本文件的内容,则不建议直接通过`Process.Start()`方法执行此操作,因为这主要用于启动独立的应用程序或文档而不返回数据流。 为了达到既能够显示又能在后台处理的需求,应该先读取文件内容到内存中再决定是否展示给用户或是做其他用途。下面是一个完整的解决方案: #### 方法一:仅读取文件内容而不实际启动记事本或其他默认关联程序 ```csharp private void ReadFileContent(string filePath) { try { string content = System.IO.File.ReadAllText(filePath); MessageBox.Show(content, "文件内容"); } catch (Exception ex) { MessageBox.Show($"发生错误: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } ``` 这种方法简单高效,适合大多数场景下的需求[^1]。 #### 方法二:结合`Process.Start`与自定义逻辑实现更复杂的行为 当确实需要模拟用户的双击行为(即真正意义上“打开”文件),同时又要获得其中的数据时,可以在调用`Process.Start`之前先行读取文件内容保存至变量内备用;或者,在新进程中附加事件监听器等待特定时刻去抓取输出——但这对于简单的文本文件来说显得过于繁琐,并不是推荐的做法。 更好的方式可能是创建临时副本供查看而保留原始路径用于后续解析: ```csharp using System; using System.Diagnostics; public partial class MainForm : Form { private void OpenAndReadTxt() { OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Filter = "Text files (*.txt)|*.txt"; if(openFileDialog.ShowDialog() == DialogResult.OK){ // 创建临时文件名 var tempFileName = Path.GetTempPath() + Guid.NewGuid().ToString() + ".txt"; File.Copy(openFileDialog.FileName, tempFileName); // 启动默认编辑器打开原文件 ProcessStartInfo psi = new ProcessStartInfo(openFileDialog.FileName); Process.Start(psi); // 读取临时文件内容 using(StreamReader sr = new StreamReader(tempFileName)){ string line; while((line=sr.ReadLine())!=null){ Console.WriteLine(line); // 或者将这些行添加到ListBox等控件里 } } // 删除临时文件 File.Delete(tempFileName); } } } ``` 这段代码展示了如何安全地复制选定的`.txt`文件到临时位置以便于阅读的同时允许用户正常访问源文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值