Try-Catch not working while invoking exe through powershell - powershell

I'm using microsoft's document translator msi to translate documents.I'm invoking this msi through powershell but if any error occures while processing document , script is unable to catch the error .
commandline to start instance of translator msi and translate document:
DocumentTranslatorCmd translatedocuments /documents:d:\testdocuments\*.docx /from:en /to:de,el
I tried below approaches but it looks like i'm doing something wrong :
using $LastExitCode
DocumentTranslatorCmd translatedocuments /documents:d:\testdocuments*.docx /from:en /to:de,el
if($LastExitCode -ne 0){
do something..
}
if error occurs during processing it does exit out of this command and control does not reaches to if().So, i used exit command like :
DocumentTranslatorCmd translatedocuments /documents:d:\testdocuments\*.docx /from:en /to:de,el | exit
-ErrorAction stop
try{
DocumentTranslatorCmd translatedocuments /documents:d:\testdocuments*.docx /from:en /to:de,el -ErrorAction stop
}catch{
}
if this is used DocumentTranslatorCmd command considering it as a argument.
Any kind of help would be greatly appreciated.

Related

How do I check if a specific exception type has been thrown in Pester 5.4.0?

I want to write a test in PowerShell with Pester 5.4.0 to check whether a specific exception type has been thrown inside a script block. It should be fairly easy, but I am somehow not doing it right. Following along the Pester v5 documentation for the Should keyword and this pre-release Pester blogpost about using Should - Throw I wrote the following (very basic) script containing one test:
Import-Module Pester -RequiredVersion 5.4.0
Describe "Testing if a service is registed." {
It "This service should not be registered in the windows services app." {
{ Get-Service -Name "this service does not exist" } | Should -Throw -ExceptionType ([Microsoft.PowerShell.Commands.ServiceCommandException])
}
}
I would expect the test to catch the ServiceCommandException that is thrown when the Get-Service Cmdlet looks for a service that does not exist, and the test to pass. Instead the error is still thrown, Pester tells me that Expected an exception, with type [Microsoft.PowerShell.Commands.ServiceCommandException] to be thrown, but no exception was thrown., and the test fails:
I am probably doing something that's very obvious wrong here, but I looked at it for a while and did some research, and I cannot see what is wrong with my script.
the type of error you get from get-service is not a throwing/operation halting error. This means that while there is an error, Powershell will continue to process your script until completed.
to make sure that any command actually halts operation and triggers pesters should -throw, you can add -erroraction stop or the alias -ea stop to the get-service command:
The issue here, however you want to look at it, is that you are testing if a command is throwing an error, and handling it this way. however the command does not throw anything. it returns an error. its not a operation stopping thing that happens (even though you can force it by setting -erroraction).
what you might want to do instead is this:
It "Testing other method" {
Get-Service -Name "this service does not exist" -ErrorVariable er -ErrorAction SilentlyContinue
$er|should -not -HaveCount 0
$er.Exception|Should -BeOfType ([Microsoft.PowerShell.Commands.ServiceCommandException])
}

Jenkins powershell plugin always builds successfully

I'm using Jenkins PowerShell plugin to build a project.
However, I found that Jenkins always considers my build successful no matter what I type inside Windows PowerShell command.
Here's an example:
As you can see, asdf isn't a legal command. Jenkins should give me FAILURE after the build.
But the console output gives me:
Started by user admin
Building in workspace C:\Users\Administrator\.jenkins\jobs\Test\workspace
[workspace] $ powershell.exe -NonInteractive -ExecutionPolicy ByPass "& 'C:\Users\ADMINI~1\AppData\Local\Temp\hudson2092642221832331776.ps1'"
The term 'asdf' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At C:\Users\ADMINI~1\AppData\Local\Temp\hudson2092642221832331776.ps1:1 char:5
+ asdf <<<<
+ CategoryInfo : ObjectNotFound: (asdf:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Finished: SUCCESS
I think the execution result of PowerShell should depend on $lastexitcode.
Is this a bug of PowerShell plugin?
As of 1.3, the plugin will not handle exceptions such as those from missing commands. You can do this yourself with try/catch:
try
{
asdf
}
catch
{
write-host "Caught an exception"
exit 1
}
See MSDN for more.
For me, I wanted the script to stop and fail in Jenkins soon as it hit an error. This was accomplished by adding this to the start of the script:
$ErrorActionPreference = "Stop"
This is discussed here: [How to stop a PowerShell script on the first error?][1]
[1]: How to stop a PowerShell script on the first error?. ..................
Per the latest version of the plugin (Version 1.3 Sept 18 2015), you must use $LastExitCode to fail a build.
Version 1.3 (Sept 18 2015)
PowerShell now runs in Non-Interactive mode to prevent interactive prompts from hanging the build
PowerShell now runs with ExcecutionPolicy set to "Bypass" to avoid execution policy issues
Scripts now exit with $LastExitCode, causing non-zero exit codes to mark a build as failed
Added help and list of available environment variables (including English and French translations)
I want to add here that I just ran into a quirk: you must have the powershell script end with exit and not return.
My jenkins pipe looked like:
script {
result = powershell(returnStatus: true, script: '''...if(error condition) { return 1 }''')
if(result) { error }
}
I was using if(error condition) { return 1 } and while the 1 was showing up as the return value in the jenkins console, it was not failing the build. When i used if(error condition) { exit 1 }, the build failed as expected.
I think this is a helpful addition to this thread - the need to use exit and not return. But I don't understand this part: the pipe is checking for result to be non-zero. What is the difference between exit and return in a powershell directive that makes if(result) { error } not work as expected when using return?
Update Feb-16-2021: Coming back to this to add some more notes from my experience: I think what I was doing and what a lot of people do that confuses things, is to use returnStdout or returnStatus and not check them and/or not fully understand what's coming back.
If you use either of those params, Jenkins will not do anything for you based on their value. You have to check them yourself and act accordingly. On the other hand, if you don't use them, Jenkins will recognize a failure code and fail the pipe if one comes back.
Think about it: If you set returnStatus, you're getting the exit code back from the step as a return value and not as something for Jenkins itself to worry about. If you set returnStdout, you're getting the stdout stream - and not any error codes or anything from stderr. So you must check the return for what you want or you will not get the behavior you are expecting.
What I've been doing for a while is actually not setting either of those params and making sure to set $ErrorActionPreference = 'Stop' at the start of any and all PowerShell scripts running in my pipes. That way any powershell failures automatically fail the pipe as expected, without having to check it.
This is how I implemented RRIROWER's solution. Hope it helps.
<yourscript>.ps1; exit $lastexitcode
Make sure your powershell scripts does exit with the desired value.
Run "exit <value>" as the last line.
Ultimately, I had to resort to the following configuration in Jenkins as none of the solutions here worked for me. Chris Nelson's answer got me on the right track. We're invoking chef-client remotely so we had to do a little magic to get the remote PS session to talk the local and then pass status on to Jenkins.
$res gives the output of chef-client.
$lastsuccess is true or false according to PS rules of engagment.
Of course, you'll have to supply your own evironment variables! :)
Write-host "Deploying $env:Computer with $env:Databag data bag... "
$secstr = ConvertTo-SecureString $env:Password -AsPlainText -Force
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $env:User, $secstr
$s = New-PSSession -ComputerName $env:Computer -Credential $cred
$res = Invoke-Command -Session $s -ScriptBlock { try {chef-client} catch {exit 1}}
$lastsuccess = Invoke-Command -Session $s -ScriptBlock {$?}
Remove-PSSession $s
write-host " --- "
write-host $res
write-host " --- "
if($lastsuccess)
{
write-host "chef deployment completed"
exit 0
}
write-host "chef deployment had errors"
exit 1

Return code and status from PowerShell command

I'm running the following command from within a Microsoft System Centre Orchestrator PowerShell activity:
Install-WindowsFeature -ConfigurationFilePath C:\DeploymentConfigTemplate.xml -ComputerName ServerXYZ
the command isn't doing what it's supposed to do, and I want to be able to return if the command was successful or not, and any error message if possible. Ignore the fact it's running in Orchestrator, as I'm more concerned about the PowerShell question. When I run the command from ISE it does what it's supposed to do, that's why I want to see what is returned from PowerShell.
Thanks.
It's hard to know what may be happening without more context. The following will record any errors encountered in an xml file that you can import later with import-clixml:
Install-WindowsFeature -ConfigurationFilePath C:\DeploymentConfigTemplate.xml -ComputerName ServerXYZ
IF (!($?)) {
$error[0] | export-clixml C:\myerror.xml
}
This solves my problem:
$Result = Install-WindowsFeature -Name SNMP-Service -IncludeAllSubFeature -IncludeManagementTools
Write-Host $Result.ExitCode

Handle exception in powershell

I have a config file when you can add a list of performance counters, for example :
\Memory\Page Faults/sec
\Memory\Available Bytes
\ASP.NET Applications(*)\Requests in Application Queue
I have a powershell script, that parses the file and does a Get-Counter parameter where parameter is each counter in my config file. Everything works well, but I would like my script to be able to handle exception when an user add a bad counter, for example :
\Memory\Page Faults/sec
\Memory\Available Bytes
\ASP.NET Applications(*)\Requests in Application Queue
ddftrigjgigjij
With this, I get a red exception in my powershell console which I would like to replace with an appropiate message like "counter not found". I am beginning with powershell and I tried to use try\catch without success.
Thanks in advance for your help.
Add -ErrorAction Stop to Get-Counter, this will make try/catch work as you expect:
try{
Get-Counter "bogus counter" -ErrorAction stop
}
catch {
echo "counter not found"
}

Capturing Non-Standard Powershell CmdLet Output for Flow Control

Currently trying to build a script utilizing cmdlets from the MS released "Team Foundation Server Power Tools" package.
I'm attempting to flow command logic from the success or failure of the "Update-TfsWorkspace" cmdlet however I can't seem get a return code out of the call nor can I capture the output using Out-String. I'm using Powershell v1.
update-tfsworkspace "C:\doesnotexist\" -recurse -version T
Yields a message of "Unable to determine the workspace." which is the error I'm trying to catch.
$ret = update-tfsworkspace "C:\doesnotexist\" -recurse -version T
Is expected to give me a $true/$false indicating success/fail but doesn't work.
update-tfsworkspace "C:\doesnotexist\" -recurse -version T | Out-Null
Is expected to prevent the cmdlet from writing the message but doesn't work.
trap{echo "fail"}
update-tfsworkspace $workspace_path -recurse -version T
Is expected to catch an error and write "fail" but doesn't work.
$msg = update-tfsworkspace $workspace_path -recurse -version T | Out-String
Is expected to populate a $msg variable with the host output but doesn't work.
I'm totally out of ideas here. Help would be appreciated!
Little hacky, but since I don't have TFS to try to figure something else out, see if this helps.
I would say that this cmdlet wasn't written correctly. First, since it didn't succeed it should have emitted an error object which would have caused $? to return false which you could have checked or trapped. Second, you can't suppress the error message using -ea 0. It looks like this snapin is using the Host api to write an error string to the host console. That's a spew!! For now, you could do what EBGreen suggests:
$msg = powershell.exe -nologo update-tfsworkspace "C:\doesnotexist\" -recurse -version T 2>&1
Just watch out for all the text your profile script spits out when a new instance of PowerShell starts up.
Your problem here is that the cmdlet is writing an error (Non-Terminating Error), but not throwing an exception (Terminating Error). You can make it throw an exception by adding the ErrorAction parameter:
trap{echo "fail"}
update-tfsworkspace $workspace_path -recurse -version T -ErrorAction "Stop"
This will cause the cmdlet to make all errors terminating (throwing an exception if it writes to the error stream).