I am trying to execute this code, which just basically copies a file from over the network to the local logged on user's desktop if it is older than the one on the network. The first line of the following code works well, but it throws an error for the part where $env:userprofile is used inside an if block. No idea what's going on here.
Copy-Item -Path "\\path1\subpath1\subpath2\Patch\help\*" -Filter *.chm -Destination "$Env:UserProfile\Desktop" -force -Recurse
$chmfileNetwork = Get-ItemPropertyvalue -Path 'path1\subpath1\subpath2\Patch\help\*' -Filter *.chm -Name 'LastWriteTime'
$chmfileLocal = Get-ItemPropertyValue -Path '$Env:UserProfile\Desktop\*' -Filter *.chm -Name 'LastWriteTime'
if ($chmfileLocal -lt $chmfileNetwork) {
Copy-Item -Path "path1\subpath1\subpath2\Patch\help\*" -Destination "$Env:UserProfile\Desktop" -force -Recurse
} else {
echo "Saul good, man"
}
That throws the error
Get-ItemPropertyValue : Cannot find drive. A drive with the name '$Env'
does not exist.
At C:\Users\user1\Downloads\PS2EXE-GUI\psfile.ps1:28 char:17
+ ... fileLocal = Get-ItemPropertyValue -Path '$Env:UserProfile\Desktop\*' ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: ($Env:String) [Get-ItemPropertyValue], DriveNotFoundException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.GetItemPropertyValueCommand
You can use $home\Desktop to get a user's desktop folder, but Ansgar Wiechers really pointed out the problem with your script as to why it was throwing the error. You used single quotes on the chmfileLocal = line. Variables are not expanded when you use single quotes, only when you use double quotes. The original script could have been fixed with the change of:
$chmfileLocal = Get-ItemPropertyValue -Path "$Env:UserProfile\Desktop\*" -Filter *.chm -Name 'LastWriteTime'
Related
I am working on small script to capture file hashes on a running system. I only have Powershell available.
This is the active part of the code:
get-childitem -path $path -filter $filename -Recurse -Force | Select FullName | foreach-object { get-filehash $_.fullname | select * }
this is the command I am testing with:
./Get-FileHashesRecursive.ps1 -path c:\ -filename *.txt
When running the script I get a series of errors because certain folders are inaccessible. I'd like to record the paths of those folders so the user has a record on completion of what failed.
the error looks like this in a console window:
get-childitem : Access to the path 'C:\$Recycle.Bin\S-1-5-21-4167544967-4010527683-3770225279-9182' is denied.
At E:\git\Get-RemoteFileHashesRecursive\Get-FileHashesRecursive.ps1:14 char:9
+ get-childitem -path $path -filter $filename -Recurse -Force | ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (C:\$Recycle.Bin...3770225279-9182:String) [Get-ChildItem], UnauthorizedAccessException
+ FullyQualifiedErrorId : DirUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand
Is there a way I can grab the path or the entire first line of the error WITHOUT stopping the rest of the script from running?
As requested, here's my earlier comments as an answer:
Get-ChildItem -Path $Path -Filter $Filename -File -Recurse -Force -ErrorVariable FailedItems -ErrorAction SilentlyContinue | ForEach-Object { Get-FileHash -Path $_.FullName | Select-Object * }
$FailedItems | Foreach-Object {$_.CategoryInfo.TargetName} | Out-File "C:\Users\sailingbikeruk\Desktop\noaccess.log"
I have added the -File parameter to Get-ChildItem, because you are specifically dealing with only files.
I also added the -ErrorVariable and -ErrorAction parameters to the Get-ChildItem command. -ErrorVariable FailedItems defines a custom name for a variable which stores errors from the command during processing. -ErrorAction SilentlyContinue, tells the script to continue without notifying you of the errors.
Once your command has finished processing, you can parse the content of the $FailedItems variable. In the example above, I've output the TargetName to a file so that you can read it at your leisure, (please remember to adjust its file path and name as needed, should you also wish to output it to a file).
This Might be an easy one. But I can figure out what is going wrong with my simple copy script.
I have a shared directory that I am copying items from. I am printing out the destination path to console so I know it is correct But I am receiving a powershell error I do not understand.
Here is my script
#Files to copy
#Get Installers from folder
$APPS = Get-ChildItem \\Server1\shared\APPS -Name
#ForEach loop to identify and move files
ForEach($APP in $APPS) {
$dest = "\\Server1\Shared\APPS\$APP"
#Write-host to see destination path on console
write-host $dest
#copy item from destination path to local directory
Copy-Item $dest -Destination "c:\apps\"
}
This seems straight forward. But I don't understand why I am receiving the following error
\\Server1\Shared\APPS\LTCDesktopSetup.exe
Copy-Item : The filename, directory name, or volume label syntax is incorrect.
At C:\Users\computer1\documents\PowerShell\Moving Installer to local drive.ps1:13 char:2
+ Copy-Item $dest -Destination "c:\apps\"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Copy-Item], IOException
+ FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Commands.CopyItemCommand
Augusto,
I'd suggest this syntax:
$APPS = (Get-ChildItem "\\mybooklive\CMShared\NAS-Downloads" -filter *.exe).FullName
ForEach ($App in $Apps) {
copy-item "$APP" -Destination "G:\Test\Copy-Test" -Force
}
or the more compact:
$APPS = (Get-ChildItem "\\mybooklive\CMShared\NAS-Downloads" -filter *.exe).FullName |
copy-item -Destination "G:\Test\Copy-Test" -Force
Getting FullName vs Name so you don't have to add the source path back in.
Using -Filter so you only get .exe files (this is an assumption from the variable name $Apps).
The force will take care of some IO problems like the file already existing.
HTH
Naturally, you'll have to substitute your paths for my test ones.
I have a script where I recursively delete some bunch of files within certain directory. The problem is in specification of that directory.
When I try to specify it explicitly (i.e. to clear only user1 dir) it works fine:
$temp = "C:\Users\user1\AppData\Local\Temp\"
Get-ChildItem $temp -Recurse -Force -Verbose -ErrorAction SilentlyContinue | remove-item -force -Verbose -recurse -ErrorVariable FailedItems -ErrorAction SilentlyContinue
However when I specify it with wildcard (i.e. to affect all users on this PC)
$temp = "C:\Users\*\AppData\Local\Temp\*"
Get-ChildItem $temp -Recurse -Force -Verbose -ErrorAction SilentlyContinue | remove-item -force -Verbose -recurse -ErrorVariable FailedItems -ErrorAction SilentlyContinue
It fails with the error
Get-ChildItem : Access is denied
At line:7 char:1
+ Get-ChildItem $localTempDir -Recurse -Force -Verbose -ErrorAction Sil ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-ChildItem], UnauthorizedAccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.GetChildItemCommand
How that could be?
It is definitely not the permissions issue, 'cause it's the same dir.
And yes, I run script with an elevated privileges.
Other dirs specified in such format, e.g.
C:\Users\*\AppData\Local\Microsoft\Windows\Caches
C:\Windows\Temp\*
are purged like a charm.
Maybe you could use something along these lines, if you want to rule out a list of profiles, and process a list of subfolders:
$targets = "AppData\Local\Microsoft\Windows\Caches",
"AppData\Local\Microsoft\Windows\Temporary Internet Files"
$special = #("Default", "Public")
$profiles = Get-ChildItem "C:\Users" -Directory |
Where-Object Name -NotIn $special |
Select-Object -ExpandProperty FullName
$profiles | ForEach-Object {
foreach($target in $targets) {
$path = Join-Path $_ $target
#delete/empty $path
}
}
NB: syntax is PS3.0+
I am trying to take a screen saver file I've made and copy it to all of our desktops and laptops \system32 folder. I created a computers text file and found this script, but I keep getting this error. Any help would be appreciated.
Running this in Powershell 3.0 on a 2012 Server logged in as an admin.
$computers = gc "\\server\share\scripts\computers.txt"
$source = "\\share\scripts\MySlideshow.scr"
$dest = "C:\Windows\System32"
foreach ($computer in $computers) {
if (test-Connection -Cn $computer -quiet) {
Copy-Item $source -Destination \\$computer\$dest -Recurse
} else {
"$computer is not online"
}
}
Error:
Copy-Item : The given path's format is not supported.
At C:\users\tech\desktop\scripts\screen.ps1:6 char:9
+ Copy-Item $source -Destination \\$computer\$dest -Recurse
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Copy-Item], NotSupportedException
+ FullyQualifiedErrorId : System.NotSupportedException,Microsoft.PowerShell.Commands.CopyItemCommand
The resulting UNC format for you destination is invalid. You're passing
"\\computer\c:\windows\system32"
when you should be passing
"\\computer\c$\windows\system32"
Try quoting the -destination parameter like this too:
Copy-Item $source -Destination "\\$computer\$dest" -Recurse
You'll also need to use single-quotes when assigning to $dest to prevent powershell from trying to expand the dollar sign as a variable sigil.
$dest = 'c$\windows\system32'
Debug your script by using copy-item -whatif ... to ensure that you're passing the correct parameters.
I have been working on a PowerShell script for the better part of well a week or two. I've been able to get some parts of it working however I'm unable to fully get this automated.
I deal with a lot of CSV files on a daily basis, I have been tasked with uploading them into our software however sometimes they're too large to handle so I break them down based upon their "type" (it's a column in the CSV) and I export it to a single CSV per "type". I've been able to accomplish this with the following:
$file = gci -Filter "*.csv";
Import-Csv $file `
| Group-Object –Property “type” `
| Foreach-Object `
{
$path=$_.name+”.csv” ; $_.group `
| Export-Csv –Path $path –NoTypeInformation
}
So this works wonderfully, for each individual CSV. Unfortunately I don't have the time to do this for each individual CSV. Now I come to my other PowerShell script:
get-childitem -Filter "*.csv" `
| select-object basename `
| foreach-object{ $path=$_.basename+".csv" #iterate through files.
if(!(Test-Path -path $_.basename)) #If the folder of the file can't be found then it will attempt to create it.
{
New-Item $_.basename -type directory; $file=$_.basename+".csv";
Import-Csv $file `
| Group-Object -Property "Type" `
| Foreach-Object {
$path=$_.name+".csv"; $_.group `
| `
if(!(Test-Path -path $path2))
{
New-Item $path2 -type directory
Export-Csv -Path $path2 + "\" + $path -NoTypeInformation
}
else
{
"Failed on: " + $_.basename
#Export-Csv -Path $_.basename + "\" + $path -NoTypeInformation
}
}
}
else
{
Import-Csv $path `
| Group-Object -Property "Type" `
| Foreach-Object {$path=$_.basename+".csv" ; $_.group
if(Test-Path -path $._)
{
New-Item $path2 -type directory
Export-Csv -Path $path2 + "\" + $path -NoTypeInformation
}
#else
#{
Write-Host "Failed on: $_.basename"
#Export-Csv -Path $_.basename + "\" + $path -NoTypeInformation
#}
}
}
}
I just can't wrap my head around "why" this isn't working effectively. I have two conditionals. Is there a folder for the CSV? If no create one. I have to have another one because one of the "types" contains a \ which errors out if I don't have the folder, so I automatically try to create it. When I run the script I get the Path is null.
The Error is:
The term ' ' is not recognized as the name of a cmdlet, function,
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 C:\Users\c.burkinshaw\foldermake.ps1:11 char:26
+ | ` <<<<
+ CategoryInfo : ObjectNotFound: ( :String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Test-Path : Cannot bind argument to parameter 'Path' because it is null.
At C:\Users\c.burkinshaw\foldermake.ps1:12 char:45
+ if(!(Test-Path -path <<<< $path2))
+ CategoryInfo : InvalidData: (:) [Test-Path], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.TestPathCommand
Any help would be greatly appreciated, if you have questions please don't hesitate to ask.
You have not defined $path2 anywhere, so something like test-path -path $path2 will say path is null. And in one place you are using $._ which will again give errors.
Edit after question updated with error message:
Your error message also says the same
Test-Path : Cannot bind argument to parameter 'Path' because it is
null. At C:\Users\c.burkinshaw\foldermake.ps1:12 char:45
+ if(!(Test-Path -path <<<< $path2))
Also the other error is in:
$path=$_.name+".csv"; $_.group `
| `
what are you trying to do here with the $_.group?
It is not proper. You cannot do $_.group | and provide some if statement.
Other comments:
Why are using $_.basename and then appending .csv? You could have just used $_.name. Try to not use the select-object basename - I don't see the value.
Extract the common import-csv and export-csv part into a function.