当前位置: 首页IT技术 → 便携软件制作的系列教程

便携软件制作的系列教程

更多
2 页 盘符替换与路径替换

例1:

设想某一天,某妞将可移动磁盘插入电脑A,电脑A为她的U盘分配了盘符 F: 。该妞使用U盘上的便携软件打开了储存于U盘上的几个文档:

F:\1.doc

F:\2.doc

……

在拔出U盘的时候,她甚至没有为最后一个文件存档,反正所有进度都会自动保存嘛!

过了几日,该妞试图在电脑B继续她的工作,插入U盘以后,电脑B为她的U盘分配了盘符G: 。当她打开便携软件的时候,她会看到“最近文档”列表那里显示着什么呢?

仍然是:

F:\1.doc

F:\2.doc

……

当她试图恢复上一次”自动保存“的文档,却提示“找不到……文件”。于是,她发怒了,发誓再也不来你的网站。

这正常吗?太正常了,上次你就是在F盘打开文件的嘛。可是你还能完美地使用“最近文件”列表、继续上一次的工作吗?

我们干革命,就是要勇于把正常变为不正常。于是,我们需要盘符替换。

什么是盘符替换

所谓盘符替换 (Driver Letter Replacement),就是在检测到盘符相对上一次运行时改变的时候,将某些文件中的旧盘符替换为新盘符,以实现用户数据的完美衔接。以上述例子为例,就是在盘符转变为 G: 的时候,将最近文档列表替换为:

G:\1.doc

G:\2.doc

……

让用户体会不到盘符改变带来的变化,而顺利继续上一次的工作进程。

什么是路径替换

例2:

设想某一个软件,在配置文件中保存了大量包含软件路径的数据,这些数据在软件首次运行时生成,指向软件的插件、模板等目录,假如这些目录设置错误,该软件便无法正常运行。

而某一天,某妞将该便携软件从同盘符的一个目录移动到另一个目录,例如:从 f:\XXXPortable 移动到 f:\PortableApps\XXXPortable 。

那么,如何保证该软件正常运行呢?假如包含路径的设置项不多,我们可以一个个地写入,而假如类似设置很多(例如ACDSee),或者数量不定,难道也要一个个写入吗?所以,我们需要在检测到路径改变时,将所有的 XXXPortable 替换为 PortableApps\XXXPortable 。

目录格式

在 PortableApps.com Launcher 中,提供了四种类型的目录格式,分别是:

%VARIABLE% : 正向单斜杠。例如:%PAL:AppDir% = x:\portableapps\xxxportable\app 。主要应对ini、xml等普通配置文件。

%VARIABLE:ForwardSlash% : 反向单斜杠。例如:%PAL:AppDir:ForwardSlash% = x:/portableapps/xxxportable/app

%VARIABLE:DoubleBackslash% : 正向双斜杠。例如:%PAL:AppDir:DoubleBackslash% = x:\\portableapps\\xxxportable\\app 。主要应用于注册表(.reg)文件。

%VARIABLE:java.util.prefs% : 反向多斜杠。例如: %PAL:AppDir:java.util.prefs% = /X:///Portable/Apps///App/Name/Portable///App 。主要应用于java程序。

我们需要根据替换文件的类型选择相应的目录形式。假如遇到这四种情况以外的目录形式,则要靠 Custom Code 解决。

实现原理与流程

为了兼顾例1与例2的两种情况,避免两种情况同时发生,我们要将盘符替换与路径替换分开,那就是:先替换盘符,再替换不带盘符的路径。

在引导过程中,读取上一次记录的INI文件,判断是否盘符/路径改变。

若改变,则读取上一次的盘符/路径,转换为正确形式。

读取当前的盘符/路径,转换为正确形式。

在文件中替换旧盘符为新盘符。

在文件中替换旧路径为新路径。

将当前的盘符、路径写入INI文件,以便下一次读取。

在 PortableApps.com Launcher 中实现:

以ACDSee Portable为例,我们需要在引导过程中替换注册表文件 HKCU.reg 中的旧盘符\路径为新。

[FileWrite1]

Type=Replace

File=%PAL:DataDir%\settings\HKCU.reg

Find=%PAL:LastDrive%\\

Replace=%PAL:Drive%\\

[FileWrite2]

Type=Replace

File=%PAL:DataDir%\settings\HKCU.reg

Find=%PAL:LastPackagePartialDir:DoubleBackslash%

Replace=%PAL:PackagePartialDir:DoubleBackslash%

效果如下:

x:\\

替换为:

y:\\

\\xxx\\AppNamePortable

替换为:

\\yyy\\AppNamePortable

请注意,在 [FileWrite1] (盘符替换)中,我在 %PAL:LastDrive% 后面加上了双斜杠。这是因为,%PAL:LastDrive% 是不带斜杠的(x:)。可能出现这种情况:替换 D:,把 DWORD: 的最后两个字母也替换了。难道PortableApps.com的人不担心这种情况吗?我认为使用PAL替换盘符的时候都要注意这一点,替换盘符一定要加斜杠。

在 Custom Code 中实现:

PortableApps.com Launcher 是一个死板的网站的死板的程序员做出的死板的工具,在险峻难料的革命事业中,我们要坚决摒弃教条主义思想。许多时候稍有变化,我们就需要用到 Custom Code 。那么,在NSIS语言中怎样实现呢?

例如,一个程序以这样的形式在 Data\File.txt 记录路径:

F__PortableApps_App_Portable

“:”、“\”、“空格”三种符号都转换为下划线。让我们来写一段 Custom Code 来解决它。

${SegmentPrePrimary}

; 替换盘符

; 首先读取Ini文件中的记录

ReadINIStr $0 $DataDirectory\settings\$AppIDSettings.ini $AppIDSettings LastDrive

; 替换三种符号为下划线

${WordReplace} "$0\" "\" "_" "+" "$R0"

${WordReplace} "$R0" ":" "_" "+" "$R0"

${WordReplace} "$R0" " " "_" "+" "$R0"

; 得到当前盘符

StrCpy $R1 "$AppDirectory" 3

; 替换三种符号为下划线

${WordReplace} "$R1" "\" "_" "+" "$R1"

${WordReplace} "$R1" ":" "_" "+" "$R1"

${WordReplace} "$R1" " " "_" "+" "$R1"

; 在文件中替换

${ReplaceInFileCS} "$DataDirectory\File.txt" $R0 $R1

; 替换路径

; 首先读取Ini文件中的记录

ReadINIStr $0 $DataDirectory\settings\$AppIDSettings.ini $AppIDSettings LastDirectory

; 替换两种符号为下划线

${WordReplace} "$0" "\" "_" "+" "$R0"

${WordReplace} "$R0" " " "_" "+" "$R0"

; 得到当前路径(不带盘符)

StrCpy $R1 "$AppDirectory" "" 2

; 替换两种符号为下划线

${WordReplace} "$R1" "\" "_" "+" "$R1"

${WordReplace} "$R1" " " "_" "+" "$R1"

; 在文件中替换

${ReplaceInFileCS} "$DataDirectory\File.txt" $R0 $R1

!macroend

请注意文件的编码,如果是 UTF-16LE 编码,用 ${ReplaceInFileUTF16LECS} 。若需要忽略大小写,取消最后的“CS”。

在原始NSIS脚本中使用,需要另外:

!include "TextReplace.nsh"

!include "ReplaceInFileWithTextReplace.nsh"

注意事项

盘符与路径替换是一种简单地衔接工作环境的方法,但我认为,在应用中需要注意以下几点:

一定要确定你替换的是盘符/路径,而非别的东西。例如,使用PAL的时候,在盘符后加入斜杠,替换 x:\ 而不是 x: 。

自行撰写代码时,注意所替换文件的编码。

在替换大文件或多次替换之间,加入Sleep。否则可能遇到替换失败。

对于重要路径,最好在替换后手动写入一次,以保障无误。盘符替换依赖INI文件中的记录,假如一次记录与实际衔接不上,可能从此都衔接不上了。

本文导航
热门评论
最新评论
昵称:
表情: 高兴 可 汗 我不要 害羞 好 下下下 送花 屎 亲亲
字数: 0/500 (您的评论需要经过审核才能显示)