C# 两个进程/exe通讯方式 两个应用程序通讯方式

C# 两个exe通讯方式 两个应用程序通讯方式

1. 命名管道(Named Pipes)

1.1. 概述

命名管道是一种用于在同一台机器或网络中不同进程之间进行双向通信的机制。它支持同步和异步通信,适用于需要高效数据传输的场景。

1.2. 特点

双向通信:支持双向数据传输。
安全性:可以设置访问权限,确保通信的安全性。
跨网络:支持跨网络通信。

1.3. 实现方式

1.3.1. 服务器端(NamedPipeServerStream)
using System;
using System.IO.Pipes;
using System.Text;
using System.Threading.Tasks;class PipeServer
{public static async Task StartServer(){using (var pipeServer = new NamedPipeServerStream("TestPipe", PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous)){Console.WriteLine("等待客户端连接...");await pipeServer.WaitForConnectionAsync();Console.WriteLine("客户端已连接。");// 接收数据byte[] buffer = new byte[256];int bytesRead = await pipeServer.ReadAsync(buffer, 0, buffer.Length);string receivedMessage = Encoding.UTF8.GetString(buffer, 0, bytesRead);Console.WriteLine($"收到消息:{receivedMessage}");// 发送回应string response = "Hello from server!";byte[] responseBytes = Encoding.UTF8.GetBytes(response);await pipeServer.WriteAsync(responseBytes, 0, responseBytes.Length);Console.WriteLine("已发送回应。");}}static void Main(string[] args){Task.Run(() => StartServer()).Wait();}
}
1.3.2. 客户端(NamedPipeClientStream)
using System;
using System.IO.Pipes;
using System.Text;
using System.Threading.Tasks;class PipeClient
{public static async Task StartClient(){using (var pipeClient = new NamedPipeClientStream(".", "TestPipe", PipeDirection.InOut, PipeOptions.Asynchronous)){Console.WriteLine("尝试连接到服务器...");await pipeClient.ConnectAsync();Console.WriteLine("已连接到服务器。");// 发送数据string message = "Hello from client!";byte[] messageBytes = Encoding.UTF8.GetBytes(message);await pipeClient.WriteAsync(messageBytes, 0, messageBytes.Length);Console.WriteLine("已发送消息。");// 接收回应byte[] buffer = new byte[256];int bytesRead = await pipeClient.ReadAsync(buffer, 0, buffer.Length);string response = Encoding.UTF8.GetString(buffer, 0, bytesRead);Console.WriteLine($"收到回应:{response}");}}static void Main(string[] args){Task.Run(() => StartClient()).Wait();}
}

1.4. 使用场景

需要高效、双向通信的应用程序。
同一台机器或网络中的进程间通信。
需要传输大量数据或复杂数据结构。

2. 套接字(Sockets)

2.1. 概述

套接字是一种底层的通信机制,支持跨网络的进程间通信。它适用于需要跨不同机器或网络通信的应用程序。

2.2. 特点

灵活性高:支持多种协议(TCP、UDP)。
跨平台:可用于不同操作系统间的通信。
高性能:适用于实时数据传输和高并发应用。

2.3. 实现方式

2.3.1. 服务器端(TCP)
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;class SocketServer
{public static async Task StartServer(){TcpListener listener = new TcpListener(IPAddress.Any, 5000);listener.Start();Console.WriteLine("服务器已启动,等待连接...");using (TcpClient client = await listener.AcceptTcpClientAsync()){Console.WriteLine("客户端已连接。");NetworkStream stream = client.GetStream();// 接收数据byte[] buffer = new byte[1024];int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);string receivedMessage = Encoding.UTF8.GetString(buffer, 0, bytesRead);Console.WriteLine($"收到消息:{receivedMessage}");// 发送回应string response = "Hello from server!";byte[] responseBytes = Encoding.UTF8.GetBytes(response);await stream.WriteAsync(responseBytes, 0, responseBytes.Length);Console.WriteLine("已发送回应。");}listener.Stop();}static void Main(string[] args){Task.Run(() => StartServer()).Wait();}
}
2.3.2. 客户端(TCP)
using System;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;class SocketClient
{public static async Task StartClient(){using (TcpClient client = new TcpClient()){Console.WriteLine("尝试连接到服务器...");await client.ConnectAsync("127.0.0.1", 5000);Console.WriteLine("已连接到服务器。");NetworkStream stream = client.GetStream();// 发送数据string message = "Hello from client!";byte[] messageBytes = Encoding.UTF8.GetBytes(message);await stream.WriteAsync(messageBytes, 0, messageBytes.Length);Console.WriteLine("已发送消息。");// 接收回应byte[] buffer = new byte[1024];int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);string response = Encoding.UTF8.GetString(buffer, 0, bytesRead);Console.WriteLine($"收到回应:{response}");}}static void Main(string[] args){Task.Run(() => StartClient()).Wait();}
}

2.4. 使用场景

需要跨不同机器或网络通信的应用程序。
实时通信,如聊天应用、游戏服务器等。
需要灵活控制通信协议和数据格式的场景。

3. 内存映射文件(Memory-Mapped Files)

3.1. 概述

内存映射文件允许多个进程共享同一块内存区域,实现高效的数据交换。它适用于需要频繁、快速共享大量数据的场景。

3.2. 特点

高性能:通过共享内存实现快速数据交换。
简单的数据共享:适用于需要在多个进程间共享复杂数据结构的应用程序。
跨语言支持:不同编程语言的进程可以通过内存映射文件进行通信。

3.3. 实现方式

3.3.1. 创建内存映射文件(服务器端)
using System;
using System.IO.MemoryMappedFiles;
using System.Text;
using System.Threading;class MemoryMappedFileServer
{static void Main(string[] args){using (var mmf = MemoryMappedFile.CreateOrOpen("SharedMemory", 1024)){Console.WriteLine("服务器已启动,等待消息...");using (var accessor = mmf.CreateViewAccessor()){while (true){byte[] buffer = new byte[256];accessor.ReadArray(0, buffer, 0, buffer.Length);string message = Encoding.UTF8.GetString(buffer).TrimEnd('\0');if (!string.IsNullOrEmpty(message)){Console.WriteLine($"收到消息:{message}");// 清空消息accessor.WriteArray(0, new byte[256], 0, 256);// 发送回应string response = "Hello from server!";byte[] responseBytes = Encoding.UTF8.GetBytes(response);accessor.WriteArray(0, responseBytes, 0, responseBytes.Length);Console.WriteLine("已发送回应。");}Thread.Sleep(1000); // 等待一段时间再检查}}}}
}
3.3.2. 读取内存映射文件(客户端)
using System;
using System.IO.MemoryMappedFiles;
using System.Text;
using System.Threading.Tasks;class MemoryMappedFileClient
{static async Task Main(string[] args){using (var mmf = MemoryMappedFile.OpenExisting("SharedMemory")){using (var accessor = mmf.CreateViewAccessor()){// 发送消息string message = "Hello from client!";byte[] messageBytes = Encoding.UTF8.GetBytes(message);accessor.WriteArray(0, messageBytes, 0, messageBytes.Length);Console.WriteLine("已发送消息。");// 等待回应while (true){byte[] buffer = new byte[256];accessor.ReadArray(0, buffer, 0, buffer.Length);string response = Encoding.UTF8.GetString(buffer).TrimEnd('\0');if (!string.IsNullOrEmpty(response)){Console.WriteLine($"收到回应:{response}");// 清空回应accessor.WriteArray(0, new byte[256], 0, 256);break;}await Task.Delay(500);}}}}
}

3.4. 使用场景

需要在多个进程间高效共享大量数据。
实时数据交换,如视频流、实时监控数据等。
复杂数据结构的共享,如图像数据、结构化信息等。

4. 信号和消息(Windows Messages)

4.1. 概述

在 Windows 环境下,进程可以通过发送和接收窗口消息来进行通信。这种方法通常用于 GUI 应用程序之间的简单通信。

4.2. 特点

适用于 GUI 应用:主要用于具有窗口的应用程序之间的通信。
简单实现:适合于发送简单的消息或命令。

4.3. 实现方式

4.3.1. 发送消息(发送方)
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;class MessageSender
{// 引入 SendMessage 函数[DllImport("user32.dll", CharSet = CharSet.Auto)]public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);// 自定义消息public const uint WM_USER = 0x0400;public const uint WM_CUSTOM = WM_USER + 1;static void Main(string[] args){// 获取目标窗口句柄,可以通过窗口标题查找IntPtr hWnd = FindWindow(null, "接收消息的窗口标题");if (hWnd != IntPtr.Zero){string message = "Hello from sender!";byte[] msgBytes = Encoding.UTF8.GetBytes(message);IntPtr lParam = Marshal.AllocHGlobal(msgBytes.Length + 1);Marshal.Copy(msgBytes, 0, lParam, msgBytes.Length);Marshal.WriteByte(lParam, msgBytes.Length, 0); // 添加 null 终止符SendMessage(hWnd, WM_CUSTOM, IntPtr.Zero, lParam);Marshal.FreeHGlobal(lParam);Console.WriteLine("已发送消息。");}else{Console.WriteLine("未找到目标窗口。");}}// 引入 FindWindow 函数[DllImport("user32.dll", SetLastError = true)]public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
}
4.3.2. 接收消息(接收方)
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;class MessageReceiver : Form
{// 自定义消息public const uint WM_USER = 0x0400;public const uint WM_CUSTOM = WM_USER + 1;// 引入 WndProcprotected override void WndProc(ref Message m){if (m.Msg == WM_CUSTOM){// 获取消息内容int length = 0;while (Marshal.ReadByte(m.LParam, length) != 0) length++;byte[] buffer = new byte[length];Marshal.Copy(m.LParam, buffer, 0, length);string receivedMessage = Encoding.UTF8.GetString(buffer);MessageBox.Show($"收到消息:{receivedMessage}");}base.WndProc(ref m);}[STAThread]static void Main(){Application.EnableVisualStyles();Application.Run(new MessageReceiver());}
}

4.4. 使用场景

简单的 GUI 应用程序之间的通信。
发送简单的命令或通知。
不需要高性能或大量数据传输的场景。

5. 内存映射数据结构(Memory-Mapped Data Structures)

5.1. 概述

除了简单的数据交换,进程间还可以共享复杂的数据结构,如对象、数组等。通过内存映射文件,可以实现多个进程共享相同的内存空间,进而共享数据结构。

5.2. 特点

高效数据共享:适用于需要共享复杂数据结构的场景。
实时更新:数据在共享内存中实时更新,适用于需要实时同步数据的应用。

5.3. 实现方式

5.3.1. 共享类库

创建一个共享的类库,定义数据结构,并确保它们在内存映射文件中正确对齐和序列化。

5.3.2. 服务器端(共享数据写入)
using System;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;
using System.Text;class SharedData
{[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]public string Message;
}class MemoryMappedFileServer
{static void Main(string[] args){using (var mmf = MemoryMappedFile.CreateOrOpen("SharedData", Marshal.SizeOf(typeof(SharedData)))){using (var accessor = mmf.CreateViewAccessor()){SharedData data = new SharedData { Message = "Hello from server!" };accessor.Write(0, ref data);Console.WriteLine("已写入共享数据。");}Console.WriteLine("按任意键退出...");Console.ReadKey();}}
}
5.3.3. 客户端(共享数据读取)
using System;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;
using System.Text;class SharedData
{[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]public string Message;
}class MemoryMappedFileClient
{static void Main(string[] args){using (var mmf = MemoryMappedFile.OpenExisting("SharedData")){using (var accessor = mmf.CreateViewAccessor()){SharedData data = new SharedData();accessor.Read(0, ref data);Console.WriteLine($"收到共享数据:{data.Message}");}}}
}

5.4. 使用场景

需要共享复杂数据结构或大量数据的进程间通信。
实时数据同步,如监控系统、实时数据分析等。

6. Windows Communication Foundation (WCF)

6.1. 概述

WCF 是一个用于构建服务导向应用程序的框架,支持多种传输协议和消息格式。它适用于需要跨平台、跨网络通信的复杂应用程序。

6.2. 特点

多协议支持:支持 HTTP, TCP, Named Pipes 等多种传输协议。
灵活性高:可配置性强,适用于不同的通信需求。
安全性:内置多种安全机制,如消息加密、身份验证等。

6.3. 实现方式

6.3.1. 定义服务契约
using System.ServiceModel;[ServiceContract]
public interface IMyService
{[OperationContract]string GetMessage(string name);
}
6.3.2. 实现服务
public class MyService : IMyService
{public string GetMessage(string name){return $"Hello, {name}!";}
}
6.3.3. 配置服务

App.config(服务器端)

<configuration><system.serviceModel><services><service name="MyService"><endpoint address="" binding="netNamedPipeBinding" contract="IMyService" /><host><baseAddresses><add baseAddress="net.pipe://localhost/MyService" /></baseAddresses></host></service></services><bindings><netNamedPipeBinding><binding name="NamedPipeBinding" /></netNamedPipeBinding></bindings></system.serviceModel>
</configuration>
6.3.4. 启动服务
using System;
using System.ServiceModel;class Program
{static void Main(string[] args){using (ServiceHost host = new ServiceHost(typeof(MyService))){host.Open();Console.WriteLine("服务已启动。按任意键退出...");Console.ReadKey();}}
}
6.3.5. 客户端调用
using System;
using System.ServiceModel;class Program
{static void Main(string[] args){var binding = new NetNamedPipeBinding();var endpoint = new EndpointAddress("net.pipe://localhost/MyService");ChannelFactory<IMyService> factory = new ChannelFactory<IMyService>(binding, endpoint);IMyService proxy = factory.CreateChannel();string response = proxy.GetMessage("Client");Console.WriteLine($"服务器回应:{response}");((IClientChannel)proxy).Close();factory.Close();}
}

6.4. 使用场景

需要跨网络或跨平台的复杂服务通信。
需要高级的安全性和可靠性。
构建服务导向架构(Service-Oriented Architecture, SOA)的应用程序。

7. 信号R(SignalR)

7.1. 概述

SignalR 是一个用于构建实时 Web 功能的库,虽然主要用于 Web 应用,但也可以用于桌面应用程序间的实时通信。

7.2. 特点

实时通信:支持实时数据传输,如聊天应用、实时监控等。
简化的 API:提供高层次的 API,简化实时通信的实现。
跨平台:支持多种客户端,包括 .NET、JavaScript、Java 等。

7.3. 实现方式

7.3.1. 服务器端(Hub)
using Microsoft.AspNetCore.SignalR;public class ChatHub : Hub
{public async Task SendMessage(string user, string message){await Clients.All.SendAsync("ReceiveMessage", user, message);}
}
7.3.2. 配置服务器

Startup.cs

public class Startup
{public void ConfigureServices(IServiceCollection services){services.AddSignalR();}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){app.UseRouting();app.UseEndpoints(endpoints =>{endpoints.MapHub<ChatHub>("/chatHub");});}
}
7.3.3. 客户端(C#)
using Microsoft.AspNetCore.SignalR.Client;
using System;
using System.Threading.Tasks;class Program
{static async Task Main(string[] args){var connection = new HubConnectionBuilder().WithUrl("http://localhost:5000/chatHub").Build();connection.On<string, string>("ReceiveMessage", (user, message) =>{Console.WriteLine($"{user}: {message}");});await connection.StartAsync();Console.WriteLine("已连接到服务器。");while (true){string input = Console.ReadLine();if (input == "exit") break;await connection.InvokeAsync("SendMessage", "Client", input);}await connection.StopAsync();}
}

7.4. 使用场景

实时数据更新,如股票行情、实时监控系统。
聊天应用、多人游戏等需要即时交互的应用。
需要实时通知和推送的桌面或移动应用。

8. 共享数据库

8.1. 概述

通过使用一个共享的数据库,两个进程可以通过读写数据库中的数据来实现通信。这种方法简单且可靠,适用于不需要实时通信的场景。

8.2. 特点

简单实现:利用现有的数据库系统,无需额外的通信机制。
持久性:数据持久存储,适用于需要记录通信历史的应用。
跨平台支持:适用于不同操作系统和编程语言的进程。

8.3. 实现方式

8.3.1. 发送方写入数据
using System;
using System.Data.SqlClient;class DatabaseSender
{static void Main(string[] args){string connectionString = "Server=your_server;Database=your_db;User Id=your_user;Password=your_password;";using (SqlConnection connection = new SqlConnection(connectionString)){connection.Open();string insertQuery = "INSERT INTO Messages (Sender, Content, Timestamp) VALUES (@sender, @content, @timestamp)";using (SqlCommand command = new SqlCommand(insertQuery, connection)){command.Parameters.AddWithValue("@sender", "SenderProcess");command.Parameters.AddWithValue("@content", "Hello from sender!");command.Parameters.AddWithValue("@timestamp", DateTime.Now);command.ExecuteNonQuery();Console.WriteLine("已发送消息到数据库。");}}}
}
8.3.2. 接收方读取数据
using System;
using System.Data.SqlClient;class DatabaseReceiver
{static void Main(string[] args){string connectionString = "Server=your_server;Database=your_db;User Id=your_user;Password=your_password;";using (SqlConnection connection = new SqlConnection(connectionString)){connection.Open();string selectQuery = "SELECT Sender, Content, Timestamp FROM Messages ORDER BY Timestamp DESC";using (SqlCommand command = new SqlCommand(selectQuery, connection)){using (SqlDataReader reader = command.ExecuteReader()){while (reader.Read()){string sender = reader.GetString(0);string content = reader.GetString(1);DateTime timestamp = reader.GetDateTime(2);Console.WriteLine($"{timestamp} - {sender}: {content}");}}}}}
}

8.4. 使用场景

不需要实时通信但需要可靠数据交换的应用程序。
需要记录通信历史或数据持久性的场景。
多个进程或服务需要共享大量数据。

8.5. 注意事项

性能:数据库通信通常比内存共享或管道通信更慢,适合不频繁的数据交换。
并发控制:需要处理多进程对数据库的并发访问,确保数据一致性。
安全性:确保数据库连接的安全性,防止未经授权的访问。

9. Windows API(Windows Messages)

9.1. 概述

利用 Windows API 发送和接收消息也是一种 IPC 方式,特别适用于 GUI 应用程序之间的通信。

9.2. 特点

适用于 GUI 应用:主要用于具有窗口句柄的应用程序。
简单实现:适合发送简单命令或通知。

9.3. 实现方式

9.3.1. 发送消息(发送方)
using System;
using System.Runtime.InteropServices;class MessageSender
{// 引入 SendMessage 函数[DllImport("user32.dll", CharSet = CharSet.Auto)]public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);// 自定义消息public const uint WM_USER = 0x0400;public const uint WM_CUSTOM = WM_USER + 1;// 引入 FindWindow 函数[DllImport("user32.dll", SetLastError = true)]public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);static void Main(string[] args){// 获取目标窗口句柄,可以通过窗口标题查找IntPtr hWnd = FindWindow(null, "接收消息的窗口标题");if (hWnd != IntPtr.Zero){string message = "Hello from sender!";byte[] msgBytes = System.Text.Encoding.UTF8.GetBytes(message);IntPtr lParam = Marshal.AllocHGlobal(msgBytes.Length + 1);Marshal.Copy(msgBytes, 0, lParam, msgBytes.Length);Marshal.WriteByte(lParam, msgBytes.Length, 0); // 添加 null 终止符SendMessage(hWnd, WM_CUSTOM, IntPtr.Zero, lParam);Marshal.FreeHGlobal(lParam);Console.WriteLine("已发送消息。");}else{Console.WriteLine("未找到目标窗口。");}}
}
9.3.2. 接收消息(接收方)
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;class MessageReceiver : Form
{// 自定义消息public const uint WM_USER = 0x0400;public const uint WM_CUSTOM = WM_USER + 1;// 重写 WndProc 方法以处理自定义消息protected override void WndProc(ref Message m){if (m.Msg == WM_CUSTOM){// 获取消息内容int length = 0;while (Marshal.ReadByte(m.LParam, length) != 0) length++;byte[] buffer = new byte[length];Marshal.Copy(m.LParam, buffer, 0, length);string receivedMessage = Encoding.UTF8.GetString(buffer);MessageBox.Show($"收到消息:{receivedMessage}");}base.WndProc(ref m);}[STAThread]static void Main(){Application.EnableVisualStyles();Application.Run(new MessageReceiver());}
}

9.4. 使用场景

简单的 GUI 应用程序之间的通信。
发送简单的命令或通知。
不需要高性能或大量数据传输的场景。

9.5. 注意事项

窗口句柄:需要获取目标窗口的句柄(Handle),可以通过窗口标题或类名查找。
消息格式:确保发送方和接收方对消息格式有一致的约定。
安全性:避免发送恶意消息,确保消息的合法性。

10. 其他 IPC 方法

10.1. COM(Component Object Model)

概述:COM 是微软的一种组件软件架构,用于不同进程或不同编程语言间的对象通信。
特点:跨语言、跨进程、支持对象导向。
使用场景:需要复杂对象交互和跨语言支持的场景。
缺点:配置复杂,学习曲线陡峭。

10.2. 共享数据库

概述:通过共享数据库(如 SQL Server, SQLite, MySQL)进行数据交换。
特点:数据持久化、易于管理、跨平台。
使用场景:不需要实时通信但需要可靠数据交换的场景。
缺点:性能较低,不适合高频率数据交换。

10.3. 文件系统

概述:通过在文件系统中读写文件来实现通信。
特点:实现简单、无需特殊配置。
使用场景:简单的数据交换,如配置文件、日志记录等。
缺点:不适合实时通信,性能较低,易受文件锁定影响。

11. 性能和安全性考虑

11.1. 性能优化

选择合适的 IPC 方法:根据通信需求(数据量、实时性、跨网络等)选择最合适的 IPC 方法。
减少数据传输量:只传输必要的数据,避免冗余传输。
使用高效的数据格式:如二进制格式代替文本格式,减少解析开销。
并发处理:利用异步编程和并发机制,提升数据处理效率。

11.2. 安全性

身份验证:确保只有授权的进程可以进行通信。
数据加密:在传输敏感数据时,使用加密机制保护数据安全。
访问控制:设置严格的访问权限,防止未授权的访问和操作。
防止注入攻击:验证和清理接收到的数据,防止恶意代码注入。

12. 总结

C# 提供了多种进程间通信(IPC)方法,涵盖了从简单的数据交换到复杂的实时通信需求。选择合适的 IPC 方法需要根据具体的应用场景、性能需求和安全要求来决定。以下是常见 IPC 方法的简要对比:

IPC 方法优点缺点适用场景
命名管道高效、支持双向通信、可跨网络仅限于同一台机器或局域网高效数据传输、双向通信
套接字(Sockets)灵活、支持多协议、跨平台实现复杂、需要处理网络延迟和安全性跨网络通信、实时应用如聊天和游戏
内存映射文件高性能、适合共享大量数据需要处理内存管理和同步问题实时数据共享、大量数据交换
信号和消息简单、适用于 GUI 应用仅适用于具有窗口句柄的应用,有限的数据传输能力简单命令或通知的 GUI 应用通信
WCF多协议支持、高度可配置、安全性强配置复杂、学习曲线陡峭复杂服务通信、跨平台和跨语言应用
SignalR实时通信、简化的 API、跨平台主要用于 Web 应用,桌面应用需要额外配置实时数据更新、聊天应用、实时监控系统
共享数据库数据持久化、易于管理、跨平台性能较低、不适合高频率实时通信可靠的数据交换、需要记录通信历史的场景
文件系统实现简单、无需特殊配置不适合实时通信、性能低、易受文件锁定影响简单的数据交换、配置文件和日志记录
COM跨语言、支持复杂对象交互配置复杂、学习曲线陡峭需要复杂对象交互和跨语言支持的场景

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

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

相关文章

【vue+printJs】前端打印, 自定义字体大小, 自定义样式, 封装共享样式

效果示例 思维导图 目录 1,基本使用1, 依赖下载2, 页面导入3, 修改字体大小(可行但不推荐) 2, 自定义样式,字体大小1, 修改字体大小(推荐)2, 自定义样式3, 封装共享样式 3, 去除页面页脚内容4, 测试案例demo, 直接cv可用5, print-js的其他参数说明 1,基本使用 1, 依赖下载 …

MyBatis-Plus 之 typeHandler 的使用

一、typeHandler 的使用 1、存储json格式字段 如果字段需要存储为json格式&#xff0c;可以使用JacksonTypeHandler处理器。使用方式非常简单&#xff0c;如下所示&#xff1a; 在domain实体类里面要加上&#xff0c;两个注解 TableName(autoResultMap true) 表示自动…

学习之面试题:偏函数

偏函数&#xff08;Partial Function&#xff09;是 Python 中的一个实用工具&#xff0c;通常用于函数式编程中&#xff0c;可以固定一个函数的部分参数&#xff0c;从而生成一个新的函数。偏函数在 Python 中通常通过 functools.partial 实现。在面试中&#xff0c;考察偏函数…

无人驾驶打造“新丝路”,驭势科技在卡塔尔设立研发运营中心

在卡塔尔多哈的街头&#xff0c;除了身穿阿拉伯长袍的人群和悠闲的骆驼队伍之外&#xff0c;又将出现一道全新的风景线&#xff0c;那就是来自驭势科技的无人驾驶车。10月8日&#xff0c;在中关村京港澳青年创新创业中心的协助与对接下&#xff0c;驭势科技在卡塔尔科技园正式成…

<Project-8.1.1 pdf2tx-mm> Python 调用 ChatGPT API 翻译PDF内容 历程心得

原因 用ZhipuAI&#xff0c;测试用的PDF里&#xff0c;有国名西部省穆斯林&#xff0c;翻译结果返回 “系统检测到输入或生成内容可能包含不安全或敏感内容&#xff0c;请您避免输入易产生敏感内容的提 示语&#xff0c;感谢您的配合” 。想过先替换掉省名、民族名等&#xff…

计量校准工作中的误差评定与不确定度

计量校准的目的是确定测量仪器的误差和不确定度&#xff0c;以评估其测量结果的可靠性。误差评定和不确定度计算是计量校准过程中的重要步骤。 误差评定是指通过比较测量仪器的测量结果与已知标准值之间的差异&#xff0c;确定仪器的准确性和精度。误差可以分为系统误差和随机误…

【Java】I/O 操作详解

&#x1f4c3;个人主页&#xff1a;island1314 ⛺️ 欢迎关注&#xff1a;&#x1f44d;点赞 &#x1f442;&#x1f3fd;留言 &#x1f60d;收藏 &#x1f49e; &#x1f49e; &#x1f49e; 目录 1. 引言 &#x1f680; 2. File 类 &#x1f4d5; 2.1 创建 File 对象 …

wpf实现新用户页面引导

第一步 第二部 部分代码: private void show(int xh, FrameworkElement fe, string con, Visibility vis Visibility.Visible) {Point point fe.TransformToAncestor(Window.GetWindow(fe)).Transform(new Point(0, 0));//获取控件坐标点RectangleGeometry rg new Rectangl…

精益与数字化的融合:制造业的创新之路

回望过去&#xff0c;精益管理作为制造业的瑰宝&#xff0c;以其“消除浪费、持续改进、顾客至上”的核心理念&#xff0c;引领了无数企业走向成功。从丰田生产方式到全球范围内的广泛实践&#xff0c;精益管理不仅提升了生产效率&#xff0c;更重塑了企业的文化和价值观。它教…

docker 相关

解释下以下命令&#xff1a; docker run --rm -v ${PWD}:/local -v ${PWD}/generated:/generated openapitools/openapi-generator-cli generate -i /local/openapi.yaml -g csharp -o /generated 这是一个用于在 Docker 容器中运行 OpenAPI Generator CLI 的命令。让我们逐个…

细说Qt的状态机框架及其用法

文章目录 使用场景基本用法状态定义添加转换历史状态QStateMachine是Qt框架中用于构建状态机的一个类,它属于Qt的状态机框架(State Machine Framework)。这个框架提供了一种模型,用于设计响应不同事件(如用户输入、文件I/O或网络活动)的应用程序的行为。通过使用状态机,开发…

音视频好文总结

RTSP play同步 ffplay播放器研究分析 ffplay播放器 暂停、逐帧、音量、快进快退seek功能分析 RTSP RTP RTCP SDP基础知识 flv格式分析与解复用 TS格式详解 m3u8格式详解 FLV格式详解 MP4格式详解 HLS协议详解 RTMP协议详解 HTTP-FLV协议详解 H.264 SPS、PPS详解 H…

3.计算机网络_端口号

端口号的由来 运输层的作用&#xff1a; 在计算机网络中&#xff0c;运输层处在用户功能的最底层、通信部分的最高层的位置&#xff0c;也就是说运输层是用户数据和实际网络通信的桥梁。因此运输层屏蔽了网络的实现部分&#xff0c;以协议的方式向用户层提供了接口&#xff…

文章解读与仿真程序复现思路——电力自动化设备EI\CSCD\北大核心《计及状态量平均超限比的综合能源系统动态能量流双层优化》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

【千图网-登录_注册安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…

【Linux进程间通信】Linux信号机制深度解析:保存与处理技巧

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;Linux “ 登神长阶 ” &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀Linux进程间通信 &#x1f4d2;1. 信号的保存&#x1f30a;在内核中的表示&#x1f342;sigs…

Python OpenCV精讲系列 - 目标检测与识别深入理解(二十)

&#x1f496;&#x1f496;⚡️⚡️专栏&#xff1a;Python OpenCV精讲⚡️⚡️&#x1f496;&#x1f496; 本专栏聚焦于Python结合OpenCV库进行计算机视觉开发的专业教程。通过系统化的课程设计&#xff0c;从基础概念入手&#xff0c;逐步深入到图像处理、特征检测、物体识…

【QT】常用控件(一)

个人主页~ 常用控件 一、控件是什么二、QWidget核心属性1、enabled2、geometry3、windowTitle4、windowIcon5、windowOpacity6、cursor7、font8、toolTip9、focusPolicy10、styleSheet 一、控件是什么 ui设计界面左边的这些都叫控件&#xff0c;除了这些以外&#xff0c;QT还允…

竹壳天气时钟(二)第二阶段任务已完成

一、简介 准备用基于esp8266的nodemcu开发板做一个天气时钟。 一步一步记录代码编写过程。 竹壳天气时钟 Bamboo shell weather clock 使用基于esp8266的NodeMCU制作。 计划用竹子做最后成品的外壳&#xff0c;所以才有了这个名称。 第一阶段任务&#xff1a; 1.开启混合模式&…

2025推荐选题|基于MVC的农业病虫害防治平台的设计与实现

作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验&#xff0c;被多个学校常年聘为校外企业导师&#xff0c;指导学生毕业设计并参与学生毕业答辩指导&#xff0c;…