使用项目/属性/设置的值.在InnoSetup脚本中设置
本文关键字:设置 InnoSetup 脚本 属性 项目 | 更新日期: 2023-09-27 18:15:40
我希望能够在c# . net 4.0项目中的一个地方更改值。为此,我使用内置的Properties/Settings.settings
文件,它本质上是一个XML文件。
当我们使用InnoSetup(这是很常见的)为我们的软件,作为settings.settings
文件是存储值的默认方式为c# . net应用程序,我想知道是否有一个方法为InnoSetup脚本从设置文件拉值,或者如果你可以给我一个脚本,可以做到这一点,设置设置脚本的变量。
我运行了XML示例,但是现在我不能使用XPath查询来获得正确的节点。这是我的脚本:
[Code]
{--- MSXML ---}
const
XMLFileName = '..'CCFinderWPF'Properties'Settings.settings';
XMLFileName2 = '..'CCFinderWPF'Properties'Settings.xml';
function Settings(Default: String): String;
var
XMLDoc, SeekedTopNode, SeekedNode, iNode, Sel: Variant;
Path, XPath: String;
begin
{ Load the XML File }
try
XMLDoc := CreateOleObject('MSXML2.DOMDocument.4.0');
except
RaiseException('Please install MSXML first.'#13#13'(Error ''' + GetExceptionMessage + ''' occurred)');
end;
XMLDoc.async := False;
XMLDoc.resolveExternals := false;
XMLDoc.preserveWhiteSpace := true;
XMLDoc.setProperty('SelectionLanguage', 'XPath');
XMLDoc.load(XMLFileName);
if XMLDoc.parseError.errorCode <> 0 then
RaiseException('Error on line ' + IntToStr(XMLDoc.parseError.line) + ', position ' + IntToStr(XMLDoc.parseError.linepos) + ': ' + XMLDoc.parseError.reason);
MsgBox('XML-File: ' + XMLFileName, mbInformation, MB_OK);
{ Modify the XML document }
iNode := XMLDoc.documentElement;
iNode := iNode.selectSingleNode('Setting[@Name="' + Default + '"]');
// **selectSingleNode returns null, seems that selectSingleNode with XPath doesn't work?**
MsgBox('The Node is: ' + iNode.nodeName, mbInformation, MB_OK);
SeekedNode := iNode.firstChild;
Result := SeekedNode.lastChild.text;
MsgBox('The XPath is: ' + XPath, mbInformation, MB_OK);
end;
我使用Inno Setup预编译器像这样调用这个函数:
#define ABAppName "{code:Settings|AppName}"
xml文件如下所示:
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="CCFinder.Properties" GeneratedClassName="Settings">
<Profiles />
<Settings>
<Setting Name="AppName" Type="System.String" Scope="Application">
<Value Profile="(Default)">CCFinder</Value>
</Setting>
...
所有这一切的目标是,我可以设置值在我的应用程序从设置。在我的c#项目中设置文件,让我的hudson实例检查我的代码,并为不同版本的应用程序更改这个XML文件,例如更改一些我在设计时不需要知道的值。我希望能够从这个XML文件中提取变量。我只是在这里使用MSXML2。
没有人知道解决方案,所以我用while循环来解决这个问题。请注意,这是我的第一个Delphi代码,所以它可能不是优雅和/或100%正确。以下是我定义所需常量的方式:
#define ABAppName "{code:Settings|AppName}"
#define ABAppVersion "{code:Settings|AppVersion}"
#define ABCompany "{code:Settings|CompanyName}"
#define ABAppTitle "{code:Settings|ApplicationTitle}"
#define ABAppTitlePro "{code:Settings|ApplicationTitle)}"+" "+"{code:Settings|ProVersionAppender}"
#define ABCompanyUrl "{code:Settings|CompanyUrl_de}"
#define ABContactEmailDe "{code:Settings|ContactEmail_de}"
#define ABYear "{code:Settings|Year}"
这些都在常量中。iss文件的纯文本,我包括在我的设置脚本与#include "constants.iss"
在开始。这是由以下代码调用的delphi代码:
const
XMLFileName = '..'CCFinder'Properties'Settings.settings';
function Settings(Default: String): String;
var
XMLDoc, iNode: Variant;
Path: String;
i : Integer;
Loop : Boolean;
begin
{ Load the XML File }
try
XMLDoc := CreateOleObject('MSXML2.DOMDocument.6.0');
except
RaiseException('Please install MSXML first.'#13#13'(Error ''' + GetExceptionMessage + ''' occurred)');
end;
try
XMLDoc.async := False;
XMLDoc.resolveExternals := false;
XMLDoc.load(XMLFileName);
if XMLDoc.parseError.errorCode <> 0 then
RaiseException('Error on line ' + IntToStr(XMLDoc.parseError.line) + ', position ' + IntToStr(XMLDoc.parseError.linepos) + ': ' + XMLDoc.parseError.reason);
iNode := XMLDoc.DocumentElement;
iNode := iNode.LastChild;
Loop := True;
i := 0;
while Loop do
begin
Try
if iNode.ChildNodes[i].attributes[0].nodeValue = Default
then
begin
Result := iNode.ChildNodes[i].text;
// MsgBox('Result for Default: ' + Result + Default, mbInformation, MB_OK);
i := i+1;
Loop := False;
Break;
end
else
begin
i := i+1;
if i = 100 then Loop := false;
end;
except
Result := '';
end;
end;
except
end;
end;
- 循环被限制为100次运行,因为我太笨拙了,无法计算Delphi中的XML节点。
- 需要安装InnoSetup预处理器。
- Inno似乎不接受路径名中的常量,因此有些值无法从属性/设置中提取。设置文件。
- 我不知道预处理器实际上并不使用Delphi代码来获取正确的值以将它们包含在脚本中,而是在使用常量的所有地方包含完整的Delphi代码调用。当然,这并不是我想要做的,因为当代码嵌入到路径中时,它甚至无法工作。因此,我更改了设置脚本,只包含一个常量,我需要用find和replace替换,例如,它用于路径名和可执行文件名。
对于其余部分,我编写了一个. net命令行应用程序,它基本上做了与delphi代码相同的事情,在Hudson上编译设置之前在Hudson中执行它。这将用所需的实际值替换代码调用(只有例外,但您应该明白这一点):
{ XmlDocument xmldoc = new XmlDocument(); xmldoc.Load(pathToSettingsFile); XmlNodeList list = xmldoc.GetElementsByTagName("Setting"); foreach (XmlNode node in list) { string keystring = node.Attributes["Name"].InnerText; string valuestring = node.FirstChild.InnerText; settingValues.Add(keystring,valuestring); } var t = File.OpenText(constantsfilename); string text; using (t) { text = t.ReadToEnd(); } string sample = "{code:Settings|"; char endsign = '}'; while (text.Contains(sample)) { int startindex = text.IndexOf(sample); int endindex = text.IndexOf(endsign, startindex); int variableIndex = startindex + sample.Length; string variable = text.Substring(variableIndex, endindex - variableIndex); text = text.Replace(sample + variable + endsign, newVal(variable)); } var w = new StreamWriter(constantsfilename); using (w) { w.Write(text); w.Flush(); } } public static string newVal(string variable) { if (settingValues.ContainsKey(variable)) return settingValues[variable]; else { return ""; } }
这意味着我现在可以在我的Settings-File中设置值,这些值可以通过hudson中的另一个命令行应用程序更改,并自动写入设置脚本。
编辑:刚刚意识到,这是Visual Studio设计器手动将设置从设置文件传输到app.config,在构建时将输出更改为ProgramName.exe.config文件。因此,您需要更改其中的值以使其生效,如果您为其提供正确的文件路径,coe应该可以工作。
EDIT2:这个app.config在编译时被重命名为YourAppName.exe.config…如果没有将其放入设置中,则没有正确初始化值。我扩展了我的代码,用XML中的值来调整Settings.designer.cs文件的设计器代码,我猜这可以做到。一个配置文件来统治所有的:-)