Error Message from Powershell Script mail to EmailAddress - email

I have constructed an script for our Dataloader in Salesforce:
**# The Function for the Check Error File**
function CheckErrorFile {
Param ([string]$perrorfilepath)
$csvlines = (Get-Content $perrorfilepath | Measure-Object -line).Lines
# header is always 1 row so we look for > 1 rows
if ($csvlines -gt 1)
{
$errorCount = $csvLines - 1
$errorMessage = [string]::Format("** errors ** {0} failed rows in {1}", $errorCount, $perrorfilepath)
# this will print red error message but not stop execution
write-error $errorMessage
}
}
**# set up locations/variables for data loader**
$dataloader = "C:\Program Files (x86)\salesforce.com\Data Loader\bin\process.bat"
$dlconfig = "U:\Projekte\Salesforce\Dataloader-Test-Infor-Files\Example-Migration-SF-Test\DataLoaderConfig"
set-location "C:\Program Files (x86)\salesforce.com\Data Loader\bin"
$dlLogFolder = "U:\Projekte\Salesforce\Dataloader-Test-Infor-Files\Example-Migration-SF-Test\Logs\"
**# execute the data loader**
& $dataloader $dlconfig testsf-delete
**# check for errors in the error.csv file**
CheckErrorFile ("{0}error_testsf.csv" -f $dlLogFolder)
So far so good it think
But what i want to is that the Error Code which comes Back from CheckErrorFile Command should sent to an Email Address.
So i had think about 2 Considerations:
when if error sent to mail
pack the error output in a variable and sent to mail adress
But i'm not so good at Powershell that i know how i have to integrate this in my script.
I found a site with an send trigger when a eventlog has changed but I'm not sure if i can use this for my purposes and how i have to integrate this:
Powershell Email when Eventlog is Changed
May someone could help
thnks

Related

How to perform conditional looping using powershell

I want to execute test cases using commands using PowerShell scripts.
How many time I want to execute those tests depend upon the $HowManyTimes variable.
It's possible that I get the success result before the $HowManyTimes
e.g As of now I set it to 3, but what if I get the successful result in the 2nd attempt itself.
I want to ignore that specific test case that got passed and proceed to execute the new test case.
I have copied the output of the command in $OutPut variable which looks like below
Not Imp Info
Errors, Failures and Warnings
Failed : UnitTestProject1.TestClass.AddTest()
Expected: 30
But was: 45
Not Imp Info
Test Run Summary
Overall result: Failed
Not Imp Info
Below if the script which I have written.
$XMLfile = 'Results.xml'
[XML]$Results = Get-Content $XMLfile
$HowManyTimes = 3 # How many time the script should run.
$TestCaseToExecute
$OutPut # Storing the result of command
$StopOperation = 0
for ($i=1; $i -le $HowManyTimes; $i++)
{
#I am reading the xml file which can have n test cases.
#For each loop on all the test case which are failed.
foreach($Result in $Results.'test-run'.'test-suite'.'test-suite'.'test-suite'.'test-suite'.'test-case' | Where-Object {$_.result -eq "Failed"})
{
Write-Host "Failed Test Case -- fullname :" ($Result).fullname
$TestCaseToExecute = ($Result).fullname
Write-Host " Executing ====>" $TestCaseToExecute
Write-Host "-----------------------------------------"
$OutPut = nunit3-console.exe UnitTestProject1\bin\Debug\UnitTestProject1.dll --test=$TestCaseToExecute | Out-String
if($OutPut -Like "*Overall result: Failed*"){
Write-Host "If Block"
continue
}else{
Write-Host "else block Stop : "
break
}
}
}
Please let me know what changes I need to make to achieve this.

Invoke-ASCmd to return error/warning in PowerShell

Running the PowerShell in my deployment pipeline:
Write-Host "Invoking deployment script... This may take several minutes."
Invoke-ASCmd -Server:$SsasServer -InputFile $path\$bim.xmla | Out-File $path\$bim.xml
Write-Host "Please check $path\$bim.xml as this is output of this deployment"
I want to take the output file of the Invoke-ASCmd: $bim.xml and determine if a warning exist or error exist. It would be ideal to return a warning messages to the console in my azure pipeline.
Example Warning message:
<return xmlns="urn:schemas-microsoft-com:xml-analysis"><root xmlns="urn:schemas-microsoft-com:xml-analysis:empty"><Exception xmlns="urn:schemas-microsoft-com:xml-analysis:exception" /><Messages xmlns="urn:schemas-microsoft-com:xml-analysis:exception"><Error ErrorCode="-1055784777" Description="The JSON DDL request failed with the following error: Failed to execute XMLA. Error returned: 'The column 'ProcessDateKey' in table 'Financial Measures' has invalid bindings specified.
'.." Source="Microsoft SQL Server 2016 Analysis Services Managed Code Module" HelpFile="" /></Messages></root></return>
I am not sure if this is the correct way to handle this xml exactly. Here is my first draft:
[xml]$XmlDocument = Get-Content -Path $path\$bim.xml
if($XmlDocument.return.root.Messages.Error){
foreach ($errorMessage in $XmlDocument.return.root.Messages.Error ){
$message = $errorMessage.Description
Write-Error $message
}
exit 1
}
You cannot use if directly on the Error node, this could also be an Error collection. I recommend using a xPath query to find all the Error messages.
Also you can get directly the Xml output from Invoke-AsCmd into an xml variable:
[xml]$xmlResult = Invoke-ASCmd -Server:$SsasServer -InputFile $path\$bim.xmla
$errors = $xmlResult.return.root.Messages.SelectNodes("*[name() = 'Error']")
if($errors.Count -gt 0){
foreach ($errorMessage in $errors){
Write-Error $message.Description
}
exit 1
}

How to capture console app output in Octopus custom PowerShell script?

I simply created an console app with argument number check at the very beginning. And after the package is deployed, in the deployment PowerShell script part, I directly call this app with no argument to test the script. It seems Octopus just captures the exit code and show there is no output from the app captured in task log at all.
static void Main(string[] args)
{
if (args.Length < 4)
{
Console.WriteLine("Invalid argument number");
Environment.ExitCode = -1;
return;
}
}
However, if I simply put "echo 'test'" or even just 'test' string in the script, the output was captured in Octopus deployment task log. Any idea what is the correct way to log console app in the script? Thanks.
Sorry, it is not fault of Octopus, It is actually the console app was built for .Net framework 4.6.1 but the tentacle server is only having 4.5.2. When I run the app on that server through remote desktop, it pops up error message saying 4.6.1 .Net framework is missing. Rebuild the app with 4.5.2 fixed this issue. However it was really hard to find this out because Octopus task log has nothing related to that. Hope this would help someone else in the future.
Create a file named "yourpowershellfile.ps1" or Create e deployment step "Run a script".
Try this powershell with OctopusDeploy,
$FullPath = "C:\MyFolder"
if ($OctopusEnvironmentName -ceq 'Development')
{
Write-Host "Console app will be execute"
& "$FullPath\yourconsolefile.exe" | Write-Host
Write-Host "Console app execution has finied"
}
You should try "Write-Output" instead of "Write-Host" Review the Octopus deploy task log.
If you found this question because you really need to get the console output following executables run in your Octopus deployment steps you can use the following code. It took a bit of research to write the following function I happily re-use accross Octopus steps where I need the console output:
Function Invoke-CmdCommand{
param(
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[ValidateScript({(Test-Path $_.Trim('"').Trim(''''))})]
[string]$Executable,
[string]$Parameters = '',
[switch]$CmdEscape
)
BEGIN{
Write-Verbose "Start '$($MyInvocation.Mycommand.Name)'"
$nl = [Environment]::NewLine
$exitCode = 0
$cmdOutput = [string]::Empty
# next line wrap string in quotes if there is a space in the path
#$Executable = (Format-WithDoubleQuotes $Executable -Verbose:$([bool]($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent)))
$command = "{0} {1}" -f $Executable, $Parameters
Write-Verbose "COMMAND: $command"
$terminatePrompt = "/C" # https://ss64.com/nt/cmd.html
$comSpec = $env:ComSpec
if($CmdEscape.IsPresent){
$command = "`"$command`""
Write-Verbose "ESCAPED COMMAND: $command"
}
}
PROCESS{
$cmdResult = .{
# script block exec: dot does not create local scope as opposed to ampersand
.$comSpec $terminatePrompt $command '2>&1' | Out-String | Tee-Object -Variable cmdOutput
return $LastExitCode
}
$exitCode = $cmdResult[$cmdResult.length-1]
if($exitCode -ne 0){
Write-Host "FAILED with ExitCode: $exitCode; ERROR executing the command:$nl$command$nl" -ForegroundColor Red
Write-Host "ERROR executing the command:$nl$command" -ForegroundColor Yellow
}else{
Write-Host "SUCCESSFULLY executed the command:$nl$command$nl"
}
}
END{
if($Host.Version.Major -le 3){
return ,$cmdOutput # -NoEnumerate equivalent syntax since it is not available in version 2.0
}else{
Write-Output -NoEnumerate $cmdOutput
}
Write-Verbose "End '$($MyInvocation.Mycommand.Name)'"
}
}
USAGE:
Invoke-CmdCommand -Executable (Join-Path (Split-Path $env:ComSpec) ping.exe) -Parameters 'localhost'
OUTPUT:
Pinging localhost [::1] with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Ping statistics for ::1:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
We just add a Deploy.ps1 to the package, with the following code:
& .\MyCompany.Foo.Bar.exe 2>&1
Resources:
In the shell, what does " 2>&1 " mean?

Powershell script error processing CSV data

I'm writing a script to load computer names from a CSV file, then look up their IP addresses.
The script creates an error when using the name from the CSV.
If I run the script in ISE, the error shows up, but the result still comes though. If I run the script from powershell, it errors and the result is null.
If I substitute the $PCname = $_.System for $PCname = "Computer01" everything works fine.
If I write-host $_.System it displays "Computer01". How can I get this to work in powershell?
$file = "\\server.contoso.net\private$\Systems.csv";
$CSV = Import-CSV $file;
$CSV | %{
if ($_.Skip -eq 0)
{
$PCname = $_.System
# $PCname = "Computer01"
write-host $PCname
try
{
$ipaddress = [System.Net.Dns]::GetHostByName($PCname).AddressList[0].IpAddressToString
}
Catch [system.exception]
{
if(1)
{ $error[0].tostring() }
}
}
}
Error displayed is:
Exception calling "GetHostByName" with "1" argument(s): "The requested name is valid, but no data of the requested type was found"
Turns out that the values in the CSV at some point had whitespace added after them, which caused a name look up error. I'm not sure why ISE would still be able to look up the host, but removing the whitespace fixed the issue.
Thanks to sha, his recommendation helped me see the whitespace.

In PowerShell, how to I send mail and enumerate in email body list of discovered errors

I have the following code snippet from my PowerShell script that...
Loops through a list of servers
Does a Select-String -notmatch on the error log at each server
Flags the server if the error log is bad, and gives the OK if the error log if fine
What I'd like to also do is send an email report that enumerates each of the discovered bad error logs in a list, and also list all the servers whose error logs are OK. Something like this in the email body:
The following servers have bad error logs:
Server3
Server6
Server14
The following servers are OK:
Server1
Server2
Server5
Here is my code snippet:
$Servers = Get-Content $ServerLst
ForEach ($Server in $Servers)
{
$ErrorLog = Get-ChildItem -Path \\$Server\$LOG_PATH -Include Error.log -Recurse | Select-String -notmatch $SEARCH_STR
If ($ErrorLog)
{
Write-Host "Bad Error Log found at $Server!"
}
Else
{
Write-Host "Error log is OK."
}
}
I'm guessing I would need a Send-Mail function where I would pass in the server names with bad error logs, etc. However, I'm not quite sure how to approach this.
Any great ideas will be greatly appreciated. Thanks!
If you are using Powershell V1 use this function from the Powershell Cookbook to send mail. In Powershell V2 you can send mail using Send-MailMessage.
$Servers = Get-Content $ServerLst
$Bad = "The following servers have bad error logs:`n`n"
$OK = "`nThe following servers are OK:`n`n"
ForEach ($Server in $Servers)
{
$ErrorLog = Get-ChildItem -Path \\$Server\$LOG_PATH -Include Error.log -Recurse | Select-String -notmatch $SEARCH_STR
If ($ErrorLog)
{
$Bad += "`t - $Server`n"
}
Else
{
$OK += "`t - $Server`n"
}
}
Send-MailMessage -Body "$Bad $OK" -Subject "Bad Logs" -SmtpServer $servername -To $to -From $from
Remark: The smtpserver parameter is called smtphost in the Powershell cookbook function.
You will need to make the function on your own, but here is some pseudo code:
Function SendMail
{
Param(...your params here)
...send the mail...
}
<...
Your code to check all your servers
You need to save your errors or issues to an array or hashtable.
I'll assume you use a 2-field array called $ErrArray
...>
# Now at the end you build a string for the body of the email to incorporate your errors
$StrBody = "Bad Error Log Report`n`n"
$ErrArray | ForEach-Object {$StrBody = $Strbody + "`n$($_[0]) server had an issue: $($_[1])`n"}
SendMail $EmailTo $EmailSubject $StrBody
So the breakdown:
Make a mail function
Save the results of your analysis to an array or hashtable
Iterate through your results object and append each result record to the string for your email
Call the email function