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

Inno Setup 学习笔记(一)

前言

最近想把自己写的Windows端的软件打包成安装程序exe,又觉得自带的界面太丑了,想自己完全做一个新的页面

网上找到的只有基础教程,记录一下进阶学习过程

生命周期

按照Vue的说法叫生命周期,Inno Setup中叫 Pascal 脚本: 事件函数。

安装程序事件函数

安装程序支持下列事件函数:

function InitializeSetup(): Boolean;

在安装程序初始化期间调用。返回 False 以中止 Setup,否则返回 True。

// 检查应用程序是否正在运行
function IsAppRunning(const AppName : string) : Boolean;
begin// 如果找到窗口名称,则应用程序正在运行Result := (FindWindowByWindowName(AppName) <> 0);
end;// 检查应用程序是否已安装
function IsAppInstalled() : Boolean;
begin// 检查注册表项是否存在Result := RegKeyExists(HKLM, 'SOFTWARE\{#MyAppName}');
end;// 初始化安装程序
function InitializeSetup(): Boolean;
begin// 初始化变量_isInstall := false;Result := true;// 检查应用程序是否正在运行if IsAppRunning('{#MyAppWindowName}') thenbegin_isInstall := true;Msgbox('{#Tip_AppRunningInstall}', mbInformation, MB_OK);Result := false;end;// 检查应用程序是否已安装if Result and IsAppInstalled() thenbegin_isInstall := true;Result := (Msgbox({#Tip_AppReinstall}, mbConfirmation, MB_YESNO) = IDYES);end;
end;

procedure InitializeWizard();

在启动时使用该事件函数来改变向导或向导页面。你不能在它被触发时使用 InitializeSetup 事件函数,因为向导窗体尚不存在。

procedure DeinitializeSetup();

仅在安装程序终止前调用。注意这个函数在即使用户在任何内容安装之前退出安装程序时也会调用。

procedure CurStepChanged(CurStep: TSetupStep);

你可以用这个事件函数执行你自己的预安装和安装后任务。

在实际安装开始之前用 CurStep=ssInstall 调用,或在实际安装完成之后用 CurStep=ssPostInstall 调用,或在安装程序终止之前和安装完成之后用 CurStep=ssDone 调用。

procedure CurInstallProgressChanged(CurProgress, MaxProgress: Integer);

在安装程序提取文件、创建快捷方式、创建 INI 条目和创建注册表项时,你可以使用该事件函数来监测进程。

function NextButtonClick(CurPageID: Integer): Boolean;

当用户单击下一步按钮时调用。如果你返回 True,向导将移到下一页面;如果返回 False,它仍保留在当前页面(用 CurPageID 指定)。

注意,该函数在静默安装时也会调用,即使没有下一步按钮让用户单击。安装程序会模拟单击下一步按钮。在静默安装中,如果你的 NextButtonClick 函数在安装之前返回 False,安装程序将自动退出。

function BackButtonClick(CurPageID: Integer): Boolean;

当用户单击上一步按钮时调用。如果你返回 True,向导将移到上一页面;如果返回 False,它仍保留在当前页面(用 CurPageID 指定)。

procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);

当用户单击取消按钮或单击窗口中的关闭按钮时调用。Cancel 参数指定是否是一般的取消进程;默认为 True。Confirm 参数指定是否显示“退出安装程序吗?”的消息框;一般它默认为 True。如果 Cancel 设为 False,那么 Confirm 值被忽略。

function ShouldSkipPage(PageID: Integer): Boolean;

向导调用这个事件函数确定是否在所有页面或不在一个特殊页面(用 PageID 指定)显示。如果返回 True,将跳过该页面;如果你返回 False,该页面被显示。

注意:这个事件函数不被 wpWelcome、wpPreparing 和 wpInstalling 页面调用,还有安装程序已经确定要跳过的页面也不会调用(例如,没有包含组件安装程序的 wpSelectComponents)。

procedure CurPageChanged(CurPageID: Integer);

在新向导页面(用 CurPageID 指定)显示后调用。

function CheckPassword(Password: String): Boolean;

如果安装程序在 Pascal 脚本中发现 CheckPassword 事件函数,它自动显示密码页面并调用 CheckPassword 检查密码。返回 True 表示接受密码,返回 False 拒绝。

要避免在编译的安装程序的 [Code] 区段内部贮存真实的密码,你应该用其它无用的信息进行比较: 计算你自己密码的 SHA1 的无用信息,然后编译到 GetSHA1OfString(Password)。通过这种方法保护实际密码值。

注意:如果安装程序带一个 /PASSWORD= 命令行参数运行,则你的 CheckPassword 函数将在任何其他事件函数之前 被调用,包括 InitializeSetup。

function NeedRestart(): Boolean;

返回 True 告诉安装程序提示用户在安装结束时重新启动系统,False 则反之。

function UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String;

如果安装程序在 Pascal 脚本中发现 UpdateReadyMemo 事件函数,当准备安装 向导页面变为活动页面时自动调用。它返回的文字显示在准备安装 向导页面的设置备注中,作为由 NewLine 参数分隔行的单个字串。参数 Space 包含一个带空格的字串。安装程序使用该字串来进行缩进设置。其它参数将包含安装程序用于设置区段的字串(可能是空的)。例如 MemoDirInfo 参数包含象选择目录 区段的字串。

procedure RegisterPreviousData(PreviousDataKey: Integer);

要在自定义向导页面中贮存用户输入的设置,在 Pascal 脚本中放入一个 RegisterPreviousData 事件函数,并调用 SetPreviousData(PreviousDataKey, ...) 替换它,每个设置一次。

function CheckSerial(Serial: String): Boolean;

如果安装程序在 Pascal 脚本中发现 CheckSerial 事件函数,将在用户信息向导页面中自动出现一个序列号对象(必须在你的 [Setup] 区段中使用 UserInfoPage=yes !)。返回 True 表示接受序列号,返回 False 拒绝。当使用序列号时,请一定要记住,这个软件无加密可言,况且 Inno Setup 源代码是免费获取的,它对于有经验的人从安装程序中删除序列号保护并不是很困难的事。使用这个只是方便用户在你的应用程序中仔细检查输入的序列号(贮存在 {userinfoserial} 常量)。

function GetCustomSetupExitCode: Integer;

返回一个非零值命令安装程序返回一个自定义退出代码。这个函数只在安装程序运行完成并且退出代码已是零时调用。同时请参见安装退出代码。

function PrepareToInstall(var NeedsRestart: Boolean): String;

你可以使用该事件函数来监测并安装丢失的先决条件和/或关闭任何有关被更新的应用程序。

返回非空字串以指示安装程序停止在准备安装向导页面,将返回的字串显示为错误消息。如果需要重新启动,请将 NeedsRestart 设置为 True(并返回非空字串)。如果以这种方式停止安装程序,它将使用安装程序退出代码中所述的专用退出代码退出。在这种情况下,不会使用由 /RESTARTEXITCODE= 命令行参数设置的任何自定义退出代码。

如果 CloseApplications 设置为 yes,则在安装程序对正在使用的文件检查前,该事件函数被调用。

仅当安装程序尚未确定无法继续时才会调用此函数,因为 [Files] 和 [InstallDelete] 区段中指定的一个或多个文件已队列(通过某些其他安装),以便在下次重新启动时进行替换或删除。

procedure RegisterExtraCloseApplicationsResources;

如果 CloseApplications 被设置为 yes,则要注册安装程序会检查正在使用的那个额外文件,在 Pascal 脚本中放置一个 RegisterExtraCloseApplicationsResources 事件函数,并在其内部调用 RegisterExtraCloseApplicationsResource,每次一个文件。

卸载事件函数

卸载支持下列函数:

function InitializeUninstall(): Boolean;

返回 False 中止卸载,True 则反之。

procedure InitializeUninstallProgressForm();

使用该事件函数对进度窗体在启动时进行更改。你不能使用 InitializeUninstall 事件函数,因为在它被触发时该进度窗体尚不存在。

procedure DeinitializeUninstall();

procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);

function UninstallNeedRestart(): Boolean;

返回 True 以指示卸载程序在成功卸载结束时,提示用户重新启动系统,False 则反之。

通过事件函数,就可以完成部分自己想要的功能,我们在其中最主要的就是禁用原有的安装界面,自己绘制安装界面

页面

在安装流程中一共有这些页面

wpWelcome, wpLicense, wpPassword, wpInfoBefore, wpUserInfo, wpSelectDir, wpSelectComponents, wpSelectProgramGroup, wpSelectTasks, wpReady, wpPreparing, wpInstalling, wpInfoAfter, wpFinished

我们通过在wpWelcome页面的时候,来创建安装界面,再去监听wpInstalling来更新进度条,wpFinished的时候来选择是否打开或者是否重启

废话不多说直接上代码!

利用定义ShouldSkipPage函数才跳过部分页面

// 定义一个函数,决定是否跳过某个安装页面
function ShouldSkipPage(PageID : integer) : boolean;
begin// 如果页面ID匹配任何一个指定的页面,则返回true表示跳过该页面if (PageID = wpLicense) then Result := true;if (PageID = wpInfoBefore) then Result := true;if (PageID = wpUserInfo) then Result := true;if (PageID = wpSelectDir) then Result := true;if (PageID = wpPassword) then Result := true;if (PageID = wpSelectComponents) then Result := true;if (PageID = wpSelectProgramGroup) then Result := true;if (PageID = wpSelectTasks) then Result := true;if (PageID = wpReady) then Result := true;if (PageID = wpPreparing) then Result := true;if (PageID = wpInfoAfter) then Result := true;
end;

 利用页面切换的函数CurPageChanged来创建界面

// 当页面改变时调用此过程
procedure CurPageChanged(CurPageID: integer);
begin// MsgBox('CurPageID:' + IntToStr(CurPageID), mbError, MB_OK);// 如果当前页面是欢迎页面if (CurPageID = wpWelcome) thenbegin// 创建密码输入框_editPassword := TEdit.Create(WizardForm);with _editPassword dobeginParent := WizardForm;Font.Name := 'Microsoft YaHei';Font.Size := 9;BorderStyle := bsNone;PasswordChar := '*';SetBounds(211, 305, 178, 24); // 设置位置和大小Color := clWhite;TabStop := true;end;// 创建“确定密码”按钮_btnConfirmPassword := BtnCreate(WizardForm.Handle, 400, 305, 100, 24, ExpandConstant('{tmp}\button_confirm.png'), 0, false);MyBtnSetEvent(_btnConfirmPassword, @on_btnConfirmPassword_clicked);// 创建安装按钮(初始隐藏)_btnInstall := BtnCreate(WizardForm.Handle, 211, 350, 178, 43, ExpandConstant('{tmp}\button_install.png'), 0, false);MyBtnSetEvent(_btnInstall, @on_btnInstall_clicked);BtnSetVisibility(_btnInstall, false);// 创建自定义设置按钮_btnCustomizeSetup := BtnCreate(WizardForm.Handle, 511, 374, 78, 16, ExpandConstant('{tmp}\button_customize_setup.png'), 0, false);MyBtnSetEvent(_btnCustomizeSetup, @on_btnCustomizeSetup_clicked);// 创建取消自定义设置按钮(初始隐藏)_btnUncustomizeSetup := BtnCreate(WizardForm.Handle, 511, 374, 78, 16, ExpandConstant('{tmp}\button_uncustomize_setup.png'), 0, false);MyBtnSetEvent(_btnUncustomizeSetup, @on_btnCustomizeSetup_clicked);BtnSetVisibility(_btnUncustomizeSetup, false);// 创建目标路径输入框_editTargetPath := TEdit.Create(WizardForm);with _editTargetPath dobeginParent := WizardForm;Text := WizardForm.DirEdit.Text;Font.Name := 'Microsoft YaHei';Font.Size := 9;BorderStyle := bsNone;SetBounds(91, 424, 402, 20);OnChange := @on_editTargetPath_changed;Color := clWhite;TabStop := false;end;_editTargetPath.Hide();// 创建产品已安装提示标签_labelProductAlreadyInstalled := TLabel.Create(WizardForm);with _labelProductAlreadyInstalled dobeginParent := WizardForm;AutoSize := false;Left := 85;Top := 449;Width := 200;Height := 20;Font.Name := 'Microsoft YaHei';Font.Size := 9;Font.Color := clGray;Caption := '{#Tip_AppDirChangeEnable}';Transparent := true;OnMouseDown := @on_mouseDown;end;_labelProductAlreadyInstalled.Hide();// 设置进度条回调PBOldProc := SetWindowLong(WizardForm.ProgressGauge.Handle, -4, PBCallBack(@ProgressbarProcedure, 4));// 创建浏览按钮_btnBrowse := BtnCreate(WizardForm.Handle, 506, 420, 75, 24, ExpandConstant('{tmp}\button_browse.png'), 0, false);MyBtnSetEvent(_btnBrowse, @on_btnBrowse_clicked);BtnSetVisibility(_btnBrowse, false);// 加载背景图像_imageFormBackground := ImgLoad(WizardForm.Handle, ExpandConstant('{tmp}\background_welcome.png'), 0, 0, WIZARDFORM_WIDTH_NORMAL, WIZARDFORM_HEIGHT_NORMAL, false, true);_imageCustomizeBackground := ImgLoad(WizardForm.Handle, ExpandConstant('{tmp}\background_welcome_more.png'), 0, 0, WIZARDFORM_WIDTH_NORMAL, WIZARDFORM_HEIGHT_MORE, false, true);ImgSetVisibility(_imageCustomizeBackground, false);WizardForm.Width := WIZARDFORM_WIDTH_NORMAL;WizardForm.Height := WIZARDFORM_HEIGHT_NORMAL;ImgApplyChanges(WizardForm.Handle);end;// 如果当前页面是安装页面if (CurPageID = wpInstalling) thenbegin_editTargetPath.Hide();BtnSetVisibility(_btnBrowse, false);BtnSetVisibility(_btnCustomizeSetup, false);BtnSetVisibility(_btnUncustomizeSetup, false);WizardForm.Height := WIZARDFORM_HEIGHT_NORMAL;// 创建安装进度标签_labelInstallProgress := TLabel.Create(WizardForm);with _labelInstallProgress dobeginParent := WizardForm;AutoSize := false;Left := 547;Top := 349;Width := 40;Height := 30;Font.Name := 'Microsoft YaHei';Font.Size := 10;Font.Color := clBlack;Caption := '';Transparent := true;Alignment := taRightJustify;OnMouseDown := @on_mouseDown;end;BtnSetEnabled(_btnExit, false);_imageFormBackground := ImgLoad(WizardForm.Handle, ExpandConstant('{tmp}\background_installing.png'), 0, 0, WIZARDFORM_WIDTH_NORMAL, WIZARDFORM_HEIGHT_NORMAL, false, true);_progressbarBackground := ImgLoad(WizardForm.Handle, ExpandConstant('{tmp}\progressbar_background.png'), 20, 374, 560, 6, false, true);_progressbarForeground := ImgLoad(WizardForm.Handle, ExpandConstant('{tmp}\progressbar_foreground.png'), 20, 374, 0, 0, true, true);BtnSetVisibility(_btnInstall, false);ImgApplyChanges(WizardForm.Handle);end;// 如果当前页面是完成页面if (CurPageID = wpFinished) thenbeginImgSetVisibility(_imageFormBackground, false);ImgSetVisibility(_progressbarBackground, false);ImgSetVisibility(_progressbarForeground, false);_labelInstallProgress.Hide();BtnSetEnabled(_btnExit, true);// 创建启动复选框_checkboxStartup := BtnCreate(WizardForm.Handle, 248, 280, 110, 17, ExpandConstant('{tmp}\checkbox_startup.png'), 0, True);MyBtnSetEvent(_checkboxStartup, @on_checkboxStartup_clicked);BtnSetChecked(_checkboxStartup, True);// 创建完成按钮_btnInstall := BtnCreate(WizardForm.Handle, 214, 315, 178, 43, ExpandConstant('{tmp}\button_finish.png'), 0, false);// 加载完成页面背景图像_imageFormBackground := ImgLoad(WizardForm.Handle, ExpandConstant('{tmp}\background_finish.png'), 0, 0, WIZARDFORM_WIDTH_NORMAL, WIZARDFORM_HEIGHT_NORMAL, false, true);MyBtnSetEvent(_btnInstall, @on_btnInstall_clicked);MyBtnSetEvent(_btnExit, @on_btnInstall_clicked);ImgApplyChanges(_btnInstall);ImgApplyChanges(WizardForm.Handle);end;end;

相关文章:

Inno Setup 学习笔记(一)

前言 最近想把自己写的Windows端的软件打包成安装程序exe&#xff0c;又觉得自带的界面太丑了&#xff0c;想自己完全做一个新的页面 网上找到的只有基础教程&#xff0c;记录一下进阶学习过程 生命周期 按照Vue的说法叫生命周期&#xff0c;Inno Setup中叫 Pascal 脚本: 事…...

从阿里云EDM到美团云:典型微服务治理平台的实战经验分享

目录 一. 阿里云 EDM&#xff08;Enterprise Distributed Application Service&#xff09; 二. 腾讯云 TSF&#xff08;Tencent Service Framework&#xff09; 三. 华为云 FusionStage 四. 京东云 JDC&#xff08;JD Cloud Microservice Platform&#xff09; 五. 百度智…...

【接口自动化测试】一文从3000字从0到1详解接口测试用例设计

接口自动化测试是软件测试中的一种重要手段&#xff0c;它能有效提高测试效率和测试覆盖率。在进行接口自动化测试之前&#xff0c;首先需要进行接口测试用例的设计。本文将从0到1详细且规范的介绍接口测试用例设计的过程&#xff0c;帮助读者快速掌握这一技能。 一、了解接口…...

反向代理-缓存篇

文章目录 强缓存一、Expires(http1.0 规范)二、cache-control(http1.1 出现的 header 信息)Cache-Control 的常用选项Cache-Control 常用选项的选择三、弊端协商缓存一、ETag二、If-None-Match三、Last-modified四、If-Modified-Since浏览器的三种刷新方式静态资源部署策略…...

【伪代码】数据结构-期末复习 线性表

目录 例1 矩阵相乘 线性表 2.1 线性表的类型定义 例2-1 求并集 LALA∪LB 例2-2 有序表归并 2. 2 线性表的顺序表示和实现 1&#xff0e;构造空表 2&#xff0e;插入 3&#xff0e;删除 4&#xff0e;定位 顺序表的优点&#xff1a; 顺序表的缺点&#xff1a; 例…...

JavaWeb学习、过滤器、ajax异步请求、json、jquery-api文档

一、过滤器&#xff1a; 按照过滤规则筛选出想要的资源。 为什么使用过滤器&#xff1f; 1. 很多地方都需要判断是否登录。如果我们在每个资源出进行判断&#xff0c;非常麻烦。我们可以使用过滤器在访问这些资源前进行判断。 &#xff08;这样就不用在主界面&#xff0c;修改…...

深入探索 JVM:原理、机制与实战

一、JVM 概述 JVM&#xff08;Java Virtual Machine&#xff09;是 Java 程序运行的核心组件&#xff0c;它提供了一个独立于硬件和操作系统的执行环境&#xff0c;使得 Java 程序能够在不同平台上具有跨平台的特性。 JVM 主要由以下几部分组成&#xff1a; 类装载器&#xf…...

JavaWeb学习(3)(Servlet详细、Servlet的三种实现方式(面试)、Servlet的生命周期、传统web.xml配置Servlet(了解))

目录 一、Servlet详细。 &#xff08;1&#xff09;基本介绍。 &#xff08;2&#xff09;基本作用。 1、接收客户端请求数据。 2、处理请求。 3、完成响应结果。 二、Servlet的三种实现方式。 &#xff08;1&#xff09;实现javax.servlet.Servlet接口。 1、基本介绍。 2、代码…...

支付宝租赁小程序助力便捷生活新方式

内容概要 支付宝租赁小程序为现代人带来了许多惊喜&#xff0c;它不仅仅是一个简单的租赁平台&#xff0c;更是生活中不可或缺的好帮手。想象一下&#xff0c;无论你缺少什么&#xff0c;从工具到家居用品&#xff0c;只需轻轻一点&#xff0c;便能轻松找到需要的物品。这个小…...

Linux-ubuntu环境配置

一&#xff0c;安装VWware&#xff0c;里面导入镜像文件 这些都是文件夹里面有的&#xff0c;然后对着正点原子视频安装就行&#xff0c;虚拟机的破解码&#xff0c;去百度搜一个能用就行&#xff0c;中间遇见俩问题。①乌班图里面不能上网&#xff0c;②插入U盘后&#xff0c;…...

深入解析下oracle的number底层存储格式

oracle数据库中&#xff0c;number数据类型用来存储数值数据&#xff0c;它既可以存储负数数值&#xff0c;也可以存储正数数值。相对于其他类型数据&#xff0c;number格式的数据底层存储格式要复杂得多。今天我们就详细探究下oracle的number底层存储格式。 一、环境搭建 1.…...

nginx代理rabbitmq和配置 Nginx 代理达梦数据库

在 Nginx 中使用 stream 模块进行 TCP 代理时&#xff0c;可以将 TCP 或 UDP 流量转发到指定的后端服务器。你给出的配置是一个用于代理 RabbitMQ 的示例&#xff0c;具体是在 TCP 层上代理 5672 端口的流量。 只能在nginx.conf配置上代理 stream {# 定义 upstream&#xff0c…...

汉语唤醒词的模糊判断(Python)

汉语唤醒词的模糊判断【Python】 说明安装库代码Demo其他 说明 这是一个简单的汉语模糊唤醒词的判断器&#xff0c;汉语发音中前后舌以及声母韵母的区别&#xff0c;如果进行精准判断&#xff0c;很容易误判。需要一个模糊判断的逻辑! 安装库 pip install pypinyin代码Demo …...

Redis篇-2--原理篇1--I/O多路复用机制(5种I/O模型,I/O多路复用)

I/O多路复用机制&#xff1a; Redis 是通过I/O多路复用机制来管理大量客户端连接。这使得redis可以实现通过单线程来处理多个客户端连接的请求&#xff0c;避免了为每个客户端创建独立的线程&#xff0c;从而减少了上下文切换的开销&#xff0c;提高了系统的并发性和性能。 理解…...

Knowledge Graph Studio:让知识图谱构建更简单、更智能

一、前言 上周和研究院的同事讨论 2025 年大模型产品规划时&#xff0c;让我产生了一些疑惑和不解&#xff0c;因为从大家交流的规划方向来看&#xff0c;更多的还是集中在Prompt提示词工程&#xff08;包括提示词的管理、测试、评估、调优&#xff09;这一块规划的确实挺细&a…...

vue 中实现音视频播放进度条(可拖拽,满足常见开发需求)

由于开发需要&#xff0c;作者封装了一个音视频播放进度条的组件&#xff0c;支持 vue2 及 vue3 &#xff0c;有需要的朋友后台私信作者获取组件源码哦&#xff08;工作日每天都在线&#xff09;&#xff0c;下面是对该款组件的介绍。 组件默认样式&#x1f447;&#xff08;组…...

[免费]SpringBoot+Vue企业OA自动化办公管理系统【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringBootVue企业OA自动化办公管理系统&#xff0c;分享下哈。 项目视频演示 【免费】SpringBootVue企业OA自动化办公管理系统 Java毕业设计_哔哩哔哩_bilibili 项目介绍 随着信息技术在管理上越来越深入…...

笔记:在WPF中BitmapSource都有哪些派生类,他们主要功能,使用方法,使用场景

一、目的&#xff1a;在WPF中BitmapSource都有哪些派生类&#xff0c;他们主要功能&#xff0c;使用方法&#xff0c;使用场景 BitmapSource 是 WPF 中图像处理的基类&#xff0c;提供了许多派生类来处理不同类型的图像源。以下是一些常见的 BitmapSource 派生类、它们的主要功…...

JAVA基础学习笔记_多线程

文章目录 多线程并发和并行多线程的实现方式Thread类实现Runnable接口方式实现callable接口和Future接口实现 常用的成员方法线程的生命周期线程的安全问题同步代码块同步方法lock锁死锁 生产者和消费者(等待唤醒机制)阻塞队列实现等待唤醒机制线程的6种状态线程池自定义线程池…...

什么是自动化办公

自动化办公是指使用技术工具或软件&#xff0c;通过预设流程或脚本&#xff0c;自动执行日常办公任务&#xff0c;从而提升效率、减少错误、节约时间的办公模式。它适用于需要重复性、规则明确的工作流程&#xff0c;让员工将精力集中在更具创造性和战略性的工作上。 自动化办公…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

九天毕昇深度学习平台 | 如何安装库?

pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子&#xff1a; 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测

uniapp 中配置 配置manifest 文档&#xff1a;manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号&#xff1a;4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

数据结构:递归的种类(Types of Recursion)

目录 尾递归&#xff08;Tail Recursion&#xff09; 什么是 Loop&#xff08;循环&#xff09;&#xff1f; 复杂度分析 头递归&#xff08;Head Recursion&#xff09; 树形递归&#xff08;Tree Recursion&#xff09; 线性递归&#xff08;Linear Recursion&#xff09;…...

ArcGIS Pro+ArcGIS给你的地图加上北回归线!

今天来看ArcGIS Pro和ArcGIS中如何给制作的中国地图或者其他大范围地图加上北回归线。 我们将在ArcGIS Pro和ArcGIS中一同介绍。 1 ArcGIS Pro中设置北回归线 1、在ArcGIS Pro中初步设置好经纬格网等&#xff0c;设置经线、纬线都以10间隔显示。 2、需要插入背会归线&#xf…...