I'm using the following code to generate a coverage report from a powershell script task in TFS 2015's Build Preview. I can run it on the build server and it generates the report correctly, but when it runs as part of the build it complains that there are no pdb files.
No results, this could be for a number of reasons. The most common
reasons are:
1) missing PDBs for the assemblies that match the filter please review the output file and refer to the Usage guide (Usage.rtf) about filters.
2) the profiler may not be registered correctly, please refer to the Usage guide and the -register switch.
After doing a bit of Googling I discovered that /noshadow should have been enough, but it seems that the parameters for nunit are getting ignored. I'm assuming they're being ignored because the /nologo command should be stripping out the copyright info from being printed, but in the console output I can still see the information being displayed.
Also using the build output directory as the working directory should have fixed this as well, but using Set-Location didn't resolve the problem during the build.
This is the script that I'm currently running:
Param
(
[string] $SourceDir = $env:BUILD_SOURCESDIRECTORY,
[string] $UnitTestDir = "",
[string] $UnitTestDll ="",
[string] $Filter = "",
[string] $ExcludeByAttribute = "System.CodeDom.Compiler.GeneratedCodeAttribute",
[string] $nUnitOutputPath = "Output.txt",
[string] $nUnitErrorOutputPath = "Error.text",
[string] $XmlOutputPath = "_CodeCoverageResult.xml",
[string] $ReportOutputPath = "_CodeCoverageReport"
)
$openCoverPath = "E:\BuildTools\OpenCover.4.5.3723\OpenCover.Console.exe"
$nUnitPath = "E:\BuildTools\NUnit.Runners.2.6.4\tools\nunit-console.exe"
$reportGeneratorPath = "E:\BuildTools\ReportGenerator.2.1.1.0\ReportGenerator.exe"
$nUnitArgs = "$SourceDir\$UnitTestDir\$UnitTestDll /noshadow /nologo"
Write-Host "[Debug] Setting location to $SourceDir\$UnitTestDir"
Set-Location $SourceDir\$UnitTestDir
if (!(Test-Path $SourceDir\CodeCoverage)) {
New-Item $SourceDir\CodeCoverage -type directory
}
Write-Host "[Debug] Running unit tests from $SourceDir\$UnitTestDir\$UnitTestDll"
Write-Host "[Debug] Command: $openCoverPath -target:$nUnitPath -targetargs:""$nUnitArgs"" -filter:$Filter -excludebyattribute:$ExcludeByAttribute -register:user -output:""$SourceDir\CodeCoverage\$XmlOutputPath"""
& $openCoverPath -target:$nUnitPath -targetargs:"$nUnitArgs" -filter:$Filter -excludebyattribute:$ExcludeByAttribute -register:user -output:"$SourceDir\CodeCoverage\$XmlOutputPath"
Write-Host "[Debug] Generating report"
Write-Host "[Debug] Command: $reportGeneratorPath ""-reports:$SourceDir\CodeCoverage\$XmlOutputPath"" ""-targetdir:$SourceDir\CodeCoverage\$ReportOutputPath"""
& $reportGeneratorPath -reports:$SourceDir\CodeCoverage\$XmlOutputPath -targetdir:$SourceDir\CodeCoverage\$ReportOutputPath
Write-Host "[Debug] Finished running tests and generating report"
You probably need to wrap your nunit args in quotes using `"
& $openCoverPath -target:$nUnitPath -targetargs:"`"$nUnitArgs`"" -filter:$Filter -excludebyattribute:$ExcludeByAttribute -register:user -output:"$SourceDir\CodeCoverage\$XmlOutputPath"
There is a fix in OpenCover for the next release which will detect when you are passing unrecognized arguments to OpenCover
Related
We have multiple systems with the same Dell program but different versions. The version number is the same but one is in the x86 folder and the other is in the x64 one as shown below. Could someone help me convert this to a command line or PowerShell script so that it would correctly from whichever location exists? It should only exist in one of the two locations and only needs to be run once.
Dell Command | Update
"%ProgramFiles%\Dell\CommandUpdate\dcu-cli.exe" /configure -updatetype=bios,firmware,driver,application,utility,others
"%ProgramFiles%\Dell\CommandUpdate\dcu-cli.exe" /applyupdates -reboot=enable -autosuspendbitlocker=enable
Dell Command | Update for Windows Universal
%programfiles(x86)%\Dell\CommandUpdate\dcu-cli.exe" /configure -updatetype=bios,firmware,driver,application,utility,others
%programfiles(x86)%\Dell\CommandUpdate\dcu-cli.exe" /applyupdates -reboot=enable -autosuspendbitlocker=enable
Using PowerShell, iterate over the paths and use Test-Path to make sure the path exists:
$possiblePaths =
"$env:ProgramFiles\Dell\CommandUpdate\dcu-cli.exe",
"${env:ProgramFiles(x86)}\Dell\CommandUpdate\dcu-cli.exe"
$correctPath = foreach( $path in $possiblePaths ) {
if( Test-Path -PathType Leaf $path ) {
$path
break
}
}
if( !$correctPath ) {
throw "Could not find dcu-cli.exe at any of the following paths: $(#( $possiblePaths ) -join ', ')"
}
# Execute found binary
& $correctPath /configure -updatetype='bios,firmware,driver,application,utility,others'
After the loop, check that $correctPath doesn't have a "falsey" evaluation (in this case, not $null or [string]::Empty). If it evaluates to $False, the file was not found in any of the possible locations, and we throw an error.
To execute, use the call-operator & to execute the path stored in $correctPath. You can include any parameters after this as if you were invoking the binary by literal name instead of as a variable. The sample above uses one of your argument strings from the question as an example.
I am distributing several powershell scripts to various machines and want to make sure it is executable and does not contain any errors before uploading the new version to our distribution system.
How can I solve this with Gitlab .gitlab-ci.yml?
I have found a solution for my issue. This step in the build process checks the Powershell script and aborts the build if there are any errors.
gitlab-ci.yml
stages:
- validate
validate_script:
stage: validate
image:
name: "mcr.microsoft.com/powershell:ubuntu-20.04"
script:
- pwsh -File validate.ps1
tags:
- docker
validate.ps1
Write-Host "Install PSScriptAnalyzer"
Install-Module PSScriptAnalyzer -Scope CurrentUser -Confirm:$False -Force
Write-Host "Check mypowershell.ps1"
$result = Invoke-ScriptAnalyzer -Path 'src/mypowershell.ps1'
if ($result.Length -gt 0) {
Write-Host "Script Error"
Write-Host ($result | Format-Table | Out-String)
exit 1;
}
Not sure if this is what you are looking for or if it applies at all to .yml files as I'm not familiar with them, but for powershell script files you can use the creation of [scriptblock] to check for syntax and other compile errors. You can create a function with this code and pass in powershell script files to it which can take the code, try to compile it, and return any exceptions encountered.
# $code = Get-Content -Raw $file
$code = #"
while {
write-host "no condition set on while "
}
do {
Write-Host "no condition set on unitl "
} until ()
"#
try {
[ScriptBlock]::Create($code)
}
catch {
$_.Exception.innerexception.errors
}
Output
Extent ErrorId Message IncompleteInput
------ ------- ------- ---------------
MissingOpenParenthesisAfterKeyword Missing opening '(' after keyword 'while'. False
MissingExpressionAfterKeyword Missing expression after 'until' in loop. False
I also recommend looking into Pester for testing scripts. If you are unfamiliar it is a testing and mocking framework for Powershell code
I am tasked with writing a PowerShell script to download the latest source code for a given branch, rebuild it and deploy it. The script I've written, is able to download projects, and in most cases has been able to rebuild them. But with one web project I get this error:
error : This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is ..\packages\Microsoft.Net.Compilers.2.0.1\build\Microsoft.Net.Compilers.props.
I've researched if PowerShell has a Update-Package command like the one available in the VS command prompt but have been unable to find the equivalent.
I know there's a cmdlet for Packages but from what I've seen they're used to update a specific package...what I need is to be able to have it download/update all packages referenced in the project.
Some points that might be of interest...
When I get latest on the solution to a new empty folder, the only thing in the packages folder is Modernizr.2.6.2. This is the same whether I'm getting latest in VS or in my PowerShell script.
If I open the solution within VS 2017, I am able to rebuild the solution with no problems. It downloads/installs over a dozen other packages...one of which is the Microsoft.Net.Compilers.props package referred to in the error message.
But if I delete everything and re-download the source code and then through my PowerShell script I call MSBuild to rebuild the solution I get the error mentioned above. It never seems to download/install the missing packages.
Anyone have any ideas how I can use MSBuild within my PowerShell script to rebuild the project and have it automatically update/install any packages it needs?
Thanks
I was able to find a solution to my problem on this page :Quickly Restore NuGet Packages With PowerShell
On that page is a script that uses Nuget.exe to download the packages based on the packages.config:
#This will be the root folder of all your solutions - we will search all children of
this folder
$SOLUTIONROOT = "C:\Projects\"
#This is where your NuGet.exe is located
$NUGETLOCATION = "C:\Projects\NuGet\NuGet.exe"
Function RestoreAllPackages ($BaseDirectory)
{
Write-Host "Starting Package Restore - This may take a few minutes ..."
$PACKAGECONFIGS = Get-ChildItem -Recurse -Force $BaseDirectory -ErrorAction SilentlyContinue | Where-Object { ($_.PSIsContainer -eq $false) -and ( $_.Name -eq "packages.config")}
ForEach($PACKAGECONFIG in $PACKAGECONFIGS)
{
Write-Host $PACKAGECONFIG.FullName
$NugetRestore = $NUGETLOCATION + " install " + " '" + $PACKAGECONFIG.FullName + "' -OutputDirectory '" + $PACKAGECONFIG.Directory.parent.FullName + "\packages'"
Write-Host $NugetRestore
Invoke-Expression $NugetRestore
}
}
RestoreAllPackages $SOLUTIONROOT
Write-Host "Press any key to continue ..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
I modified and added this function to my PS script and call it first to download all the packages and that does the job!
You need to call the restore target of MSBuild to download NuGet packages. You can do that by running something like:
git clone [your repo]
cd [your repo]
msbuild /target:Restore [Your Solution]
msbuild [Your Solution]
function buildVS
{
param
(
[parameter(Mandatory=$true)]
[String] $path,
[parameter(Mandatory=$false)]
[bool] $nuget = $true,
[parameter(Mandatory=$false)]
[bool] $clean = $true
)
process
{
$msBuildExe = 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin\MSBuild.exe'
if ($nuget) {
Write-Host "Restoring NuGet packages" -foregroundcolor green
& "$($msBuildExe)" "$($path)" /p:Configuration=Release /p:platform=x64 /t:restore
}
if ($clean) {
Write-Host "Cleaning $($path)" -foregroundcolor green
& "$($msBuildExe)" "$($path)" /t:Clean /m
}
Write-Host "Building $($path)" -foregroundcolor green
& "$($msBuildExe)" "$($path)" /t:Build /p:Configuration=Release /p:platform=x64
}
}
I'm trying to create a .exe file that will run a powershell script that I have to install various components of an application. I'm working on step 1 of 4 to get this entire application installed and want to get it into one package. Things are not going well with it. I am using Ps1 to Exe by f2ko. There is no documentation that I can find on the software, but it does what I want it to. The issue is in the packaged files and how it is run. I am running into a couple issues. The primary issue seems to be with Start-Process, When the exe is running I get an error that states
Start-Process : This command cannot be run completely because the system cannot find all the information required.
At C:\Users\adminjp\AppData\Local\Temp\2605.tml\2606.tmp\2607.ps1:9 char:16
The remainder of the error is obscured by a status bar for the installer. The status bar runs, but the process does not. I initially had an issue with ExecutionPolicy but that is rectified by manually changing the value in order to run the script. I have been having multiple issues getting this script to run and am running out of articles online that I haven't read. Here is my powershell script:
Set-ExecutionPolicy -Force remotesigned
$NETfile = "env:p2eincfilepath\1 - NDP471-KB4033342-x86-x64-AllOS-ENU.exe"
$NETargs = "/q"
$SQLfile = "env:p2eincfilepath\setup.exe"
$SQLargs = "/ConfigurationFile=`".\ConfigurationFile_SQLExpress.ini`""
function Show-Progress ($file, $arguments, $component){
$process = Start-Process $file $arguments -PassThru
for($i = 0; $i -le 100; $i = ($i + 1) % 100)
{
Write-Progress -Activity "Installer" -PercentComplete $i -Status "Installing $component"
Start-Sleep -Milliseconds 100
if ($process.HasExited) {
Write-Progress -Activity "Installer" -Completed
break
}
}
}
Show-Progress $NETfile $NETargs ".NET 4.7.2"
Show-Progress $SQLfile $SQLargs "SQL Express"
The program that converts this script to an exe is what sets the extraction location and, to the best of my knowledge, I have no way to set that. Attached is a screenshot of their explanation of how to reference the embeded files:
I am using env:p2eincfilepath because that is the powershell method of accessing environment variables and the application appears to create or use an environment variable. Please let me know if there is any other information you might need. The Ps1 appears to work correctly if I run it directly from powershell and put the files in the root directory, calling them with ./ I would really like to keep this function in use since this is what gives me my status bar letting the user know what is being installed:
I think you need to have a $ sign in front of the env variable for it to fill in. e.g.
$NETfile = "$env:p2eincfilepath\1 - NDP471-KB4033342-x86-x64-AllOS-ENU.exe"
$NETargs = "/q"
$SQLfile = "$env:p2eincfilepath\setup.exe"
$SQLargs = "/ConfigurationFile=`".\ConfigurationFile_SQLExpress.ini`""
I have the following PowerShell script for building a VS solution. This works, however, what I need to test is whether the build succeeded or failed. How can I tell if the build failed or not from within the PS script?
CODE
[string] $res = $null
$log = "buildlog.txt"
$DevenvExe = 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE\devenv.exe'
$MsBuildExe = 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\msbuild.exe'
$SolutionPath = ".\MyLocalSolution.sln"
#... There's some code here...
###########################
# BRANCH - ATTEMPT COMPILE
###########################
$res = & $DevenvExe $SolutionPath /upgrade /out $res
LogError
$res = & $MsBuildExe $SolutionPath /p:Configuration=Release /nr:false /m:4
LogError
NOTE: LogError is a function that checks the $res value. If $res is empty, it's considered there isn't an error. This is setup for some commands that happen above the build. Of course, I can change how the building process checks for errors. In fact, that's what I'm asking. Currently $res is filled with successful build details. I'd rather find a way to check and see if there were any build errors.
Check $LASTEXITCODE for a suitable exit code. Typically this will be 0 on success.
$res = & $DevEnvExe $arguments
if ( $LASTEXITCODE -ne 0 ) {
LogError
}
$res = & $MsBuildExe $arguments
if( $LASTEXITCODE -ne 0 ) {
LogError
}
This can be extended to check the result of any program run from Powershell, not just devenv or msbuild. Though you will need to understand which exit codes mean success, warnings, or other conditions you may still want to consider a success.