'Rename-Item' makes a copy with the new name - powershell

Trying to make a script to backup specific folders and then rename the GUID key for the target user under HKLM...\ProfileLists but the rename-item command makes a copy of the key and creates a new key with the appended name though having full access
Tried with -force, tried with move-item instead of rename but it gives the exact same results, a new identical key as original but with an appended name
if ((Test-Path $FULLPATH)) {
Rename-Item $FULLPATH -NewName "$SSID.bak" -Force
if ($?) {
Write-Host "$USERNAME was SUCCESSFULLY renamed in the registry"
}
}
Expected result is to only rename the GUID-key in the registry.
Actual result is a duplicate key with the new duplicate to have the correct appended name.
Rename-Item : The registry key at the specified path does not exist.
At line:9 char:5
+ Rename-Item $FULLPATH -NewName "$SSID.bak" -Force
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (HKEY_LOCAL_MACH...\folderredirect:String) [Rename-Item], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.RenameItemCommand
Rename-Item : Object reference not set to an instance of an object.
At line:9 char:5
+ Rename-Item $FULLPATH -NewName "$SSID.bak" -Force
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Rename-Item], NullReferenceException
+ FullyQualifiedErrorId : System.NullReferenceException,Microsoft.PowerShell.Commands.RenameItemCommand
The key does exist and I can run the same command again as proof (due to the test-path).
Verbose output do confirm its copying
VERBOSE: Performing the operation "Copy Key" on target "the key in question"

It works for me. Are your variables set in this way?
$SSID = 'S-1-5-21-1212123708-1212126490-1212120831-1001'
$FULLPATH = 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion\ProfileList\S-1-5-21-1212123708-1212126490-1212120831-1001'
rename-item $fullpath -newname "$SSID.bak"

I was unable to rename the keys with rename-item with full paths and not using variables either. However resolved it by replacing rename-item to
# Rename the Registry profile
if ((Test-Path $FULLPATH)) {
reg copy "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$SSID" "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$SSID-$(Get-Date -f yyy-MM-DD)" /s /f
if (( $? -eq 'True' )) {
reg delete "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$SSID" /f
}
if (( $? -eq 'True' )) {
Write-Host "$USERNAME was SUCCESSFULLY renamed in the registry"
}
had to use half the full path in the reg copy/delete commands as the syntax is different (no colon). This worked

Related

PowerShell script to set "date created" to specific times according to a csv file

I have some thousands of files in a folder that I need to bulk edit their creation time to a specific order.
I have prepared a csv file with all file names and the preferred creation times, like this:
filename;filecreationTime;
file1.mp4;10/11/2022 2:50;
file2.mp4;10/11/2022 2:49;
file3.mp4;10/11/2022 2:49;
etc
I have used this suggestion to a similar previous question: https://stackoverflow.com/a/36348448/20467894 and created a code like this:
Set-Location 'path to files'
Import-Csv -Path 'path to csv file' |
ForEach-Object { (Get-Item $_.filename).CreationTime = (Get-date $_.filecreationTime) }
The outcome is this error, for each line of the csv:
Get-Item : Cannot bind argument to parameter 'Path' because it is null.
At line:2 char:32
+ ForEach-Object { (Get-Item $_.filename).CreationTime = (Get-date ...
+ ~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Get-Item], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.GetItemComm
and
What am I doing wrong?
EDIT: After Theos' comment, it run once in a sample subset of my files but never run again. Now it can indeed read the filenames, but it brings a new error:
Get-date$_.filecreationTime : The term 'Get-date$_.filecreationTime' is not recognized as the name of a cmdlet, functio
n, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is
correct and try again.
At line:2 char:57
+ ... (Get-Item $_.filename).CreationTime = (Get-date$_.filecreationTime) }
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Get-date$_.filecreationTime:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Thanks everyone for your suggestions.
As pointed out by Theo, the problem was that in my language and regional formats the delimiter of the csv files is set to ";" instead of ",", as the latter is used as decimal...
So I had to insert an additional argument into the import csv (that was not obvious by the error expression), in order to clarify the non default delimiter:
-Delimiter ';'
So, the correct code for me was the following:
Set-Location 'path to files'
Import-Csv -Delimiter ';' -Path 'path to csv file' |
ForEach-Object { (Get-Item $_.filename).CreationTime = (Get-date $_.filecreationTime) }

Array with Commands

I have a list of files which I would like to move to other destinations. Issues:
Destination is different
Errors can occur, e.g. File does already exist in Destination.
If so, I would like to delete the existing file (e.g. $StartM\C\A.Lnk)
How can I do this with a list / foreach or other possibility?
Move-Item -Path "$StartM\C\A.Lnk" -Destination "$StartM\Maintenance"
Move-Item -Path "$StartM\C\B.Lnk" -Destination "$StartM"
The canonical way of dealing with a situation like that is to define a mapping between sources and destinations:
$shortcuts = #{
"$StartM\C\A.Lnk" = "$StartM\Maintenance"
"$StartM\C\B.Lnk" = "$StartM"
}
and then process that mapping like this:
foreach ($src in $shortcuts.Keys) {
Remove-Item $shortcuts[$src] -Force -EA SiltenlyContinue
Move-Item $src -Destination $shortcuts[$src]
}
Thank you Ansgar. I got some issues:
1. Remove-Item:
The Argument can not be bound with the Parameter "Path", because it is an empty string.
CategoryInfo: InvalidData: (:) [Remove-Item], ParameterBindingValidationException
FullyQualifiedErrorId: ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.RemoveItemCommand
2. Move-Item:
No position parameter was found, which accept the argument "\Maintenance"
May be there is a missunderstanding. Source should be deleted if exists in Destination. E.g.: "$StartM\C\A.Lnk" = "$StartM\Maintenance".
Goal: "$StartM\C\A.Lnk" should be deleted if "A.Lnk" exists in "$StartM\Maintenance\A.Lnk".
Move-Item $src = $shortcuts[$src]
CategoryInfo: InvalidArgument: (:) [Move-Item], ParameterBindingException
FullyQualifiedErrorId: PositionalParameterNotFound,Microsoft.PowerShell.Commands.MoveItemCommand
3. ErrorAction
Remove-Item: The Parameter "ErrorAction" can not be bound. Type "SiltenlyContinue" can not be converted in type "System.Management.Automation.ActionPreference" ...
I just changed "-EA" ... -Force -EA SilentlyContinuefrom to "-Error Action". This type of Error has gone.
4. Double keys
If there are some constelations in the array like this:
"$StartM\C\B.Lnk" & "$End\C\B.Lnk" I got an error that double keys are not allowed in Hashliterals.
CategoryInfo : InvalidOperation: (System.Collections.Hashtable:Hashtable) [], RuntimeException
FullyQualifiedErrorId : DuplicateKeyInHashLiteral

Copy-Item: Illegal characters in path

I'm trying to create a powershell script that will copy files from a source to the same path on multiple destination machines. I found this on the web and have pointed toward my test data, however, I continue to receive the following error (for each system it finds in the pc_list.txt).
Script:
$Computers = gc "C:\Temp\Script\PC_List.txt"
$Source = "C:\Temp\Script\AAAAA.txt"
$Destination = "C$\Temp\"
foreach ($Computer in $Computers) {
Copy-Item -Path $Source -Destination "\\$Computer\$Destination\" -Recurse
}
Error:
Copy-Item : Illegal characters in path.
At line:4 char:36
+ ... Computers) {Copy-Item $Source -Destination "\\$Computer\$Destination\ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Copy-Item], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.CopyItemCommand
PC Names in PC_List.txt:
DEPT-PC1
DEPT-PC2
DEPT-PC3
Can someone point me in the right direction?
BenH is correct. While I did not have any blank lines in the PC_List.txt, I did have a space at the end of each line... Great catch!!!
Now I’m getting “The target account name is incorrect”.
I’m thinking I’m going to need to add a $session credentials line but will need to figure out how to implement that piece...

Trying to use built-in PS1 methods Get-Date, Convert-Path, rename-item getting errors

I am new to PowerShell and trying to write my first script to copy files from one directory to another and then rename the files in the $DESTINATION directory once they are copied over there.
I am executing the script below from C:\Scripts directory on my machine.
The first foreach loop works great and my files land in the $DESTINATION.
But when I to through the 2nd loop I get the errors below
Any help/direction would be appreciated. Thanks.
Here is my code:
# Define variables.
$Source = "C:\ETLFILES\WinSCP\FilesETL\*.*"
$Destination = "C:\ETLFILES\WinSCP\SFE_Archive\"
$DestinationFiles = "C:\ETLFILES\WinSCP\SFE_Archive\*.*"
# Create the $sourceFileList variable to loop through
$sourceFileList = Get-ChildItem -path $Source
# Loop through the $soureFileList and copy the items to the $Destination.
foreach ($item in $sourceFileList) {
Copy-Item -Path $Source -Destination $Destination
}
# Create the $destinationFileList variable to loop through
$destinationFileList = Get-ChildItem -path $DestinationFiles
# Loop through the $destinationFileList and rename the files with appended DateTime stamp.
foreach ($itemDest in $destinationFileList) {
$Date = (Get-Date).ToString("yyyyMMdd_HHmmss")
$newFileName = $Date + "_" + $itemDest
Rename-Item $itemDest $newFileName
}
Here are the errors I'm getting and I think that I need to change the -path as it is looking to where the script is executing from and not looking at the $DestinationFiles directory like it looked to the $Source above:
PS C:\Scripts> C:\Scripts\ArchiveSFE_files.ps1
Rename-Item : Cannot rename the specified target, because it represents a path or device name.
At C:\Scripts\ArchiveSFE_files.ps1:21 char:5
+ Rename-Item $itemDest $newFileName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Rename-Item], PSArgumentException
+ FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.RenameItemCommand
Rename-Item : Cannot rename the specified target, because it represents a path or device name.
At C:\Scripts\ArchiveSFE_files.ps1:21 char:5
+ Rename-Item $itemDest $newFileName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Rename-Item], PSArgumentException
+ FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.RenameItemCommand
Rename-Item : Cannot rename the specified target, because it represents a path or device name.
At C:\Scripts\ArchiveSFE_files.ps1:21 char:5
+ Rename-Item $itemDest $newFileName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Rename-Item], PSArgumentException
+ FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.RenameItemCommand
Rename-Item : Cannot rename the specified target, because it represents a path or device name.
At C:\Scripts\ArchiveSFE_files.ps1:21 char:5
+ Rename-Item $itemDest $newFileName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Rename-Item], PSArgumentException
+ FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.RenameItemCommand
PS C:\Scripts>
PowerShell can be a bit tricky if you're used to text-based languages and tools, because everything in PowerShell is a .NET object.
This line:
$newFileName = Get-Date + "_" + $item # .ToString("yyyyMMdd-HHmmss") + "_" + $item
will most certainly result in an error. Get-Date returns a [datetime] object.
Although [datetime] does support the + operator, it expects an argument of the type [timespan] - and the string "_" can't be converted to a timespan.
What you want is a string representing the current date. Either use the ToString() statement that you've commented out, or use the -Format parameter to produce a formatted string instead of a [datetime] object:
$newFileName = (Get-Date).ToString("yyyyMMdd-HHmmss") + "_" + $item
or
$newFileName = (Get-Date -Format "yyyyMMdd-HHmmss") + "_" + $item
I'm not a betting man, but I'll bet the error you're having is this one.
Get-Date : Cannot bind parameter 'Date'. Cannot convert value "+" to type "System.DateTime".
Error: "String was not recognized as a valid DateTime."
This is because the code you've got here is trying to add a character to a PowerShell DateTime object, and that simply does not fly. You can pick a single property though and concatenate characters onto that, however.
But, I noticed that you commented out some lines in your code, and am guessing that you'd like to get the date in this format: "yyyyMMdd-HHmmss".
If that's so, this little snippet will do that for you:
# Define logic to rename and copy .
foreach ($item in $sourceFileList) {
$newFileName = $(Get-Date -UFormat %Y%m%d-%H%m%S) + "_" + $item
"the item $($item.BaseName) would become $newFileName"
}
This will output to the screen the new name for the file, like this:
the item q1 would become 20160921-110907_q1.png
the item q2 would become 20160921-110907_q2.png
the item q3 would become 20160921-110907_q3.png
You can comment out that line once you're happy with the new name. And the best part? Just drop this into your code inplace of your current $newFileName line and it will work with your previous code.
If I'm wrong, let me know the error you're getting and I'll help you get this sorted.
Looks like you are trying to write a file with : in the time part of the Get-Date when you try to rename to $newFileName. This will kick an error out.
$Date = Get-Date.ToString("yyyyMMdd_HHmmss")
$newFileName = $Date + "_" + $item
Include the above and that should prevent that problem.
thanks for everyone's help and input. I really appreciate it. I was finally able to resolve my problem whereby in the variable assigned in the foreach loop the FULL PATH was being defined that is what was generating the errors above. Once I used the .NAME property the issue was resolved. Thanks again to everyone.

Test-Path returns true but Remove-Item could not find path

I'm creating a script in PowerShell which is supposed to find a user's UPM folder and append .old to it (to facilitate a profile rebuild).
The snippet below is the code that I have:
# Rename the UPM profile
Exit-PSSession
cd '\\SYLX-FS-01\D$\UPMProfiles'
$UPMPath = "$target.upm"
$UPMOld = "$target.upm.old"
if (Test-Path $UPMPath -IsValid) {
if (Test-Path $UPMOld -IsValid) {
Remove-Item $UPMOld
Rename-Item $UPMPath -NewName $UPMOld
Write-Host "Renamed UPMProfile"
} else {
Rename-Item $UPMPath -NewName $UPMOld
Write-Host "Renamed UPMProfile"
}
} else {
# Write-Host "UPM Profile not found, no action has been taken on the file server."
$UPM = "False"
}
Every time I run this it returns an error that the file could not be found.
Remove-Item : Cannot find path '\\SYLX-FS-01\D$\UPMProfiles\bill.odwyer.upm.old'
because it does not exist.
At line:8 char:20
+ Remove-Item <<<< $UPMOld
+ CategoryInfo : ObjectNotFound: (\\SYLX-FS-01...er.upm.old:String) [Remove-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand
As far as I can tell, it should only be going to line 8 if the $UPMPath exists, and if not then it should just skip to else. What am I missing?
If you drop the flag "-IsValid" it should work.
IsValid returns true if the path itself is a valid (legal) path. It doesn't check if the file/folder exists.
If you drop the -IsValid the Test-path checks and returns true/false if the path exists or not.
Read more on: https://technet.microsoft.com/en-us/library/hh849776.aspx
Test-Path -IsValid checks if a path specification is valid, not if the path actually exists. Remove the parameter -IsValid to verify the existence of a path.
From the documentation:
-IsValid
Determines whether the syntax of the path is correct, regardless of whether the elements of the path exist. This parameter returns TRUE if the path syntax is valid and FALSE if it is not.