powershell - मेरे पावरहेल बाहर निकलने वाले कोड हमेशा "0" क्यों हैं?




teamcity exit-code (3)

मुझे निम्नानुसार एक पावरहेल स्क्रिप्ट मिली है

##teamcity[progressMessage 'Beginning build']
# If the build computer is not running the appropriate version of .NET, then the build will not run. Throw an error immediately.
if( (ls "$env:windir\Microsoft.NET\Framework\v4.0*") -eq $null ) {
    throw "This project requires .NET 4.0 to compile. Unfortunatly .NET 4.0 doesn't appear to be installed on this machine."
    ##teamcity[buildStatus status='FAILURE' ]
}


##teamcity[progressMessage 'Setting up variables']
# Set up varriables for build script
$invocation = (Get-Variable MyInvocation).Value
$directorypath = Split-Path $invocation.MyCommand.Path
$v4_net_version = (ls "$env:windir\Microsoft.NET\Framework\v4.0*").Name
$nl = [Environment]::NewLine

Copy-Item -LiteralPath "$directorypath\packages\NUnit.2.6.2\lib\nunit.framework.dll" "$directorypath\Pandell.Tests\bin\debug" -Force

##teamcity[progressMessage 'Using msbuild.exe to build the project']
# Build the project using msbuild.exe.
# note, we've already determined that .NET is already installed on this computer.
cmd /c C:\Windows\Microsoft.NET\Framework\$v4_net_version\msbuild.exe "$directorypath\Pandell.sln" /p:Configuration=Release 
cmd /c C:\Windows\Microsoft.NET\Framework\$v4_net_version\msbuild.exe "$directorypath\Pandell.sln" /p:Configuration=Debug

# Break if the build throws an error.
if(! $?) {
    throw "Fatal error, project build failed"
    ##teamcity[buildStatus status='FAILURE' ]
}


##teamcity[progressMessage 'Build Passed']
# Good, the build passed
Write-Host "$nl project build passed."  -ForegroundColor Green


##teamcity[progressMessage 'running tests']
# Run the tests.
cmd /c $directorypath\build_tools\nunit\nunit-console.exe $directorypath\Pandell.Tests\bin\debug\Pandell.Tests.dll

# Break if the tests throw an error.
if(! $?) {
    throw "Test run failed."
    ##teamcity[buildStatus status='FAILURE' ]   
}

##teamcity[progressMessage 'Tests passed']

जो मुझे विश्वास है, उससे एक बेकार Throw का परिणाम 1 का एक्जिट कोड होगा, लेकिन दुर्भाग्यवश टीमसिटी अन्यथा कह रही है।

[19:32:20]Test run failed.  
[19:32:20]At C:\BuildAgent\work\e903de7564e599c8\build.ps1:44 char:2  
[19:32:20]+     throw "Test run failed."  
[19:32:20]+     ~~~~~~~~~~~~~~~~~~~~~~~~  
[19:32:20]    + CategoryInfo          : OperationStopped: (Test run failed.:String) [],    
[19:32:20]   RuntimeException  
[19:32:20]    + FullyQualifiedErrorId : Test run failed.  
[19:32:20]   
[19:32:20]Process exited with code 0  
[19:32:20]Publishing internal artifacts  
[19:32:20][Publishing internal artifacts] Sending build.finish.properties.gz file  
[19:32:20]Build finished

यह भी ध्यान रखना महत्वपूर्ण हो सकता है कि मेरा Execution Mode Execute .ps1 script with "-File" arguement करने के लिए सेट है।

मैंने Put script into PowerShell stdin with "-Command -" arguements बदलने की कोशिश की लेकिन फिर यह परीक्षा उत्तीर्ण होने के साथ 1 बाहर निकलने के कोड में विफल रहा। मुझे यकीन है कि इसे चलाने के रूप में -File सही तरीका होने जा रहा है।

यदि मैं C:\BuildAgent\work\e903de7564e599c8\build.ps1 पर स्थित स्क्रिप्ट C:\BuildAgent\work\e903de7564e599c8\build.ps1 और इसे मैन्युअल रूप से सीएमडी में चलाता C:\BuildAgent\work\e903de7564e599c8\build.ps1 , तो यह वही काम करता है ... IE: असफल परीक्षण विफल हो जाते हैं, और %errorlevel% अभी भी 0

हां, अगर मैं इसे $LASTEXITCODE और $LASTEXITCODE कॉल करता $LASTEXITCODE यह हर बार सही कोड देता है।


-फाइल के साथ चलते समय मुझे यह सटीक मुद्दा था, लेकिन कुछ कारणों से केविन द्वारा प्रदान किए गए जाल सिंटैक्स या 'बाहर निकलने' वाक्यविन्यास मेरे परिदृश्य में काम नहीं कर रहा था। निश्चित नहीं है क्यों, लेकिन अगर किसी और ने एक ही समस्या को हिट किया है, तो मैंने नीचे दिए गए वाक्यविन्यास का उपयोग किया और यह मेरे लिए काम किया:

try{
    #DO SOMETHING HERE
}
catch
{
    Write-Error $_
    ##teamcity[buildStatus status='FAILURE']
    [System.Environment]::Exit(1)
}

इनमें से कोई भी विकल्प मेरे पावरहेल स्क्रिप्ट में किसी भी कारण से मेरे लिए काम नहीं करता है। मैंने इस पर घंटों बिताए।

मेरे लिए टीमसिटी और पावरहेल के बीच एक परत डालने का सबसे अच्छा विकल्प था। तो मैंने बस एसी # कंसोल ऐप लिखा जो पावरहेल स्क्रिप्ट को कॉल करता है।

जिस तरह से मैं करता हूं, टीमसिटी में हम नामक एक स्क्रिप्ट कहते हैं: RemoteFile.ps1

स्क्रिप्ट तर्कों के साथ:% system.RemoteServerFQDN%% system.RemoteUser%% system.RemoteUserPassword%% system.RemoteScriptName%% system.RemotePropertiesFile%% system.BildVersion%% system.RunList%

param (
[Parameter(Mandatory=$true)]
$Computername,
[Parameter(Mandatory=$true)]
$Username,
[Parameter(Mandatory=$true)]
$Password,
[Parameter(Mandatory=$true)]
$ScriptName,
[Parameter(Mandatory=$true)]    
$Propfile,
[Parameter(Mandatory=$true)]
$Version,
[Parameter(Mandatory=$true)]
[string[]]$DeploymentTypes

)

$securePassword = ConvertTo-SecureString -AsPlainText -Force $Password 
$cred = New-Object System.Management.Automation.PSCredential $Username, $securePassword
write-host "Readying to execute invoke-command..."
Invoke-Command -ComputerName $Computername -Credential $cred -ScriptBlock {       D:\Deployment\PowershellWrapper.exe $using:ScriptName $using:Propfile $using:Version      $using:DeploymentTypes } -ArgumentList $ScriptName,$Propfile,$Version,$DeploymentTypes

निर्दिष्ट स्थान में रिमोट सर्वर पर कौन सा मौजूद है।

तब वह फ़ाइल इसे कॉल करती है: powershellwrapper.exe निर्दिष्ट स्थान पर भी (मेरी स्क्रिप्ट में पावरहेल को पास करने के लिए 4 पैरामीटर हैं)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;

namespace PowershellWrapper
{
class Program
{
    static void Main(string[] args)
    {

        try
        {

            string argFull = @"""{0} {1} {2} {3}""";
            string arg0 = args[0];
            string arg1 = args[1];
            string arg2 = args[2];
            string arg3 = args[3];
            string argFinal = string.Format(argFull, arg0, arg1, arg2, arg3);

            ProcessStartInfo startInfo = new ProcessStartInfo();
            startInfo.FileName = @"powershell.exe";
            startInfo.Arguments = argFinal;
            startInfo.RedirectStandardOutput = false;
            startInfo.RedirectStandardError = false;
            startInfo.UseShellExecute = false;
            startInfo.RedirectStandardInput = true;
            startInfo.CreateNoWindow = false;
            Process process = new Process();
            process.StartInfo = startInfo;
            process.Start();

        }
        catch (Exception e)
        {
            Console.WriteLine("{0} Exception caught.", e);
            Console.WriteLine("An error occurred in the deployment.", e);
            Console.WriteLine("Please contact [email protected] if error occurs.");
        }

    }
}

}

और वह मेरी स्क्रिप्ट को 4 पैरामीटर के साथ कॉल करता है, स्क्रिप्ट पहला पैरामीटर है, साथ ही 3 तर्क भी। तो अनिवार्य रूप से यहां क्या हो रहा है कि मैं पावरहेल स्क्रिप्ट के बजाय PowerSllWrapper.exe को निष्पादित कर रहा हूं, गलत गलती कोड 0 को कैप्चर करने के लिए और यह अभी भी पूरी तरह से टीमसिटी लॉग पर चलने वाली पूरी स्क्रिप्ट की रिपोर्ट करता है।

उम्मीद है कि समझ में आता है, यह हमारे लिए एक आकर्षण की तरह काम करता है।


यह PowerShell के साथ एक ज्ञात मुद्दा है। -फाइल के साथ एक स्क्रिप्ट निष्पादित करने पर 0 का एक्जिट कोड लौटाता है जब इसे नहीं करना चाहिए।

(अपडेट करें: नीचे दिए गए लिंक अब काम नहीं करते हैं। कृपया https://windowsserver.uservoice.com/forums/301869-powershell पर इस समस्या को https://windowsserver.uservoice.com/forums/301869-powershell , या रिपोर्ट https://windowsserver.uservoice.com/forums/301869-powershell )

चूंकि -command आपके लिए काम नहीं कर रहा था, इसलिए आप स्क्रिप्ट के शीर्ष पर एक जाल जोड़ने का प्रयास कर सकते हैं:

trap
{
    write-output $_
    ##teamcity[buildStatus status='FAILURE' ]
    exit 1
}

अपवाद फेंकने पर उपर्युक्त उचित निकास कोड का परिणाम होना चाहिए।





exit-code