Powershell Copy-Item Error when moving Bookmarks - windows

One of my scripts is to move Google Chrome bookmarks from one machine on the network to another. When I run the script, it appears to run and then throws a Copy-Item error. Pretty sure there's something wrong with my file path, but I can't figure out what it is.
Code first, error follows:
[CmdletBinding()]
param(
[String]$SourceComputerName,
[String]$DestinationComputerName,
[String]$UserName
)
BEGIN {
$ErrorActionPreference = 'Continue'
$CMDOUT=#{ #This is used so that the function accepts -Verbose / -Debug parameters
Verbose=If ($PSBoundParameters.Verbose -eq $true) { $true } else { $false };
Debug=If ($PSBoundParameters.Debug -eq $true) { $true } else { $false }
}
$SourcePath = '\\' + $SourceComputerName + '\C$\users\' + $UserName + '\AppData\Local\Google\Chrome\User Data\Default' #Transfer Bookmarks from here
$DestinationPath = '\\' + $DestinationComputerName + '\C$\users\' + $UserName + '\AppData\Local\Google\Chrome\User Data\Default' #Transfer Bookmarks to here
}
PROCESS{
#Create copy of destination backup file, make sure not to overwrite other backup files that might exsist
If(Test-Path ($DestinationPath + '\Bookmarks')){
$i = 1
do{
$BackupPath = ($DestinationPath + '\Bookmarks') + '_' + $i.ToString('000') + '.old'
$i++
}
while(Test-Path $BackupPath)
Copy-Item -Path ($SourcePath + '\Bookmarks') -Destination $BackupPath #CMDOUT
}
#Copy Bookmarks to DestinationComputer
Copy-Item -Path ($SourcePath + '\Bookmarks') -Destination ($DestinationPath + '\Bookmarks') -Force #CMDOUT
#Replace the Chrome create Bookmark backup (.bak) file
Copy-Item -Path ($SourcePath + '\Bookmarks') -Destination ($DestinationPath + '\Bookmarks.bak') -Force #CMDOUT
#Copy Favicons (for bookmarks)
If(Test-Path ($DestinationPath + '\Favicons')){
Copy-Item -Path ($SourcePath + '\Favicons') -Destination ($DestinationPath + '\Favicons') -Force #CMDOUT
}
}
END{
}
}
Copy-Item : The network path was not found
At C:\Users\Shane.goldsberry\PowerShellScripts\PS1\MigrateChromeBookmarks.ps1:61 char:9
Copy-Item -Path ($SourcePath + '\Bookmarks') -Destination ($D ...
+ CategoryInfo : NotSpecified: (:) [Copy-Item], IOException
+ FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Commands.CopyItemCommand
Copy-Item : The network path was not found At C:\Users\Shane.goldsberry\PowerShellScripts\PS1\MigrateChromeBookmarks.ps1:63 char:9 Copy-Item -Path ($SourcePath + '\Bookmarks') -Destination ($D ...
+ CategoryInfo : NotSpecified: (:) [Copy-Item], IOException
+ FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Commands.CopyItemCommand

Related

How to delete an image file based on its dimensions with PowerShell

I am trying to delete an image based on the dimensions of said image, but I've run into a problem.
I am trying to delete images whose length or width are less than 490 pixels. However, the code I have tried throws an error for every item. This is the error:
Remove-Item : Cannot remove item (file path): The process cannot access the file
'(file path)' because it is being used by another process.
At line:6 char:9
+ Remove-Item $_
+ ~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: ((file path):FileInfo) [Remove-Item], IOException
+ FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Here is my code:
[Void][Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$(Get-ChildItem -Filter *.jpg).FullName | ForEach-Object {
$img = [Drawing.Image]::FromFile($_);
If (($img.Width -lt 490) -or ($img.Height -lt 490)) {
Remove-Item $_
}
}
I am not running any apparent processes that would be using the images. When using Handle64, it says that powershell.exe is using the files. Any help would be appreciated!
The $img object is keeping the file in use, so you need to dispose of that before you can delete the file:
Add-Type -AssemblyName System.Drawing
(Get-ChildItem -Filter '*.jpg' -File).FullName | ForEach-Object {
$img = [System.Drawing.Image]::FromFile($_)
$w = $img.Width
$h = $img.Height
# get rid of the Image object and release the lock on the file
$img.Dispose()
If (($w -lt 490) -or ($h -lt 490)) {
Remove-Item -Path $_
}
}

Key not valid for use in specified state - A positional parameter cannot be found that accepts argument '+'

I am trying to understand what this error actually means. I am new to PowerShell and cannot
figure this one out. I have searched for similar questions but the content differs to my
requirement.
In a nut shell the script is queering a data historian system for a batch/lot number and the
start time of that batch.
This script will run every minute using task scheduler. This has not been set up yet as I am
still in the testing phase.
I have set up a service account is order for the script to run. The details of which are
stored in a cred file.
The script creates a folder using this batch/lot number.
The script creates a log file with the batch number and the start date and time of the batch.
Then the script searches a source folder on the server when a file is uploaded from the
factory floor into the source folder the script moves the file into the already created folder
with the correct batch number.
If files that are outside of the batch start and end time then the files are moved to no batch
folder where they will be reviewed manually.
I have done tests whereby I manually added files to the source folder on the server and
everything worked and did not get the "a positional parameter cannot be found that accepts
argument "+" from the script.
I am looking into the server configuration and permission levels but to my knowledge, nothing
has changed. I cannot see what is wrong with the script but hopefully, someone can give me
some pointers.
Error Code below
`PS C:\Users\a-graydx2> E:\Kistler Script\Batch ID with log 2021-11-29.ps1
An error occurred:
Key not valid for use in specified state.
Add-Content : A positional parameter cannot be found that accepts argument '+'.
At E:\Kistler Script\Batch ID with log 2021-11-29.ps1:186 char:11
+ Add-Content -Path $ErrorFileName -Value (Get-Date -Format " ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Add-Content], ParameterBindingException
+ FullyQualifiedErrorId :
PositionalParameterNotFound,Microsoft.PowerShell.Commands.AddContentCommand
An error occurred:
Key not valid for use in specified state.
Add-Content : A positional parameter cannot be found that accepts argument '+'.
At E:\Kistler Script\Batch ID with log 2021-11-29.ps1:186 char:11
+ Add-Content -Path $ErrorFileName -Value (Get-Date -Format " ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Add-Content], ParameterBindingException
+ FullyQualifiedErrorId :
PositionalParameterNotFound,Microsoft.PowerShell.Commands.AddContentCommand`
Script is below
Thanks for your help
`# Declare global variables
$fmSourcePath = "E:\Kistler\CoMo Services\Data\5336_L1.4345277\"
$shSourcePath = "E:\Kistler\CoMo Services\Data\5338_L1.5338_L1\"
$fmDesinationPath = "E:\Kistler XML Files\FM\"
$shDesinationPath = "E:\Kistler XML Files\SH\"
$fmWebAPI = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
$shWebAPI = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# the path to stored credential
$credPath = "E:\Kistler Script\Cred.xml"
$logFileName = "BatchLog.txt"
#Path to the error log file
$ErrorFileName = "E:\Kistler Script\errorlog.txt"
function Move_Kistler_Files {
param (
[string]$url,
[string]$SourcePath,
[string]$DestinationPath
)
try {
# check for stored credential
if ( Test-Path $credPath ) {
#crendetial is stored, load it
$cred = Import-CliXml -Path $credPath
} else {
# no stored credential then: create store, get credential and save it
$parent = split-path $credpath -parent
if ( -not ( test-Path $parent ) ) {
New-Item -ItemType Directory -Force -Path $parent
}
$cred = get-credential
$cred | Export-CliXml -Path $credPath
}
# Get the current batch id using the Web-API call
$result = Invoke-RestMethod -Uri $url -Credential $Cred
$BatchID = $result.Value
$BatchFolder = $DestinationPath + $BatchID
Write-Host $BatchFolder
# Create a new folder in the destination path based on the Batch ID
If(!(test-path $BatchFolder))
{
New-Item -ItemType Directory -Force -Path $BatchFolder | Out-Null
# Add the current date/time to the log file
$LogFile = $DestinationPath + $logFileName
# if file exist Update the last record with the batch end date
If((test-path $LogFile)){
$txt = get-content $LogFile
$txt[$txt.length - 1 ] = $txt[$txt.length - 1 ] + ", " + (Get-Date)
$txt | set-content $LogFile
}else{
#add a header row in the file
Add-Content -Path $LogFile -Value "BatchID, StartDate, EndDate"
}
# create a new record in the log file with current Batch Id and date as start of
batch indicator
$msg = $BatchID + ", " + (Get-Date)
Add-Content -Path $LogFile -Value $msg
}
##############################################################################
# Copy the Kistler XML files from the source to the destination
##############################################################################
# get al the Kistler XML files in the source folder
$Files = get-childitem -path $SourcePath -Recurse | Where-Object {$_.Extension -eq ".XML"}
| Sort-Object LastWriteTime -Descending
# If we have files to process do it
if ($Files.Length -gt 0) {
# read back the batch start and end dates from the log table
$LogFile = $DestinationPath + $logFileName
$txt = get-content $LogFile
# Get the latest Batch Id and it's start date
$FileMoveCount = 0
$FileNotMoveCount = 0
$ptr = 1
$batchArray =$txt[$txt.length - $ptr ].Split(",")
$MoveToPath = $DestinationPath + $batchArray[0]
$batchStartDate = $batchArray[1]
#Process each XML file
Foreach ($File in $Files ) {
$FileTime = $File.LastWriteTime
#write-host $File.FullName $File.Name $FileTime $MoveToPath $batchStartDate
#if the XML file's date-time is older than the batch start time, skip to the
previus Batch Id and start time
while ( ([DateTime]$FileTime -lt [DateTime]$batchStartDate) -and ($ptr -lt
($txt.length)-1) ) {
#Write a log for the number of files copied
if ($FileMoveCount -gt 0){
Add-Content -Path $ErrorFileName -Value ((Get-Date -Format "dd/MM/yyyy
HH:mm") + ": " + $FileMoveCount + " XML files moved to " + $MoveToPath)
$FileMoveCount = 0
}
$ptr++
$batchArray =$txt[$txt.length - $ptr ].Split(",")
$MoveToPath = $DestinationPath + $batchArray[0]
$batchStartDate = $batchArray[1]
#write-host $MoveToPath $batchStartDate
}
#Copy the XML file to the destination folder
if ([DateTime]$FileTime -ge [DateTime]$batchStartDate){
Move-Item $File.FullName -Destination ($MoveToPath + "\" + $File.Name)
$FileMoveCount++
}else{
Move-Item $File.FullName -Destination ($DestinationPath + "\NoBatch\" +
$File.Name)
$FileNotMoveCount++
}
}
#Write a log for the number of files copied
if ($FileMoveCount -gt 0){
Add-Content -Path $ErrorFileName -Value ((Get-Date -Format "dd/MM/yyyy HH:mm") + ": "
+ $FileMoveCount + " XML files moved to " + $MoveToPath)
}
if ($FileNotMoveCount -gt 0){
Add-Content -Path $ErrorFileName -Value ((Get-Date -Format "dd/MM/yyyy HH:mm") + ":
Could not find batch ID for " + $FileNotMoveCount + " XML files " )
}
}
}catch{
#Write the error
Write-Host "An error occurred:" -ForegroundColor red
Write-Host $_ -ForegroundColor red
Add-Content -Path $ErrorFileName -Value (Get-Date -Format "dd/MM/yyyy HH:mm") + ": " +
$_
}
}
### Process the FM Kistler files
Move_Kistler_Files $fmWebAPI $fmSourcePath $fmDesinationPath
### Process the SH Kistler files
Move_Kistler_Files $shWebAPI $shSourcePath $shDesinationPath`

PowerShell Script For Creating Same Folders In Multiple Directories

Current folder structure:
\\Server\Source\A1\A1 101\
\\Server\Source\A1\A1 102\
\\Server\Source\A2\A2 101\
\\Server\Source\A2\A2 102\
\\Server\Source\A3\A3 101\
\\Server\Source\A3\A3 102\
I need to be able to create 3 folders, A, B, and C, inside each of the second level folders under source (A1 101, A2 101, etc.). FolderDir.txt has A, B, C on their own line. Is there a better way other than the following? There are a LOT more sub directories than listed above:
Foreach($folder in Get-Content "C:\temp\folderDir.txt")
{
New-Item "\\Server\Source\A1\A1 101\$folder" -ItemType directory
New-Item "\\Server\Source\A1\A1 102\$folder" -ItemType directory
New-Item "\\Server\Source\A2\A2 101\$folder" -ItemType directory
New-Item "\\Server\Source\A2\A2 102\$folder" -ItemType directory
New-Item "\\Server\Source\A3\A3 101\$folder" -ItemType directory
New-Item "\\Server\Source\A3\A3 102\$folder" -ItemType directory
}
Thanks! I'm still pretty new to PowerShell.
This is what I came up with:
Foreach($folder in Get-Content "C:\temp\folderDir.txt")
{
$lesson = Get-ChildItem -Path \\Server\Source\A*\*
New-Item $lesson\$folder -ItemType Directory
}
But I'm getting the error:
New-Item : Could not find a part of the path 'A'.
At line:4 char:1
+ New-Item $lesson\$folder -ItemType Directory
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (\\Server\Source...\A:String) [New-Item], DirectoryNotFoundException
+ FullyQualifiedErrorId : CreateDirectoryIOError,Microsoft.PowerShell.Commands.NewItemCommand
New-Item : Could not find a part of the path 'B'.
At line:4 char:1
+ New-Item $lesson\$folder -ItemType Directory
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (\\Server\Source...\B:String) [New-Item], DirectoryNotFoundException
+ FullyQualifiedErrorId : CreateDirectoryIOError,Microsoft.PowerShell.Commands.NewItemCommand
New-Item : Could not find a part of the path 'C'.
At line:4 char:1
+ New-Item $lesson\$folder -ItemType Directory
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (\\Server\Source...\C:String) [New-Item], DirectoryNotFoundException
+ FullyQualifiedErrorId : CreateDirectoryIOError,Microsoft.PowerShell.Commands.NewItemCommand
However, if I put -WhatIf command on the end (after "directory") it appears to be able to do what I want...
Because the folderlist is iterated over several times it should be read in first
untested:
$folderlist = Get-Content "C:\temp\folderDir.txt"
Get-ChildItem -Path '\\Server\Source\*\*' -Directory | ForEach-Object {
ForEach ($folder in $folderlist){
New-Item (Join-Path $_.FullName $folder) -ItemType directory -Force -WhatIf
}
}
If the output look OK remove the -WhatIf

Get-Acl does not seem to work on UNC path?

I have difficulty getting Get-Acl to work on a UNC path to get the share permissions of a directory and all underlying files and directories.
The code I use looks like this:
$OutFile = "C:\Users\xxxx\Desktop\Permissions.csv"
$Header = "Folder Path,IdentityReference,AccessControlType,IsInherited,InheritanceFlags,PropagationFlags,FileSystemRights"
del $OutFile
Add-Content -Value $Header -Path $OutFile
$RootPath = "\\intranet\sites\folder1\folder2\target-folder-as-root"
$Folders = dir $RootPath -Recurse
#| where {$_.psiscontainer -eq $true}-recurse
foreach ($Folder in $Folders) {
$ACLs = Get-Acl $Folder.Fullname | ForEach-Object { $_.Access }
foreach ($ACL in $ACLs) {
$OutInfo = $Folder.Fullname + "," + $ACL.IdentityReference + "," +
$ACL.AccessControlType + "," + $ACL.IsInherited + "," +
$ACL.InheritanceFlags + "," + $ACL.PropagationFlags + "," +
$ACL.FileSystemRights
Add-Content -Value $OutInfo -Path $OutFile
}
}
Not taking into account the filename size limit issue this might cause, I get the following error:
Get-Acl : Method failed with unexpected error code 1.
At C:\Users\xxxx\Documents\ntfs_permissions.ps1:12 char:10
+ $ACLs = Get-Acl $Folder.Fullname | ForEach-Object { $_.Access }
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-Acl], InvalidOperationException
+ FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.PowerShell.Commands.GetAclCommand
I find documentation on listing the shared permissions on a shared drive using the UNC path (I don't want to list the permissions starting from the root, but only starting from a subfolder) is very limited.
Try to use: $ACLs = (Get-Acl $Folder.fullname).Access
Instead of: $ACLs = Get-Acl $Folder.Fullname | ForEach-Object { $_.Access }

Little issue with New-ItemProperty in PowerShell

I'm new to PowerShell and I can't seem to find how to fix this after countless Google searches. I know it's probably easy, but here's basically what I want to do and the error that shows:
PS C:\Windows\system32> $path = "HKLM:\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}"
Get-Childitem $path -ErrorAction SilentlyContinue | Foreach {
$key = Get-Item $_.PSPath
if($key.Property -eq "VMnet") {
New-ItemProperty $key -name "*NdisDeviceType" -value "1"
}
}
New-ItemProperty : Cannot find path 'C:\Windows\system32\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0014' because it does not exist.
At line:7 char:25
+ New-ItemProperty <<<< $key -name "*NdisDeviceType" -value "1"
+ CategoryInfo : ObjectNotFound: (C:\Windows\syst...02BE10318}\0014:String) [New-ItemProperty], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.NewItemPropertyCommand
New-ItemProperty : Cannot find path 'C:\Windows\system32\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0015' because it does not exist.
At line:7 char:25
+ New-ItemProperty <<<< $key -name "*NdisDeviceType" -value "1"
+ CategoryInfo : ObjectNotFound: (C:\Windows\syst...02BE10318}\0015:String) [New-ItemProperty], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.NewItemPropertyCommand
I clearly understand the error, it's obvious. But I don't know the proper way/command to fix it...
Try this:
$path = "HKLM:\SYSTEM\CurrentControlSet\Control\Class\" +
"{4D36E972-E325-11CE-BFC1-08002BE10318}"
Get-Childitem $path -ErrorAction SilentlyContinue |
Where {(Get-ItemProperty $_.PSPath DriverDesc) -match 'VMnet' } |
Foreach {
New-ItemProperty $_.PSPath -name "*NdisDeviceType" -value "1"
}
}
BTW I don't see any regkeys for values named "Property" perhaps you could match on the DriverDesc reg value? Anyway, the reason you're getting the error is you have to specify the PSPath to New-ItemProperty ie in your script $key.PSPath.

Resources