Powershell incorrect parameter - powershell

So I am trying to pass the file directory to the function convert at the bottom. When I run the script I receive the output:
Succes
C:\test 2\00000027627-00001\PROCESSING CHECKLIST
convert : Invalid Parameter - 2\00000027627-00001\PROCESSING
At C:\Users\pmanca\Desktop\msbxmlreader.ps1:35 char:13
+ convert([string]$hostdirectoryPlusLoanPlusDocType)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (Invalid Paramet...0001\PROCESSING:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
It appears to be cutting off the file path after C:\test. Could the file path be too long? even so i wouldn't imagine getting the error at the function call and instead somewhere in the function when it couldn't resolve the path.
#? is a shortcut for where object and % is a shortcut for foreach-object
cls
#count 1 = Loan Number
#count 4 = Cust Num
#count 5 = Document Type
$hostdirectory = "C:\test 2"
$count = 0
$file = (Select-xml -Path "$hostdirectory\index.xml" -XPath / ).Node
$test = $file.ExportedResult.Docs.ExportedDoc.Doc.UdiValues.UdiValue.Value# | Select-Object {$_.UdiValue.Value.InnerXML} -Unique #|? {$_.UdiValue.Name -eq "Loan Number"}
$test | ForEach-Object{
$count++
# Write-Host $_.innerxml "----" $count
if($count -eq 1){
[string]$xmlHold = $_.InnerXML
$hostdirectoryPlusLoan = "$hostdirectory\$xmlHold"
if(!(test-path $hostdirectoryPlusLoan)){
New-Item $hostdirectoryPlusLoan -ItemType directory
}
}
if($count -eq 5){
[string]$xmlHold = $_.InnerXML
$hostdirectoryPlusLoanPlusDocType = "$hostdirectoryPlusLoan\$xmlHold"
if(!(test-path $hostdirectoryPlusLoanPlusDocType)){
New-Item $hostdirectoryPlusLoanPlusDocType -ItemType directory
}
if(Test-Path "$hostdirectory\$xmlhold.pdf"){
$check = Copy-Item "$hostdirectory\$xmlHold.pdf" -Destination $hostdirectoryPlusLoanPlusDocType -ErrorAction SilentlyContinue
if(-not $?) {write-warning "Copy Failed"; Write-Host $Error[0].exception.message}
else {write-host "Succes"}
Write-Host $hostdirectoryPlusLoanPlusDocType
convert([string]$hostdirectoryPlusLoanPlusDocType)
}
}
if($count -ge 8){
$count = 0
# Write-Host "-----------------------------------"
}
}
function convert([string]$inputDirectory){
write-host $inputDirectory
#Variable to hold current input directory
$InputPathFilter = $InputDirectory + '\*.pdf'
#Variable to hold the list of PDFs from the current input directory
$PDFList = #(gci $InputPathFilter | foreach {write-output $_.name})
#Loop through list of PDF files to convert to TIF image files.
for ($j=0; $j -lt $PDFList.count; $j++) {
#Each PDF will go into its own directory/batch
#Create a variable with only the file name
$FileName = $PDFList[$j] -replace(".pdf",'')
#Variable of the full path to the current PDF
$InputPath = $InputDirectory + '\' + $PDFList[$j]
#Variable to hold output path of each TIF file. Filename format is that used by batches in ScerIS (i.e. 00010001.tif, 00010002.tif, etc...)
$OutputFullDirectory = $inputlDirectory + '\' + $FileName + "_" + "{0:D4}" -f + '1' + '%04d.tif'
#Calls Ghostscript command line executable to process each PDF file into a group of single page TIF image files
&'C:\Program Files\gs\gs9.14\bin\gswin64c.exe' -sDEVICE=tiffg4 -dBATCH -dNOPAUSE -q -r600 "-sOutputFile=$OutputFullDirectory" "$InputPath"
#Increment the counter for the loop
$DocCounter = $j + 1
#Rename the current pdf so that it isn't processed again.
$RenamePath = $PdfList[$j] -replace("pdf", "pd_")
Rename-Item $InputPath $RenamePath -Force
}
}

First : In PowerShell, when you call a function you must not use parenthesis :
convert $hostdirectoryPlusLoanPlusDocType
or as suggested in comment
convert -inputDirectory $hostdirectoryPlusLoanPlusDocType
but not :
convert([string]$hostdirectoryPlusLoanPlusDocType)
Second : Your function should be declarated first and use after :
function toto ($var)
{
Write-Host $var
}
toto "voila"
and not
toto "voila"
function toto ($var)
{
Write-Host $var
}

Related

How to improve this Powershell script?

I wrote a powershell script that merges go pro video files if they have multiple files. It works when the videos are at the root drive i.e. C:, but otherwise not. The mergevideos.txt file is not created if I run the script from a different directory. Or the txt is created but it's empty. Not sure what's going on when run from a different directory.
So is there a way to fix these issues and refactor this code to make it better? Ideally I want the script to automatically look at the directory it's in or allows me to specify the directory it should work in so I can just call it from the same location but the videos can be anywhere.
$path = "C:/NewVideos/"
$oldvids = Get-ChildItem -Path $path *.mp4
foreach ($oldvid in $oldvids) {
$curpath = $oldvid.DirectoryName
$name = [System.IO.Path]::GetFileNameWithoutExtension($oldvid)
$ext = [System.IO.Path]::GetExtension($oldvid)
if ($name.StartsWith("GX01") -and !($name.EndsWith("_merged")))
{
$newvid = $curpath + $name + "_merged" + $ext
if ([System.IO.File]::Exists($newvid))
{
Write-Output "$name | ALREADY MERGED"
continue
}
$count = 1
for ($num = 2; $num -lt 10; $num++)
{
$nextpart = $name.Replace("GX01", "GX0" + $num)
if ([System.IO.File]::Exists($curpath + "/" + $nextpart + $ext))
{
$count = $num
}
}
if ($count -eq 1)
{
Write-Output "$name | SINGLE VIDEO"
continue
}
$mergefile = $curpath + "mergevideos.txt"
if (!(Test-Path $mergefile))
{
New-Item -path $curpath -name mergevideos.txt -type "file"
}
Clear-Content $mergefile
for ($num = 1; $num -le $count; $num++)
{
$nextpart = $name.Replace("GX01", "GX0" + $num)
$videofilename = "file '" + $nextpart + $ext + "'"
Add-Content $mergefile $videofilename
}
Write-Output "$name | MERGING $count VIDEOS"
ffmpeg -f concat -safe 0 -i $mergefile -c copy $newvid
}
}

Unable to delete or rename directories or Files with Multiple Square ([[...]] brackets in Path [duplicate]

This question already has answers here:
How can I make PowerShell handle [ or ] in file name well?
(2 answers)
Error "Could not find a part of the path" while setting attributes on an existing file
(2 answers)
Closed 4 months ago.
This post was edited and submitted for review 4 months ago and failed to reopen the post:
Original close reason(s) were not resolved
I have regular Jobs to clean up old User Windows-Profile directories on a central NAS.
Last time I had Directories containing double square Brackets in the path (Import from Macromedia or so). This looks like:
\server.ad.local\HOME1\Username\System\Anwendungsdaten\Macromedia\FlashPlayer\SharedObjects\G5EUZBX2\www.daserste.de\[[IMPORT]]\players.edgesuite.net\flash\plugins\osmf\advanced-streaming-plugin\v3.4\osmf2.0\AkamaiAdvancedStreamingPlugin.swf\HDCore.sol
As this Job should run automatically with Powershell I tired various things:
Tried to replace the brackets an rename the folder - no success
Tried LiteralPath for Remove-Item - no success
Tried to Deleted with Scripting.FileSystemObject - no success
I always get the following error Message:
The Element ... cannot be removed: A part of the Path "HDCore.sol" cannot be found.
Are there any ideas?
Tried to rename the Folder, tried remove-item with -LiteralPath, tried to use FileSystemObject.
All of the actions gave the same result: Error
Just to complete: here are the functions I used last:
Function RemoveChar
{
Param ($Path)
$Pattern = '#|&|%|\[{1,}|\]{1,}|\^|\s|\.{2,}'
if ($Path -imatch $Pattern){
Rename-Item -Path $Path -NewName ($Path -replace $Pattern,'') -ErrorAction SilentlyContinue
return ($Path -replace $Pattern,'')
} else {
return $Path
}
}
Function Truncate
{
Param ($Path)
$total_path_length_threshold = 248 # maximal erlaubte Zeichenzahl (248 für Verzeichnisse, 260 für Dateien)
$characters_to_truncate = 60 # Anzahl der zeichen, um die der name zu kürzen ist. Ein eindeutiger Index wird angehangen
$virtual_drive = "v:" # Für temp. Prozessing muss das Format "v:" haben
$collection = cmd /c dir $Path /s /b |? {$_.length -gt $total_path_length_threshold }
$count_paths = ($collection | measure).count - 1
foreach ($pathlong in $collection) {
$parent_path = Split-path -path $pathlong
subst $virtual_drive $parent_path
$leaf = split-path -leaf $pathlong
$short_virtual_path = join-path $virtual_drive $leaf
$item = Get-Item -LiteralPath $short_virtual_path
if (Test-Path -LiteralPath $item) {
$filename = $item.name
$filename_extension = $item.Extension
$basename = $item.BaseName
$basename_length = $basename.length
$new_index = "X" + $counter + "X"
$adjusted_characters_to_truncate = $characters_to_truncate + $new_index.length
if ( $basename_length -gt $adjusted_characters_to_truncate ) {
$length_to_use = $basename_length - $adjusted_characters_to_truncate
$new_filename = $basename.substring(0, $length_to_use ) + $new_index + $filename_extension
$new_path = $parent_path + $new_filename
$Path = $new_path
Rename-Item -LiteralPath $short_virtual_path -NewName $new_filename
}
}
subst v: /d
}
return $Path
}
Function removeRecursive
{
param([String] $Path)
$fso = new-object -com "Scripting.FileSystemObject"
function proc {
param($folder)
$folder.Files | foreach-object {
RemoveChar $_
}
$folder.Files | foreach-object {
$short = $fso.GetFile($_.FullName).ShortPath
LogWrite "$FullDate : Processing: $short"
$fso.DeleteFile($short,$true)
}
$folder.SubFolders | foreach-object {
proc $_
}
}
proc $fso.GetFolder($Path)
}
The function I call from main code is removeRecursive. And yes I tried Remove-Item -LiteralPath SomePath -Recursive -Force too but no success as well.

Powershell output formatting?

I have a script that scans for a specific folder in users AppData folder. If it finds the folder, it then returns the path to a txt file. So we can see the computer name and username where it was found.
I would like to be able to format the what is actually written to the text file, so it removes everything from the path except the Computer and User names.
Script:
foreach($computer in $computers){
$BetterNet = "\\$computer\c$\users\*\AppData\Local\Google\Chrome\User Data\Default\Extensions\gjknjjomckknofjidppipffbpoekiipm"
Get-ChildItem $BetterNet | ForEach-Object {
$count++
$betternetCount++
write-host BetterNet found on: $computer
Add-Content "\\SERVERNAME\PowershellScans\$date\$time\BetterNet.txt" $_`n
write-host
}
}
The text files contain information like this
\\computer-11-1004S10\c$\users\turtle\AppData\Local\Google\Chrome\User Data\Default\Extensions\gjknjjomckknofjidppipffbpoekiipm
\\computer-1004-24S\c$\users\camel\AppData\Local\Google\Chrome\User Data\Default\Extensions\gjknjjomckknofjidppipffbpoekiipm
\\computer-1004-23S\c$\users\rabbit\AppData\Local\Google\Chrome\User Data\Default\Extensions\gjknjjomckknofjidppipffbpoekiipm
If you have each line in a form of the string $string_containing_path then it is easy to split using split method and then add index(1) and (4) that you need:
$afterSplit = $string_containing_path.Split('\')
$stringThatYouNeed = $afterSplit[1] + " " + $afterSplit[4]
You can also use simple script that will fix your current logs:
$path_in = "C:\temp\list.txt"
$path_out= "C:\temp\output.txt"
$reader = [System.IO.File]::OpenText($path_in)
try {
while($true){
$line = $reader.ReadLine()
if ($line -eq $null) { break }
$line_after_split_method = $line.Split('\')
$stringToOutput = $line_after_split_method[1] + " " + $line_after_split_method[4] + "`r`n"
add-content $path_out $stringToOutput
}
add-content $path_out "End"
}
finally {
$reader.Close()
}
If you split your loop into two foreach loops, one for computer and user directory it would be easier to output the name of the user directory.
$output = foreach($computer in $computers){
$UserDirectories = Get-ChildItem "\\$computer\c$\users\" -Directory
foreach ($Directory in $UserDirectories) {
$BetterNet = Get-ChildItem (Join-Path $Directory.fullname "\AppData\Local\Google\Chrome\User Data\Default\Extensions\gjknjjomckknofjidppipffbpoekiipm")
Add-Content "\\SERVERNAME\PowershellScans\$date\$time\BetterNet.txt" "$computer $($Directory.name)`r`n"
write-host BetterNet found on: $computer
$BetterNet
}
}
$output.count

The term '-replace' is not recognized as the name of a cmdlet, function, script file, or operable program

I was editing my powershell script and it suddenly started to give me strange errors:
-replace : The term '-replace' is not recognized as the name of a cmdlet, function, script file, or operable program
and
-Get-TfsItemHistory : The term 'Get-TfsItemHistory' is not recognized as the name of a cmdlet, function, script file, or operable program
I would understand the second error, but -replace? Thats strange.
Get-TfsItemHistory is used in referenced file VersionsCache.ps1
Script.ps1:
#For all projects, that has been changed since last build updates [AssemblyVersion], [AssemblyFileVersion], and [AssemblyInformationalVersion], attributes in all assemblyinfo.cs files.
$rootDir = "C:\Projects\UI\Evis\Dev"
$version = "2.0.0"
$buildType = "beta"
$currentChangeset = 1789
$versionsCacheFile ="C:\Projects\UI\Evis\versionsCache.txt"
. "$rootDir\VersionsCache.ps1"
$projects = Get-ChildItem "$rootDir\*.csproj" -Recurse;
function UpdateAssemblyInfo{
Param ([string]$dir, [string]$assemblyVersion, [string]$assemblyInformationalVersion)
$assemblyVersionPattern = 'AssemblyVersion\("[0-9]+(\.([0-9]+|\*)){1,3}"\)'
$assemblyFileVersionPattern = 'AssemblyFileVersion\("[0-9]+(\.([0-9]+|\*)){1,3}"\)'
$assemblyInformationalVersionPattern = 'AssemblyInformationalVersion\(.*\)'
$newVersion = 'AssemblyVersion("' + $assemblyVersion + '")';
$newFileVersion = 'AssemblyFileVersion("' + $assemblyVersion + '")';
$newInformationalVersion = 'AssemblyInformationalVersion("' + $assemblyInformationalVersion + '")';
$assemblyInfoFile = Get-ChildItem $dir -Filter assemblyinfo.cs -Recurse -Depth 1
$assemblyInfoContent = (Get-Content $assemblyInfoFile.FullName)
-replace $assemblyVersionPattern, $newVersion
-replace $assemblyFileVersionPattern, $newVersion
if ($assemblyInfoContent -match $assemblyInformationalVersionPattern)
{
$assemblyInfoContent = $assemblyInfoContent -replace $assemblyInformationalVersionPattern, $newInformationalVersion
}
else{
$assemblyInfoContent = $assemblyInfoContent + "`r`n[assembly: $newInformationalVersion]"
}
$assemblyInfoContent| Out-File $assemblyInfoFile.FullName
}
$publishedChangesetsCache = Load-Versions $versionsCacheFile
foreach ($project in $projects)
{
$projectDir = $project.Directory.FullName;
$assemblyInfo = Get-ChildItem $projectDir -Filter assemblyinfo.cs -Recurse -Depth 1 | select -First 1
Write-Host $projectDir -NoNewLine
$publishedChangesets = GetpublishedChangesets -dir $projectDir -publishedChangesetsCache $publishedChangesetsCache
$latestChangesetId = GetLatestChangeset $dir
Write-Host "changeset: $latestChangesetId"
if (IsChangedSinceLastBuild $latestChangesetId $publishedChangesets){
$publishedChangesets.Insert(0,$currentChangeset)
}
$changesetToPublish = $publishedChangesets[0]
$informationalVersion = "$version.$changesetToPublish"
if ($buildType -ne ""){
$informationalVersion = "$version-$buildType$changesetToPublish"
}
UpdateAssemblyInfo $projectDir -assemblyVersion "$version.$changesetToPublish" -assemblyInformationalVersion $informationalVersion
}
Save-Versions $publishedChangesetsCache -file versionsCacheFile
I guess I have some syntactic error, because it worked yesterday, but I can't figure out where.
You need to add backticks if you want to put the -replace statement in a new line:
$assemblyInfoContent = (Get-Content $assemblyInfoFile.FullName) `
-replace $assemblyVersionPattern, $newVersion `
-replace $assemblyFileVersionPattern, $newVersion
Or just write it in one line...

Renaming Folders ascending

I want to automate my backups and Keep always some old versions. The idea was to use Windows Backup on a share and use a PowerShell script to start it.
I'm almost done, but I stuck at the renaming.
Share: \\Server\SysBackup\WindowsImageBackup
in that share there are Folders for all PC's I have. So for example I want to Keep the three last backups, it should to the following:
Current Backup: PC1
Old Backups: PC1_1, PC1_2
Now I want to rename them to one higher number
PC1_2 → PC1_3
PC1_1 → PC1_2
PC1 → PC1_1
So the backup now can use the PC1 Folder for the newest backup.
That's what I tried so far:
$BackupFolder = Get-ChildItem -Directory ($Target + "\WindowsImageBackup") |
Where-Object -Property Name -Like $env:computername* |
Select-Object -Property Name
$CurrentBackups = $BackupFolder.Count
if ($CurrentBackups -ge 1) {
Push-Location ($Target + "\WindowsImageBackup")
$i = 0
$xCurrentArray = $CurrentBackups - 1
$NewSubVersion = $CurrentBackups
while ($i -le $CurrentBackups) {
$NewName = $BackupFolder[$xCurrentArray].Name.TrimEnd("_")
Rename-Item $BackupFolder[$xCurrentArray] -NewName
}
Pop-Location
Clear-Variable $i
}
The files are not renamed, and I'm getting the following error:
You cannot call a method on a null-valued expression.
Rename-Item : Missing an argument for parameter 'NewName'. Specify a parameter of type 'System.String' and try again.
Where is my mistake?
I found the error
if ($CurrentBackups -ge 1)
{
Push-Location ($Target + "\WindowsImageBackup\")
$i= 0
$xCurrentArray = $CurrentBackups - 1
$NewSubVersion = $CurrentBackups
while ($i -lt $CurrentBackups)
{
if ($BackupFolder[$xCurrentArray].Contains("_"))
{
$Index = $BackupFolder[$xCurrentArray].IndexOf("_")
$NewName = $BackupFolder[$xCurrentArray].Substring(0, $Index)
Rename-Item $BackupFolder[$xCurrentArray] -NewName ($NewName + "_" + $NewSubVersion)
Clear-Variable Index
$NewSubVersion--
}
else
{
$NewName = $BackupFolder[$xCurrentArray]
Rename-Item $BackupFolder[$xCurrentArray] -NewName ($NewName + "_1")
}
$i++
$xCurrentArray--
}
Pop-Location
Clear-Variable i
}