TFS 2017 - [ProjectName].setParameters.xml with powershell - powershell

I create a zip Package in my build then i deploy it to a diffrent machine i am pasing few Parameters in my parameters.xml
<?xml version="1.0" encoding="utf-8"?>
<parameters>
<parameter name="WebSiteUserName" description="Please enter the username" defaultvalue="__WebSiteUserName__" tags="">
<parameterentry kind="XmlFile" scope="\\web.config$" match="/configuration/connectionStrings/add[#key='WebSiteUserName']/#value">
</parameterentry>
</parameter>
<parameter name="WebSiteUserPassword" description="Please enter the password" defaultvalue="__UserPassword__" tags="">
<parameterentry kind="XmlFile" scope="\\web.config$" match="/configuration/connectionStrings/add[#key='WebSiteUserPassword']/#value">
</parameterentry>
</parameter>
<parameter name="WebSiteDomain" description="Domiain" defaultvalue="__Domain__" tags="">
<parameterentry kind="XmlFile" scope="\\web.config$" match="/configuration/appSettings/add[#key='WebSiteDomain']/#value">
</parameterentry>
</parameter>
</parameters>
</parameters>
Then i run a powershell script
param(
[string]$paramsFilePath
)
Write-Verbose -Verbose "Entering script Replace-SetParameters.ps1"
Write-Verbose -Verbose ("Path to SetParametersFile: {0}" -f $paramsFilePath)
# get the environment variables
$vars = Get-ChildItem -path env:*
# read in the setParameters file
$contents = Get-Content -Path $paramsFilePath
# perform a regex replacement
$newContents = "";
$contents | % {
$line = $_
if ($_ -match "__(\w+[\.\w+]*)__") {
$setting = Get-ChildItem -path env:* | ? { $_.Name -eq $Matches[1] }
while ($setting) {
Write-Verbose -Verbose ("Replacing key {0} with value from environment" -f $setting.Name)
$line = $_ -replace "__(\w+[\.\w+]*)__", $setting.Value
}
}
$newContents += $line + [Environment]::NewLine
}
Write-Verbose -Verbose "Overwriting SetParameters file with new values"
Set-Content $paramsFilePath -Value $newContents
Write-Verbose " Assigning Parameters"
Write-Verbose -Verbose "Exiting script Replace-SetParameters.ps1"
It will go through the parameters file and replace the parameters token with the enviromental variable.
In my setParamaters.xml file The WebSiteUsername only gets changed
<?xml version="1.0" encoding="utf-8"?>
<parameters>
<setParameter name="IIS Web Application Name" value="Default Web Site/SomeWebsite" />
<setParameter name="WebSiteUserName" value="username" />
<setParameter name="WebSiteUserPassword" value="__UserPassword__" />
<setParameter name="Web.config Connection String" value="SomeValueForConnection" />
</parameters>
I dont know why this is happening. Any Thoughts?

I think you want to get the password from a TFS release definition environment.
You can´t access hidden fields with
$vars = Get-ChildItem -path env:secretVariable
There is a way but that´s only works in the context of a TFS VNext build or release extension.
In your case the only possibility of access is to set the variable as a script argument like this:
-paramsFilePath $(paramsFilePath) -password $(secretVariable)
In your script add the parameter like
param(
[string]$paramsFilePath,
[string]$password
)

Related

How can I update a changing value in Powershell in a web.config file?

I am trying to update text inside a web.config file with powershell, but I am having a very, very difficult time.
The problem is this line
<add key="Models.Catalog.Repository" value=Server23 />
You see where the Server23 is? this value sometimes can be empty, which will be represented as "" or sometimes it can have a different name like "\Server25\path"
How do I tell PowerShell to replace/insert data if the field is empty/has some text in it?
here is the full code
$GP_AP= "Server1"
$NewMD = "\\JohnWick"
Invoke-Command -ComputerName $GP_AP -ScriptBlock {
$date= Get-Date -Format "dd_MM_yyyy_HHMM_ss"
$webfile = "C:\Program Files\TEST\IIS\Web.config"
(Copy-Item -Path $webfile -Destination $webfile_Test_$Date)
#[xml]$webconfigfile = Get-Content "C:\Program Files\TEST\IIS\Web.config"
#[xml]$2 = Get-Content "\\Server1\C$\Program Files\TEST\IIS\Web.config"
$olddata = "*"
#(Get-Content $webfile -raw).Replace("<add key=`"Models.Catalog.Repository`" value=$olddata />","<add key=`"Models.Catalog.Repository`" value=$Using:NewMD />") `
#| Set-Content "C:\Program Files\TEST\IIS\Web.config" -Force -Encoding UTF8 -ErrorAction Stop
(Get-Content $webfile -raw).Replace('<add key="Models.Catalog.Repository" value=Server23 />',"<add key=`"Models.Catalog.Repository`" value=$Using:NewMD />") `
| Set-Content "C:\Program Files\TEST\IIS\Web.config" -Force -Encoding UTF8 -ErrorAction Stop
} # end of script block
The script below will allow you to set values in a web config's <appSettings> based on key names. All the nodes must exist. This script will not create them. You'll obviously need to edit the script's default params.
param(
[string] $pathToWebConfig = "$PSScriptRoot\web.config"
[System.Collections.Hashtable] $appSettings = #{
someKey = 'somevalue';
someOtherKey = 'someOtherValue'
}
)
function UpdateXmlConfigAppSettings(
[Parameter(mandatory=$true)]
[string] $configFilePath,
[Parameter(mandatory=$true)]
[System.Collections.Hashtable] $appSettingsDict
) {
[xml] $webConfig = Get-Content $configFilePath
foreach($key in $appSettingsDict.Keys) {
$node = $webConfig.SelectSingleNode("//appSettings/add[#key = '$key']")
if ($null -ne $node) {
$node.SetAttribute('value', $appSettingsDict[$key])
}
else {
throw "$appSettingsDict[$key] is not a valid key in AppSettings"
}
}
$webConfig.Save($configFilePath)
}
UpdateXmlConfigAppSettings -configFilePath $pathToWebConfig -appSettingsDict $appSettings
$path = '\\server\c$\Program Files\TEST\IIS\web.config'
[xml]$config = Get-Content -Path $path -Raw
$stuffIwant = "\\Blah-244"
$config.SelectNodes("//add[#key='Models.Catalog.Repository']") | `
ForEach-Object { $_.SetAttribute("value", $stuffIwant) }
$config.Save($path)

Get recurring events from sharepoint (2010) with powershell + CAML

* EDIT: *
Managed to fetch the reccuring events.
How do I overcome the year limit?
<Value Type='DateTime'>
<Year/>
</Value>
I want to get all items, even 5 years ahead.
-------- Original ----------
I am trying to run a PowerShell script to export all events from a SharePoint-2010 calendar including recurring events.
I got references from
https://github.com/CompartiMOSS/SharePoint-PowerShell/blob/master/SharePoint/Administration/PS_HowToDoCAMLQuery.ps1
Expand Recurring Events from a Sharepoint Calendar over WebServices?
The script is running, but the recurring events are not showing.
What am I missing?
If ((Get-PSSnapIn -Name Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue) -eq $null )
{ Add-PSSnapIn -Name Microsoft.SharePoint.PowerShell }
$host.Runspace.ThreadOptions = "ReuseThread"
#Definition of the function that allows to do the CAML query
function DoCAMLQuery
{
param ($sSiteCollection,$sListName)
try
{
$spSite=Get-SPSite -Identity $sSiteCollection
$spwWeb=$spSite.OpenWeb()
$splList = $spwWeb.Lists.TryGetList($sListName)
if ($splList)
{
$spqQuery = New-Object Microsoft.SharePoint.SPQuery
$spqQuery.Query =
"<GetListItems
xmlns='http://schemas.microsoft.com/sharepoint/soap/'>
<listName>'Event Calendar'</listName>
<query>
<Query>
<Where>
<DateRangesOverlap>
<FieldRef Name='EventDate' />
<FieldRef Name='EndDate' />
<FieldRef Name='RecurrenceID' />
<FieldRef Name='fRecurrence' />
<FieldRef Name='RecurrenceData' />
<Value Type='DateTime'><Year/>
</Value>
</DateRangesOverlap>
</Where>
</Query>
</query>
<queryOptions>
<QueryOptions>
<ExpandRecurrence>TRUE</ExpandRecurrence>
</QueryOptions>
</queryOptions>
</GetListItems>"
$spqQuery.ExpandRecurrence = $true
$splListItems = $splList.GetItems($spqQuery)
$iNumber=1
foreach ($splListItem in $splListItems)
{
write-host "File # $iNumber - Name: " $splListItem.Name " ," "Title:" $splListItem["ows_LinkTitle"] -ForegroundColor Green
$iNumber+=1
}
}
$spSite.Dispose()
}
catch [System.Exception]
{
write-host -f red $_.Exception.ToString()
}
}
Start-SPAssignment –Global
#Calling the function
$sSiteCollection="http://sharepoint/"
$sListName="Compliance Events"
DoCamlQuery -sSiteCollection $sSiteCollection -sListName $sListName
Stop-SPAssignment –Global
Remove-PSSnapin Microsoft.SharePoint.PowerShell
Thanks!
S
Below sample script will return events from Now() till next two years.
if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) {
Add-PSSnapin "Microsoft.SharePoint.PowerShell"
}
$siteURL="http://sp"
$site = Get-SPSite $siteURL
$web = $site.OpenWeb()
$splList = $web.Lists.TryGetList("MyCalendar")
$spqQuery = New-Object Microsoft.SharePoint.SPQuery
$spqQuery.Query = "<Where><DateRangesOverlap><FieldRef Name='EventDate' /><FieldRef Name='EndDate' /><FieldRef Name='RecurrenceID' /><Value Type='DateTime'><Now /></Value></DateRangesOverlap></Where>";
$spqQuery.ExpandRecurrence = $true
$splListItems = $splList.GetItems($spqQuery)
Write-Host $splListItems.Count
One thread for your reference

TFS-2017 - Add a step to enter Username and password

I have a build that creates .zip package and projectName.SetParameters.xml i want to overide the parameters in The projectName.SetParameters.xml file with my script
I have a powershell script with Mandotary parameters, I want the user to input their username and password before they can deploy to IIS in TFS i was following this guide link
UPDATE: The REalese build works but it doesn't ask the user to input the username and password, Do i have to set them manually inside the argument box on the Powershell step?
In my TFS I Have a powershell step i added the argument -paramsFilePath C:/somepath/.../.../projectName.SetParameters.xml
param(
[string]$paramsFilePath,
[Parameter(Mandatory=$true)]
[string]$username,
[Parameter(Mandatory=$true)]
$password
)
Write-Verbose -Verbose "Entering script setParameters.ps1"
Write-Verbose -Verbose ("Path to Parameters: {0}" -f $paramsFilePath)
# get the environment variables
$vars = Get-ChildItem -path env:*
# read in the setParameters file
$contents = Get-Content -Path $paramsFilePath
# perform a regex replacement
$newContents = "";
$contents | % {
$line = $_
if ($_ -match "__Username__") {
$setting = Get-ChildItem -path env:* | ? { $_.Name -eq $Matches[1] }
if ($setting) {
Write-Verbose -Verbose ("Replacing key {0} with value from environment" -f $username.Name)
$line = $_ -replace "__Username__", $username.Value
}
}
$newContents = $line
}
Write-Verbose -Verbose "Overwriting SetParameters file with new values"
Set-Content $paramsFilePath -Value $newContents
Write-Verbose -Verbose "Exiting script setParameters.ps1"
Here is my Parameters.xml code
<!--?xml version="1.0" encoding="utf-8" ?-->
<parameters>
<parameter name="machineURL" description="Please enter the name of the Environment" defaultvalue="_UrlValue_" tags="">
<parameterentry kind="XmlFile" scope="\\web.config$" match="/configuration/appSettings/add[#key='machineURL']/#value">
</parameterentry>
</parameter>
<parameter name="username" description="Please enter the username" defaultvalue="__UserName__" tags="">
<parameterentry kind="XmlFile" scope="\\web.config$" match="/configuration/appSettings/add[#key='username']/#value">
</parameterentry>
</parameter>
<parameter name="password" description="Please enter the password" defaultvalue="__Password__" tags="">
<parameterentry kind="XmlFile" scope="\\web.config$" match="/configuration/appSettings/add[#key='password']/#value">
</parameterentry>
</parameter>
</parameters>
The PowerShell execution in TFS Build and Release is only in non-interactive mode possible. The build and release process will only streams the execution result to the build console.
You have to create a variable with the username. For the password you should use hidden variable:
Yes you have to place the arguments inside the argument box of the
PowerShell step
Note: The password field seems secure and not readable but it is not really hard to read the content of a hidden variable.
Create the variables and set the values. After that you can use this command line parameter in the PowerShell step argument box.
-paramsFilePath $(paramsFilePath) -username $(username) -password $(password)

PowerShell issue when using string variable from web.config in concatenation

I have this issue with a string ($dataBaseName variable) I'm pulling from a web.config file via a function.
When I Write-Host it displays the value, and when I use GetType() it shows that it is a System.String, but it will not pull the value when concatenating with another variable. Eventually, I want to use it as a parameter to call from the module I'm writing.
Here is the code I use to get the $dataBaseName variable I'm having trouble with.
# Get WebConfig Detail
$configPath = Get-ItemProperty 'HKLM:\SOFTWARE\Wow6432NodeItem\Key\Settings' `
| Select #{Name="Path";Expression={$_.installPath + "\Item\Web.config" }} `
-ExpandProperty Path
$config = [xml](Get-Content $configPath)
function Get-WebConfigKey($key) {
$config.SelectSingleNode("//appSettings/add[#key='$key']").Value
}
# Set Database Variable
$databaseName = Get-WebConfigKey "databaseName"
Later I try to reference it by combining it with the computer variable using many different ways to concatenate it using (with (), string.format, etc.), but it will only display "ComputerName\" for the value of the $instance variable.
$computer = Get-Content env:computername
$instance = $computer + "\" + $databaseName
If I hard-code the database name it works fine.
$instance = $computer + "\" + "exampleDatabase"
I'm using the information to an SQL query as below. I'm actually going to use a secure string for the password later, but this is for reference.
$computer = Get-Content env:computername
$instance = $computer + "\" + $databaseName
$server = new-object ('Microsoft.SqlServer.Management.Smo.Server') $instance
$server.ConnectionContext.LoginSecure=$false
$server.ConnectionContext.set_Login("sa")
$server.ConnectionContext.set_Password("examplePassword")
$db = $server.Databases.Item("Maduro")
[String] $sql = "SELECT SomeRow FROM SomeTalbe;"
$result = $db.ExecuteWithResults($sql)
$table = $result.Tables[0]
foreach ($row in $table) {
$someVarible = $row.SomeRow
}
Web.config excerpt:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<!--NEXT GEN EF DB INFO-->
<add key="providerName" value="System.Data.SqlClient" />
<add key="serverName" value="LOCALHOST\Instance" />
<add key="databaseName" value="database" />
</appSettings>
</configuration>

Trying to get log4net working with PowerShell (with a log4net config file in the mix)

I have been struggling with getting log4net working with PowerShell. I have the following PowerShell code that pulls in log4net with a configuration file and then attempts to make a simple log file entry but which errors out.
Clear-History
Clear-Host
#
Write-Host "BEGIN: Importing module psm_logger.psm1"
Import-Module "C:\Users\Administrator\Desktop\ps\IIS\psm_logger.psm1" -Force
Write-Host "BEGIN: log4net configuration definition"
$log = New-Logger -Configuration "C:\Users\Administrator\Desktop\ps\IIS\logging\log4net.config" -Dll "C:\Users\Administrator\Desktop\ps\IIS\logging\log4net.dll"
Write-Host "END: log4net configuration definition"
Write-Host "BEGIN: log4net configuration DEBUG definition"
#$log.DebugFormat("Logger configuration file is : '{0}'", (Resolve-Path "C:\Users\Administrator\Desktop\ps\IIS\logging\log4net.config"))
Write-Host "END: log4net DEBUG configuration definition"
#======================
$ThisHostname = $env:COMPUTERNAME
#======================
Write-Host "BEGIN: Module/Snapin import/addition"
Write-Host ""
$log.Info("BEGIN: Module/Snapin import/addition")
#======================
The above referenced psm_logger.psm1 file contains:
function New-Logger
{
#Write-Host "BEGIN: New-Logger"
<#
.SYNOPSIS
This function creates a log4net logger instance already configured
.OUTPUTS
The log4net logger instance ready to be used
#>
[CmdletBinding()]
Param
(
[string]
# Path of the configuration file of log4net
$Configuration,
[Alias("Dll")]
[string]
# Log4net dll path
$log4netDllPath
)
Write-Verbose "[New-Logger] Logger initialization"
$log4netDllPath = Resolve-Path $log4netDllPath -ErrorAction SilentlyContinue -ErrorVariable Err
if ($Err)
{
throw "Log4net library cannot be found on the path $log4netDllPath"
}
else
{
Write-Verbose "[New-Logger] Log4net dll path is : '$log4netDllPath'"
[void][Reflection.Assembly]::LoadFrom($log4netDllPath) | Out-Null
# Log4net configuration loading
$log4netConfigFilePath = Resolve-Path $Configuration -ErrorAction SilentlyContinue -ErrorVariable Err
if ($Err)
{
throw "Log4Net configuration file $Configuration cannot be found"
}
else
{
Write-Verbose "[New-Logger] Log4net configuration file is '$log4netConfigFilePath' "
$FileInfo = New-Object System.IO.FileInfo($log4netConfigFilePath)
[log4net.Config.XmlConfigurator]::Configure($FileInfo)
$script:MyCommonLogger = [log4net.LogManager]::GetLogger("root")
Write-Verbose "[New-Logger] Logger is configured"
return $MyCommonLogger
}
}
}
The configuration file for log4net looks like:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" **requirePermission="false"**/>
</configSections>
<log4net>
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
<param name="File" value="C:\Users\Administrator\Desktop\ps\IIS\LOGS\LogTest2.txt" />
<param name="AppendToFile" value="true" />
<layout type="log4net.Layout.PatternLayout">
<param name="Header" value="[Header]\r\n" />
<param name="Footer" value="[Footer]\r\n" />
<param name="ConversionPattern" value="%d [%t] %-5p %c %m%n" />
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="LogFileAppender" />
</root>
</log4net>
</configuration>
When run the output AND error produced is:
BEGIN: Importing module psm_logger.psm1
BEGIN: log4net configuration definition
END: log4net configuration definition
BEGIN: log4net configuration DEBUG definition
END: log4net DEBUG configuration definition
BEGIN: Module/Snapin import/addition
Method invocation failed because [System.Object[]] doesn't contain a method named 'Info'.
At C:\Users\Administrator\Desktop\ps\IIS\IIS_localLogs.ps1:18 char:10
+ $log.Info <<<< ("BEGIN: Module/Snapin import/addition")
+ CategoryInfo : InvalidOperation: (Info:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Any help would be greatly appreciated!
(FYI: I originally got this code from a best practices blog entry here: http://blog.octo.com/en/powershell-v2-my-best-practices/ which I found very helpful)
Found the solution...
The config file was corrupted by the presence of some asterisks towards the top. Removing those fixed the issue. Thank you to anybody who may have started to look at this and I hope this helps somebody else in the future.
The configuration file now looks like:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" requirePermission="false"/>
</configSections>
<log4net>
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
<param name="File" value="C:\Users\Administrator\Desktop\ps\IIS\LOGS\LogTest2.txt" />
<param name="AppendToFile" value="true" />
<layout type="log4net.Layout.PatternLayout">
<param name="Header" value="[Header]\r\n" />
<param name="Footer" value="[Footer]\r\n" />
<param name="ConversionPattern" value="%d [%t] %-5p %c %m%n" />
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="LogFileAppender" />
</root>
</log4net>
</configuration>
New-Logger is such a useful cmdlet, it's worth updating for newer versions of Powershell. psm_logger.psm1 currently gives a System.Void error under PS V3 and later. Changing the assembly load to
[Reflection.Assembly]::LoadFrom($log4netDllPath) | Out-Null
without the [Void] sorts out the problem.