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

Windows 重启 explorer 的正确做法

目录

一、关于 Restart Manager

二、重启管理器实例

三、完整实现代码和测试


本文属于原创文章,转载请注明出处:

https://blog.csdn.net/qq_59075481/article/details/136179191。

我们往往使用 TerminateProcess 并传入 PID 和特殊结束代码 1 或者 taskkill /f /im 等方法重启资源管理器( explorer.exe ),其实这是不正确的。我们应该使用重启管理器接口来重启 explorer 进程。

一、关于 Restart Manager

重启管理器 API 可以消除或减少完成安装或更新所需的系统重启次数。软件更新在安装或更新期间需要重启系统的主要原因是,正在运行的应用程序或服务当前正在使用某些正在更新的文件。 重启管理器允许关闭并重启除关键系统服务外的所有服务 。这会释放正在使用的文件,并允许完成安装操作。

安装程序可以使用重启管理器来注册应在安装应用程序或更新期间替换的文件。然后,在后续更新或安装期间,安装程序可以使用重启管理器来确定哪些文件因当前正在使用而无法更新。重启管理器可以关闭并重启当前使用这些文件的非关键服务或应用程序。安装程序可以指示重启管理器根据正在使用的文件、进程 ID (PID) 或 Windows 服务的短名称来关闭和重启应用程序或服务。

二、重启管理器实例

实现一个简易的重启管理器实例主要需要 RmStartSession 、RmRegisterResources、RmShutdown、RmEndSession 等函数。

首先我们需要在代码中引入头文件:

#include <restartmanager.h>
#pragma comment(lib, "Rstrtmgr.lib")

然后我们用 RmStartSession 创建会话。其中会话的密钥是 GUID ,为其分配缓冲区时候需要计算好缓冲区大小。

#define RM_SESSIONKEY_LEN sizeof(GUID) * 2 + 1
DWORD dwRmStatus = 0;
DWORD dwSessionHandle = 0;
WCHAR strSessionKey[RM_SESSIONKEY_LEN] = { 0 };
dwRmStatus = RmStartSession(&dwSessionHandle, NULL, strSessionKey);
if (ERROR_SUCCESS != dwRmStatus)
{std::cerr << "RmStartSession failed: " << std::dec << dwRmStatus << std::endl;return -1;
}

随后需要将要重启的进程信息放到 RM_UNIQUE_PROCESS 结构体数组中,该结构体如下:

typedef struct _RM_UNIQUE_PROCESS {DWORD    dwProcessId;FILETIME ProcessStartTime;
} RM_UNIQUE_PROCESS, *PRM_UNIQUE_PROCESS;

第一个是进程的 PID,第二个是进程的创建时间,使用 GetProcessTimes 函数的 lpCreationTime 参数获取。

BOOL GetProcessTimes([in]  HANDLE     hProcess,[out] LPFILETIME lpCreationTime,[out] LPFILETIME lpExitTime,[out] LPFILETIME lpKernelTime,[out] LPFILETIME lpUserTime
);

我使用 Toolhelp32 枚举 explorer 进程,并生成 RM_UNIQUE_PROCESS 结构体数组。

BOOL GetShellProcessRmInfoEx(PRM_UNIQUE_PROCESS* lpRmProcList, DWORD_PTR* lpdwCountNum
)
{PROCESSENTRY32W pe32 = { 0 };FILETIME lpCreationTime = { 0 };FILETIME lpExitTime = { 0 };FILETIME lpKernelTime = { 0 };FILETIME lpUserTime = { 0 };HANDLE hProcess = nullptr;RM_UNIQUE_PROCESS tpProc = { 0 };std::vector<RM_UNIQUE_PROCESS> RmProcVec;SIZE_T VecLength = 0;// 在使用这个结构前,先设置它的大小pe32.dwSize = sizeof(pe32);// 给系统内所有的进程拍个快照HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (hProcessSnap == INVALID_HANDLE_VALUE){std::cerr << "CreateToolhelp32Snapshot 调用失败." << std::endl;return FALSE;}// 遍历进程快照,轮流显示每个进程的信息BOOL bMore = Process32FirstW(hProcessSnap, &pe32);while (bMore){if (!_wcsicmp(pe32.szExeFile, L"explorer.exe")){hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pe32.th32ProcessID);if (hProcess != nullptr){memset(&lpCreationTime, 0, sizeof(FILETIME));if (GetProcessTimes(hProcess,&lpCreationTime, &lpExitTime,&lpKernelTime, &lpUserTime) == TRUE){tpProc.dwProcessId = pe32.th32ProcessID;tpProc.ProcessStartTime = lpCreationTime;RmProcVec.push_back(tpProc);}CloseHandle(hProcess);hProcess = nullptr;}}bMore = Process32NextW(hProcessSnap, &pe32);}// 清除 snapshot 对象CloseHandle(hProcessSnap);VecLength = RmProcVec.size();if (VecLength != 0 && VecLength < (SIZE_T)0xf4236u){RM_UNIQUE_PROCESS* lprmUniqueProc = new(std::nothrow) RM_UNIQUE_PROCESS[VecLength];if (lprmUniqueProc != nullptr){SIZE_T rSize = VecLength * sizeof(RM_UNIQUE_PROCESS);if (rSize < (SIZE_T)0xC80000u && rSize > 0){if (!memcpy_s(lprmUniqueProc, rSize, &RmProcVec[0], rSize)){*lpdwCountNum = VecLength;*lpRmProcList = lprmUniqueProc;return TRUE;}}else {std::cerr << "Vector Size to large!" << std::endl;}}else {std::cerr << "Alloc memory failed!" << std::endl;}}else {std::cerr << "Vector Size to large!" << std::endl;}return FALSE;
}

使用 RmRegisterResources 函数将资源注册到重启管理器会话。重启管理器使用向会话注册的资源列表来确定必须关闭和重启哪些应用程序和服务。 可以通过文件名、服务短名称或描述正在运行的应用程序 RM_UNIQUE_PROCESS 结构来标识资源。参数解释如下:

参数解释

代码如下: 

dwRmStatus = RmRegisterResources(dwSessionHandle,0, NULL, dwNum, lpRmProcList, 0, NULL);
if (ERROR_SUCCESS != dwRmStatus)
{std::cerr << "RmRegisterResources failed: " << std::dec << dwRmStatus << std::endl;RmProcMemFree(lpRmProcList, lpdwCountNum);return -1;
}

然后使用 RmShutdown 就可以请求结束进程,可以指定第二个参数来选择强制或者非强制两种状态。

完成任务后使用 RmRestart 重新启动被关闭的进程即可,程序会尝试恢复并刷新状态。

所有操作完成后,使用 RmEndSession 关闭会话句柄。

三、完整实现代码和测试

完整代码如下:

#include <iostream>
#include <Windows.h>
#include <restartmanager.h>
#include <TlHelp32.h>
#include <vector>#pragma comment(lib, "Rstrtmgr.lib")#define RM_SESSIONKEY_LEN sizeof(GUID) * 2 + 1BOOL GetShellProcessRmInfoEx(PRM_UNIQUE_PROCESS* lpRmProcList,DWORD_PTR* lpdwCountNum
);
void RmProcMemFree(PRM_UNIQUE_PROCESS lpRmProcList,DWORD_PTR lpdwCountNum
);void RmWriteStatusCallback(UINT nPercentComplete
);int main()
{DWORD dwRmStatus = 0;DWORD dwSessionHandle = 0;WCHAR strSessionKey[RM_SESSIONKEY_LEN] = { 0 };dwRmStatus = RmStartSession(&dwSessionHandle, NULL, strSessionKey);if (ERROR_SUCCESS != dwRmStatus){std::cerr << "RmStartSession failed: " << std::dec << dwRmStatus << std::endl;return -1;}PRM_UNIQUE_PROCESS lpRmProcList = nullptr;DWORD_PTR lpdwCountNum = 0;if (!GetShellProcessRmInfoEx(&lpRmProcList, &lpdwCountNum)){std::cerr << "GetShellProcessRmInfoEx failed."<< std::endl;return -1;}UINT dwNum = static_cast<UINT>(lpdwCountNum);std::cout << "Process Count: " << dwNum << std::endl;std::cout << "Shell PID: "<< std::endl;for (UINT i = 0; i < dwNum; i++){std::cout << " > " << lpRmProcList[i].dwProcessId << std::endl;}dwRmStatus = RmRegisterResources(dwSessionHandle,0, NULL, dwNum, lpRmProcList, 0, NULL);if (ERROR_SUCCESS != dwRmStatus){std::cerr << "RmRegisterResources failed: " << std::dec << dwRmStatus << std::endl;RmProcMemFree(lpRmProcList, lpdwCountNum);return -1;}dwRmStatus = RmShutdown(dwSessionHandle, RmForceShutdown, RmWriteStatusCallback);if (ERROR_SUCCESS != dwRmStatus){std::cerr << "RmShutdown failed: " << std::dec << dwRmStatus << std::endl;// return -1;}Sleep(5000);dwRmStatus = RmRestart(dwSessionHandle, 0, RmWriteStatusCallback);if (ERROR_SUCCESS != dwRmStatus){std::cerr << "RmRestart failed: " << std::dec << dwRmStatus << std::endl;// return -1;}dwRmStatus = RmEndSession(dwSessionHandle);if (ERROR_SUCCESS != dwRmStatus){std::cerr << "RmEndSession failed: " << std::dec << dwRmStatus << std::endl;// return -1;}RmProcMemFree(lpRmProcList, lpdwCountNum);return 0;
}void RmWriteStatusCallback(UINT nPercentComplete
)
{std::cout << "Task completion level: " << std::dec << nPercentComplete << std::endl;
}BOOL GetShellProcessRmInfoEx(PRM_UNIQUE_PROCESS* lpRmProcList, DWORD_PTR* lpdwCountNum
)
{PROCESSENTRY32W pe32 = { 0 };FILETIME lpCreationTime = { 0 };FILETIME lpExitTime = { 0 };FILETIME lpKernelTime = { 0 };FILETIME lpUserTime = { 0 };HANDLE hProcess = nullptr;RM_UNIQUE_PROCESS tpProc = { 0 };std::vector<RM_UNIQUE_PROCESS> RmProcVec;SIZE_T VecLength = 0;// 在使用这个结构前,先设置它的大小pe32.dwSize = sizeof(pe32);// 给系统内所有的进程拍个快照HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (hProcessSnap == INVALID_HANDLE_VALUE){std::cerr << "CreateToolhelp32Snapshot 调用失败." << std::endl;return FALSE;}// 遍历进程快照,轮流显示每个进程的信息BOOL bMore = Process32FirstW(hProcessSnap, &pe32);while (bMore){if (!_wcsicmp(pe32.szExeFile, L"explorer.exe")){hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pe32.th32ProcessID);if (hProcess != nullptr){memset(&lpCreationTime, 0, sizeof(FILETIME));if (GetProcessTimes(hProcess,&lpCreationTime, &lpExitTime,&lpKernelTime, &lpUserTime) == TRUE){tpProc.dwProcessId = pe32.th32ProcessID;tpProc.ProcessStartTime = lpCreationTime;RmProcVec.push_back(tpProc);}CloseHandle(hProcess);hProcess = nullptr;}}bMore = Process32NextW(hProcessSnap, &pe32);}// 清除 snapshot 对象CloseHandle(hProcessSnap);VecLength = RmProcVec.size();if (VecLength != 0 && VecLength < (SIZE_T)0xf4236u){RM_UNIQUE_PROCESS* lprmUniqueProc = new(std::nothrow) RM_UNIQUE_PROCESS[VecLength];if (lprmUniqueProc != nullptr){SIZE_T rSize = VecLength * sizeof(RM_UNIQUE_PROCESS);if (rSize < (SIZE_T)0xC80000u && rSize > 0){if (!memcpy_s(lprmUniqueProc, rSize, &RmProcVec[0], rSize)){*lpdwCountNum = VecLength;*lpRmProcList = lprmUniqueProc;return TRUE;}}else {std::cerr << "Vector Size to large!" << std::endl;}}else {std::cerr << "Alloc memory failed!" << std::endl;}}else {std::cerr << "Vector Size to large!" << std::endl;}return FALSE;
}void RmProcMemFree(PRM_UNIQUE_PROCESS lpRmProcList, DWORD_PTR lpdwCountNum)
{__try{DWORD_PTR dwCountNum = lpdwCountNum;if (lpRmProcList != nullptr && dwCountNum > 0){while (--dwCountNum){if (IsBadWritePtr(&lpRmProcList[dwCountNum], sizeof(RM_UNIQUE_PROCESS))){throw(L"BadWritePtr event!");break;}memset(&lpRmProcList[dwCountNum], 0, sizeof(RM_UNIQUE_PROCESS));}delete[] lpRmProcList;}}__except (EXCEPTION_EXECUTE_HANDLER){// 处理 SEH 异常std::cerr << "Error access violation." << std::endl;exit(-1);}
}

测试效果如图所示:

测试结果截图

测试内容:首先结束所有 explorer 进程,随后重启进程。 


本文属于原创文章,转载请注明出处:

https://blog.csdn.net/qq_59075481/article/details/136179191。

文章发布于:2024.02.19,更新于:2024.02.19.

相关文章:

Windows 重启 explorer 的正确做法

目录 一、关于 Restart Manager 二、重启管理器实例 三、完整实现代码和测试 本文属于原创文章&#xff0c;转载请注明出处&#xff1a; https://blog.csdn.net/qq_59075481/article/details/136179191。 我们往往使用 TerminateProcess 并传入 PID 和特殊结束代码 1 或者…...

linux基础学习(10):基本权限与相关命令

1.基本权限 用ls -l查看当前目录文件时&#xff0c;可以看到文件的基本权限 其由10位组成&#xff0c;其中&#xff1a; 第1位&#xff1a;代表文件类型。 - d lbc普通文件目录文件软链接文件块设备文件&#xff0c;也就是硬盘等存储设备的文件字符设备文件&#xff0c;是鼠…...

木马植入方式及防范手段

木马植入方式&#xff1a; 1. 诱骗下载和安装&#xff1a;通过欺骗、社交工程等手段&#xff0c;诱使用户下载和安装包含木马的软件或文件。 2. 隐秘附加&#xff1a;将木马隐藏在合法软件的背后&#xff0c;并伴随软件一起安装&#xff0c;用户在不知情的情况下也会安装木马。…...

Unity3D中刚体、碰撞组件、物理组件的区别详解

前言 Unity3D提供了丰富的功能和组件&#xff0c;其中包括刚体、碰撞组件和物理组件。这些组件在游戏开发中起着非常重要的作用&#xff0c;能够让游戏世界更加真实和有趣。本文将详细介绍这三种组件的区别以及如何在Unity3D中实现它们。 对惹&#xff0c;这里有一个游戏开发…...

Java实现Redis延时队列

“如何实现Redis延时队列”这个面试题应该也是比较常见的&#xff0c;解答如下&#xff1a; 使用sortedset&#xff08;有序集合&#xff09; &#xff0c;拿时间戳作为 score &#xff0c;消息内容作为key 调用 zadd 来生产消息&#xff0c;消费者用zrangebyscore 指令获取 N …...

Selenium折线图自动化测试

目录 获取折线图echarts实例 获取折线图实例锚点的坐标 通过echarts实例的getOption()方法获取坐标数据 将折线图坐标点转换为像素坐标值 整合折线图坐标数据 根据折线图坐标计算出锚点相对于浏览器中的坐标 计算canvas画布原点的坐标 计算折线图相对于浏览器的坐标 使用…...

<网络安全>《41 网络攻防专业课<第七课 - IIS上传和Tomcat弱口令漏洞攻击与防范>》

1 中间件PUT漏洞介绍 中间件包括apache、tomcat、IIS、weblogic等&#xff0c;这些中间件可以设置支持的HTTP方法。&#xff08;HTTP方法包括GET、POST、HEAD、DELETE、PUT、OPTIONS等&#xff09; 每一个HTTP方法都有其对应的功能&#xff0c;在这些方法中&#xff0c;PUT可…...

云计算基础-虚拟化概述

虚拟化概述 虚拟化是一种资源管理技术&#xff0c;能够将计算机的各种实体资源&#xff08;如CPU、内存、磁盘空间、网络适配器等&#xff09;予以抽象、转换后呈现出来并可供分割、组合为一个或多个逻辑上的资源。这种技术通过在计算机硬件上创建一个抽象层&#xff0c;将单台…...

ElementUI +++ Echarts面试题答案汇总

官网地址&#xff1a;http://element-cn.eleme.io/#/zh-CN ElementUI是一套基于VUE2.0的桌面端组件库&#xff0c;ElementUI提供了丰富的组件帮助开发人员快速构建功能强大、风格统一的页面。 ElementUi是怎么做表单验证的&#xff1f;在循环里对每个input验证怎么做呢&#x…...

notepad++打开文本文件乱码的解决办法

目录 第一步 在编码菜单栏下选择GB2312中文。如果已经选了忽略这一步 第二步 点击编码&#xff0c;红框圈出来的一个个试。我切换到UTF-8编码就正常了。 乱码如图。下面分享我的解决办法 第一步 在编码菜单栏下选择GB2312中文。如果已经选了忽略这一步 第二步 点击编码&#…...

道可云元宇宙每日资讯|上海开放大学发布“智慧学习中心元宇宙”

道可云元宇宙每日简报&#xff08;2024年2月19日&#xff09;讯&#xff0c;今日元宇宙新鲜事有&#xff1a; 上海开放大学发布“智慧学习中心元宇宙” 上海开放大学首次发布了“智慧学习中心元宇宙”&#xff0c;初步构筑了上海开放大学5g元宇宙孪生学习环境&#xff0c;13所…...

压缩感知(Compressed Sensing,CS)的基础知识

压缩感知&#xff08;Compressed Sensing&#xff0c;CS&#xff09;是一种用于信号处理的技术&#xff0c;旨在以少于奈奎斯特采样定理所要求的样本频率来重构信号。该技术利用信号的稀疏性&#xff0c;即信号可以用较少的非零系数表示。压缩感知在图像获取中的应用使得在采集…...

如何系统地学习Python

建议系统学习Python的途径遵循理论与实践相结合的教学方法。以下是一个分阶段的学习计划&#xff1a; 阶段一&#xff1a;基础知识 理解Python的特点&#xff1a; 认识Python的历史与设计哲学。学习Python的基本语法和运行环境。 安装Python&#xff1a; 学习如何在不同操作系…...

SMT2020:半导体制造流程标准仿真测试数据介绍

文章目录 问题背景SMT2020 涉及的主要功能1. 包含多种仿真模型类型2. 包含非计划性动作3. 区分不同类型设备的加工速率4. 特殊的复杂操作SMT2020 数据概览1. AutoSched 仿真模型数据2. General Data 输入数据问题背景 在半导体的生产制造当中,由于晶元片及设备等的高价值性,…...

沁恒CH32V30X学习笔记11---使用外部时钟模式2采集脉冲计数

使用外部时钟模式2采集脉冲计数 使用外部触发模式 2 能在外部时钟引脚输入的每一个上升沿或下降沿计数。将 ECE 位置位时,将使用外部时钟源模式 2。使用外部时钟源模式 2 时,ETRF 被选定为 CK_PSC。ETR 引脚经过可选的反相器(ETP),分频器(ETPS)后成为 ETRP,再经过滤波…...

ffmpeg for android编译全过程与遇到的问题

编译前准备 编译环境&#xff1a;Ubuntu16&#xff0c;可自行下载VMWare最新版并百度永久许可证或在服务器上安装Ubuntu ffmpeg源码&#xff1a;ffmpeg4.2.2 NDK下载&#xff1a;Android NDK r21e 有条件的最好还是在Liunx平台下编译吧&#xff0c;Windows平台下编译坑更多…...

【无标题】力扣报错:member access within null pointer of type ‘struct ListNode‘

项目场景&#xff1a; 做单链表反转题目&#xff0c;报错&#xff1a;member access within null pointer of type ‘struct ListNode’ 题目链接:LINK 问题描述 我明明在初始化指针时候&#xff0c;已经处理了n2->next情况却依然报错 这个报错提示含义是&#xff1a;大概就…...

Qt之Qchar类的接口1

Qt类的构造函数 QChar类提供了许多个不同原型的构造函数&#xff0c;以方便不同场合下使用。 QChar(); //构造一个空字符&#xff0c;即‘\0’ QChar(char ch); //由字符数据ch构造 QChar(uchar ch)…...

vue的十大面试题详情

1 v-show与v-if区别 v-if与v-show可以根据条件的结果,来决定是否显示指定内容&#xff1a; v-if: 条件不满足时, 元素不会存在. v-show: 条件不满足时, 元素不会显示(但仍然存在). <div id"app"><button click"show !show">点我</but…...

(十四)devops持续集成开发——jenkins流水线使用pipeline方式发布项目

前言 本节内容我们使用另外一种方式pipeline实现项目的流水线部署发布&#xff0c;Jenkins Pipeline是一种允许以代码方式定义持续集成和持续交付流水线的工具。通过Jenkins Pipeline&#xff0c;可以将整个项目的构建、测试和部署过程以脚本的形式写入Jenkinsfile中&#xff…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中&#xff0c;从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备&#xff08;如专用硬件设备&#xff09;&#xff0c;从而消除了直接物理连接的需要。USB over IP的…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

MySQL 部分重点知识篇

一、数据库对象 1. 主键 定义 &#xff1a;主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 &#xff1a;确保数据的完整性&#xff0c;便于数据的查询和管理。 示例 &#xff1a;在学生信息表中&#xff0c;学号可以作为主键&#xff…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...

mac:大模型系列测试

0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何&#xff0c;是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试&#xff0c;是可以跑通文章里面的代码。训练速度也是很快的。 注意…...

comfyui 工作流中 图生视频 如何增加视频的长度到5秒

comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗&#xff1f; 在ComfyUI中实现图生视频并延长到5秒&#xff0c;需要结合多个扩展和技巧。以下是完整解决方案&#xff1a; 核心工作流配置&#xff08;24fps下5秒120帧&#xff09; #mermaid-svg-yP…...