dotnet 6 使用 File.Exists 判断管道是否存在将让下次连接失败
我尝试在 dotnet 6 使用 File.Exists 判断管道是否存在,如果管道存在再进行连接。然而这个逻辑将会接下来的 NamedPipeClientStream 调用 Connect 连接失败
这个问题似乎是 CLR 底层的问题,我将问题报告给官方,请看 Using File.Exists to check the pipe created will make the NamedPipeClientStream connect fail · Issue #69604 · dotnet/runtime
使用 File.Exists 判断管道是否存在的代码如下
File.Exists(@"\\.\pipe\" + PipeName);
然而以上代码将会在 dotnet 6 下让 NamedPipeClientStream 调用 Connect 连接失败。这个逻辑如果放在 .NET Framework 下运行,是能成功的
最简复现步骤如下,先使用 NamedPipeServerStream 启动管道服务
void StartServer()
{
var server = new NamedPipeServerStream(PipeName,
PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous, 1024, 1024);
server.BeginWaitForConnection(OnWaitForConnection, server);
}
接下来使用 File.Exists 判断管道是否存在
File.Exists(@"\\.\pipe\" + PipeName);
再使用 NamedPipeClientStream 进行连接
void StartClient()
{
var localServer = ".";
var pipeDirection = PipeDirection.InOut;
var client = new NamedPipeClientStream(localServer,
PipeName, pipeDirection, PipeOptions.Asynchronous);
var timeout = 1000 * 5;
client.Connect(timeout);
}
运行代码,可以看到 Connect 方法抛出 TimeoutException 错误
核心原因是在 .NET 6 通过 GetFileAttributesW 去判断管道是否存在,然而根据堆栈网 的描述,通过 GetFileAttributesW 去判断一个非文件系统的对象,会有非预期的行为。这也就是管道连接失败的原因。那为什么 .NET Framework 没问题?因为 .NET Framework 是先调用 FindFirstFile 进行判断
因此一个解决方法是采用和 .NET Framework 一样的 FindFirstFile 方法进行判断管道是否存在,代码如下
private static bool IsPipeExists(string pipeName)
{
try
{
// 不要用 File.Exists 判断,内部会调用 GetFileAttributes 导致管道无法被连接
unsafe
{
// 这里是一个结构体,但是不关心内容,直接栈上分配点空间给它
var findFileData = stackalloc byte[604];
var file = FindFirstFile(@"\\.\pipe\" + pipeName, (IntPtr)findFileData);
const nint INVALID_HANDLE_VALUE = -1;
if (file != INVALID_HANDLE_VALUE)
{
FindClose(file);
return true;
}
}
}
catch
{
}
return false;
}
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, EntryPoint = "FindFirstFileW", ExactSpelling = true)]
private static extern SafeFileHandle FindFirstFile([In] string lpFileName, [In] IntPtr lpFindFileData);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, EntryPoint = "FindClose", ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool FindClose([In] IntPtr hFindFile);
如果不想碰不安全代码,也可以采用判断文件夹里面的文件是否存在的方法判断管道是否存在
Directory.EnumerateFiles(@"\\.\pipe\", PipeName).Any();
只是文件夹的判断方法会比使用 FindFirstFile 的速度慢一点点,我测试大概是 3-5 毫秒左右
更多请看 Detecting that NamedPipe exists - Andrii Snihyr
本文以上的测试代码放在github 和 gitee 欢迎访问
可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin e26bdd0bced93db8edf8be18f1062e571f3d1861
以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
获取代码之后,进入 HallwhallkernarbafejaNakeldibi 文件夹
dotnet 6 使用 File.Exists 判断管道是否存在将让下次连接失败的更多相关文章
- C# File.Exists 判断系统文件,警惕32位和64位的差异
今天在调试一个Winform程序,使用File.Exists 判断一个已经存在的驱动文件,程序一直返回false.因为驱动文件属于系统目录,心想难道是权限不够导致的?然后用管理员身份运行软件,依然返回 ...
- File.Exists 判断不了虚拟路径
https://www.shuzhiduo.com/topic/file-exists-%E5%88%A4%E6%96%AD%E4%B8%8D%E4%BA%86%E8%99%9A%E6%8B%9F%E ...
- C# 文件存在,但是File.Exists 判断不存在的问题
这里说的不是文件路径错了的情况,而是明明文件就存在,但是File.Exists返回false. win10系统. 查看接口说明才知道,如果你不是按管理员方式启动VS,而此文件需要管理员权限才能访问,此 ...
- C#中当程序的访问权限不足时,Directory.Exists和File.Exists方法不会抛出异常报错
有些时候,我们开发的C#应用程序的执行账号,可能没有对一些文件夹和文件的访问权限,当我们使用Directory.Exists和File.Exists方法去判断这些文件夹和文件是否存在的时候,Direc ...
- 谨慎使用 FileInfo.Exists 实例方法,而是使用 File.Exists 静态方法替代
如果你在代码中使用了 FileInfo.Exists 实例方法来判断一个文件是否存在,也许会发现此方法可能错误地判断来一个文件是否真的存在.这是一个坑. 本文将介绍坑的原因,并提供填坑的办法. 本文内 ...
- C# IO流 File.Exists,Directory.Exists, File.Create,Directory.CreateDirectory
void Start() { CreateDirectory(); CreateFile(); } //平台的路径(封装起来的一个属性,这不是一个方法) public string path { ge ...
- File类 判断功能和获取功能
package cn.zmh.File; import java.io.File; /* * * File判断功能 * * */ public class FileDemo3判断功能 { public ...
- 关于 System.IO.File.Exists 需要注意的事项
各位: .NET Framework 本省在设计的时候,他对于异常没有完全做到抛出,这样可能会有很多意想不到的问题. 比如 你在asp.net 应用程序中判断文件是否存在,这个文件可能是一个共 ...
- File类获取功能的方法和File类判断功能的方法
File类获取功能的方法-public String getAbsolutePath() :返回此file的绝对路径名字符串 -public String getPath() :将此File转换为路径 ...
- File类获取功能的方法-File类判断功能的方法
File类获取功能的方法 获取功能的方法 public string getAbsolutePath()∶返回此File的绝对路径名字符串. public string getPath() ︰将此Fi ...
随机推荐
- 阿里二面:Java中锁的分类有哪些?你能说全吗?
引言 在多线程并发编程场景中,锁作为一种至关重要的同步工具,承担着协调多个线程对共享资源访问秩序的任务.其核心作用在于确保在特定时间段内,仅有一个线程能够对资源进行访问或修改操作,从而有效地保护数据的 ...
- Prompt工程全攻略:15+Prompt框架一网打尽(BROKE、COAST、LangGPT)、学会提示词让大模型更高效
Prompt工程全攻略:15+Prompt框架一网打尽(BROKE.COAST.LangGPT).学会提示词让大模型更高效 0.相关文章推荐 更多Prompt框架技术细节和原理见相关文章 Prompt ...
- VS2010插件NuGet
下载地址 NuGet Package Manager - Visual Studio Marketplace NuGet包地址 NuGet Gallery | Home
- Atcoder DP contest 题解
动态规划(Atcoder DP 26题) on Atcoder on Luogu 本文同步发表于知乎专栏. Frog 1 $N$ 个石头,编号为 $1,2,...,N$.对于每个 $i(1 \leq ...
- 【已解决】ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (10061)---mysql数据库本地服务器localhost连接失败
出现错误mysql数据库本地服务器localhost连接失败: 1.输入命令 mysql -uroot -p 输入密码进入数据库发现错误 2.输入命令 mysqld --install 出现Serv ...
- js实现多列排序-存在问题
js实现多列排序 根据业务逻辑调整 sortData 的数据. 排序的规则是按照第一列排序,第一列相同按照第二列排序,依次类推 // 要排序的数据 const array = [{ name: '甲' ...
- 使用OHOS SDK构建benchmark
参照OHOS IDE和SDK的安装方法配置好开发环境. 从github下载源码. 执行如下命令: git clone --depth=1 https://github.com/google/bench ...
- OpenHarmony创新赛人气投票活动,最佳人气作品由你来定!
12月1日至12月15日 十大入围作品线上投票激战正酣 最佳人气作品,由你来定! 投票链接:https://forums.openharmony.cn/forum.php?mod=viewth ...
- HarmonyOS网络管理开发—HTTP与WebSocket
一. 网络管理开发概述 网络管理模块主要提供以下功能: ● HTTP数据请求:通过HTTP发起一个数据请求. ● WebSocket连接:使用WebSocket建立服务器与客户端的双向连接. ● ...
- 把vim配置成顺手的python轻量级IDE(一)
把vim配置成顺手的python轻量级IDE(一) 地球的外星人君 Linux云计算和Python推动市场提升的学习研究者. 分享一篇文章,正好最近正在折腾VIM,原文在把vim配置成顺手的pytho ...