使用项目/属性/设置的值.在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。

使用项目/属性/设置的值.在InnoSetup脚本中设置

没有人知道解决方案,所以我用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文件的设计器代码,我猜这可以做到。一个配置文件来统治所有的:-)