Excel.Application: Microsoft Excel cannot access the file '[<filename>]' There are several possible reasons: - excel

I have a PowerShell script that works, it helps me run multiple queries against multiple servers and save each output in different CSV and then merge them together into an Excel file.
$Servers = get-content -Path "Servers.txt"
$DatabaseName ="master"
#$credential = Get-Credential #Prompt for user credentials
$secpasswd = ConvertTo-SecureString "MyPassword" -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ("sa", $secpasswd)
$QueriesFolder = "Queries\"
$ResultFolder = "Results\"
ForEach($Server in $Servers)
{
$DateTime = (Get-Date).tostring("yyyy-MM-dd")
ForEach ($filename in get-childitem -path $QueriesFolder -filter "*.sql" | sort-object {if (($i = $_.BaseName -as [int])) {$i} else {$_}} )
{
$oresults = invoke-sqlcmd -ServerInstance $Server -Database $DatabaseName -Credential $credential -InputFile $filename.fullname
write-host "Executing $filename on $Server"
$BaseNameOnly = Get-Item $filename.fullname | Select-Object -ExpandProperty BaseName
$oresults | export-csv $ResultFolder$BaseNameOnly.csv -NoTypeInformation -Force
}
$All_CSVs = get-childitem -path $ResultFolder -filter "*.csv" | sort-object {if (($i = $_.BaseName -as [int])) {$i} else {$_}}
$Count_CSVs = $All_CSVs.Count
Write-Host "Detected the following CSV files: ($Count_CSVs)"
Write-Host " "$All_CSVs.Name"`n"
$ExcelApp = New-Object -ComObject Excel.Application
$ExcelApp.SheetsInNewWorkbook = $All_CSVs.Count
$output = "C:\Users\FrancescoM\Desktop\CSV\Results\" + $Server + " $DateTime.xlsx"
if (Test-Path $output)
{
Remove-Item $output
Write-Host Removing: $output because it exists already
}
$xlsx = $ExcelApp.Workbooks.Add()
for($i=1;$i -le $Count_CSVs;$i++)
{
$worksheet = $xlsx.Worksheets.Item($i)
$worksheet.Name = $All_CSVs[$i-1].Name
$file = (Import-Csv $All_CSVs[$i-1].FullName)
$file | ConvertTo-Csv -Delimiter "`t" -NoTypeInformation | Clip
$worksheet.Cells.Item(1).PasteSpecial()|out-null
}
$xlsx.SaveAs($output)
Write-Host Creating: $output
$ExcelApp.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($xlsx) | Out-Null;
Write-Host "Closing all worksheet"
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($ExcelApp) | Out-Null;
Write-Host "Closing Excel"
[System.GC]::Collect();
[System.GC]::WaitForPendingFinalizers()
Remove-Item "$ResultFolder\*" -Include *.csv
Write-Host "Cleaning all *.csv"
Start-Sleep -Seconds 3
}
In order to make this script more portable I want all the paths mentioned into it to be stored into a variable and then concatenated.
But as soon as I change:
$output = "C:\Users\FrancescoM\Desktop\CSV\Results\" + $Server + " $DateTime.xlsx"
into:
$output = $ResultFolder + $Server + " $DateTime.xlsx"
things get nasty and I receive the error:
Microsoft Excel cannot access the file 'C:\Users\FrancescoM\Documents\Results\0DC80000'.
There are several possible reasons:
• The file name or path does not exist.
• The file is being used by another program.
• The workbook you are trying to save has the same name as a currently open workbook.
At C:\Users\FrancescoM\Desktop\CSV\QueryLauncher.ps1:50 char:2
+ $xlsx.SaveAs($output)
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
I don't understand, I think I'm concatenating things right.
I also followed this StackOverflow post and restarted my computer after adding "C:\Windows\SysWOW64\config\systemprofile\desktop" but the problem isn't fixed.
How can a variable path mess things up with Excel?

Because you are not defining the full path in the $ResultFolder variable, it will be expanded using the current working directory.
Just look at the path you want it to be:
"C:\Users\FrancescoM\Desktop\CSV\Results\" + $Server + " $DateTime.xlsx"
and the resulting path using the partial $ResultFolder variable:
C:\Users\FrancescoM\Documents\Results\0DC80000
Since you want the output file in a folder on your desktop, set the $output to
$output = Join-Path $([Environment]::GetFolderPath("Desktop")) "CSV\Results\$Server $DateTime.xlsx"
EDIT
From your last comment I understand that you want the output to be in a subfolder called "Results" that resides inside the folder the script itself is in.
In that case do this:
# get the folder this script is running from
$ScriptFolder = if ($PSScriptRoot) { $PSScriptRoot } else { Split-Path $MyInvocation.MyCommand.Path }
# the following paths are relative to the path this script is in
$QueriesFolder = Join-Path -Path $ScriptFolder -ChildPath 'Queries'
$ResultFolder = Join-Path -Path $ScriptFolder -ChildPath 'Results'
# make sure the 'Results' folder exists; create if not
if (!(Test-Path -Path $ResultFolder -PathType Container)) {
New-Item -Path $ResultFolder -ItemType Directory | Out-Null
}
Then, when it becomes time to save the xlsx file, create the full path and filename using:
$output = Join-Path -Path $ResultFolder -ChildPath "$Server $DateTime.xlsx"
$xlsx.SaveAs($output)
P.S. I advice to use the Join-Path cmdlet to combine file paths or to make use of [System.IO.Path]::Combine() instead of joining paths together like you do with this line: $oresults | export-csv $ResultFolder$BaseNameOnly.csv. Using the latter can lead to unforeseen pathnames if ever you forget to postfix the first path part with a backslash.
P.S.2 Excel has its own default output path set in Tools->Options->General->Default File Location and has no idea of the relative path for the script. This is why you should save using a Full path and filename.

Related

PowerShell for Excel: Sever external connections / remove queries / unlink external table data

I have a script which copies CSVs for each sheet in a formatted ("staging") workbook. The workbook is externally connected to a data source: a CSV export from our webform solution. Once this is completed, the script copies the staging workbook as well. But, in this new directory, the instance which is to display a specific form submission is still externally connected, so it's presently a pointless backup because it refreshes to the current form submissions export each time it opens.
TL;DR
How do I sever external connections / remove queries / unlink external table data in PowerShell?
Thanks in advance! And for the record, there are several business limitations so unless it's a mild adjustment to the current workflow, I won't be able to fulfill suggestions, i.e.- API, querying WP DB, Ansible, etc.
`
#set-executionpolicy -executionpolicy bypass
$Hosts = ".\ESXiHosts.csv"
$vCenter = ".\vCenter.csv"
$vSwitchPortGroups = ".\vSwitchPortGroups.csv"
$source = ".\source.csv"
$pivot = ".\pivot.csv"
If ((test-path $Hosts) -eq $true) {
Remove-Item $Hosts}
If ((test-path $vCenter) -eq $true) {
Remove-Item $vCenter}
If ((test-path $vSwitchPortGroups) -eq $true) {
Remove-Item $vSwitchPortGroups}
If ((test-path $vSwitchPortGroups) -eq $true) {
Remove-Item $source}
If ((test-path $vSwitchPortGroups) -eq $true) {
Remove-Item $pivot}
$staging = "formidableforms_staging"
$staging_file = $staging + ".xlsx"
$xlsxLoc = "\\blahblah\fs\groups\SysOps\Managed Infrastructure\Client Intake\Formidable Forms\"
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $false
$Excel.DisplayAlerts = $false
$staging_wb = $Excel.Workbooks.Open($xlsxLoc+$staging_file)
$staging_wb.refreshall()
$connections = $staging_wb.Connections
while($connections | ForEach-Object {if($_.OLEDBConnection.Refreshing){$true}}){
Start-Sleep -Seconds 1
}
$staging_wb.Save()
$Excel.Quit()
Function ExportWSToCSV ($excelFileName, $csvLoc)
{
$excelFile = $excelFileName + ".xlsx"
$E = New-Object -ComObject Excel.Application
$E.Visible = $false
$E.DisplayAlerts = $false
$wb = $E.Workbooks.Open($csvLoc+$excelFile)
foreach ($ws in $wb.Worksheets)
{
$n = $ws.Name
$ws.SaveAs($csvLoc + $n + ".csv", 6)
}
$E.Quit()
}
ExportWSToCSV -excelFileName "formidableforms_staging" -csvLoc "\\blahblah\fs\groups\SysOps\Managed Infrastructure\Client Intake\Formidable Forms\"
stop-process -processname EXCEL
#Remove-Item -path "\\blahblah\fs\groups\SysOps\Managed Infrastructure\Client Intake\Formidable Forms\pivot.csv"
#Remove-Item -path "\\blahblah\fs\groups\SysOps\Managed Infrastructure\Client Intake\Formidable Forms\source.csv"
$CleanupHosts = Import-CSV $Hosts
$CleanupHosts | Where-Object {$_.ESXiHostDNSName -ne ''} | Export-CSV -path ".\ESXiHosts.csv" -NoTypeInformation -Force
$CleanupvCenter = Import-CSV $vCenter
$CleanupvCenter | Where-Object {$_.vCenterFQDN -ne ''} | Export-CSV -path ".\vCenter.csv" -NoTypeInformation -Force
$CleanupvSwitchPortGroups = Import-CSV $vSwitchPortGroups
$CleanupvSwitchPortGroups | Where-Object {$_.Type -ne ''} | Export-CSV -path ".\vSwitchPortGroups.csv" -NoTypeInformation -Force
$createdir = Import-CSV $vCenter
$custfolder = ($createdir).FOLDER
$FOLDERdate = (Get-Date -Format "MM-dd-yyyy_HHmm")
Try {new-item -path . -name $custfolder -itemtype "directory" -ErrorAction Stop}
Catch {write-host "The folder: $custfolder already exists."}
new-item -path $custfolder\ -name $FOLDERdate -itemtype "directory"
Copy-item *.CSV -Destination .\$custfolder\$FOLDERdate
Remove-item .\ESXiHosts.csv
Remove-item .\vCenter.csv
Remove-item .\vSwitchPortGroups.csv
Remove-item .\pivot.csv
Remove-item .\source.csv
Remove-item .\Hosts.csv
Remove-item .\Network.csv
Remove-item .\Storage.csv
Remove-item .\Other.csv
cd "\\blahblah\fs\groups\SysOps\Managed Infrastructure\Client Intake\Formidable Forms\"
Copy-item *.XLSX -Destination .\$custfolder\$FOLDERdate\$custfolder.xlsx
cd .\$custfolder\$FOLDERdate
Remove-item .\pivot.csv
cd "\\blahblah\fs\groups\SysOps\Managed Infrastructure\Client Intake\Formidable Forms\"
`
I cannot find documentation for any of the requested items, only adjusting the existing properties of the connection, or GUI how-tos.

Powershell If Statement not working - Posh-ACME

I am struggling to get the last if statement to work.
I have a blob storage account which contains the directories mentioned and a certificate.
I want to import that certificate to the keyvault.
When I run the pipeline (which contains the below script), it just runs to where I have put the Write-host 'everything..'
Can someone please assist why it won't work, I have tried to separate to 3 if statements, remove the if statement nothing has worked.
param (
[string] $CertificateNames,
[string] $KeyVaultResourceId
)
# Split certificate names by comma or semi-colon
$certificateName = $CertificateNames.Replace(',', ';') -split ';' | ForEach-Object -Process { $_.Trim() } | Select-Object -First 1
# For wildcard certificates, Posh-ACME replaces * with ! in the directory name
$certificateName = $certificateName.Replace('*', '!')
# Set working directory
$workingDirectory = Join-Path -Path "." -ChildPath "pa"
# Set Posh-ACME working directory
$env:POSHACME_HOME = $workingDirectory
Import-Module -Name Posh-ACME -Force
# Resolve the details of the certificate
$currentServerName = ((Get-PAServer).location) -split "/" | Where-Object -FilterScript { $_ } | Select-Object -Skip 1 -First 1
$currentAccountName = (Get-PAAccount).id
# Determine paths to resources
$orderDirectoryPath = Join-Path -Path $workingDirectory -ChildPath $currentServerName | Join-Path -ChildPath $currentAccountName | Join-Path -ChildPath $certificateName
$orderDataPath = Join-Path -Path $orderDirectoryPath -ChildPath "order.json"
$pfxFilePath = Join-Path -Path $orderDirectoryPath -ChildPath "fullchain.pfx"
Write-Host 'everything works up until here.. then breaks'
# If we have a order and certificate available
if ((Test-Path -Path $orderDirectoryPath) -and (Test-Path -Path $orderDataPath) -and (Test-Path -Path $pfxFilePath)) {
Write-Host 'check paths are ok'
$pfxPass = (Get-PAOrder $certificateName).PfxPass
# Load PFX
$certificate = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList $pfxFilePath, $pfxPass, 'EphemeralKeySet'
# Get the current certificate from key vault (if any)
$azureKeyVaultCertificateName = $certificateName.Replace(".", "-").Replace("!", "wildcard")
$keyVaultResource = Get-AzResource -ResourceId $KeyVaultResourceId
$azureKeyVaultCertificate = Get-AzKeyVaultCertificate -VaultName $keyVaultResource.Name -Name $azureKeyVaultCertificateName -ErrorAction SilentlyContinue
Write-Host 'check if certificate is in kv'
# If we have a different certificate, import it
If (-not $azureKeyVaultCertificate -or $azureKeyVaultCertificate.Thumbprint -ne $certificate.Thumbprint) {
Import-AzKeyVaultCertificate -VaultName $keyVaultResource.Name -Name $azureKeyVaultCertificateName -FilePath $pfxFilePath -Password (ConvertTo-SecureString -String $pfxPass -AsPlainText -Force) | Out-Null
}
Write-Host 'check if upload is success'
}
When the pipeline is run, it breaks and there is no errors:
see screenshot here
Resolved this, the issue was the file paths didn't exist so the if statement couldn't check against an invalid file path.
As there was no errors, this was a bit harder to find the reason, instead I removed the if statement and added Write-Host "test" to see where things were broken in the code.

Powershell code cannot recognize all excel file(*.xlsm) in current location

I'm currently working on Powershell to handle excel files(*.xlsm).
The problem is the code below can only read "test.xlsm".
When the name is not test like "this.xlsm" , that code cannot read the file.
Any help...?
Thanks for your answer in advance :)
$destination = "C:\JJ\"
$dirName = Get-ChildItem -Name -Filter *.xlsm
$saveAs = $destination + "new\"
foreach($z in $dirName){
$excel=New-Object -ComObject Excel.Application
$excel.visible=$false
$excel.Displ`ayAlerts=$false
$book=$excel.Workbooks.Open($destination + $z)
$sheet=$book.Worksheets.item(1)
$sheet.Cells.Item(1,5)="=max(B2:B6)"
$book.SaveAs($saveAs + $z)
$excel.Quit()
$excel=$null
}
You are using confusing variable names in your code.. Why call the source path $destination??
Anyway, you should use the -File switch on your Get-ChildItem cmdlet to make sure this will only return FileInfo objects, not DirectoryInfo objects aswell. (these are Objects, not strings)
Then, there is a better way to construct paths. Use Join-Path instead of concatenating things like with $destination + $z.
Lastly, I would create the Excel object only once, before the loop and cleanup memory afterwards. Now, you are creating new COM objects in every iteration and never release them from memory.
Below code should do what you intend:
$source = "C:\JJ"
$destination = Join-Path -Path $source -ChildPath 'new'
# test if the destination path already exists and if not, create it
if (!(Test-Path -Path $destination -PathType Container)) {
$null = New-Item -Path $destination -ItemType Directory
}
# create the Excel COM object outside the loop
$excel = New-Object -ComObject Excel.Application
$excel.visible = $false
$excel.DisplayAlerts = $false
# get all *.xlsm files inside the source folder
Get-ChildItem -Path $source -Filter '*.xlsm' -File | ForEach-Object {
# The $_ automatic variable represents 1 FileInfo object in each iteration
$book = $excel.Workbooks.Open($_.FullName)
$sheet = $book.Worksheets.item(1)
$sheet.Cells.Item(1,5) = "=max(B2:B6)"
# join the destination path and the file name for output
$saveAs = Join-Path -Path $destination -ChildPath $_.Name
$book.SaveAs($saveAs)
$book.Close()
}
# cleanup Com objects
$excel.Quit()
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($sheet)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($book)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
$excel = $null
Note, If you have PowerShell version below 3.0, the -File switch is not available. Instead, then use
Get-ChildItem -Path $source -Filter '*.xlsm' | Where-Object {!$_.PSIsContainer} | ForEach-Object { ... }
# remove -name to get a directory object instead of a string
$dirName = Get-ChildItem -Filter *.xlsm
# you need the file name from the directory object listing
foreach($z in $dirName.name){ ...... }

Powershell Unable to find Excel and open Excel File

I am trying to have Powershell copy, rename than edit a excel file. It copies and renames the file as intended however when I go to open the file with excel it is unable to find the file. See attached code.
Thank you for the help.
#Export Textbox outputs
$S0 = $textBox1.Text
$jobname = $textBox2.Text
$contractor = $TextBox3.Text
#combine textbox outputs
$folder = "$S0" + "_" + "$jobname" + "_" + "$contractor"
$subsubfolder = ".\"+"$folder" + "\Dir"
$takeoffname = "$s0" + "_takeoff.xlsx"
#Excel
$xl = New-Object -ComObject excel.application
Start-Sleep -Seconds 5
$xl.Visible = $true
Start-Sleep -Seconds 5
$wb = $xl.Workbooks.Open("$subsubfolder\$takeoffname")
$data = $wb.Worksheets.Item("Storm")
$Data.Cells.Item(1,2) = "$jobname"
$data.Cells.Item(1,7) = "$S0"
$wb.Save()
$xl.Quit()
NEW updated Code - Added Join path and It broke the create folder loop. Sorry IF the added requirement to make the folder creates extra problems.
$S0 = $TextBox1.Text
$jobname = $TextBox2.Text
$contractor = $TextBox3.Text
$folder = ' {0}_{1}_{2}' -f $S0, $jobname, $Contractor
$file = '{0}_takeoff.xlsx' -f $S0
$PILname = 'PIL_{0}.xlsx' -f $S0
Write-host $folder
New-Item -ItemType Directory "./$folder"
foreach($line in Get-Content $Filenames)
{
New-Item $folder\$line -ItemType Directory
}
$subfolder = '{0}\1 - Estimating Original Quote Material' -f $folder
$subsubfolder = Join-Path -Path $PWD - ChildPath $Subfolder
$filePath = Join-Path -Path $PWD -ChildPath (Join-Path -Path $subsubfolderfolder -ChildPath $file)
$PILpath = Join-Path -Path $PWD -ChildPath (Join-Path -Path $subsubfolderfolder -ChildPath $PILname)
Write-host $filePath
Write-host $subsubfolder
pause
#Copy Files
Copy-Item '.\_master_takeoff.xlsx' "$subsubfolder\_master_takeoff.xlsx"
Copy-Item '.\PIL_S0XXXXX .xlsx' $subsubfolder
#Rename Files
Rename-Item -Path "$subsubfolder\_master_takeoff.xlsx" -newname $takeoffname
Rename-Item -Path "$subsubfolder\PIL_S0XXXXX .xlsx" -newname $PILpath
$xl = New-Object -ComObject excel.application
Start-Sleep -Seconds 5
$xl.Visible = $true
Start-Sleep -Seconds 5
$wb = $xl.Workbooks.Open("$subsubfolder\$takeoffname")
$data = $wb.Worksheets.Item("Storm")
$Data.Cells.Item(1,2) = "$jobname"
$data.Cells.Item(1,7) = "$S0"
$wb.Save()
$xl.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($wb) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($xl) | Out-Null
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
By taking strings off textboxes and combining that to a file path with string concatenation, you're bound to end up with a path that doesn't exist.
Having said that, the error comes from using the .\ in the path.
Powershell may know where that is, but Excel will have no idea where to look for the file. Excel has its own Default path, usually pointing to the Documents folder and when given relative paths, it will use that.
Always use existing, absolute file paths for opening stuff in external applications.
Better use something like this
#Export Textbox outputs
$prefix = $TextBox1.Text
$jobname = $TextBox2.Text
$contractor = $TextBox3.Text
#combine textbox outputs to form the directory (I like using the -f format operator)
$file = '{0}_takeoff.xlsx' -f $prefix
$folder = '{0}_(1}_{2}\Dir' -f $prefix, $jobname, $contractor
$filePath = Join-Path -Path $PWD -ChildPath (Join-Path -Path $folder -ChildPath $file)
# test if the file can be founc
if (Test-Path $filePath -PathType Leaf) {
$xl = New-Object -ComObject excel.application
$xl.Visible = $true
$wb = $xl.Workbooks.Open($filePath)
$data = $wb.Worksheets.Item("Storm")
$Data.Cells.Item(1,2) = $jobname
$data.Cells.Item(1,7) = $prefix
$wb.Save()
$xl.Quit()
# important: clean-up COM objects after use
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($wb) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($xl) | Out-Null
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
}
else {
Write-Warning "File '$filePath' not found"
}
Instead of using $PWD (Print Working Directory) you can also use Get-Location which in fact is the same thing
Since I have no idea why your updated code is creating subfolders, I'll leave that out here.
Please look at how the -f Format operator works because now you're doing that wrong.
Also, to not confuse the working directory for PowerShell and the default path for Excel anymore, define the full root path first in the code. Below I'm using a variable called $workingDir for that.
Copy-Item can copy and rename at the same time.
# let's forget about the 'Set-Location' and use absolute paths from the beginning
$workingDir = '\\Server\Share\Folder' # set this to the real path
# Export Textbox outputs
$S0 = $TextBox1.Text
$jobname = $TextBox2.Text
$contractor = $TextBox3.Text
# combine textbox outputs to form the directory (I like using the -f format operator)
$PILname = 'PIL_{0}.xlsx' -f $S0
$file = '{0}_takeoff.xlsx' -f $S0
$folder = '{0}_(1}_{2}\1 - Estimating Original Quote Material' -f $S0, $jobname, $contractor
$folderPath = Join-Path -Path $workingDir -ChildPath $folder # --> Full absolute path to the working folder
$filePath = Join-Path -Path $folderPath -ChildPath $file # --> Full absolute path to the file
Write-host $filePath
Write-host $folderPath
#Copy and rename master Files
$masterFile = Join-Path -Path $workingDir -ChildPath '_master_takeoff.xlsx'
$pilFile = Join-Path -Path $workingDir -ChildPath 'PIL_S0XXXXX.xlsx'
Copy-Item -Path $masterFile -Destination $filePath
Copy-Item -Path $pilFile -Destination (Join-Path -Path $folderPath -ChildPath $PILname)
############################
#Write to new take off file
############################
# Call excel and open file
$xl = New-Object -ComObject excel.application
$xl.Visible = $true
$wb = $xl.Workbooks.Open($filePath)
$data = $wb.Worksheets.Item("Storm")
$Data.Cells.Item(1,2) = $jobname
$data.Cells.Item(1,7) = $S0
$wb.Save()
$xl.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($wb) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($xl) | Out-Null
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
Everything seems ok with the code, but you are using relative paths.
If you are doing that, you need to change the working directory before opening the excel.
Ex: Set-Location C:\

Threads Output move-item verbose to file

I need some help with 2 problems to my script:
I have a script that moves all pictures (if there are any) from all the subfolder locations to a new subfolder under the "PRO" folder.
Problem 1:
I've turned on the -verbose command on move-item in hopes of outputting it to a log.txt file, but due to the threads it gives me errors "file is allready being used by another proces".
Problem 2:
Either i turn on the -Force command on the move-item and risk losing pictures when there are files with the same name or i find some way to rename them on the fly....
what i have sofar:
the extensions i want to move:
$movefiles_foto = #("*.tif", "*.tiff","*.gif","*.jpeg","*.jpg","*.jif","*.jfif", "*.jp2","*.jpx", "*.j2k", "*.j2c","*.fpx","*.pcd","*.png","*.JPEG")
the moving scriptblock:
$movefilesfoto = {
Param($extension,$loc)
$archive = "FOTO"
Get-ChildItem -Path $loc -Recurse -File -Filter $extension -Exclude $archive | ForEach-Object {
if ($_.FullName.IndexOf('\PRO\') -gt 0) {
$Destination = Join-Path -Path $_.FullName.Substring(0,$_.FullName.IndexOf('\PRO\') + 5) -ChildPath 'FOTO';
if (-not (Test-Path -LiteralPath $Destination -PathType Container)) {
New-Item -Type Directory -Path $Destination | Out-Null
}
$_ | Move-Item -Destination $Destination -Verbose;
} else {throw ("\PRO\ path not found in '$($_.FullName)'");}}}
starting the jobs part:
write-host "move foto"
foreach ($foto_file in $movefiles_foto)
{
Start-Job -ScriptBlock $movefilesfoto -ArgumentList $foto_file, $location
}
Get-Job | Wait-Job | Receive-Job | Out-File -FilePath $location\log.txt
My apolegies if this is too many questions at once, but wanted to avoid having to ask 3 seperate questions that might be related.
thanks in advance for any input
UPDATE:
verbose output to file is solved, so scratch problem 1!
The verbose info claiming it moves files from the same folder to the same folder disappeared and can't seem to be reproduced. So that leaves problem 2, the renaming
Problem 1:
An article on Stream redirection (full support introduced in PSv5)
Example:
Write-Verbose 'Example message!' -Verbose 4>&1 | Out-File C:\ex.txt -Force
Problem 2:
Function MoveFilesFoto
{
Param([String[]]$Extensions,[String]$Location)
$Archive = 'FOTO'
Get-ChildItem -Path $Location -Recurse -Filter -Include $Extensions -Exclude $Archive |
ForEach-Object {
If ($_.FullName -cmatch '\\PRO\\')
{
$Destination = Join-Path 'Parent' $Archive
If (!(Test-Path $Destination))
{
New-Item -Type Directory -Path $Destination > $Null
}
Move-Item -Path $_.FullName -Destination $Destination -Verbose 4>&1 | Out-File $Destination\Log.txt -Append -Force
}
Else
{
Throw "Could not find \PRO\ in $($_.FullName)"
}
}
}

Resources