Ok, here is the problem, randomly the LoadFiles option doesn't like a certain input file and produces an error. This error is always a terminating error and I cannot figure out any way to get it to continue. Any Ideas?
Function ProcessImage {
Param(
[Parameter(ValueFromPipeline=$true)]
[System.IO.FileInfo]$File
)
If ($Excluded_Owners -notcontains $(get-acl -path $File.FullName).owner) { #Check owner of the file and compare it to list of blacklisted file owners.
Try{
$Image = New-Object -ComObject Wia.ImageFile
$Image.LoadFile($File.fullname)
} Catch{
LogWriter -OutPut "File Failed Process File in WIA - `"$($File.fullname)`""
Write-Error $_.Exception.Message
continue
}
If($Image.width -gt $PictureMinWidth -or $Image.height -gt $PictureMinHeight) { #Check image dimensions.
IF ($Script:Copy) {
$CopyTryCount = 0
While ((Test-Path -Path "$CopyDir\$($Script:MF_ImagesCopied + 1)$($File.extension)" -PathType Leaf) -EQ $False -AND $CopyTryCount -le 3) { #After the script says the picture was copied without error, verify it indeed was.
$CopyTryCount++
Try {
Copy-Item -Path $File.FullName -Destination "$CopyDir\$($Script:MF_ImagesCopied + 1)$($File.extension)" -Force #If the picture meets all requirements, attempt to copy the image.
} Catch {
LogWriter -Status "Failure" -Output "File Failed to Copy (Attempt $CopyTryCount) - `"$($File.fullname)`""
}
}
IF (Test-Path -Path "$CopyDir\$($Script:MF_ImagesCopied + 1)$($File.extension)" -PathType Leaf) { #Check the CopyDir directory for the image.
LogWriter -Status "Success" -Output "File Successfully Copied - `"$($File.fullname)`"" #If the image was copied successfully, log that.
[Int]$Script:MF_ImagesCopied += 1
$Temp_ProcessImage_Success=$True
} Else {
LogWriter -Status "Failure" -Output "File Failed to Copy after 3 tries - `"$($File.fullname)`"" #If the image was not copied successfully, log that.
[Int]$Script:MF_ImagesFailed+= 1
}
}
} Else {
LogWriter -Status "Skipped" -Output "Incorrect Dimensions - `"$($File.fullname)`""
[Int]$Script:MF_ImagesSkipped += 1
}
} Else {
LogWriter -Status "Skipped" -Output "Excluded Owner - `"$($File.fullname)`""
[Int]$Script:MF_ImagesSkipped += 1
}
}#End ProcessImage
This is the troublesome error.
ProcessImage : Exception calling "LoadFile" with "1" argument(s): "The
segment is already disca rded and cannot be locked. " At
L:\MediaFinder.ps1:400 char:83
+ If ($Images -AND $ImageFileTypes -contains "*"+$.Extension) {ProcessImage <<<< $}
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,ProcessImage
You have caught the terminating error in a catch block and turned it into a non-terminating error. That's the first important step. BTW the continue in your catch block may also be causing premature termination. Continue is meant to be used with loops and with the Trap statement. Remove it and replace with a return statement.
The reason your function doesn't process any other files is that it isn't written quite right. So the second step is to put your script in a process block so it can process each $File object passed down the pipeline e.g.:
function ProcessImage {
param(
[Parameter(ValueFromPipeline=$true)]
$File
)
process {
try {
if ($file -eq 'foo') {
throw 'kaboom'
}
else {
"Processing $file"
}
}
catch {
Write-Error $_
return # can't continue - don't have valid file obj
}
"Still processing $file"
}
}
And if I run the above with these parameters, you can see that it processes objects after the one that throws a terminating error:
C:\PS> 'bar','foo','baz' | ProcessImage
Processing bar
Still processing bar
ProcessImage : kaboom
At line:1 char:21
+ 'bar','foo','baz' | ProcessImage
+ ~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,ProcessImage
Processing baz
Still processing baz
Related
Publish-AzWebApp throws an error when uploading the Source Code for the aplication. The code is the following:
$job = Publish-AzWebApp `
-WebApp $webApp `
-ArchivePath (Join-Path -Path $rootPath -ChildPath $archiveRelativePath) `
-Force `
-AsJob
# # #
# ...code...
# # #
# Later on
$job | Receive-Job -AutoRemoveJob -Wait -WriteJobInResults | ForEach-Object {
if ("AzureLongRunningJob" -eq $_.GetType().BaseType.Name) {
if ("Completed" -eq $_.JobStateInfo.State) {
Write-Log -Message "Published the Source Code for $($webApp.Name) successfully." -Level INFO
}
else {
Write-Log -Message $_.JobStateInfo -Level ERROR
throw $_.JobStateInfo
}
}
}
The error is the following:
Deployment failed with status code ServiceUnavailable
+ CategoryInfo : InvalidResult: (:) [], Exception
+ FullyQualifiedErrorId :
The thing is that between the beginning of the job and the end of the job I am also uploading WebJobs and and also I'm setting the AppSettings from the Configuration Blade.
I also noticed that this happens when I am creating the app then doing this procedure in one go. But if the app exists, the error is less likely to occur. Still it doesn't seem like it is stable. What could I do?
Within Powershell, the CopyHere method for the Shell-Application Namespace is asynchronous. My main goal with this is to convert a KML file to a KMZ file. The process of doing this is to create a ZIP file with the same name, copy the KML into the KMZ (compresses the file) and then rename the ZIP to KMZ. Unfortunately, being asynchronous means the rename function is being called before the CopyHere method is completed. I have found many examples of solving this. The cleanest one I found is below:
$kmlPath = $global:directoryPath + "Test.kml"
$zip = $global:directoryPath + "Test.zip"
New-Item $zip -ItemType file
$shellApplication = new-object -com shell.application
$zipPackage = $shellApplication.NameSpace($zip)
$zipPackage.CopyHere($kmlPath, 16)
while($zipPackage.Items().Item($zip.Name) -Eq $null)
{
start-sleep -seconds 1
write-host "." -nonewline
}
write-host "."
Rename-Item -Path $zip -NewName $([System.IO.Path]::ChangeExtension($zip, ".kmz"))
This responds with the following error:
Exception calling "Item" with "1" argument(s): "Not implemented
(Exception from HRESULT: 0x80004001 (E_NOTIMPL))"
+ while($zipPackage.Items().Item($zip.Name) -Eq $null)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
Am I misusing the Item method for this particular package? I am confused why something that "appears" to be neatly done is not working. I have also tried the snippet of code provided Here. It also complains about the .Item method in this particular situation.
The issue i ran into was trying to find away to check on zip status.
So instead i did a trigger for a while that would fire ...If the Zipfile was openable and the File name was inside.
function kml_to_kmz([string]$kmlPath){
[Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem')
$kmlInfo = Get-ChildItem -Path $kmlPath
$zipLocation = ($kmlInfo.Directory.FullName + '\' + $kmlInfo.Name.Remove($kmlInfo.Name.LastIndexOf('.')) + '.zip')
New-item $zipLocation
((new-object -com shell.application).NameSpace($zipLocation)).CopyHere($kmlPath, 16)
$trigger = $false
while ($trigger -eq $false){
try{
$zip = [IO.Compression.ZipFile]::OpenRead($zipLocation)
If(($zip.Entries | %{$_.Name}) -contains $kmlInfo.Name){
$zip.Dispose();
$trigger = $true
break;
}
}catch{}
start-sleep -seconds 1
write-host "." -nonewline
}
[IO.Compression.ZipFile]::OpenRead($zipLocation).Dispose()
Rename-Item -Path $zipLocation -NewName $([System.IO.Path]::ChangeExtension($zipLocation, '.kmz'))
}
kml_to_kmz -kmlPath "C:\Users\Default\Desktop\Test.kml"
I see below error logs when ever i try to copy items from a path to destination . This PS script task is scheduled under a Jenkins Job. This is messing up things as build fails every time.
Error Logs-
Copy-Item : The process cannot access the file
'\\10.0.1.190\d$\Build\RPC\Fortius.RPC.AmadeusAir\Common.Logging.Core.dll' because it is being used by another process.
At C:\Users\Administrator\AppData\Local\Temp\hudson5254771699639808940.ps1:33 char:1
+ Copy-Item "$ReleaseDir\*" $AmadeusDir -Force -Recurse
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Copy-Item], IOException
+ FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Commands.CopyItemCommand
PS Script-
# force strict - so any variable used before being assigned causes an error
Set-PsDebug -Strict
# force PowerShell to exit with a non-zero code on the first error
$ErrorActionPreference = 'Stop'
# set directories here once, so we can reuse
$AmadeusDir = "\\$env:SERVER\d$\Build\RPC\Fortius.RPC.AmadeusAir"
$ReleaseDir = "C:\Amadeus\BTP\src\Fortius.Amadeus.Air.RPC.Host\bin\Release"
# get directory contents (are you expecting these to return to Jenkins?)
Get-ChildItem "$AmadeusDir\*"
Get-ChildItem "$ReleaseDir\*"
# create the search directory if it doesn't exist
if (-not (Test-Path -Path $AmadeusDir -PathType Container)) { New-Item -Path $AmadeusDir -type directory -Force }
# get the service, but fail gracefully if it doesn't exist
$service = Get-Service -Name AmadeusAirWindowsService -Computername $env:SERVER -ErrorAction SilentlyContinue
# if we have a service, stop and delete it
if($service.Status)
{
sc.exe \\$env:SERVER stop AmadeusAirWindowsService
if ($LASTEXITCODE -ne 0) { throw "error stopping the service: $LASTEXITCODE" }
Write-Host "AmadeusAirWindowsService STOPPED"
sc.exe \\$env:SERVER delete AmadeusAirWindowsService
if ($LASTEXITCODE -ne 0) { throw "error deleting the service: $LASTEXITCODE" }
Write-Host "AmadeusAirWindowsService DELETED"
}
# copy release to search
Copy-Item "$ReleaseDir\*" $AmadeusDir -Force -Recurse
# (re)create the service
sc.exe \\$env:SERVER create AmadeusAirWindowsService start=auto DisplayName="Fortius Amadeus Air RPC Service" binPath= D:\Build\RPC\Fortius.RPC.AmadeusAir\WorldVentures.Fortius.Amadeus.Air.RPC.Host.exe
if ($LASTEXITCODE -ne 0) { throw "error creating the service: $LASTEXITCODE" }
sc.exe \\$env:SERVER description AmadeusAirWindowsService "This service hosts Fortius Amadeus Air RPC service"
if ($LASTEXITCODE -ne 0) { throw "error adding description to service: $LASTEXITCODE" }
sc.exe \\$env:SERVER start AmadeusAirWindowsService
if ($LASTEXITCODE -ne 0) { throw "error starting the service: $LASTEXITCODE" }
Write-Host "AmadeusAirWindowsService STARTED"
As an alternate I am using
xcopy "From" "destination" /k/e/d/Y to do that
You're trying to copy over stuff while the destination still has files in use. Have you checked what is keeping this/these file(s) locked? You already stopped the service I see, did you actually check if that went successfully? Also SysInternals has "handle" and "process explorer" which can both checks what is keeping your file locked.
Here is my for loop
function Generate_bin($input_1, $bin_file_name, $Codes){
$counter=1
foreach ($Code in $Codes)
{
Write-Host "Code = $Code"
$input_11 = "$input_1" + "$counter"
$pattern = "0x"
$New = ""
$Code = [regex]::replace($Code, $pattern, "$New")
$bin_file_name2 = "$bin_file_name"
$bin_file_name2 += "$Code" + ".bin"
#This utility generates "out.bin"
Invoke-Command -ScriptBlock {.\xyz.exe -i -t "$input_1"}
Rename-Item out.bin -NewName $bin_file_name2
$counter++
}
}
I am getting following error
Rename-Item : Cannot create a file when that file already exists.
At C:\script\myParser_unique.ps1:18 char:7
+ Rename-Item out.bin -NewName $bin_file_name2
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (C:\Users\v-ashi...Unified\out.bin:String) [Rename-Item], IOException
+ FullyQualifiedErrorId : RenameItemIOError,Microsoft.PowerShell.Commands.RenameItemCommand
You should add -Force parameter to the Rename-Item to make it overwrite existing files.
If your code happens to generate multiple equal file names you could add a counter to the filename.
I'm working on a PowerShell library that automates some network management operations. Some of these operations have arbitrary delays, and each can fail in unique ways. To handle these delays gracefully, I'm creating a generic retry function that has three main purposes:
Execute an arbitrary command (with parameters)
If it fails in a recognized way, try it again, up to some limit
If it fails in an unexpected way, bail and report
The problem is item #2. I want to be able to specify the expected exception type for the command. How can I do this in PowerShell?
Here's my function:
Function Retry-Command {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True, Position=0)]
[String] $name,
[Parameter(Mandatory=$True, Position=1)]
[String] $scriptBlock,
[String[]] $argumentList,
[Int] $maxAttempts=3,
[Int] $retrySeconds=10,
[System.Exception] $retryException=[System.Management.Automation.RuntimeException]
)
$attempts = 1
$keepTrying = $True
$cmd = [ScriptBlock]::Create($scriptblock)
do {
try {
&$cmd #argumentList
$keepTrying = $False
Write-Verbose "Command [$commandName] succeeded after $attmpts attempts."
} catch [$retryException] {
$msg = "Command [$commandName] failed. Attempt $attempts of $maxAttempts."
Write-Verbose $msg;
if ($maxAttempts -gt $attempts) {
Write-Debug "Sleeping $retrySeconds"
Start-Sleep -Seconds $retrySeconds
} else {
$keepTrying = $False
Write-Debug "Reached $attempts attempts. Re-raising exception."
Throw $_.Exception
}
} catch [System.Exception] {
$keepTrying = $False
$msg = "Unexpected exception while executing command [$CommandName]: "
Write-Error $msg + $_.Exception.ToString()
Throw $_.Exception
} finally {
$attempts += 1
}
} while ($True -eq $keepTrying)
}
I call it like this:
$result = Retry-Command -Name = "Foo the bar" -ScriptBlock $cmd -ArgumentList $cmdArgs
But this is the result:
Retry-Command : Cannot process argument transformation on parameter 'retryException'.
Cannot convert the "System.Management.Automation.RuntimeException" value of type "System.RuntimeType" to type "System.Exception".
At Foo.ps1:111 char:11
+ $result = Retry-Command <<<< -Name "Foo the bar" -ScriptBlock $cmd -ArgumentList $cmdArgs
+ CategoryInfo : InvalidData: (:) [Retry-Command], ParameterBindin...mationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,Retry-Command
This seems to be saying that the type of [System.Management.Automation.RuntimeException] is not itself a [System.Exception], but is instead a [System.RuntimeType] which makes sense.
So, how do I specify the type of the exception to be caught?
It's not possible to use a variable as a catch criteria, it has to be a type-object (or something), everything else gives you an error. A workaround would be something like this:
#You can get the name of the exception using the following (or .Name for just the short name)
#PS > $myerr.Exception.GetType().Fullname
#System.UnauthorizedAccessException
function test {
param(
#Validate that specified name is a class that inherits from System.Exception base class
[ValidateScript({[System.Exception].IsAssignableFrom([type]$_)})]
$ExceptionType
)
try {
#Test-script, Will throw UnauthorizedAccessException when not run as admin
(Get-Content C:\test.txt) | % { $_ -replace 'test','lol' } | Set-Content C:\test.txt
}
catch [System.Exception] {
#Check if exceptiontype is equal to the value specified in exceptiontype parameter
if($_.Exception.GetType() -eq ([type]$ExceptionType)) {
"Hello. You caught me"
} else {
"Uncaught stuff: $($_.Exception.Gettype())"
}
}
}
A few tests. One with non-existing type, then with non-exception type, and finally a working one
PS > test -ExceptionType system.unaut
test : Cannot validate argument on parameter 'ExceptionType'. Cannot convert the "system.unaut" val
ue of type "System.String" to type "System.Type".
At line:1 char:21
+ test -ExceptionType system.unaut
+ ~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [test], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,test
PS > test -ExceptionType String
test : Cannot validate argument on parameter 'ExceptionType'. The "[System.Exception].IsAssignableF
rom([type]$_)" validation script for the argument with value "String" did not return true. Determin
e why the validation script failed and then try the command again.
At line:1 char:21
+ test -ExceptionType String
+ ~~~~~~
+ CategoryInfo : InvalidData: (:) [test], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,test
PS > test -ExceptionType UnauthorizedAccessException
Hello. You caught me