Ok, I created a PS Script seems to break somewhere in the middle of it and need help understanding why it skips a function. I am new to scripting and I have no idea how to debug so any help would be greatful.
Script Funtions:
Pull PGP encrypted files from external server to a specific folder
Decrypt the PGP encrypted files and outputs with a .csv extension
Move the original files to specific archive folder
Copy decrypted files to SharePoint Online library
Move decrypted files to specific archive folder
When the script runs it either skips the decrypt process or does not decrypt all the files. If I run the code by itself, it will decrypt the files correctly. If I run the part of the code that does step 2-5 manually, it does not work.
My goal is to make sure it will process steps 1-5 without intervention and somehow put validation in the script, which I have yet to learn how to do.
Validation goals:
Confirm files were pulled
For each file pulled, confirm there is a decrypted file created
Once copied to SPO, confirm all the files that were decrypted are in SPO
Can anyone help me or point me in a direction on how to fix my script, debug, and/or how to perform validation in scripts? I would be beyond grateful!!
$files = Get-ChildItem -Path "\\WebDrive\clientSFTP\From_client\*.*" -File
foreach ($file in $files)
{
#Write-Output "Retrieving File: $file"
Write-Output "$file TO \\servername\records\client\Received\"
try
{
Move-Item -Path "$file" "\\servername\records\client\Received\" -Force
}
catch
{
Write-Output "Error pulling down the files. ($file)"
}
}
#Pause script for 10 seconds
Start-Sleep 10
#If I run the below all together it still fails.
#-----------------------
$DestPath = "\\servername\records\client\Received"
$files = Get-ChildItem $DestPath -File
ForEach($file in $files)
{
# try
#{
$outfile = $file.BaseName
Write-Output "PGP Procesing: Input=$DestPath\$file, Output=$DestPath\$outfile"
Start-Process -FilePath "C:\Program Files (x86)\GnuPG\bin\gpg.exe" -WorkingDirectory "$DestPath" -ArgumentList "--pinentry-mode=loopback --passphrase passwordhere -o $DestPath\$outfile $DestPath\$file"
#}
#catch
#{
# Write-Output "Error during PGP decryption of: $file"
#}
}
#---------------
#If I run the lines of code between the #------ it will decrypt all the files correctly.
$files = Get-ChildItem "$DestPath\*.csv" -File
ForEach($file in $files)
{
try {
Copy-Item -Path "$file" -Destination "\\WebDrive\SpoProfile\Shared Documents\client\02.From_client\" -Force
Move-Item -Path "$file" -Destination "\\servername\records\client\Received\Archive\Decrypted\" -Force
}
catch
{
Write-Output "Error Moving file: $file"
}
}
$files = Get-ChildItem "$DestPath\*.pgp" -File
ForEach($file in $files)
{
try
{
Move-Item -Path "$file" -Destination "\\servername\records\client\Received\Archive\Original\" -Force
}
catch
{
Write-Output "Error Moving file: $file"
}
}
So it's decrypting the files correctly, but the latter portion is failing.
I believe that is due to the line $outfile = $file.BaseName and the fact that the latter portion of the script is searching for files based off the file extensions. BaseName returns the filename, minus the extension, so if your file was named banana.csv $file.BaseName would return banana
You actually have no functions in this posted code.
Never run destructive code (Create, New, Update, Modify, Move, Delete...) without checking yourself first. This is why the -WhatIf parameter exists.
Anyway, try this refactored code.
$DestPath = "\\$ServerName\records\client\Received"
$WebDrive = 'PathToSource'
Get-ChildItem -Path "\\$WebDrive\clientSFTP\From_client\*.*" -File |
ForEach-Object {
Write-Output "$PSItem TO \\$ServerName\records\client\Received\"
Try
{
$moveItemSplat = #{
Destination = "\\$ServerName\records\client\Received\"
Path = $PSItem
Force = $true
ErrorAction = 'Stop'
}
Move-Item #moveItemSplat -WhatIf
}
Catch {Write-Warning -Message "Error pulling down the files. $PSItem"}
}
Start-Sleep 10
Get-ChildItem $DestPath -File |
ForEach-Object {
Try
{
$CurrentErrorActionPreference = $ErrorActionPreference
$ErrorActionPreference = 'Stop'
"PGP Procesing: Input=$DestPath\$PSItem, Output=$DestPath\$($PSItem.FullName)"
$startProcessSplat = #{
FilePath = 'C:\Program Files (x86)\GnuPG\bin\gpg.exe'
ArgumentList = "--pinentry-mode=loopback --passphrase passwordhere -o $DestPath\$($PSItem.FullName) $DestPath\$PSItem"
WorkingDirectory = $DestPath
}
Start-Process #startProcessSplat
}
Catch {Write-Warning -Message "Error during PGP decryption of: $PSitem"}
Finally {$ErrorActionPreference = $CurrentErrorActionPreference}
}
Get-ChildItem "$DestPath\*.csv" -File |
ForEach-Object {
Try
{
$CurrentErrorActionPreference = $ErrorActionPreference
$ErrorActionPreference = 'Stop'
$copyItemSplat = #{
Destination = "\\$WebDrive\SpoProfile\Shared Documents\client\02.From_client\"
Path = $PSItem.FullName
Force = $true
}
Copy-Item #copyItemSplat
$moveItemSplat = #{
Destination = "\\$ServerName\records\client\Received\Archive\Decrypted\"
Path = $PSItem.FullName
Force = $true
}
Move-Item #moveItemSplat -WhatIf
}
Catch {Write-Warning -Messate "Error Moving file: $file"}
Finally {$ErrorActionPreference = $CurrentErrorActionPreference}
}
Get-ChildItem "$DestPath\*.pgp" -File |
ForEach-Object {
Try
{
$moveItemSplat = #{
Destination = "\\$ServerName\records\client\Received\Archive\Original\"
Path = $PSItem.FullName
Force = $true
ErrorAction = 'Stop'
}
Move-Item #moveItemSplat -WhatIf
}
Catch {Write-Warning -Messate "Error Moving file: $file"}
}
Related
I was wondering if another set of eyes can spot where I'm going wrong.
I'm trying to add am exceptions.sites file to a users Java folder via GPO so as to allow for Edge Compatibility mode to work without user intervention. We have a lot of legacy applications and a lot of users so automating this would be great.
The script seems to run without error.
$Source = '\\thepath\Policies\{1FA921CE-231E-4982-8EBA-29E3AD4A44EF}\Machine\Scripts\Startup\exception.sites'
$users = (Get-ChildItem 'c:\Users\').name
$JavaFolder = "C:\Program Files\Java\"
$isJava = $false
$SEL = "Select string"
$DAFMComputer = "ControlPC"
#Do PC check to apply to only one PC
if ($DAFMComputer -like "ControlPC")
{
if (JavaPath -Path $JavaFolder) #if Java is installed
{
Foreach ($user in $users)
{
if (FileExists -Path "c:\Users\$user\AppData\LocalLow\Sun\Java\Deployment\security\exception.sites") #check for the file
{
$SEL = Select-String -Path "c:\Users\$user\AppData\LocalLow\Sun\Java\Deployment\security\exception.sites" -Pattern https://agapps.agriculture.gov.ie #Check for the string pattern
if ($SEL -ne $null)
{
#do nothing as the exception file exists with the URL we need do nothing
Copy-Item -Path \\thepath\Policies\{1FA921CE-231E-4982-8EBA-29E3AD4A44EF}\Machine\Scripts\Startup\exception.sites -Destination "c:\Temp\AlreadyThere\"
}
else
{
#add the following lines.
Add-Content "c:\Users\$user\AppData\LocalLow\Sun\Java\Deployment\security\exception.sites" "`nhttps://app.company.com/"
Add-Content "c:\Users\$user\AppData\LocalLow\Sun\Java\Deployment\security\exception.sites" "`nhttps://app.company.com/"
Add-Content "c:\Users\$user\AppData\LocalLow\Sun\Java\Deployment\security\exception.sites" "`We are adding lines"
Copy-Item -Path \\thepath\Policies\{1FA921CE-231E-4982-8EBA-29E3AD4A44EF}\Machine\Scripts\Startup\exception.sites -Destination "c:\Temp\FileExistsAddlines\"
}
}
else #file does not exist
{
Copy-Item -Path $Source -Destination "c:\Users\$user\AppData\LocalLow\Sun\Java\Deployment\security\exception.sites" -force
Copy-Item -Path \\thepath\Policies\{1FA921CE-231E-4982-8EBA-29E3AD4A44EF}\Machine\Scripts\Startup\exception.sites -Destination "c:\Temp\Filecopy\"
}
}
} # end file copy.
else
{
#No Java Do nothing
Copy-Item -Path \\thepath\Policies\{1FA921CE-231E-4982-8EBA-29E3AD4A44EF}\Machine\Scripts\Startup\exception.sites -Destination "c:\Temp\NoJavaDoNothing\"
}
else
{
Copy-Item -Path \\thepath\Policies\{1FA921CE-231E-4982-8EBA-29E3AD4A44EF}\Machine\Scripts\Startup\exception.sites -Destination "c:\Temp\NoComputerMatch\"
#do nothing as the PC name does not match
}
}
#Control line showing the script runs.
Copy-Item -Path \\thepath\Policies\{1FA921CE-231E-4982-8EBA-29E3AD4A44EF}\Machine\Scripts\Startup\exception.sites -Destination "c:\Temp\Running\"
The only line that reliably runs is the last control line on line 55 which copies a file to a folder. I've used similar copy file indicators in the if else loops to track and see where the loop is. But none of these are ever populated.
It's all the if elses are evaluating to false and no matter what i can't get it to enter the loop.
Any suggestions / pointers would be welcome
Thanks
John
I'm working on a script to test if a file exists in a target directory, and if false, execute an application installation.
The goal is to test if the file exists and if it does, abort with a log as to why. If the file does not exist, then the application installer should be executed.
I first tried creating a dummy file using New-Item to create both the directory and the dummy file.
New-Item -ItemType Directory -Force -Path "C:\temp"
New-Item -Path "C:\temp\vistaupdated.txt" -ItemType "file" -Value "Updated"
# Test if computer is updated
$file = Get-Content "C:\temp\vistaupdated.txt"
$containsWord = $file | %{$_ -match "Updated"}
if ($containsWord -contains $false) { ###start running the install stuff
However, this errors out if the file does not exist with an Object-NotFound. I then decided to switch tactics and use Test-Path:
$file = Test-Path -Path "C:\temp\vistaupdated.txt"
if ($file -eq $false) { ###start running the install stuff
In this case, I believe $file would evaluate to False and as a result execute the installation. On execution all I get is a return of the script's path:
PS C:\users\me\desktop> $filetest = Test-Path -Path "C:\temp\vistaupdated.txt"
PS C:\users\me\desktop> $filetest
False
PS C:\users\me\desktop> C:\Users\me\Desktop\vistaupdate.ps1
The above reference to the PS1 file doesn't execute. It's only what's returned if I run the script through ISE as administrator. If I do the same with the console, then the output is blank without any action taken.
# Test if computer is updated
$file = Test-Path -Path "C:\temp\vistaupdated.txt"
if ($file -eq $False) {
#package repository
$VistaInsPath = "\\apps\shared\me\vista\6.16.0"
#package installation command
$VistaInsEXE = "VistaClient.6.16.0.896"
#package installation parameters
$VistaInsParam = "/s /v/qn"
#logging
$logFile = "\\apps\shared\me\vista\6.16.0\log\vista_install.log"
#timestamp for logging
function Get-TimeStamp {
return "[{0:MM/dd/yy} {0:HH:mm:ss}]" -f (Get-Date)
}
#main function
function Vista-Install {
$errFlag = $false
try {
$cmdLine = "$VistaInsPath$VistaInsEXE"
Start-Process -FilePath $cmdLine -ArgumentList $VistaInsParam -Wait
} catch {
$(Get-TimeStamp) + "[" + $env:COMPUTERNAME +"]" + "[" + $env:USERNAME +"]" + "Error has occurred: " + $_.Exception.Message | Out-File $logFile -Append
$error.Clear()
$errFlag = $true
}
#if no error, notify success
if (-not $errFlag) {
$(Get-TimeStamp) + "[" + $env:COMPUTERNAME +"]" + "[" + $env:USERNAME +"]" + "Completed Successfully" | Out-File $logFile -Append
}
# Place dummy file to tag computer as updated
New-Item -ItemType Directory -Force -Path "C:\temp"
New-Item -Path "C:\temp\vistaupdated.txt" -ItemType "file" -Value "Updated"
}
} else {
$(Get-TimeStamp) + "[" + $env:COMPUTERNAME +"]" + "[" + $env:USERNAME +"]" + "Computer Already Updated. Aborting" | Out-File $logFile -Append
}
If Test-Path is False, then the installer should kick off in the first if statement. Instead the script spits back the path of the script itself and exits.
As #lit already pointed out in the comments to your question, you never invoke the function Vista-Install, so it's rather unsurprising that your code doesn't actually do anything. And you shouldn't define functions (or your $Vista* and $LogFile variables) in a nested scope anyway. The code in the else branch won't be able to find Get-TimeStamp or $LogFile with what you currently have.
Allow me to suggest some improvements:
Your logging code has a lot of redundant information. Instead of defining a function just for generating the timestamp, make a function that takes the log message as a parameter and otherwise completely encapsulates the logging.
$cmdLine = "$VistaInsPath$VistaInsEXE" will combine directory path and filename without a path separator, resulting in an incorrect path. Either put a backslash between the variables:
$cmdLine = "$VistaInsPath\$VistaInsEXE
or (better) use the Join-Path cmdlet, as #Theo suggested:
$cmdLine = Join-Path $VistaInsPath $VistaInsEXE
Put Test-Path directly in the if condition. There's no need to assign the result to a variable first.
The variable $errFlag is pointless. Just put the log statement after Start-Process. If an exception is thrown the code will go to the catch block without reaching that statement.
I assume you want the file vistaupdated.txt created only if the installation didn't throw an error, so that code should go in the try block too.
New-Item outputs an object for the item. You may want to suppress that.
The function Vista-Install doesn't make much sense either, as it would only install one specific program. Since it has very little code to begin with I would just drop it and put the code directly in the "then" branch. But if you wanted it to be a function you should name and parametrize it properly: pass program and arguments as parameters (preferably named after the parameters of Start-Process, so you can simply splat the $PSBoundParameters variable) and use a name conforming to the naming conventions:
function Install-Program {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true, Position=0)]
[string]$FilePath,
[Parameter(Mandatory=$false, Position=1)]
[string]$ArgumentList = #()
)
try {
Start-Process #PSBoundParameters
...
} catch {
...
}
}
Install-Program -FilePath (Join-Path $VistaInsPath $VistaInsEXE) -ArgumentList $VistaInsParam
Simplified code:
$VistaInsPath = '\\apps\shared\me\vista\6.16.0'
$VistaInsEXE = 'VistaClient.6.16.0.896'
$VistaInsParam = '/s', '/v', '/qn'
$logFile = '\\apps\shared\me\vista\6.16.0\log\vista_install.log'
function Write-Log {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$false)]
[string]$Message = ''
)
"[{0:MM/dd/yy HH:mm:ss}]`t[{1}\{2}]`t{3}" -f (Get-Date), $env:COMPUTERNAME, $env:USERNAME, $Message |
Out-File $script:LogFile -Append
}
if (-not (Test-Path -Path 'C:\temp\vistaupdated.txt')) {
$cmdLine = Join-Path $VistaInsPath $VistaInsEXE
try {
Start-Process -FilePath $cmdLine -ArgumentList $VistaInsParam -Wait
New-Item -Path 'C:\temp' -Type Directory -Force | Out-Null
New-Item -Path 'C:\temp\vistaupdated.txt' -Type File -Value 'Updated' | Out-Null
Write-Log 'Completed successfully.'
} catch {
Write-Log ('Error has occurred: {0}' -f $_.Exception.Message)
}
} else {
Write-Log 'Computer already updated. Aborting.'
}
Arguments could be made for flipping "then" and "else" branch to avoid a negated condition:
if (Test-Path -Path 'C:\temp\vistaupdated.txt') {
Write-Log 'Computer already updated. Aborting.'
} else {
$cmdLine = ...
...
}
or exiting from the script directly if the file exists in order to avoid an else branch entirely:
if (Test-Path -Path 'C:\temp\vistaupdated.txt') {
Write-Log 'Computer already updated. Aborting.'
exit
}
$cmdLine = ...
...
I'm trying to copy files from a source folder to a destination folder, and rename the files in the process.
$Source = "C:\Source"
$File01 = Get-ChildItem $Source | Where-Object {$_.name -like "File*"}
$Destination = "\\Server01\Destination"
Copy-Item "$Source\$File01" "$Destination\File01.test" -Force -
Confirm:$False -ErrorAction silentlyContinue
if(-not $?) {write-warning "Copy Failed"}
else {write-host "Successfully moved $Source\$File01 to
$Destination\File01.test"}
The problem is that since Get-ChildItem doesn't throw an error message if the file is not found, but rather just gives you a blank, I end up with a folder called File01.test in destination if no file named File* exists in $Source.
If it does exist, the copy operation carries out just fine. But I don't want a folder to be created if no matching files exist in $Source, rather I just want an error message logged in a log file, and no file operation to occur.
This shouldn't matter what the file name is, but it won't account for files that already exist in the destination. So if there is already File01.txt and you're trying to copy File01.txt again you'll have problems.
param
(
$Source = "C:\Source",
$Destination = "\\Server01\Destination",
$Filter = "File*"
)
$Files = `
Get-ChildItem -Path $Source `
| Where-Object -Property Name -Like -Value $Filter
for ($i=0;$i -lt $Files.Count;$i++ )
{
$NewName = '{0}{1:D2}{3}' -f $Files[$i].BaseName,$i,$Files[$i].Extension
$NewPath = Join-Path -Path $Destination -ChildPath $NewName
try
{
Write-Host "Moving file from '$($Files[$i].FullName)' to '$NewPath'"
Copy-Item -Path $Files[$i] -Destination
}
catch
{
throw "Error moving file from '$($Files[$i].FullName)' to '$NewPath'"
}
}
You can add an "if" statement to ensure that the code to copy the files only runs when the file exists.
$Source = "C:\Source"
$Destination = "\\Server01\Destination"
$File01 = Get-ChildItem $Source | Where-Object {$_.name -like "File*"}
if ($File01) {
Copy-Item "$Source\$File01" "$Destination\File01.test" -Force -Confirm:$False -ErrorAction silentlyContinue
if(-not $?) {write-warning "Copy Failed"}
else {write-host "Successfully moved $Source\$File01 to
$Destination\File01.test"}
} else {
Write-Output "File did not exist in $source" | Out-File log.log
}
In the "if" block, it will check to see if $File01 has anything in it, and if so, then it'll run the subsequent code. In the "else" block, if the previous code did not run, it'll send the output to the log file "log.log".
I am a complete novice when it comes to powershell, but I have been given a script that I need to improve so that we can move updated or new files from one server to another. I've managed to get to grips with the current script but am struggling to find the right cmdlets and paramters to achieve the desired behaviour.
The script I have is successful at detecting changed files and moving them to a location ready for transfer to another server, but it doesn't detect any new files.
Can anyone give me some guidance as to how I would be able to achieve both behaviours?
$CurrentLocation = "C:\current"
$PreviousLocation = "C:\prev"
$DeltaLocation = "C:\delta"
$source = #{}
#
# Get the Current Location file information
#
Get-ChildItem -recurse $CurrentLocation | Foreach-Object {
if ($_.PSIsContainer) { return }
$source.Add($_.FullName.Replace($CurrentLocation, ""), $_.LastWriteTime.ToString())
}
Write-Host "Content of Source"
$source
$changesDelta = #{}
$changesPrevious = #{}
#
# Get the Previous Directory contents and compare the dates against the Current Directory contents
#
Get-ChildItem -recurse $PreviousLocation | Foreach-Object {
if ($_.PSIsContainer) { return }
$File = $_.FullName.Replace($PreviousLocation, "")
if ($source.ContainsKey($File)) {
if ($source.Get_Item($File) -ne $_.LastWriteTime.ToString()) {
$changesDelta.Add($CurrentLocation+$File, $DeltaLocation+$File)
$changesPrevious.Add($CurrentLocation+$File, $PreviousLocation+$File)
}
}
}
Write-Host "Content of changesDelta:"
$changesDelta
Write-Host "Content of changesPrevious:"
$changesPrevious
#
# Copy the files into a temporary directory
#
foreach ($key in $changesDelta.Keys) {
New-Item -ItemType File -Path $changesDelta.Get_Item($key) -Force
Copy-Item $key $changesDelta.Get_Item($key) -Force
}
Write-Host $changesDelta.Count "Files copied to" $DeltaLocation
#
# Copy the files into the Previous Location to match the Current Location
#
foreach ($key in $changesPrevious.Keys) {
Copy-Item $key $changesDelta.Get_Item($key) -Force
}
Here's a simplified approach to your needs. One thing to note is that some of the constructs I've used require PSv3+. This does not copy directory structure, just the files. Additionally, it compares the basenames (ignoring extensions) which may or may not do what you want. It can be expanded to include extensions by using .Name instead of .BaseName
#requires -Version 3
$CurrentLocation = 'C:\current'
$PreviousLocation = 'C:\prev'
$DeltaLocation = 'C:\delta'
$Current = Get-ChildItem -LiteralPath $CurrentLocation -Recurse -File
$Previous = Get-ChildItem -LiteralPath $PreviousLocation -Recurse -File
ForEach ($File in $Current)
{
If ($File.BaseName -in $Previous.BaseName)
{
If ($File.LastWriteTime -gt ($Previous | Where-Object { $_.BaseName -eq $File.BaseName }).LastWriteTime)
{
Write-Output "File has been updated: $($File.FullName)"
Copy-Item -LiteralPath $File.FullName -Destination $DeltaLocation
}
}
Else
{
Write-Output "New file detected: $($File.FullName)"
Copy-Item -LiteralPath $File.FullName -Destination $DeltaLocation
}
}
Copy-Item -Path "$DeltaLocation\*" -Destination $PreviousLocation -Force
I have the following PowerShell script that copies all of the config files in certain directories to my local system. This script works as expected on many of my servers, but on 4 servers it fails:
$source = #()
switch ([System.Net.Dns]::GetHostByName(($env:computerName)).HostName)
# populate an array with a list of paths that contain config files to be copied
{
"SERVER1.DOMAIN" {
$source = #("C:\Program Files\MXC\", "C:\inetpub\wwwroot\")
$target = "\\tsclient\C\Backups\Configs\SERVER1\"
}
"SERVER2.DOMAIN" {
$source = #("C:\Program Files\MXC\")
$target = "\\tsclient\C\Backups\Configs\SERVER2\"
}
"SERVER3.DOMAIN" {
$source = #("C:\inetpub\wwwroot\ccb\001\", "C:\inetpub\wwwroot\eab\020\")
$target = "\\tsclient\C\Backups\Configs\SERVER3\"
}
"SERVER4.DOMAIN" {
$source = #("C:\inetpub\wwwroot\arv\drv\", "C:\inetpub\wwwroot\arv\imp\")
$target = "\\tsclient\C\Backups\Configs\SERVER4\"
}
function CopyConfigs ($configsList) {
try {
foreach ($file in $configsList) {
# get the folder the config file lives in so it can be created in the target dir
$folder = $file.DirectoryName | Split-Path -Leaf
$dest = $target + $folder + "\"
# if the $dest dir does not exist, create it.
if (-not (Test-Path -Path $dest -PathType Container -ErrorAction SilentlyContinue)) {
New-Item -ItemType Directory -Force -Path $dest
}
# copy the config file to the target directory
Copy-Item $file -Destination $dest -Force
}
Write-Host " End copying config files ====="
} catch {
Write-Host "** ERROR: An error occurred while trying to copy the $file to $dest"
return $Error[0].Exception
exit 1
}
}
try {
# get the locations and names of the config files to copy
foreach ($dir in $source) {
$configsList += get-childitem -Recurse -Path $dir *.config -Exclude *.dll.config,*.vshost*,*app.config,*packages.config,*-*,*company.config*
}
CopyConfigs $configsList
} catch {
Write-Host "** ERROR: An error occurred while trying to get a list of config files to copy."
Write-Host $Error[0].Exception
return 1
}
When it fails the error is:
Method invocation failed because [System.IO.FileInfo] does not contain a method named 'op_Addition'.
at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception)
at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
I verified PowerShell 4.0 is on all systems and that all paths are valid. This script both succeeds and fails on Windows Server 2008 R2 and Wdows Server 2012 servers.
I researched the 'op_Addition' error but I saw nothing about it working some times and not others. Normally this error has to do with trying to operate on something that is not an array, but I believe I've accounted for that in my script. And, it does work sometimes.
I'm really not sure what the problem is. Any help you can provide is greatly appreciated.
Just getting into Powershell, and I came across the same error message. The way I fixed this was to call the ".toString()" method where I was doing the string concatenation. I hope this helps someone else
foreach ($file in $configsList) {
# get the folder the config file lives in so it can be created in the target dir
$folder = $file.DirectoryName | Split-Path -Leaf
# $dest = $target + $folder + "\" <-- these are objects, so make them strings as below:
$dest = $target.ToString() + $folder.ToString() + "\"
# if the $dest dir does not exist, create it.
if (-not (Test-Path -Path $dest -PathType Container -ErrorAction SilentlyContinue)) {
New-Item -ItemType Directory -Force -Path $dest
}
# copy the config file to the target directory
Copy-Item $file -Destination $dest -Force
}
Write-Host " End copying config files ====="
Another way is to explicitly cast the variable as an array of file objects when assigning the result of Get-ChildItem:
...
foreach ($dir in $source) {
[System.IO.FileSystemInfo[]]$configsList += get-childitem -Recurse -Path $dir *.config -Exclude *.dll.config,*.vshost*,*app.config,*packages.config,*-*,*company.config*
}
...
You need to initialize the variable as an array first. Add this before you use it:
$configsList = #()