C# VB.NET多进程-管道通信,命名管道(Named Pipes)

要向已运行的进程发送特定命令(如/exit),而不是启动新进程,需要使用进程间通信(IPC)机制。以下是几种常见的实现方法:

一、使用命名管道(Named Pipes)

如果ABC.EXE支持通过命名管道接收命令,可以这样实现:

1. 在 ABC.EXE 中添加管道服务器代码
' ABC.EXE 中添加以下代码(需在启动时运行)
Imports System.IO.PipesPublic Sub StartPipeServer()Dim thread As New Threading.Thread(AddressOf PipeServerThread)thread.IsBackground = Truethread.Start()
End SubPrivate Sub PipeServerThread()TryWhile TrueUsing server As New NamedPipeServerStream("ABCControlPipe")Console.WriteLine("等待客户端连接...")server.WaitForConnection()Using reader As New StreamReader(server)Dim command As String = reader.ReadLine()Console.WriteLine($"收到命令: {command}")' 处理命令If command = "/exit" Then' 执行退出逻辑Application.Exit()End IfEnd UsingEnd UsingEnd WhileCatch ex As ExceptionConsole.WriteLine($"管道服务器错误: {ex.Message}")End Try
End Sub
2. 在监控程序中发送命令

vb

Imports System.IO.PipesPublic Sub SendCommandToRunningProcess(command As String)TryUsing client As New NamedPipeClientStream(".", "ABCControlPipe", PipeDirection.Out)client.Connect(2000)  ' 等待2秒连接Using writer As New StreamWriter(client)writer.WriteLine(command)writer.Flush()Console.WriteLine($"命令已发送: {command}")End UsingEnd UsingCatch ex As ExceptionConsole.WriteLine($"发送命令失败: {ex.Message}")End Try
End Sub' 使用示例
SendCommandToRunningProcess("/exit")

二、使用命令行参数 + 进程查找

如果ABC.EXE支持通过创建特定文件或命令行参数触发行为,可以这样实现:

1. 修改 ABC.EXE 定期检查命令文件

vb

' 在ABC.EXE中添加定时检查逻辑
Private Sub StartCommandChecker()Dim timer As New Timer(1000)  ' 每秒检查一次AddHandler timer.Elapsed, AddressOf CheckForCommandstimer.Start()
End SubPrivate Sub CheckForCommands(sender As Object, e As ElapsedEventArgs)Dim commandFile As String = Path.Combine(Application.StartupPath, "command.txt")If File.Exists(commandFile) ThenTryDim command As String = File.ReadAllText(commandFile)File.Delete(commandFile)  ' 处理后删除If command = "/exit" ThenApplication.Exit()End IfCatch ex As ExceptionConsole.WriteLine($"读取命令文件失败: {ex.Message}")End TryEnd If
End Sub
2. 在监控程序中创建命令文件

vb

Public Sub SendCommandToRunningProcess(command As String)Dim commandFile As String = Path.Combine(Path.GetDirectoryName(Process.GetProcessesByName("ABC").FirstOrDefault()?.MainModule.FileName),"command.txt")TryFile.WriteAllText(commandFile, command)Console.WriteLine($"命令已写入文件: {command}")Catch ex As ExceptionConsole.WriteLine($"发送命令失败: {ex.Message}")End Try
End Sub

三、使用 Windows 消息(适用于有窗口的进程)

如果ABC.EXE有隐藏窗口,可以发送自定义 Windows 消息:

1. 在 ABC.EXE 中注册并处理自定义消息

vb

Imports System.Runtime.InteropServicesPublic Class MainForm' 注册自定义消息Private Const WM_USER As Integer = &H400Private Const WM_EXIT_COMMAND As Integer = WM_USER + 100<DllImport("user32.dll", CharSet:=CharSet.Auto)>Private Shared Function RegisterWindowMessage(ByVal lpString As String) As IntegerEnd FunctionPrivate exitMessageId As Integer = RegisterWindowMessage("ABC_EXIT_COMMAND")Protected Overrides Sub WndProc(ByRef m As Message)If m.Msg = exitMessageId OrElse m.Msg = WM_EXIT_COMMAND Then' 处理退出命令Application.Exit()ReturnEnd IfMyBase.WndProc(m)End Sub
End Class
2. 在监控程序中发送消息

vb

Imports System.Runtime.InteropServicesPublic Sub SendExitMessageToProcess()Dim processes() As Process = Process.GetProcessesByName("ABC")If processes.Length > 0 ThenDim mainWindowHandle As IntPtr = processes(0).MainWindowHandleIf mainWindowHandle <> IntPtr.Zero Then' 注册相同的消息IDDim exitMessageId As Integer = RegisterWindowMessage("ABC_EXIT_COMMAND")' 发送消息PostMessage(mainWindowHandle, exitMessageId, IntPtr.Zero, IntPtr.Zero)Console.WriteLine("退出消息已发送")ElseConsole.WriteLine("未找到主窗口句柄")End IfEnd If
End Sub<DllImport("user32.dll", CharSet:=CharSet.Auto)>
Private Shared Function RegisterWindowMessage(ByVal lpString As String) As Integer
End Function<DllImport("user32.dll", CharSet:=CharSet.Auto)>
Private Shared Function PostMessage(ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Boolean
End Function

四、总结

选择哪种方法取决于ABC.EXE的实现:

  1. 优先使用命名管道:灵活且安全,需修改ABC.EXE代码。
  2. 命令文件方式:简单但有延迟(取决于检查频率)。
  3. Windows 消息:适用于有窗口的进程。

如果无法修改ABC.EXE,可考虑使用外部工具(如 AutoHotkey 发送模拟按键),但可靠性较低。

分享

如果多个进程,管道名称是否要不一样?

是的,如果需要同时管理多个进程实例,每个进程的管道名称必须唯一。否则,不同进程会监听同一个管道,导致命令混淆或无法正确识别目标进程。以下是几种实现多进程管道通信的方案:

一、基于进程 ID(PID)的唯一管道名称

最简单的方法是将进程 ID(PID)作为管道名称的一部分:

1. 在 ABC.EXE 中创建唯一管道

vb

Imports System.IO.PipesPublic Class ABCApplicationPrivate pipeServer As NamedPipeServerStreamPrivate pipeName As StringPublic Sub StartPipeServer()' 使用进程ID生成唯一管道名称pipeName = $"ABCControlPipe_{Process.GetCurrentProcess().Id}"' 创建并启动管道服务器pipeServer = New NamedPipeServerStream(pipeName, PipeDirection.InOut)Dim thread As New Threading.Thread(AddressOf HandleIncomingConnections)thread.IsBackground = Truethread.Start()End SubPrivate Sub HandleIncomingConnections()TryWhile TruepipeServer.WaitForConnection()' 处理命令...Using reader As New StreamReader(pipeServer)Dim command As String = reader.ReadLine()If command = "/exit" Then' 优雅退出逻辑Application.Exit()End IfEnd Using' 重置管道以接收下一个连接pipeServer.Disconnect()End WhileCatch ex As Exception' 错误处理End TryEnd Sub
End Class
2. 在监控程序中发送命令到特定进程
Imports System.IO.PipesPublic Sub SendCommandToProcess(pid As Integer, command As String)Dim pipeName As String = $"ABCControlPipe_{pid}"TryUsing client As New NamedPipeClientStream(".", pipeName, PipeDirection.Out)client.Connect(2000)  ' 2秒超时Using writer As New StreamWriter(client)writer.WriteLine(command)writer.Flush()End UsingEnd UsingCatch ex As ExceptionConsole.WriteLine($"发送命令到进程 {pid} 失败: {ex.Message}")End Try
End Sub' 示例:向所有ABC进程发送退出命令
Public Sub SendExitToAllProcesses()Dim processes() As Process = Process.GetProcessesByName("ABC")For Each proc In processesSendCommandToProcess(proc.Id, "/exit")Next
End Sub

二、使用中央管道管理器(更高级的方案)

如果进程数量较多或需要更复杂的管理,可以实现一个中央管道管理器:

1. 中央管理器设计
Imports System.Collections.ConcurrentPublic Class PipeManagerPrivate Shared pipeMap As New ConcurrentDictionary(Of Integer, NamedPipeServerStream)' 注册新进程的管道Public Shared Function RegisterProcess(pid As Integer) As StringDim pipeName As String = $"ABCControlPipe_{Guid.NewGuid()}"  ' 使用GUID确保唯一性Dim server As New NamedPipeServerStream(pipeName, PipeDirection.InOut)pipeMap.TryAdd(pid, server)' 启动监听线程Dim thread As New Threading.Thread(Sub() HandleConnections(pid, server))thread.IsBackground = Truethread.Start()Return pipeNameEnd Function' 处理管道连接Private Shared Sub HandleConnections(pid As Integer, server As NamedPipeServerStream)TryWhile pipeMap.ContainsKey(pid)server.WaitForConnection()' 处理命令...Using reader As New StreamReader(server)Dim command As String = reader.ReadLine()' 根据PID转发命令到对应进程End Usingserver.Disconnect()End WhileCatch ex As Exception' 错误处理End TryEnd Sub' 向特定进程发送命令Public Shared Sub SendCommand(pid As Integer, command As String)If pipeMap.TryGetValue(pid, out Dim server) Then' 通过管道发送命令...End IfEnd Sub
End Class
2. 进程端注册

vb

' 在ABC.EXE启动时
Public Sub Main()' 向管理器注册自己并获取唯一管道名称Dim pipeName As String = PipeManager.RegisterProcess(Process.GetCurrentProcess().Id)' 保存管道名称用于后续通信My.Settings.PipeName = pipeNameMy.Settings.Save()' 其他初始化逻辑...
End Sub

三、关键注意事项

  1. 管道名称唯一性

    • 确保每个进程的管道名称包含唯一标识符(如 PID、GUID)。
    • 避免使用硬编码的固定名称。
  2. 资源清理

    • 进程退出时,确保关闭并释放管道资源。
    • 可以通过Process.Exited事件监听进程退出,清理对应的管道。
  3. 安全性考虑

    • 对管道名称进行权限控制,防止未授权访问。
    • 考虑使用加密或身份验证增强安全性(如使用PipeSecurity)。
  4. 错误处理

    • 处理管道连接超时、断开等异常情况。
    • 实现重试机制,确保命令可靠发送。

四、总结

通过为每个进程分配唯一的管道名称,可以有效管理多个进程实例。选择哪种方案取决于具体需求:

  • PID 方案:简单直接,适用于大多数场景。
  • 中央管理器:适合复杂系统,提供更灵活的控制和监控能力。

无论采用哪种方式,核心原则是确保管道名称的唯一性和通信的可靠性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/88755.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/88755.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++ 右值引用 (Rvalue References)

右值引用是C11引入的革命性特性&#xff0c;它彻底改变了C中资源管理和参数传递的方式。下面我将从多个维度深入讲解右值引用。一、核心概念1. 值类别(Value Categories)lvalue (左值): 有标识符、可取地址的表达式int x 10; // x是左值 int* p &x; // 可以取地址rvalue…

反激变换器设计全流程(一)——电路拓扑及工作流程

一、电路拓扑原理 拓扑结构概述 开关反激电源采用反激式拓扑结构&#xff0c;主要由开关管&#xff08;通常为 MOSFET&#xff09;、变压器、输出整流二极管、输出滤波电容以及控制电路等组成。其基本工作原理是通过开关管的周期性开关动作&#xff0c;将输入直流电压转换为高…

uniapp语音播报天气预报微信小程序

1.产品展示2.页面功能(1)点击上方按钮实现语音播报4天天气情况。3.uniapp代码<template><view class"container"><view class"header"><text class"place">地址:{{city}}</text><text class"time"&g…

Pycharm 报错 Environment location directory is not empty 如何解决

好长时间不看不写代码了&#xff0c;人也跟着犯糊涂。今天在Pycharm 导入虚拟环境时&#xff0c;一直报错&#xff1a;“Environment location directory is not empty”&#xff0c;在网上百度很多很多方法都无法解决&#xff0c;直到我翻出我之前自己写的导入虚拟环境的详细过…

React强大且灵活hooks库——ahooks入门实践之场景类(scene)hook详解

什么是 ahooks&#xff1f; ahooks 是一个 React Hooks 库&#xff0c;提供了大量实用的自定义 hooks&#xff0c;帮助开发者更高效地构建 React 应用。其中场景类 hooks 是 ahooks 的一个重要分类&#xff0c;专门针对特定业务场景提供解决方案。 安装 ahooks npm install …

大模型之Langchain篇(二)——RAG

写在前面 跟着楼兰老师学习【LangChain教程】2025吃透LangChain框架快速上手与深度实战&#xff0c;全程干货无废话&#xff0c;三天学完&#xff0c;让你少走百分之99弯路&#xff01;_哔哩哔哩_bilibili 计算相似度 一般用的余弦相似度&#xff0c;这里只是演示计算。 fr…

深入理解图像二值化:从静态图像到视频流实时处理

一、引言&#xff1a;图像分析&#xff0c;从“黑与白”开始在计算机视觉任务中&#xff0c;**图像二值化&#xff08;Image Binarization&#xff09;**是最基础也是最关键的图像预处理技术之一。它通过将灰度图像中每个像素转换为两个离散值&#xff08;通常是0和255&#xf…

云蝠智能 VoiceAgent重构企业呼入场景服务范式

在数字化转型浪潮中&#xff0c;企业呼入场景面临客户服务需求激增与人力成本攀升的双重挑战。传统呼叫中心日均处理仅 300-500 通电话&#xff0c;人力成本占比超 60%&#xff0c;且服务质量受情绪波动影响显著。云蝠智能推出的 VoiceAgent 语音智能体&#xff0c;通过全栈自研…

java进阶(一)+学习笔记

1.JAVA设计模式1.1 什么是设计模式设计模式是软件开发过程中前辈们在长期实践中针对重复出现的问题总结出来的最佳解决方案。这些模式不是具体的代码实现&#xff0c;而是经过验证的、可重用的设计思想&#xff0c;能够帮助开发者更高效地解决特定类型的问题。设计模式的重要性…

Pandas-数据清洗与处理

Pandas-数据清洗与处理一、数据清洗的核心目标二、缺失值处理1. 缺失值检测2. 缺失值处理策略&#xff08;1&#xff09;删除法&#xff08;2&#xff09;填充法三、异常值识别与处理1. 异常值检测方法&#xff08;1&#xff09;统计法&#xff08;2&#xff09;业务规则法2. 异…

在 MacOS 上安装和配置 Kafka

消息代理是一种软件&#xff0c;充当在不同应用程序之间发送消息的中介。它的功能类似于服务器&#xff0c;从一个应用程序&#xff08;称为生产者&#xff09;接收消息&#xff0c;并将其路由到一个或多个其他应用程序&#xff08;称为消费者&#xff09;。消息代理的主要目的…

基于Leaflet调用天地图在线API的多层级地名检索实战

目录 前言 一、天地图在线检索 1、在线检索功能 2、再谈后后接口 二、Leaflet多层级实现实例 1、层级调用实现原理 2、Leaflet中多层级调用 3、成果展示 三、总结 前言 “地图是世界的索引&#xff0c;而地名则是索引中的索引。”当互联网地图进入 Web 2.0 时代&#x…

基于Prompt结构的语校解析:3H日本语学校信息建模实录(4/500)

基于Prompt结构的语校解析&#xff1a;3H日本语学校信息建模实录&#xff08;4/500&#xff09; 系列延续&#xff1a;500所日本语言学校结构数据工程 关键词&#xff1a;招生结构、JLPTEJU、国籍比例、认定校、Prompt训练集 一、我们在构建什么样的语言学校语料&#xff1f; …

Leaflet面试题及答案(61-80)

查看本专栏目录 文章目录 🟢 面试问题及答案(61-80)61. 如何在地图上显示一个动态更新的图层?62. 如何实现地图上的热力图(Heatmap)?63. 如何自定义地图控件的位置?64. 如何处理地图加载失败的情况?65. 如何实现地图的离线功能?66. 如何将地图导出为图片?67. 如何实…

MIG_IP核的时钟系统

MIG_IP核的时钟系统时钟的种类和配置时钟的种类和配置 整体框图 DDR_PHY_CLK&#xff1a;DDR3的工作频率&#xff0c;用来得到想要的线速率。假设此时钟为800M&#xff0c;那么DDR双沿采样&#xff0c;线速率为1600Mbit&#xff1b; UI_CLK&#xff1a;DDR_PHY_CLK的四分之一…

若依框架集成阿里云OSS实现文件上传优化

背景介绍 在若依框架目前的实现中&#xff0c;是把图片存储到了服务器本地的目录&#xff0c;通过服务进行访问&#xff0c;这样做存储的是比较省事&#xff0c;但是缺点也有很多&#xff1a; 硬件与网络要求&#xff1a;服务器通常需要高性能的硬件和稳定的网络环境&#xff0…

Mac如何连接惠普M126a打印机(教程篇)

这里写自定义目录标题Mac如何连接惠普M126a打印机&#xff08;教程篇&#xff09;教程配置如下&#xff1a;Mac如何连接惠普M126a打印机&#xff08;教程篇&#xff09; 惠普M126a连接Mac&#xff08;教程篇&#xff09; 教程配置如下&#xff1a; 首先&#xff0c;先获取与HP打…

感恩日记:记录生活中的美好时刻

感恩日记的landing page登录注册填写感恩事项私信可以体验一下

一扇门铃,万向感应——用 eventfd 实现零延迟通信

&#x1f50d; 本篇概要 eventfd 是 Linux 提供的一种轻量级事件通知机制。你可以把它想象成一个“计数器盒子”。它里面维护的是一个64位的计数器。写入&#xff1a;往盒子里放一些数字&#xff08;比如 1、5、10&#xff09;&#xff0c;表示有几件事发生了。读取&#xff1a…

基于Node.js的线上教学系统的设计与实现(源码+论文+调试+安装+售后)

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。系统背景近年来&#xff0c;全球数字化浪潮的推进与教育公平化需求的增长&#xff0c;促使线上教学迎…