Alter/modify/change a MSBuild property from a command line - command-line

Suppose I have the MSBuild script with the following property set up:
<PropertyGroup ...>
<DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
I want to build my project from a command-line, but add an additional symbol to that property. For example, I want to add TEST, so the property's value would be TEST;DEBUG or DEBUG;TEST.
What is a good way of doing so?
For example, I could run:
msbuild ... /p:DCC_Define="TEST"
but that would override (e.g. replace) the property value. So the final value would be just TEST.
Attempt to run like this:
msbuild ... /p:DCC_Define="TEST;$(DCC_Define)"
does not help: the TEST symbol is present, while the DEBUG one is not.
Any suggestions? Am I missing something?

You could use the _kibitz target.
msbuild <projectfile> /p:config=Release /target:_kibitz /p:_kibitztask="EvaluateProperty" /p:_EvaluateName="DCC_Define" /NoLogo /verbosity:normal
This would result in output like:
Der Buildvorgang wurde am 09.06.2022 12:00:46 gestartet.
Projekt"<Projectfile>" auf Knoten "1", _kibitz Ziel(e).
_EvaluateProperty: EvaluateProperty=RELEASE;;FRAMEWORK_VCL
Die Erstellung des Projekts "<projectfile>" ist abgeschlossen, _kibitz Ziel(e).
You could then parse the _EvaluateProperty line to retrieve the value. This value can then be used for a subsequent call.

Related

How to replace value with more than one attribute in config file in Azure DevOps?

I have a file called entlib.config like below:
<loggingConfiguration name="Logging Application Block" tracingEnabled="true"
defaultCategory="General" logWarningsWhenNoCategoriesMatch="true">
<listeners >
<add name="Email TraceListener" toAddress="axx.xxx#xxx.com" fromAddress="axx.xxx#xxx.com" subjectLineStarter="xxxxx " subjectLineEnder="" smtpServer="xxx.com" smtpPort="xxx" formatter="Text Formatter"
Now,in this file needs to replace fromAddress, toAddress and subjectLineStarter attribute has a variables groups for azure pipeline... how to do this change ? can we do have an option to change any config file that has been created as xml to change more than one attribute ?
To replace the vaules in **.config file with the variables in Variable group, you can try the following methods:
1.You can use the XML variable substitution option in the Azure App service deploy task or IIS deploy task.
For more detailed steps, refer to this doc: XML variable substitution
2.You can use PowerShell script to modify attributes in the config file.
Here is the PowerShell script sample:
$entlibConfig = 'path\entlib.config'
Function updateConfig($config)
{
$doc = (Get-Content $config) -as [Xml]
$root = $doc.get_DocumentElement();
$activeConnection = $root.loggingConfiguration.listeners.SelectNodes("add"); #You need to define the correct location of the parameter
$activeConnection.SetAttribute("fromAddress", "$(fromAddress)");
$activeConnection.SetAttribute("toAddress ", "$(toAddress )“);
$activeConnection.SetAttribute("subjectLineStarter ", "$(subjectLineStarter )“);
$doc.Save($config)
}
updateConfig($entlibConfig)
3.When you add the mark: #{..}# in entlib.config file, you can try to use the Replace Token task from Replace Tokens Extension.
Refer to the example in this ticket:How to perform XML Element substitution in web.config using Replace Tokens?

How to replace variables of JSON file in Team Services?

I'm stuck with a release variable substitution of an angular project. I have a settings.json file which I would like to replace some variables:
{
test : "variable to replace"
}
I tried to find some custom task on the marketplace but all of the tasks seems to work only with xml files for the web.config.
I use the "Replace tokens" from the Marketplace https://marketplace.visualstudio.com/items?itemName=qetza.replacetokens
You define the desired values as variables in the Release Definition and then you add the Replace Tokens task and configure a wildcard path for all target text files in your repository where you want to replace values (for example: **/*.json). The token that gets replaced has configurable prefix and postfix (default are '#{' and '}#'). So if you have a variable named constr you can put in your config.json
{
"connectionstring": "#{constr}#"
}
and it will deploy the file like
{
"connectionstring": "server=localhost,user id=admin,password=secret"
}
The IIS Web App Deploy Task in VSTS Releases has JSON variable substitution under *File Transforms & Variable Substitution Options.
Provide a list of json files and JSONPath expressions for the variables that need replacing
For example, to replace the value of ‘ConnectionString’ in the sample below, you need to define a variable as ‘Data.DefaultConnection.ConnectionString’ in the build/release definition (or release definition’s environment).
{
  "Data": {
    "DefaultConnection": {
      "ConnectionString": "Server=(localdb)\SQLEXPRESS;Database=MyDB;Trusted_Connection=True"
    }
  }
}
You can add a variable in release variables Tab, and then use PowerShell task to update the content of your settings.json.
Assume the original content is
{
test : "old
}
And you want to change it to
{
test : "new"
}
So you can replace the variable in json file with below steps:
1. Add variable
Define a variable in release variable tab with the value you want to replace with (variable test with value new):
2. Add PowerShell task
Settings for powershell task:
Type: Inline Script.
Inline Script:
# System.DefaultWorkingDirectory is the path like C:\_work\r1\a, so you need specify where your appsettings.json is.
$path="$(System.DefaultWorkingDirectory)\buildName\drop\WebApplication1\src\WebApplication1\appsettings.json"
(Get-Content $path) -replace "old",$(test) | out-file $path

Is there an MSBuild macro for build date/time?

Suppose I have a build script with a Target section like the following:
<Target Name="AssemblyVersionMAIN" Inputs="#(AssemblyVersionFiles)" Outputs="UpdatedAssemblyVersionFiles">
<Attrib Files="%(AssemblyVersionFiles.FullPath)" Normal="true"/>
<AssemblyInfo
CodeLanguage="CS"
OutputFile="%(AssemblyVersionFiles.FullPath)"
AssemblyProduct="$(ProductName)"
AssemblyTitle="$(ProductName)"
AssemblyCompany="$(CompanyName)"
AssemblyCopyright="© $(CompanyName) 2014" <!-- THIS LINE -->
AssemblyVersion="$(Major).$(Minor).$(Build).$(Revision)"
AssemblyFileVersion="$(Major).$(Minor).$(Build).$(Revision)"
AssemblyInformationalVersion="$(Major).$(Minor).$(Build).$(Revision)">
<Output TaskParameter="OutputFile" ItemName="UpdatedAssemblyVersionFiles"/>
</AssemblyInfo>
</Target>
At the moment, the year is static and has to be changed manually. Is there a simple way of replacing "2014" with something like $(Year)? I've checked the MSBuild reference but nothing jumps out at me.
Since you are using MsBuild 4 you could also use a property function for this, like e.g.:
<PropertyGroup>
<CurrentDate>$([System.DateTime]::Now.ToString(yyyy.MM.dd))</CurrentDate>
</PropertyGroup>
Just format the recieved date as you need it. There are also plenty of other functions available, see also http://msdn.microsoft.com/en-us/library/dd633440(v=vs.100).aspx.
Since I'm using MSBuild Community Tasks and MSBuild 4, I can substitute the following:
AssemblyCopyright="© $(CompanyName) $([System.DateTime]::Now.ToString(`yyyy`))"
which seems to work.

Why Msbuild task failed to deploy database, but Exec work fine

I'm trying to deploy database project ( dbproj format, not new SSDT sqlproj ) inside automated build server processing. I found the following:
When I'm calling deploy with Exec task in my Msbuild script - everything working fine:
<Exec Command="$(MSBuildPath)\MSBuild.exe $(SourceFilesPath)\$(DeployDatabaseProjectName)\$(DeployDatabaseProjectName).dbproj
/t:Deploy
/p:OutputPath=$(BaseOutput)\$(DeployDatabaseProjectName)\
/p:TargetDatabase=$(DeployDatabaseName)
/p:TargetConnectionString=$(DeployDatabaseConnectionString)" />
But when I try to repeat this with Msbuild task - it behaves differently:
<MSBuild Projects="$(SourceFilesPath)\$(DeployDatabaseProjectName)\$(DeployDatabaseProjectName).dbproj"
Targets="Deploy"
Properties="Configuration=$(BuildConfiguration);
TargetDatabase=$(DeployDatabaseName);
TargetConnectionString="$(DeployDatabaseConnectionString)";
OutputPath=$(BaseOutput)\$(DeployDatabaseProjectName)\;
" />
Msbuild task broke on semicolons in DeployDatabaseConnectionString:
<DeployDatabaseConnectionString>Data Source=$(DeployDatabaseServer);Integrated Security=True;Pooling=False</DeployDatabaseConnectionString>
It will report something like this:
The name "Integrated Security" contains an invalid character " ".
But if I replace semicolons with percent encoding value - %3B - it will broke inside SqlDeployTask:
error MSB4018: The "SqlDeployTask" task failed unexpectedly.
What is the proper way to pass TargetConnectionString to Deploy target of SqlProject ?
PS: I Could live with exec task fine, but make a call to msbuild.exe inside msbuild script just hurts my inner perfectionist man.
I found the proper way - new Msbuild allow to define AdditionalProperties metadata on item. So with this feature everything work fine and have no problems with escaping\encoding
<ItemGroup>
<DbProjectToBuild Include="$(SourceFilesPath)\$(DeployDatabaseProjectName)\$(DeployDatabaseProjectName).dbproj">
<AdditionalProperties>Configuration=$(BuildConfiguration)</AdditionalProperties>
<AdditionalProperties>OutputPath=$(BaseOutput)\$(DeployDatabaseProjectName)\</AdditionalProperties>
<AdditionalProperties>TargetDatabase=$(DeployDatabaseName)</AdditionalProperties>
<AdditionalProperties>TargetConnectionString="Data Source=$(DeployDatabaseServer);Integrated Security=True;Pooling=False"</AdditionalProperties>
</DbProjectToBuild>
</ItemGroup>
<MSBuild Projects="%(DbProjectToBuild.Identity)" Targets="Build;Deploy" />

Use AppCmd to LIST CONFIG in APPHOST only

I have a requirement to use powershell to configure IIS7.5 on WebApplications that have not yet had code deployed (possibly at all, possibly old/broken web.configs exist) to the file system. I would like to be able to do this all at the APPHOST level. (Note at the bottom about use of Powershell > AppCmd).
I can SET all the values properly, however, being somewhat diligent, I like to also validate the values were set properly by retrieving them after setting.
Here's the scenario:
I can set this value using AppCmd so the setting is applied at the APPHOST level using the /Commit:APPHOST flag. However, I havent found a way to READ the values exclusively at the APPHOST level.
Setting the Code is successful:
C:\Windows\System32\inetsrv\appcmd.exe set config "webSiteName/webAppName" -section:system.webServer/security/authentication/anonymousAuthentication /enabled:"True" /commit:apphost
However, I cant find a way to read the values using AppCmd (or Powershell):
Running the following AppCmd returns an error due to the broken pre-existing web.config in the folder (the specific error is unimportant, as it is reading the WebApp's web.config instead of the ApplicationHost.config/APPHOST):
C:\Windows\System32\inetsrv\appcmd.exe list config "MACHINE/WEBROOT/APPHOST/webSiteName/webAppName" -section:system.webServer/security/authentication/anonymousAuthentication
ERROR ( message:Configuration error
Filename: \\?\c:\inetpub\wwwroot\webSiteName\webAppName\web.config
Line Number: 254
Description: The configuration section 'system.runtime.caching' cannot be read because it is missing a section declaration
. )
Note: I would prefer to do this all in Powershell instead of using AppCmd, so if anyone has the syntax for modifying the APPHOST settings for anonymousAuthentication section of a WebApplication, that lives under a Website, from inside Powershell (Get-WebConfiguration seems to only use the WebApp web.config), that would be totally awesome and much appreciated!
Here's how to do this in PowerShell:
[Reflection.Assembly]::Load(
"Microsoft.Web.Administration, Version=7.0.0.0,
Culture=Neutral, PublicKeyToken=31bf3856ad364e35") > $null
$serverManager = New-Object Microsoft.Web.Administration.ServerManager
$config = $serverManager.GetApplicationHostConfiguration()
$anonymousAuthenticationSection = $config.GetSection("system.webServer/security/authentication/anonymousAuthentication", "simpleasp.net")
Write-Host "Current value: " $anonymousAuthenticationSection["enabled"]
# Now set new value
$anonymousAuthenticationSection["enabled"] = $true
$serverManager.CommitChanges()