I am working on a powershell script that will create TFS build definitions. I have used below example as my starting point.
http://geekswithblogs.net/jakob/archive/2010/04/26/creating-a-build-definition-using-the-tfs-2010-api.aspx
I have the script done in powershell and it creates me a build definition file in TFS. One thing I am stuck in is creating Process information such as "Item to build" and "Projects to build". The C# code for this is given below
//Set process parameters
varprocess = WorkflowHelpers.DeserializeProcessParameters(buildDefinition.ProcessParameters);
//Set BuildSettings properties
BuildSettings settings = newBuildSettings();
settings.ProjectsToBuild = newStringList("$/pathToProject/project.sln");
settings.PlatformConfigurations = newPlatformConfigurationList();
settings.PlatformConfigurations.Add(newPlatformConfiguration("Any CPU", "Debug"));
process.Add("BuildSettings", settings);
buildDefinition.ProcessParameters = WorkflowHelpers.SerializeProcessParameters(process);
Below is the powershell code I have written to achive above.
Write-Host"Set process parameters "$now
$process=[Microsoft.TeamFoundation.Build.Workflow.WorkflowHelpers]::DeserializeProcessParameters($def.ProcessParameters)
Write-Host"Set build settings properties "$now
$settings=new-object-`enter code here`TypeNameMicrosoft.TeamFoundation.Build.Workflow.Activities.BuildSettings
$sList=New-Object-TypeNameMicrosoft.TeamFoundation.Build.Workflow.Activities.StringList
$sList="$/pathToProject/project.sln"
$settings.ProjectsToBuild =$sList
$process.Add("BuildSettings", $sList)
But the above segment of code does not create me the Build settings in my build definition file. Myquestion is am I doing this the correct way in powershell? I feel I am not writing the powershell code incorrectly as I am newbie to powershell. Any guidance and
help would be appreciated
Calling a constructor with parameters should be done like this in PowerShell:
$ns = 'Microsoft.TeamFoundation.Build.Workflow.Activities'
$settings.ProjectsToBuild = new-object "$ns.StringList" '$/pathToProject/project.sln'
Also note the use of single quotes around the TF server path. $ is s special character in PowerShell - tells it what follows is either a variable name or sub-expression even in a string. Unless that string is single quoted. In which case, PowerShell doesn't interpret any special characters within the string.
Related
I have a PowerShell script that reads a register.psd1 file with contents as below.
#{
# Building Zig compiler
zig = #{
name = "zig"
path = ./python/buildzig.py
language = "Python"
os = "all"
}
# Building Windows Terminal for Windows 10.
windowsterminal = #{
name = "WindowsTerminal"
path = ./powershell/msterminal.ps1
language = "Python"
os = "windows"
}
}
I read the file using the following command.
Import-PowerShellDataFile -Path register.psd1
After running the script I get the following error message.
Import-PowerShellDataFile : Cannot generate a PowerShell object for a ScriptBlock evaluating dynamic expressions.
What am I doing wrong and what is the possible solution?
*.psd1 files contain PowerShell hashtable literals and therefore require the same syntax as when defining such literals in code:
Therefore, if you want to create an entry with key path that contains the string literal ./python/buildzig.py (or ./powershell/msterminal.ps1), you must quote it - either form is OK here:
path = '.\powershell\msterminal.ps1'
path = ".\powershell\msterminal.ps1"
However, given that in the context of a *.psd1 file you're virtually limited to literal values, use of '...' (single quotes) makes more sense (see about_Quoting_Rules).
As for what you tried:
A hashtable entry such as path = ./python/buildzig.py attempts to create an entry with key path and the value that is the result of executing file ./python/buildzig.py, because - in the absence of quoting - the token is interpreted as a command (see about_Parsing to learn about how PowerShell parses commands and expressions).
The - unfortunately vague - error message you saw (Cannot generate a PowerShell object for a ScriptBlock evaluating dynamic expressions.), stems from the fact that for security reasons, executing commands isn't permitted in *.psd1 files, which are (mostly[1]) limited to defining literal values.
[1] You can use the following "variables", which in effect are constants: $true, $false, $null. Additionally, depending on the purpose of the *.psd1 file, a select few additional automatic variables are permitted: $PSCulture and $PSUICulture, except in files to be read by Import-PowerShellDataFile, and, additionally, $PSScriptRoot, $PSEdition, and $EnabledExperimentalFeatures in module manifests - see about_Language_Modes.
I have just added ' ' for the path parameters as following after that the error was gone. hope this is the output you wanted.
path = '.\powershell\msterminal.ps1'
I want to use a variable which is composed of another vsts variable and text, for instance:
vnetname = $vnet_prefix + "vnetid"
However i get an error saying that "A positional parameter cannot be found that accepts argument +.
Anyone advise?
If you mean use the variable in build/release processes, then you can add a variable like this (reference below screenshot):
vnetname = $(vnet_prefix)_vnetid
Then you can use the variable $vnetname or $(vnetname) directly, see Build variables-Format for how to use the variables in different tools.
Alternatively you can pass the value with Logging Commands:
Copy and paste below strings then save as *.ps1 file:
$value = $env:vnet_prefix + "vnetid"
Write-Host "##vso[task.setvariable variable=vnetname]$value"
Check in the PS file
Add a PowerShell task to run the PS file
Use the variable $vnetname in later steps
I am using WinSCP to write to connect a SQL Server to an SFTP server. I am trying to write a file to an SFTP server where I only have write access, not modify. I am having a problem because I get back
Cannot create remote file '/xxx.filepart'.
The documentation suggests this is because I do not have modify access to the target directory. I did this WinSCP -> Preferences -> Endurance -> Disable
I checked the winscp.ini file and ResumeSupport is 2 (I believe this means disabled). I ran "echo $transferOptions.ResumeSupport" and it says that it is in a default state.
I have checked this documentation:
https://winscp.net/eng/docs/ui_pref_resume
https://winscp.net/eng/docs/library_transferoptions#resumesupport
However, I don't see a PowerShell example, just C#.
I have tried various permutations of $transferOptions.ResumeSupport.State = Off, $transferOptions.ResumeSupport.Off, and whatnot. One of these says that it's read-only.
I know $transferOptions is a variable here but it comes from the default script. The object determines transfer options $transferOptions = New-Object WinSCP.TransferOptions
Thanks in advance for help
edit: The overall problem is I only have write access to the server, but not modify. I am getting a new error: "Cannot overwrite remote file '/xxx'.$$. It looks like the dollar signs are some sort of temp file that it's trying to create. Is there a way to disable whatever setting is causing this?
Syntax for using an enumeration in PowerShell is described in
the article Using WinSCP .NET assembly from PowerShell.
Enumeration values are accessed using static field syntax [Namespace.Type]::Member, for example [WinSCP.Protocol]::Sftp.
You can find a PowerShell example for TransferResumeSupport.State in Converting to .NET assembly section of get and put command documentation:
$transferOptions = New-Object WinSCP.TransferOptions
$transferOptions.ResumeSupport.State = [WinSCP.TransferResumeSupportState]::Off
$session.GetFiles(..., ..., $False, $transferOptions).Check()
WinSCP GUI can also generate a code template (including TransferOptions and TransferResumeSupportState code) for you.
So I have created a build process template in TFS 2012 that has to pass a path name to a Powershell Script, which in turn concatenates files in the specified directory.
Some of these path names might have two consecutive spaces, which has turned out to be a problem.
When I invoke the powershell script, I enclose the path name in single quotes, and the command that is executed looks something like this.
powershell C:\psScript.ps1 'C:\tmp\two spaces\myFolder'.
However, when I try and open the directory in Powershell, I get the following error:
Get-Item : Cannot find path 'C:\tmp\two spaces\myFolder'
because it does not exist.
The two spaces seem to have become one, and the path can't be found.
Does anyone know what might be causing this?
I have a TFS 2010 build which calls a powershell script for deployment. I've defined several arguments for the build script and these have worked great. They are used by the build and also included in the arguments that are passed into Powershell via the Arguments property of the InvokeProcess control.
I now have a requirement for the powershell script to deploy to a variable number of servers, so I'd like to pass the server ID's in on the argument list from TFS.
In the build definition, I have declared a new argument called TargetServers of type string[]. I have populated this from the Build Process Parameters dialog prior to executing a build.
I have set the FileName property of the InvokeProcess control to "Powershell", and the Arguments property as follows:
String.Format(" ""& '{0}' '{1}' '{2}' '{3}' '{4}' '{5}' '{6}' '{7}' '{8}' '{9}' "" ", DeploymentScriptFileName, IO.Path.GetDirectoryName(DeploymentScriptFileName), "ExecuteBizTalkAppMSI.ps1", MSIFileName, BTDFFilename, TargetServerPath, TargetServers, ServerDeploymentFolder, InstallFolder, HostInstanceFilter, ApplicationName)
My problem is that the TargetServers argument being passed to Powershell is simply System.String[].
From the build log I can see the following output of the Invoke Process control:
Powershell "& 'C:\Builds\3\x.Int.MIS.Deployment\CopyDeployScriptThenExecute.ps1'
'C:\Builds\3\\x.Int.MIS.Deployment' 'ExecuteBizTalkAppMSI.ps1'
'x.Int.MIS-3.0.0.msi' 'x.Int.MIS.Deployment.btdfproj'
'\\d-vasbiz01\BizTalkDeployment' 'System.String[]' 'c:\BizTalkDeployment'
'c:\Program Files (x86)\x.Int.MIS for BizTalk 2010\3.0' 'BTSSvc*MIS*' "
Can anyone please advise how to pass the array?
As strings delimited by commas:
PS> function foo([string[]]$x){$x}
PS> foo a,2,3
a
2
3
If you want, you can put quotes around each individual item but you don't need to unless they contain spaces or other characters reserved for the syntax.