当前位置: 首页 > news >正文

2024.8.19 学习记录 —— 作业

一、TCP机械臂测试

#include <myhead.h>#define SER_PORT 8888          // 与服务器保持一致
#define SER_IP "192.168.0.114" // 服务器ip地址int main(int argc, const char *argv[])
{// 创建文件描述符打开键盘文件int fd = open("/dev/input/event1", O_RDONLY);if (fd == -1){perror("open error");return -1;}// 定义结构体接收键盘文件的数据struct input_event ie;// 创建用于通信的套接字文件描述符int cfd = socket(AF_INET, SOCK_STREAM, 0);if (cfd == -1){perror("socket error");return -1;}printf("cfd = %d\n", cfd); // 连接到服务器// 填充服务器地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET;                // 通信域sin.sin_port = htons(SER_PORT);          // 服务器端口号sin.sin_addr.s_addr = inet_addr(SER_IP); // 服务器ip地址// 连接服务器if (connect(cfd, (struct sockaddr *)&sin, sizeof(sin)) == -1){perror("connect error");return -1;}printf("连接服务器成功\n");// 准备数据char rbuf[5] = {0xff, 0x02, 0x00, 0x10, 0xff};unsigned char bbuf[5] = {0xff, 0x02, 0x01, 0x10, 0xff};// 发送给服务器,以初始化机械臂send(cfd, rbuf, sizeof(rbuf), 0);sleep(1);send(cfd, bbuf, sizeof(bbuf), 0);printf("%#x\n", rbuf[3]);printf("%#x\n", bbuf[3]);while (1){// 接收键盘文件数据read(fd, &ie, sizeof(ie));switch (ie.code * ie.value){case 32: // d键rbuf[3] += 1;if (rbuf[3] > 90){rbuf[3] = 90;}send(cfd, rbuf, sizeof(rbuf), 0); // 传输数据给机械臂break;case 30: // a键rbuf[3] -= 1;if (rbuf[3] < -90){rbuf[3] = -90;}send(cfd, rbuf, sizeof(rbuf), 0); // 传输数据给机械臂break;case 31: // s键bbuf[3] -= 1;if (bbuf[3] <= 0){bbuf[3] = 0;}send(cfd, bbuf, sizeof(bbuf), 0); // 传输数据给机械臂break;case 17: // w键bbuf[3] += 1;if (bbuf[3] > 180){bbuf[3] = 180;}if (bbuf[3] < 0){bbuf[3] = 0;}send(cfd, bbuf, sizeof(bbuf), 0); // 传输数据给机械臂break;default:break;}/*if (buf == 'd') // 红机械臂右移一度{rbuf[3] = rbuf[3] + 1; // 修改角度printf("%#x\n", rbuf[3]);send(cfd, rbuf, sizeof(rbuf), 0); // 传输结果}if (buf == 'a') // 红机械臂左移一度{rbuf[3] = rbuf[3] - 1;printf("%#x\n", rbuf[3]);send(cfd, rbuf, sizeof(rbuf), 0);}if (buf == 's') // 蓝机械臂上移一度{bbuf[3] = bbuf[3] + 1;printf("%#x\n", bbuf[3]);send(cfd, bbuf, sizeof(bbuf), 0);}if (buf == 'w') // 蓝机械臂下移一度{bbuf[3] = bbuf[3] - 1;printf("%#x\n", bbuf[3]);send(cfd, bbuf, sizeof(bbuf), 0);}if (buf == 'q') // 直接设置{int val = 0;printf("红机械臂增减角度:");scanf("%d", &val);        // 获取增减角度rbuf[3] = rbuf[3] + val;  // 修改角度printf("%#x\n", rbuf[3]); // 传输结果getchar();printf("蓝机械臂增减角度:");scanf("%d", &val);bbuf[3] = bbuf[3] + val;printf("%#x\n", bbuf[3]);getchar();send(cfd, rbuf, sizeof(rbuf), 0);usleep(100);send(cfd, bbuf, sizeof(bbuf), 0);}buf = 0;*/}// 5、关闭套接字close(cfd);return 0;
}

二、基于UDP的TFTP文件传输

#include <myhead.h>
int main(int argc, char const *argv[])
{int sfd = socket(AF_INET, SOCK_DGRAM, 0);if (sfd == -1){perror("socket error");return -1;}// 下载请求包char buf[516] = "";short *p1 = (short *)buf; // 操作码*p1 = htons(1);char *p2 = buf + 2; // 文件名strcpy(p2, "5.png");char *p4 = p2 + strlen(p2) + 1; // 模式位strcpy(p4, "octet");int size = 2 + strlen(p2) + strlen(p4) + 2; // 请求包总长// 服务器地址信息struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(69);sin.sin_addr.s_addr = inet_addr("192.168.0.114");// 向服务器发送a下载请求sendto(sfd, buf, size, 0, (struct sockaddr *)&sin, sizeof(sin));int newfd = 0;if ((newfd = open("./5.png", O_WRONLY | O_CREAT | O_APPEND | O_TRUNC, 0664)) == -1){perror("open error");return -1;}while (1){socklen_t size_sin = sizeof(sin);bzero(buf, sizeof(buf)); // 清空bufint res = 0; // 接收服务器发送的数据if ((res = recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr *)&sin, &size_sin)) == -1){perror("recvform error");return -1;}if (res <516){write(newfd, buf + 4, res - 4);*p1 = htons(4);sendto(sfd, buf, 4, 0, (struct sockaddr *)&sin, sizeof(sin));printf("下载结束\n");break;}write(newfd, buf + 4, res - 4);                               // 写入数据*p1 = htons(4);                                               // 操作码置位 4sendto(sfd, buf, 4, 0, (struct sockaddr *)&sin, sizeof(sin)); // 发送ACK}close(sfd);close(newfd);return 0;
}

 三、基于UDP的聊天室

1、服务器端

#include <myhead.h>
#define SER_PORT 6666            // 服务器端口号
#define SER_IP "192.168.179.128" // 服务器ip地址
// 定义结构体用于存储客服端的信息
struct MSG
{char type; // 信息类型 'L'表示登录 'T'表示群聊 'Q'表示退出 'S'表示系统消息char name[20];char msg[256];
};// 定义链表用于存储不同的客服端信息
struct ADDR
{struct sockaddr_in cin;struct ADDR *next;
};// 登录操作的函数
void do_login(int sfd, struct MSG buf, struct ADDR *addr, struct sockaddr_in cin)
{// 先遍历链表 将新用户加入群聊的消息发给所有人struct ADDR *tmp = addr; // 记录链表头节点while (tmp->next != NULL){tmp = tmp->next;if (-1 == sendto(sfd, &buf, sizeof(buf), 0, (struct sockaddr *)&(tmp->cin), sizeof(tmp->cin))){perror("sendto error");}}// 将新用户的网络信息结构体 头插入链表struct ADDR *pnew = NULL;if (NULL == (pnew = (struct ADDR *)malloc(sizeof(struct ADDR)))){printf("malloc error\n");return;}pnew->cin = cin;pnew->next = addr->next;addr->next = pnew;return;
}// 群聊操作的函数
void do_chat(int sfd, struct MSG buf, struct ADDR *addr, struct sockaddr_in cin)
{// 遍历链表,将群聊消息发给除了自己之外的所有人struct ADDR *ptmp = addr;while (ptmp->next != NULL){ptmp = ptmp->next;if (memcmp(&cin, &(ptmp->cin), sizeof(cin))){// 不是自己 就发送数据sendto(sfd, &buf, sizeof(buf), 0, (struct sockaddr *)&(ptmp->cin), sizeof(ptmp->cin));}}return;
}// 退出操作的函数
void do_quit(int sfd, struct MSG buf, struct ADDR *addr, struct sockaddr_in cin)
{// 遍历链表 是自己就将自己在链表中删除// 不是自己 就发送 退出群聊的数据struct ADDR *ptmp = addr;struct ADDR *del = NULL;while (ptmp->next != NULL){if (memcmp(&(ptmp->next->cin), &cin, sizeof(cin))){// 不是自己ptmp = ptmp->next;strcat(buf.name,"-系统接管");sendto(sfd, &buf, sizeof(buf), 0, (struct sockaddr *)&(ptmp->cin), sizeof(ptmp->cin));}else{// 是自己del = ptmp->next;ptmp->next = del->next;free(del);del = NULL;}}return;
}int main(int argc, char const *argv[])
{// 1、创建用于通信的套接字文件描述符int sfd = socket(AF_INET, SOCK_DGRAM, 0);if (sfd == -1){perror("scoket error");return -1;}printf("sfd = %d\n", sfd); // 3// 2、绑定ip地址和端口号//  2.1 填充地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET;                // 通信域sin.sin_port = htons(SER_PORT);          // 端口号sin.sin_addr.s_addr = inet_addr(SER_IP); // ip地址// 2.2、 绑定if (bind(sfd, (struct sockaddr *)&sin, sizeof(sin)) == -1){perror("bind error");return -1;}printf("bind success\n");// 3、数据接收struct MSG buf; // 定义用于信息接收的变量// 定义用于接收客服端网络信息的变量struct sockaddr_in cin;          // 接收对端地址信息socklen_t addrlen = sizeof(cin); // 接收地址长度// 4、创建父子进程用于不同功能pid_t pid = 0;if (-1 == (pid = fork())){perror("fork error");return -1;}if (0 == pid) // 子进程,用于信息的处理{// 创建保存客户端信息的链表头节点struct ADDR *addr;if (NULL == (addr = (struct ADDR *)malloc(sizeof(struct ADDR)))){printf("malloc error\n");return -1;}memset(addr, 0, sizeof(addr));addr->next = NULL;while (1){ // 循环收发数据// 清空容器,确保信息准确memset(&buf, 0, sizeof(buf));memset(&cin, 0, sizeof(cin));// 接收客户端发送的消息,存放在msg中if (-1 == recvfrom(sfd, &buf, sizeof(buf), 0, (struct sockaddr *)&cin, &addrlen)){perror("recvfrom error");return -1;}switch (buf.type){         // 判断消息中的操作码,根据操作码执行对应操作case 'L': // 登录操作do_login(sfd, buf, addr, cin);break;case 'T': // 群聊操作do_chat(sfd, buf, addr, cin);break;case 'Q': // 退出操作do_quit(sfd, buf, addr, cin);break;}}}else // 父进程,用于发送系统信息{strcpy(buf.name, "系统消息");buf.type = 'T';while (1) // 循环在终端接收消息{memset(buf.msg, 0, sizeof(buf.msg));printf("输入信息:");fgets(buf.msg, 256, stdin);buf.msg[strlen(buf.msg) - 1] = 0;sendto(sfd, &buf, sizeof(buf), 0, (struct sockaddr *)&sin, addrlen);// 向子进程发送信息}}// 4、关闭文件描述符close(sfd);return 0;
}

2、客服端

#include <myhead.h>
#define SER_PORT 6666            // 与服务器保持一致
#define SER_IP "192.168.179.128" // 服务器ip地址// 用于信息发送的结构体
struct msgTyp
{char type;     // 信息类型 L-》注册名 T-》聊天信息 Q-》退出char name[20]; // 注册名char msg[256]; // 聊天信息
};int main(int argc, char const *argv[])
{// 1、 创建用于通信的套接字文件描述符int cfd = socket(AF_INET, SOCK_DGRAM, 0);if (cfd == -1){perror("socket error");return -1;}printf("cfd = %d\n", cfd);// 2、信息发送// 2.1数据结构体定义struct msgTyp buf;bzero(&buf, 0);// 2.2 填充服务器地址信息结构体struct sockaddr_in sin;                  // 接收对端地址信息sin.sin_family = AF_INET;                // 服务器的通信域sin.sin_port = htons(SER_PORT);          // 服务器的端口号sin.sin_addr.s_addr = inet_addr(SER_IP); // 服务器的ip地址socklen_t seraddr_len = sizeof(sin);     // 服务器信息结构体大小// 2.3 注册buf.type = 'L'; // 指定消息类型printf("注册用户名:");fgets(buf.name, sizeof(buf.name), stdin);buf.name[strlen(buf.name) - 1] = 0;strcpy(buf.msg, "登录");// 向服务器发送登录信息sendto(cfd, &buf, sizeof(buf), 0, (struct sockaddr *)&sin, seraddr_len);// 3 创建父子进程用于处理不同工作pid_t pid = 0;if (-1 == (pid = fork())){perror("fork error");return -1;}// 子进程,用于接收信息if (0 == pid){while (1){if (-1 == recvfrom(cfd, &buf, sizeof(buf), 0, NULL, NULL)){perror("recvfrom error");return -1;}// 打印接收到的信息printf("[%s]:%s\n", buf.name, buf.msg);}}else if (0 < pid) // 父进程,用于向其他客服端发送信息{while (1){bzero(&buf, 0); // 清空容器,以保证信息的准确性printf("输入信息:");fgets(buf.msg, 256, stdin);buf.msg[strlen(buf.msg) - 1] = 0;if (!strcmp(buf.msg, "quit")){buf.type = 'Q';strcpy(buf.msg, "退出群聊");sendto(cfd, &buf, sizeof(buf), 0, (struct sockaddr *)&sin, seraddr_len);break;}else{buf.type = 'T';// 发送信息sendto(cfd, &buf, sizeof(buf), 0, (struct sockaddr *)&sin, seraddr_len);}}// 退出子进程kill(pid, SIGKILL);wait(NULL); // 阻塞回收子进程资源}// 3、关闭套接字close(cfd);return 0;
}

 

相关文章:

2024.8.19 学习记录 —— 作业

一、TCP机械臂测试 #include <myhead.h>#define SER_PORT 8888 // 与服务器保持一致 #define SER_IP "192.168.0.114" // 服务器ip地址int main(int argc, const char *argv[]) {// 创建文件描述符打开键盘文件int fd open("/dev/input/event1…...

Java 阿里云视频直播开发流程

首先来看一下直播效果 推流工具有很多种&#xff08;例如OBS、阿里云直播Demo推流、等等&#xff0c;我用的是芯象导播&#xff09;阿里播放器地址 一、直播基础服务概述 官方文档说明 二、直播域名配置需要两个域名&#xff08;推流域名、播流域名&#xff09; 官方文档说…...

SQLite 轻量级的嵌入式关系型数据库的替代软件

SQLite 是一个轻量级的嵌入式关系型数据库&#xff0c;由于其简单易用和跨平台的特性&#xff0c;被广泛应用于各种应用程序中。以下是一些可作为SQLite替代品的数据库软件或可视化管理工具&#xff1a; 1. **SQLiteStudio**&#xff1a;这是一个免费、开源的跨平台SQLite数据…...

Flutter-自适用高度PageView

需求 在 Flutter 中&#xff0c;PageView 是一个非常常用的组件&#xff0c;能够实现多个页面的滑动切换。然而&#xff0c;默认的 PageView 高度是固定的&#xff0c;这在展示不同高度的页面时&#xff0c;可能会导致不必要的空白或内容裁剪问题。为了使 PageView 能够根据每…...

群晖NAS本地搭建可远程交互的大型语言模型LLM聊天机器人

文章目录 前言1. 拉取相关的Docker镜像2. 运行Ollama 镜像3. 运行Chatbot Ollama镜像4. 本地访问5. 群晖安装Cpolar6. 配置公网地址7. 公网访问8. 固定公网地址 前言 本文主要分享如何在群晖NAS本地部署并运行一个基于大语言模型Llama 2的个人本地聊天机器人并结合内网穿透工具…...

TypeScript 构建工具之 webpack

在实际开发中&#xff0c;直接使用TypeScript 编译器的情况不多。 在项目中&#xff0c;需要使用构建工具对代码进行打包&#xff0c;不可能脱离项目使用TypeScript 编译器单独打包TypeScript 。 那如何将 webpack 和 TypeScript 进行集成&#xff1f; 参考文档&#xff1a; w…...

conda环境下在pycharm中调试scrapy项目

前提条件 已经创建好了conda环境已经安装好了scrapy框架项目初始化完成 编写一个爬虫脚本 import scrapyclass StackOverflowSpider(scrapy.Spider):name stackoverflowstart_urls [http://stackoverflow.com/questions?sortvotes]def parse(self, response):print("…...

contenteditable=“true“的标签限制字数的时候修改光标位置

contenteditable"true"的标签限制字数的时候修改光标位置 有时候input和textarea并不能完全满足ui需求&#xff0c;这个时候我们就用contenteditable"true"来将别的标签修改为可编辑状态&#xff0c;但当我们通过js修改了内容之后光标的位置就是一个问题&…...

51单片机-LED灯蜂鸣器数码管按键DS18B20温度传感器

LDE灯的相关程序 LED灯闪烁 LED流水灯 方法1 方法二&#xff1a; 因为P1口可以直接控制P1^0~P1^7的8个led灯&#xff0c;利用一个8位的二进制数字来进行控制即可。如果要点亮P1^0 只需要给P1口传递 1111 1110即可。 蜂鸣器的使用 什么是蜂鸣器&#xff1f; 蜂鸣器是一种一…...

笔记本一线品牌有哪些

笔记本电脑的一线品牌通常指的是在市场上具有较高市场份额、良好口碑、较强的技术实力和服务能力的品牌。根据目前的信息&#xff0c;笔记本电脑市场的一线品牌主要包括以下几个&#xff1a; 联想 (Lenovo)&#xff1a;联想在全球笔记本市场上的占有率较高&#xff0c;其产品线…...

mysql聚合函数和分组

我最近开了几个专栏&#xff0c;诚信互三&#xff01; > |||《算法专栏》&#xff1a;&#xff1a;刷题教程来自网站《代码随想录》。||| > |||《C专栏》&#xff1a;&#xff1a;记录我学习C的经历&#xff0c;看完你一定会有收获。||| > |||《Linux专栏》&#xff1…...

ubuntu20.04+RealSenseD455

ubuntu20.04安装驱动双目相机RealSenseD455 安装环境安装RealSense SDK 2.0ROS包安装启动Realsense摄像头存在的 bugD455标定安装环境 系统:Ubuntu20.04 ROS:Noetic 视觉传感器:Intel RealSense D455 安装RealSense SDK 2.0 该安装有两种方式,一个是用命令安装,另一个是…...

WAF绕过技巧

WAF绕过技巧 WAF&#xff08;Web Application Firewall&#xff09;是一种安全系统&#xff0c;旨在监控和控制网络流量&#xff0c;以防止攻击&#xff0c;如SQL 注入、跨站脚本&#xff08;XSS&#xff09;和拒绝服务&#xff08;DoS&#xff09;。 WAF 可以通过多种方式绕过…...

HarmonyOS应用三之组件生命周期和参数传递

目录&#xff1a; 1、生命周期的执行顺序2、页面数据传递3、图片的读取4、数据的备份和恢复5、轮播图6、页面布局图 1、生命周期的执行顺序 /** Copyright (c) 2023 Huawei Device Co., Ltd.* Licensed under the Apache License, Version 2.0 (the "License");* yo…...

[Qt][Qt 网络][上]详细讲解

目录 0.概述1.UDP Socket1.核心API概览2.回显服务器3.回显客户端 0.概述 要使用Qt中有关网络编程的API&#xff0c;需要添加network模块 1.UDP Socket 1.核心API概览 主要的类有两个&#xff1a;QUdpSocket和QNetworkDatagramQUdpSocket表⽰⼀个UDP的socket⽂件 bind(const …...

读零信任网络:在不可信网络中构建安全系统21读后总结与感想兼导读

1. 基本信息 零信任网络&#xff1a;在不可信网络中构建安全系统 道格巴斯&#xff08;Doug Barth&#xff09; 著 人民邮电出版社,2019年8月出版 1.1. 读薄率 书籍总字数252千字&#xff0c;笔记总字数73194字。 读薄率73194252000≈29.5% 这个读薄率是最高的吧&#x…...

Java基础——注释

在开发中注释是必不可少的&#xff0c;帮助我们更好的标记阅读代码&#xff0c;下面介绍几种常用的注释方式。 一、注释种类 1. 单行注释 使用//一行代码来进行注释&#xff0c;只能注释一行内容 2. 多行注释 使用斜杠星号的方式 /*注释多行代码*/&#xff0c;注释多行代…...

Redis未授权访问漏洞利用合集

一、基本信息 靶机&#xff1a;IP:192.168.100.40 攻击机&#xff1a;IP:192.168.100.60 二、漏洞 & 过程 Redis 未授权访问漏洞利用无口令远程登录靶机 靶机 cd redis-4.0.8/src./redis-server ../redis.conf 攻击机 ./redis-cli -h 192.168.100.40 Redis 未授权访问…...

基于asp.net的在线考试系统、基于c#的在线考试管理系统

摘 要 伴随着社会以及科学技术的发展&#xff0c;互联网已经渗透在人们的身边&#xff0c;网络慢慢的变成了人们的生活必不可少的一部分&#xff0c;紧接着网络飞速的发展&#xff0c;管理系统这一名词已不陌生&#xff0c;越来越多的学校、公司等机构都会定制一款属于自己个…...

将 hugo 博客搬迁到服务器

1. 说明 在 Ubuntu 22.04 上使用 root 账号&#xff0c;创建普通账号&#xff0c;并赋予 root 权限。 演示站点&#xff1a;https://woniu336.github.io/ 魔改hugo主题: https://github.com/woniu336/hugo-magic 2. 服务器配置 建立 git 用户 adduser git安装 git sudo apt …...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中&#xff0c;时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志&#xff0c;到供应链系统的物流节点时间戳&#xff0c;时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库&#xff0c;其日期时间类型的…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

基于IDIG-GAN的小样本电机轴承故障诊断

目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) ​梯度归一化(Gradient Normalization)​​ (2) ​判别器梯度间隙正则化(Discriminator Gradient Gap Regularization)​​ (3) ​自注意力机制(Self-Attention)​​ 3. 完整损失函数 二…...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】&#xff0c;注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录&#xff08;即exe所在文件夹&#xff09;加入系统变量…...

WPF八大法则:告别模态窗口卡顿

⚙️ 核心问题&#xff1a;阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程&#xff0c;导致后续逻辑无法执行&#xff1a; var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题&#xff1a…...