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进行开发的,直接修改注册表,需重启电脑后才生效
随机推荐
- 写一个ORM框架的第一步
新一次的内部提升开始了,如果您想写一个框架从Apache Commons DbUtils开始学习是一种不错的选择,我们先学习应用这个小“框架”再把源代码理解,然后写一个属于自己的ORM框架不是梦. 一 ...
- Nginx平滑升级源码分析
一.平滑升级步骤 1.重命名之前的sbin/nginx文件,将新的nginx文件放到sbin/目录下 #mv ./sbin/nginx ./sbin/nginx.old #cp ~/nginx ./s ...
- Python 基础系列一:初识python(二)基本数据类型
上节拾遗 1.编码转换过程,utf-8转换gbk 过程 经过解码(py27): x.decode('utf-8')-->unicode-->编码x.encode('gbk') ps:py3 ...
- Winform窗体间传递数据
public string passText { get { return textBox1.Text; } } //Form1中还有个按钮button1在其点击事件中有: private void ...
- jquery系列教程6-ajax的应用全解
点击打开: jquery系列教程1-选择器全解 jquery系列教程2-style样式操作全解 jquery系列教程3-DOM操作全解 jquery系列教程4-事件操作全解 jquery系列教程5-动 ...
- SAP 动态设置 GUI STATUS 灰色不可用 或者隐藏(转)
http://blog.sina.com.cn/s/blog_66110f6201017rul.html 有时候需要根据用户的权限或者是操作动态设置gui状态上的某些按钮的可用和不可用. 1.先定 ...
- php中各种定义变量的方法
1.定义常量define("CONSTANT", "Hello world."); 常量只能包含标量数据(boolean,integer,float 和 s ...
- CSS之 relative 特性
1. 自身特性: 如left,right,top,bottom定位都是相对于自身位置定位. 当left与right同时存在,lfet生效. 当top与bottom同时存在,top生效. 无侵入,保留原 ...
- Python学习笔记(四)
Python学习笔记(四) 作业讲解 编码和解码 1. 作业讲解 重复代码瘦身 # 定义地图 nav = {'省略'} # 现在所处的层 current_layer = nav # 记录你去过的地方 ...
- CSS样式之表格,表单
布局样式 .container:固定宽度并具响应式 .container-fluid自由宽度(100%宽度) 标题样式 <h1>到<h6> 样式已经写好了,可以直接用,兼容性也 ...