Delphi工程版本号修改工具
自动修改某目录下符合条件的Delphi工程(dproj)版本号, 支持命令行调用
支持通配符忽略文件
-p [Path] 在[Path]路径下查询所有dproj文件(可以为空, 默认路径为程序当前路径)
-v [Version] 将查询到的dproj文件中Base节点版本改为[Version]并删除其他节点版本信息(可以为空, 进入程序后输入)
-i [File1,File2...]要忽略的文件, 支持? *的通配符, 忽略大小写, 包含路径, 不要包含扩展名, 如: work\project?
-b 修改时备份原文件到文件所在路径的dproj_bak目录下(默认不备份)
-ac 工作结束自动关闭程序(默认不关闭)
已经编译完的程序放CSDN了, 不过有点坑, 提交的资源不能修改内容, 也不能修改下载积分(当初没看, 直接选了5分...呵呵)
http://download.csdn.net/download/hskill/10120236
下面直接给出源码, 是个控制台程序
PS: 里面用到了QXML, 但是QXML会吧单引号转义, 不过不影响IDE的读取保存
program dproj_Version; // ***************************************************************************
//
// 版本: 1.0
// 作者: 刘志林
// 修改日期: 2017-11-15
// QQ: 17948876
// E-mail: lzl_17948876@hotmail.com
// 博客: http://www.cnblogs.com/lzl_17948876/
//
// !!! 若有修改,请通知作者,谢谢合作 !!!
//
// *************************************************************************** {$APPTYPE CONSOLE} {$R *.res} uses
System.SysUtils, System.Classes, System.IOUtils, System.Types, System.Masks,
QXML, QString; function _GetXNode(AXNParent: TQXMLNode; AName: string; out AValue: string): TQXMLNode;
begin
Result := AXNParent.ItemByName(AName);
if Result = nil then
Result := AXNParent.Add(AName);
AValue := Result.Text;
end; type
EInvalidVersion = Class(Exception); TVersion = record
public
procedure Init;
function IsEmpty: Boolean;
procedure FromString(AStr: string);
function ToString(ADelimiter: Char = '.'): string; case Integer of
: (Data: array[..] of UInt32);
: (MajorVer, MinorVer, Release, Build: UInt32);
end; { TVersion } procedure TVersion.FromString(AStr: string);
var
i: Integer;
begin
Init;
with TStringList.Create do
try
Delimiter := '.';
StrictDelimiter := True;
DelimitedText := AStr;
try
if Count <> then
Abort;
for i := to do
Data[i] := StrToInt(Strings[i]);
if IsEmpty then
Abort;
except
Init;
raise EInvalidVersion.Create(AStr + '不是有效的版本号');
end;
finally
Free;
end;
end; procedure TVersion.Init;
begin
MajorVer := ;
MinorVer := ;
Release := ;
Build := ;
end; function TVersion.IsEmpty: Boolean;
begin
Result := Data[] + Data[] + Data[] + Data[] = ;
end; function TVersion.ToString(ADelimiter: Char = '.'): string;
begin
Result := Format('%1:d%0:s%2:d%0:s%3:d%0:s%4:d', [ADelimiter, Data[], Data[], Data[], Data[]])
end; function _Compare(const AStr: string; const AL: array of string): Boolean;
var
i: Integer;
begin
Result := False;
for i := Low(AL) to High(AL) do
begin
if CompareText(AStr, AL[i]) <> then
Continue;
Result := True;
Break;
end;
end; function IsIgnored(AName: string; const AIGList: TArray<string>): Boolean;
var
i: Integer;
begin
Result := False;
for i := Low(AIGList) to High(AIGList) do
begin
if not MatchesMask(AName, AIGList[i]) then
Continue;
Result := True;
Break;
end;
end; const
_EXT = '.dproj'; const
Helps: array[..] of string = (
'-p [Path] 在[Path]路径下查询所有dproj文件(可以为空, 默认路径为程序当前路径)',
'-v [Version] 将查询到的dproj文件中Base节点版本改为[Version]并删除其他节点版本信息(可以为空, 进入程序后输入)',
'-i [File1,File2...]要忽略的文件, 支持? *的通配符, 忽略大小写, 包含路径, 不要包含扩展名, 如: work\project?',
'-b 修改时备份原文件到文件所在路径的dproj_bak目录下(默认不备份)',
'-ac 工作结束自动关闭程序(默认不关闭)'
); var
nXDOC: TQXML;
nXNRoot, nXN, nXNV: TQXMLNode;
l, i, nParamIndex, nFileIndex, nXNIndex, nIKIndex: Integer;
nStrs: TStringList;
nName, nVersionStr, nPath, nFile, nStr, nPK: string;
nIgnoredList: TArray<string>;
nVersion, nOldVersion: TVersion;
nFiles: TStringDynArray;
nBackup, nAutoClose: Boolean;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
ChDir(ExtractFilePath(ParamStr())); nPath := '.\';
nVersion.Init;
SetLength(nIgnoredList, );
nBackup := False;
nAutoClose := False; nParamIndex := ;
while nParamIndex <= ParamCount do
begin
nStr := ParamStr(nParamIndex); l := nStr.Length;
if not (nStr[] in ['-', '/']) then
Continue;
nStr := Copy(nStr, , l - ); if _Compare(nStr, ['p']) then {路径}
begin
nPath := ParamStr(nParamIndex + );
Inc(nParamIndex, );
end
else if _Compare(nStr, ['v']) then {版本号}
begin
nVersionStr := ParamStr(nParamIndex + );
Inc(nParamIndex, );
end
else if _Compare(nStr, ['i']) then {忽略的文件}
begin
with TStringList.Create do
try
StrictDelimiter := True;
Delimiter := ',';
DelimitedText := ParamStr(nParamIndex + );
SetLength(nIgnoredList, Count);
for i := to Count - do
nIgnoredList[i] := '*' + ChangeFileExt(Strings[i], '') + _EXT;
finally
Free;
end;
Inc(nParamIndex, );
end
else if _Compare(nStr, ['b']) then {备份}
begin
nBackup := True;
Inc(nParamIndex, );
end
else if _Compare(nStr, ['ac']) then {自动关闭}
begin
nAutoClose := True;
Inc(nParamIndex, );
end
else if _Compare(nStr, ['h', '?', 'help']) then {帮助}
begin
for i := Low(Helps) to High(Helps) do
Writeln(Helps[i]);
Abort;
end
else
Inc(nParamIndex, );
end; if nPath = '' then
raise Exception.Create('无效的路径');
nPath := TPath.GetFullPath(nPath);
if not DirectoryExists(nPath) then
raise Exception.CreateFmt('"%s" 路径不存在', [nPath]); if nVersionStr = '' then
Writeln('清输入版本号:')
else
try
nVersion.FromString(nVersionStr);
except
on E: Exception do
Writeln('错误: ' + E.Message);
end; while nVersion.IsEmpty do
begin
Write('> ');
Readln(nVersionStr);
try
nVersion.FromString(nVersionStr);
except
on E: Exception do
Writeln('错误: ' + E.Message);
end;
end; Writeln('');
Writeln('******** 开始处理 ********');
Writeln(Format('目标目录: %s', [nPath]));
Write('忽略的对象:');
for i := Low(nIgnoredList) to High(nIgnoredList) do
Write(Format(' "%s"', [nIgnoredList[i]]));
Write(#); nFiles := TDirectory.GetFiles(nPath, '*' + _EXT, TSearchOption.soAllDirectories); if Length(nFiles) = then
raise Exception.Create('待处理的文件数量为0'); Writeln(Format('待处理文件数量: %d', [Length(nFiles)]));
Writeln(''); nXDOC := TQXML.Create;
nStrs := TStringList.Create;
try
nStrs.Delimiter := ';';
nStrs.StrictDelimiter := True; for nFileIndex := Low(nFiles) to High(nFiles) do
begin
if IsIgnored(nFiles[nFileIndex], nIgnoredList) then
begin
Writeln('* 忽略 ' + nFiles[nFileIndex]);
Continue;
end; Writeln(nFiles[nFileIndex]);
try
nOldVersion.Init;
nXDOC.LoadFromFile(nFiles[nFileIndex]);
nXNRoot := nXDOC.Items[];
for nXNIndex := to nXNRoot.Count - do
begin
nXN := nXNRoot.Items[nXNIndex];
if nXN.Name <> 'PropertyGroup' then
Continue;
if nXN.Attrs.AsString['Condition'] = '''$(Base)''!=''''' then
begin
_GetXNode(nXN, 'VerInfo_MajorVer', nStr).Text := nVersion.MajorVer.ToString;
nOldVersion.MajorVer := StrToIntDef(nStr, );
_GetXNode(nXN, 'VerInfo_MinorVer', nStr).Text := nVersion.MinorVer.ToString;
nOldVersion.MinorVer := StrToIntDef(nStr, );
_GetXNode(nXN, 'VerInfo_Release', nStr).Text := nVersion.Release.ToString;
nOldVersion.Release := StrToIntDef(nStr, );
_GetXNode(nXN, 'VerInfo_Build', nStr).Text := nVersion.Build.ToString;
nOldVersion.Build := StrToIntDef(nStr, ); with _GetXNode(nXN, 'VerInfo_Keys', nStr) do
begin
nStrs.DelimitedText := Text;
for nIKIndex := to nStrs.Count - do
begin
nName := nStrs.KeyNames[nIKIndex];
if CompareText('FileVersion', nName) = then
nStrs[nIKIndex] := 'FileVersion=' + nVersion.ToString;
end;
Text := nStrs.DelimitedText;
end; _GetXNode(nXN, 'VerInfo_IncludeVerInfo', nStr).Text := True.ToString(TUseBoolStrs.True);
end
else
begin
{删除其他版本信息}
nXN.Delete('VerInfo_MajorVer');
nXN.Delete('VerInfo_MinorVer');
nXN.Delete('VerInfo_Release');
nXN.Delete('VerInfo_Build');
nXN.Delete('VerInfo_Keys');
end;
end;
if nBackup then
begin
nPath := ExtractFilePath(nFiles[nFileIndex]) + '\dproj_bak\';
ForceDirectories(nPath);
nStr := nPath + ExtractFileName(nFiles[nFileIndex]) + '.#' + nOldVersion.ToString + '#.bak';
if FileExists(nStr) then
TFile.Delete(nStr);
TFile.Copy(nFiles[nFileIndex], nStr);
end;
nXDOC.SaveToFile(nFiles[nFileIndex], TTextEncoding.teUTF8, True, False, True);
except
on E: Exception do
Writeln('错误: ' + E.Message);
end;
end;
finally
nStrs.Free;
nXDOC.Free;
end;
Writeln('');
Writeln('******** 处理完毕 ********')
except
on E: EAbort do;
on E: Exception do
begin
Writeln('错误: ', E.Message);
nAutoClose := False;
end;
end;
if not nAutoClose then
begin
Writeln('');
Writeln('按任意键关闭');
Read(nStr);
end;
end.
Delphi工程版本号修改工具的更多相关文章
- Git学习(一) 版本号管理工具
Git 是一个分布式版本号控制工具.它的作者 Linus Torvalds 是这样给我们介绍 Git -- The stupid content tracker(傻瓜式的内容跟踪器) 1. Git ...
- git版本号管理工具的上手
git是一个分布式的版本号管理工具 和其它集中式版本号管理 工具相比具有下面长处: 1.能够在不联网的情况下开发 2.能够方便的建立本地分支 3.本地化的日志,高速获得信息 git命令的使用 mkdi ...
- [c#][福利]BTTool种子文件修改工具
前言 不知道各位看官是否有过类似的经历.好不容易找到一个电影的种子文件,想用百度云的离线下载功能去下载文件,却被百度云无情提示“离线文件因含有违规内容被系统屏蔽无法下载”!假设有这么一个场景,比如最近 ...
- 用户组修改工具samusrgrp
用户组修改工具samusrgrp Windows系统内置了很多用户组,如Administrators.PowerUser.User等.用户隶属不同的组,就具备对应的权限.Kali Linux提供一 ...
- 网络数据修改工具netsed
网络数据修改工具netsed 通过修改网络数据,可以绕过软件和防火墙的限制,达到特定的目的.Kali Linux提供一个简易数据修改工具netsed.该工具支持对TCP和UDP的数据进行修改.渗透 ...
- (外挂破解)Cheat Engine(内存修改工具)V6.2中文版软件介绍
Heat Engine是一款内存修改编辑工具,Cheat Engine允许你修改你的游戏,所以你将总是赢.它包括16进制编辑,反汇编程序,内存查找工具.与同类修改工具相比,它具有强大的反汇编功能,且自 ...
- Android 获取手机的厂商、型号、Android系统版本号等工具类(转载)
Android 获取手机的厂商.型号.Android系统版本号等工具类 1.获取手机制造厂商 2.获取手机型号 3.获取手机系统当前使用的语言 4.获取Android系统版本号 5.获取手机IMEI串 ...
- jar包名修改工具
jar包名修改工具 软件传送门:链接: https://pan.baidu.com/s/12StRdEkYGmMn1DuNSquXSw 提取码: i9w1 闲暇之余,利用jarjar.jar写了一 ...
- Delphi开发的IP地址修改工具
用Delphi进行开发的,直接修改注册表,需重启电脑后才生效
随机推荐
- 在Ubuntu上安装Docker
原文链接:https://docs.docker.com/engine/installation/linux/ubuntu/ 这里记录的是社区版安装方式,由于平时只做开发使用所以不需要安装企业版, ...
- 手把手教你用npm发布一个包,详细教程
我们已经实现了路由的自动化构建,但是我们可以看到,一大串代码怼在里面.当然你也可以说,把它封装在一个JS文件里面,然后使用require('./autoRoute.js')给引入进来,那也行.但是,为 ...
- fiddler 监听HttpClient发送的请求
用HttpClient模拟浏览器发送请求,设置一下代理httpClient.getHostConfiguration().setProxy("127.0.0.1", 8888);
- struts2-学习笔记(一)
Struts2学习笔记(一) 一.Struts2概述 1. 是什么? Struts2 是一个非常优秀的MVC框架,基于Model2 设计模型 Struts2是一个M(模型---域--范围模型)V ...
- canvas图表详解系列(1):柱状图
本章建议学习时间4小时 学习方式:详细阅读,并手动实现相关代码(如果没有canvas基础,需要先学习前面的canvas基础笔记) 学习目标:此教程将教会大家如何使用canvas绘制各种图表,详细分解步 ...
- WPF使用资源字典组织资源
转载:http://blog.163.com/wangzhenguo2005@126/blog/static/371405262010111413321728/ 首先在解决方案资源管理器中添加 ...
- Linux硬链接和软连接详解
硬链接: 硬链接是通过索引节点inode来进行链接的(关于inode,http://www.cnblogs.com/ZGreMount/p/7653307.html).在Linux(ext2,ext3 ...
- jquery系列教程6-ajax的应用全解
点击打开: jquery系列教程1-选择器全解 jquery系列教程2-style样式操作全解 jquery系列教程3-DOM操作全解 jquery系列教程4-事件操作全解 jquery系列教程5-动 ...
- [译]ASP.NET Core 2.0 中间件
问题 如何创建一个最简单的ASP.NET Core中间件? 答案 使用VS创建一个ASP.NET Core 2.0的空项目,注意Startup.cs中的Configure()方法: public vo ...
- 多个 (li) 标签如何获取获取选中的里面的某个特定值??
两种方式: 1/.根据div中的class属性 指定ul 找到选中的单个li $(".f_dingdan ul li").click(function(){ var a=$( ...