How to get Build Successes details including Associated Changes and Associated Work Items from TFS 2015 in .txt file? Which API should I have to use - tfs-2015

TFS build successes URL
I have to write AssocoatedChanges and Associated WorkItems in txt file after build success. Team foundation providing any API which will give build details response?

You can use the REST API to get build details including Associated Changes and Associated Work Items:
Associated Changes:
GET https://{instance}/DefaultCollection/{project}/_apis/build/builds/{buildId}/changes?api-version={version}
Associated Work Items:
POST https://{instance}/DefaultCollection/{project}/_apis/build/builds/{buildId}/workitems?api-version={version}
Please see Get build details for details.
UPDATE:
You can use below PowerShell script to get the build details including Associated Changes and Associated Work Items from TFS 2015 in .txt file (Just specify the correct parameters):
Param(
[string]$collectionurl = "http://server:8080/tfs/defaultcollection",
[string]$project = "0323ScrumTFVC",
[string]$BuildID = "1",
[string]$user = "username",
[string]$token = "password",
[string]$FilePath = 'C:\temp.txt'
)
# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
#BaseUrl
$WITbaseUrl = "$collectionurl/$project/_apis/build/builds/$($BuildID)/workitems"
$ChangebaseUrl = "$collectionurl/$project/_apis/build/builds/$($BuildID)/changes"
#Response
$WITresponse = (Invoke-RestMethod -Uri $WITbaseUrl -Method Get -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}).value
$Changeresponse = (Invoke-RestMethod -Uri $ChangebaseUrl -Method Get -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}).value
#Output the Associated Work items to a text file.
$WITrequests = #()
foreach($WITrequest in $WITresponse){
$customObject = new-object PSObject -property #{
"WorkitemID" = $WITrequest.id
"WorkitemURL" = $WITrequest.url
}
$WITrequests += $customObject
}
$WITrequests | Select `
WorkitemID,
WorkitemURL | Out-File -FilePath $FilePath -Width 200
#Output the Associated Changes to the text file.
$Changerequests = #()
foreach($Changerequest in $Changeresponse){
$customObject = new-object PSObject -property #{
"ChangesetID" = $Changerequest.id
"Comments" = $Changerequest.message
"Author" = $Changerequest.author.uniqueName
"Timestamp" = $Changerequest.timestamp
"Location" = $Changerequest.location
}
$Changerequests += $customObject
}
$Changerequests | Select `
ChangesetID,
Comments,
Author,
Timestamp,
Location | Out-File -FilePath $FilePath -Width 200 -Append # (with -Append, the contents will increment to txt file )

Related

how to increment and save variable in azure devops pipeline

Anyone know how can I increment the value of a variable under some conditions, (for example only if the pipeline succeeded) and save it for next build?
Example:
I set a variable: number=5.
If the pipeline succeeded and job number 2 ran, I want number=6 on the next build.
Is this possible?
You can set the value of your variable by using following command:
Bash
echo "##vso[task.setvariable variable=number;]newValue"
PowerShell
Write-Host "##vso[task.setvariable variable=number;]newValue"
Basically, your number will be set to the newValue after running this command.
how to increment and save variable in azure devops pipeline
Since you could not use the counter, you could try to use the REST API Definitions - Update to update the variable:
PUT https://dev.azure.com/{organization}/{project}/_apis/build/definitions/{definitionId}?api-version=5.0
The test scripts:
$url = "https://dev.azure.com/{organization}/{project}/_apis/build/definitions/{definitionId}?api-version=6.0"
Write-Host "URL: $url"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"
$counter = [int]$pipeline.variables.Test.value
$counter++
$pipeline.variables.Test.value = $counter
####****************** update the modified object **************************
$json = #($pipeline) | ConvertTo-Json -Depth 99
$updatedef = Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
write-host "=========================================================="
Write-host "The value of Varialbe 'Test' is updated to" $updatedef.variables.Test.value
Note: We neeed to declare the variable type as int before we can use ++
$counter = [int]$pipeline.variables.Test.value
$counter++
If you met any premission issue, please refer this thead for some more details.

Powershell way to send email with query result in SQL server

Currenly, I am working to setup a powershell job in SQL server to send database mail for some results in a table format. Here is my script:
$SMTPProperties = #{
To = "abc#abc.com.hk","test#test.com"
Cc = "xyz#xyz.com"
From = "test#abc.com.hk"
Subject = "SQL Report Status"
SMTPServer = "192.168.xx.xx"
}
$server = "192.168.xx.xx"
$database = "DBName"
$username = "abc"
$password = "abc124"
$query = "select top 10* from testing"
function ExecuteSqlQuery ($Server, $Database, $query) {
$Connection = New-Object System.Data.SQLClient.SQLConnection
$Connection.ConnectionString = "server='$Server';database='$Database';User ID='$username'; Password='$password';trusted_connection=true;"
$Connection.Open()
$Command = New-Object System.Data.SQLClient.SQLCommand
$Command.Connection = $Connection
$Command.CommandText = $query
$Reader = $Command.ExecuteReader()
$Datatable = New-Object System.Data.DataTable
$Datatable.Load($Reader)
$Connection.Close()
return $Datatable
}
$resultsDataTable = New-Object System.Data.DataTable
$resultsDataTable = ExecuteSqlQuery $Server $Database $query
Send-MailMessage #SMTPProperties -Body $query -BodyAsHTML | Format-Table
A few questions comes:
1. In #SMTPProperties, how can I send to multiple recipients? Solved
2. The script works but in content of the received email, it simply returns
text of the query (select top 10* from testing). It is not the
query result.
3. Is my script correct to output a HTML table in the email
content? If not , how can I change it?
4. How can I run above without provide UID and Password in above script.
Thank you.
For more recipients you can use Cc field
I use this for sending mails for my Powershell scripts.
Send-MailMessage `
-Credential $anonCredentials `
-From FromMailAddress#Domain.com `
-To MainMailAddress#Domain.com `
-Cc "FirstRecipient#Domain.com","SecondRecipient#Domain.om","ThirdRecipient#Domain.com" `
-Subject "Enter your subject" -Body "This is an automated message from the server with some data" `
-SmtpServer 192.168.x.x `
-Attachments "C:\ThedataIwanttosend.rar"
If you try to export your report in an html file or something else and then mail it to those that must receive it? does this solution works for you? if you run your script you have any results?
You are setting $Query to a text and then you never update with something new.
your -body takes $query as text so it is right to get that text as a mail.
Send-MailMessage #SMTPProperties -Body $query -BodyAsHTML | Format-Table
Are you getting the right data from the Function you are using? if yes then you have to put those results in a variable and write that variable as a body.
now you have :
$query = "select top 10* from testing"
Send-MailMessage #SMTPProperties -Body $query -BodyAsHTML | Format-Table
so the mail you are getting gets the -body data from the $query variable that is the text you set on the $query variable.
If you want something else in that mail body you have to save it into the $query variable or create a new variable with the results and then add it to the -Body.
Hope it helps.

How to delete mail items using office 365 REST API in provided powershell script sample

I have been trying to find a solution to this problem for quite a while now and nothing I've found seems to work. I am hoping to use this script:
##-----------------------------------------------------##
## PICK AUTH Method ##
##-----------------------------------------------------##
## HARD CODING PSW ##
#$password = ConvertTo-SecureString "xxx" -AsPlainText -Force
#$cred = New-Object System.Management.Automation.PSCredential "xxx#xxx.onmicrosofot.com",$password
## USER PROMPT PSW ##
#$cred = Get-Credential
##-----------------------------------------------------##
## END PICK
##-----------------------------------------------------##
$url = "https://outlook.office365.com/api/v1.0/me/messages"
$date = "2014-11-21"
## Get all messages that have attachments where received date is greater than $date
$messageQuery = "" + $url + "?`$select=Id&`$filter=HasAttachments eq true and DateTimeReceived ge " + $date
$messages = Invoke-RestMethod $messageQuery -Credential $cred
## Loop through each results
foreach ($message in $messages.value)
{
# get attachments and save to file system
$query = $url + "/" + $message.Id + "/attachments"
$attachments = Invoke-RestMethod $query -Credential $cred
# in case of multiple attachments in email
foreach ($attachment in $attachments.value)
{
$attachment.Name
$path = "c:\Temp\" + $attachment.Name
$Content = [System.Convert]::FromBase64String($attachment.ContentBytes)
Set-Content -Path $path -Value $Content -Encoding Byte
}
}
That I found from link - TechNet Office 365 Scripts
I can get the script to work fine, it connects to mailbox and downloads the attachments for emails specified after the date variable. Problem is that I would like to run this on an hourly schedule and delete previously processed emails so that their attachments are not stripped on consecutive runs.
I've tried lots of different commands to delete the email with no success and also tried altering the $messageQuery to include only items within a specific date range but can't get anything working.
Can anyone provide the correct syntax for the delete command in powershell and an example of how to use it in this context please?
Thanks
Rich
UPDATE - I think adding in:
$query2 = $url + "/" + $message.Id
And
Invoke-RestMethod $query2 -Credential $cred -Method Delete
Is getting me closer but I now get operation timed out.
UPDATE - Full code as it stands and as requested:
##-----------------------------------------------------##
## PICK AUTH Method ##
##-----------------------------------------------------##
## HARD CODING PSW ##
$password = ConvertTo-SecureString "password" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential "email#address.co.uk",$password
## USER PROMPT PSW ##
##$cred = Get-Credential
##-----------------------------------------------------##
## END PICK
##-----------------------------------------------------##
#$url = "https://outlook.office365.com/api/v1.0/me/messages"
$url = "https://outlook.office365.com/EWS/ODATA/me/messages"
$today = Get-Date -format yyyy-MM-dd
$date = (Get-Date).AddDays(-2).ToString("yyyy-MM-dd")
## Set date and query
$messageQuery = "" + $url + "?`$select=Id&`$filter=HasAttachments eq true and DateTimeReceived lt " + $today #+ " and DateTimeReceived gt" + $date
$messages = Invoke-RestMethod $messageQuery -Credential $cred
## Loop through each results
foreach ($message in $messages.value)
{
# get attachments and save to file system
$query = $url + "/" + $message.Id + "/attachments"
$query2 = $url + "/" + $message.Id
$attachments = Invoke-RestMethod $query -Credential $cred
# in case of multiple attachments in email
foreach ($attachment in $attachments.value)
{
$attachment.Name
$path = "\\SomePath\" + $attachment.Name
$Content = [System.Convert]::FromBase64String($attachment.ContentBytes)
Set-Content -Path $path -Value $Content -Encoding Byte
}
Invoke-RestMethod $query2 -Credential $cred -Method Delete -TimeoutSec 100
}
#Move pdf files to another folder
#Move-Item '\\SomePath\*.pdf' '\\SomePath'
#Then delete any existing files from directory
#Remove-Item '\\SomePath\*'
I tried to alter the date section to allow for a start and end date so the script could be run once a day, do the extraction but not reprocess attachments from previous days but ran into issues working out the syntax to alter the $messageQuery.
Response from running the script is:
Invoke-RestMethod : The operation has timed out.
At C:\Scripts\EmailExtractServiceContract365.ps1:26 char:13
+ $messages = Invoke-RestMethod $messageQuery -Credential $cred
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
Not an answer
Use Fiddler to capture the request. Use the https://outlook.office365.com/api/v1.0/me/messages endpoint. The other one has been deprecated (I think). Post your sanitized request/response here.
Your script is probably not the problem
I got the script to work fine; it finds an email with attachment, saves the attachment, then deletes the email. I'm not sure what is going on in your environment until I see the requests (remove the auth headers if you post the request). I only changed the $today value to capture emails with attachments today.
$password = ConvertTo-SecureString "password" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential "user#contoso.com",$password
$url = "https://outlook.office365.com/api/v1.0/me/messages"
$today = (Get-Date).AddDays(1).ToString("yyyy-MM-dd")
$date = (Get-Date).AddDays(-2).ToString("yyyy-MM-dd")
## Set date and query
$messageQuery = "" + $url + "?`$select=Id&`$filter=HasAttachments eq true and DateTimeReceived lt " + $today #+ " and DateTimeReceived gt" + $date
$messages = Invoke-RestMethod $messageQuery -Credential $cred
## Loop through each results
foreach ($message in $messages.value)
{
# get attachments and save to file system
$query = $url + "/" + $message.Id + "/attachments"
$query2 = $url + "/" + $message.Id
$attachments = Invoke-RestMethod $query -Credential $cred
# in case of multiple attachments in email
foreach ($attachment in $attachments.value)
{
$attachment.Name
$path = "C:\temp\" + $attachment.Name
$Content = [System.Convert]::FromBase64String($attachment.ContentBytes)
Set-Content -Path $path -Value $Content -Encoding Byte
}
Invoke-RestMethod $query2 -Credential $cred -Method Delete -TimeoutSec 100
}
REQUEST
Here's what the request and response should look like to delete the email.
DELETE https://outlook.office365.com/api/v1.0/me/messages/AAMkADBjYXXXXXXXXXX= HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.0.10586.0
Authorization: XXXXXXXXXXXXXXXXXXXXXXXXX
Host: outlook.office365.com
Cookie: ClientId=CQA
Content-Length: 0
RESPONSE
HTTP/1.1 204 No Content

Access ASANA via windows powershell using APIKEY

I have created this following two codes in powershell to access ASANA.
But both of them dont work. I always get this error
"The remote server returned an error: (401) Unauthorized."
Any help appreciated. If you have a working C# code that can connect to any secure server with only APIKey, please post it. I could convert it to powershell code.
Code 1
Function Get-WebResponseString
{
param (
[Parameter(Mandatory=$true)]
[String]$Url,
[Parameter(Mandatory=$true)]
[String]$Method,
[Parameter(Mandatory=$false)]
[System.Net.NetworkCredential]$Credential
)
$Request = [System.Net.WebRequest]::Create($Url)
$Request.Method = $Method
$Request.ContentType = "application/x-www-form-urlencoded";
if ($Credential -ne $null)
{
$Request.Credentials = $credential
write-host "****" -foregroundcolor blue
}
$Response = $Request.GetResponse()
$StreamReader = New-Object System.IO.StreamReader $Response.GetResponseStream()
$StreamReader.ReadToEnd()
}
$Url = "https://app.asana.com/api/1.0/tasks"
$Username = "MMuthusamy#xxxxxx.xom"
$apikey="xxxxxxxxx"
$credential = New-Object System.Net.NetworkCredential #($Username, $apikey)
Get-WebResponseString -Url $Url -Credential $credential -Method "GET"
Code 2
$sha = New-Object System.Security.Cryptography.SHA1CryptoServiceProvider
$apikey="xxxxxxx"
#Add colon
$authinfo=$apikey+":";
$string1 = $authinfo
Write-Host $string1 -ForeGroundColor Green
#Encoding format
$enc = [system.Text.Encoding]::UTF8
#get bytes
$data1 = $enc.GetBytes($string1)
#Encode
$result1 = $sha.ComputeHash($data1)
#convert to 64 bit
$mykey=[System.Convert]::ToBase64String($result1)
Write-Host $mykey -ForeGroundColor Green
$url = "https://app.asana.com/api/1.0/tasks"
$url="https://app.asana.com/api/1.0/users"
$request = [System.Net.WebRequest]::Create($url)
$authorization = "Authorization: Basic " + $myKey
Write-Host $authorization -ForeGroundColor Green
$request.Headers.Add($authorization)
#$request.Headers.Add("Authorization: BASIC $mykey")
$response = $request.GetResponse()
Write-Host $Response -ForeGroundColor Green
(I work at Asana)
The 401 header is a clue that the problem lies somewhere in your authorization header.
The HTTP Basic Auth spec does not call for a SHA1 hash of the username:password. It's just straight base64 encoding of that string. Try passing $authinfo to your call to ToBase64String instead of hashed data.

Powershell using file? "being used by another process"

I have this powershell script running. The first time it runs it runs flawlessly, the second time it runs i get the error that the .csv cannont be access "because it is being used by another process. Any idea which part of the script is "holding onto" the file and how i can make it let it go at the end?
clear
set-executionpolicy remotesigned
# change this to the directory that the script is sitting in
cd d:\directory
#############################################
# Saves usernames/accountNumbers into array #
# and creates sql file for writing to #
#############################################
# This is the location of the text file containing accounts
$accountNumbers = (Get-Content input.txt) | Sort-Object
$accountID=0
$numAccounts = $accountNumbers.Count
$outString =$null
# the name of the sql file containing the query
$file = New-Item -ItemType file -name sql.sql -Force
###################################
# Load SqlServerProviderSnapin100 #
###################################
if (!(Get-PSSnapin | ?{$_.name -eq 'SqlServerProviderSnapin110'}))
{
if(Get-PSSnapin -registered | ?{$_.name -eq 'SqlServerProviderSnapin110'})
{
add-pssnapin SqlServerProviderSnapin100
Write-host SQL Server Provider Snapin Loaded
}
else
{
}
}
else
{
Write-host SQL Server Provider Snapin was already loaded
}
#################################
# Load SqlServerCmdletSnapin100 #
#################################
if (!(Get-PSSnapin | ?{$_.name -eq 'SqlServerCmdletSnapin100'}))
{
if(Get-PSSnapin -registered | ?{$_.name -eq 'SqlServerCmdletSnapin100'})
{
add-pssnapin SqlServerCmdletSnapin100
Write-host SQL Server Cmdlet Snapin Loaded
}
else
{
}
}
else
{
Write-host SQL Server CMDlet Snapin was already loaded
}
####################
# Create SQL query #
####################
# This part of the query is COMPLETELY static. What is put in here will not change. It will usually end with either % or '
$outString = "SELECT stuff FROM table LIKE '%"
# Statement ends at '. loop adds in "xxx' or like 'xxx"
IF ($numAccounts -gt 0)
{
For ($i =1; $i -le ($AccountNumbers.Count - 1); $i++)
{
$outString = $outstring + $AccountNumbers[$accountID]
$outString = $outString + "' OR ca.accountnumber LIKE '"
$accountID++
}
$outString = $outString + $AccountNumbers[$AccountNumbers.Count - 1]
}
else
{
$outString = $outString + $AccountNumbers
}
# This is the end of the query. This is also COMPLETELY static. usually starts with either % or '
$outString = $outString + "%'more sql stuff"
add-content $file $outString
Write-host Sql query dynamically written and saved to file
###########################
# Create CSV to email out #
###########################
#Make sure to point it to the correct input file (sql query made above) and correct output csv.
Invoke-Sqlcmd -ServerInstance instance -Database database -Username username -Password password -InputFile sql.sql | Export-Csv -Path output.csv
####################################
# Email the CSV to selected people #
####################################
$emailFrom = "to"
$emailTo = "from"
$subject = "test"
$body = "test"
$smtpServer = "server"
# Point this to the correct csv created above
$filename = "output.csv"
$att = new-object Net.mail.attachment($filename)
$msg = new-object net.mail.mailmessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.from = $emailFrom
$msg.to.add($emailto)
$msg.subject = $subject
$msg.body = $body
$msg.attachments.add($att)
$smtp.Send($msg)
Can you try to add at th end :
$att.Dispose()
$msg.Dispose()
$smtp.Dispose()
You could also try and use a tool like procmon and see what does the script do whenever it acquires a lock on the file and doesn't release it. Also, since (supposedly) the problem is with the .csv file, you could load it as byte array instead of passing it's path as an attachment. This way the file should be read once and not locked.