Unable to unzip using powershell - powershell

I am trying to unzip using powershell with below command --
powershell.exe -nologo -noprofile -command "& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::ExtractToDirectory('E:\test.zip', 'E:\'); }"
I get below log
'E:\test1.txt'
already exists."
At line:1 char:53
+ & { Add-Type -A 'System.IO.Compression.FileSystem';
[IO.Compression.ZipFile]::Ex ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : IOException
===============================
I don't see the archive being unzipped.
Update 1
E:\test1.txt already exists at the destination. How to change the command to overwrite files.
Update 2
The version of powershell available doesn't support Expand-Archive

You can't overwrite files with that method. You need to read the documentation for ZipFileExtensions.ExtractToDirectory(source, destinationDirectoryName):
This method creates the directory specified by
destinationDirectoryName. If the destination directory already exists, this method does not overwrite it; it throws an IOException
exception. The method also creates subdirectories that reflect the
hierarchy in the zip archive. If an error occurs during extraction,
the archive remains partially extracted. Each extracted file has the
same relative path to the directory specified by
destinationDirectoryName as its source entry has to the root of the archive.
If you want to use ZipFileExtensions.ExtractToDirectory() with overwrite, you'll need to extract the files to a temporary folder and then copy/move them to the desired location.
Try something like:
do {
$TempFolder = Join-Path -Path $([System.IO.Path]::GetTempPath()) -ChildPath $([System.IO.Path]::GetRandomFileName());
} while ((Test-Path -Path $TempFolder));
mkdir $TempFolder | Out-Null;
[IO.Compression.ZipFile]::ExtractToDirectory('E:\test.zip',$TempFolder);
Get-ChildItem -Path $TempFolder -Recurse | Move-Item -Destination 'E:\' -Force;
rmdir $TempFolder;
Note that this code is untested.

Below is what solved my problem
md E:\temp
move E:\test.zip E:\temp
powershell.exe -nologo -noprofile -command "& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::ExtractToDirectory('E:\temp\test.zip', 'E:\temp\'); }"
del E:\temp\test.zip
move /Y E:\temp\* E:\
rd E:\temp

Related

Remove-Item command is not removing a folder and its contents

I have an application that will be un installed across our estate, so I am creating a PowerShell script to do this (it will be distributed through Intune). However after the uninstall a folder and 2 files remain. I added in Remove-Item but it will not remove the folder and content even with -Force and -Recurse included as it states it is in use, but I can manually delete the folder and contents without any issues.
My script is (I have changed sensitive information)
$FileName = "C:\Users\$env:USERNAME\AppData\Local\my_app\app1.exe"
if (Test-Path $FileName) {
Write-Host "File Exists"
}
else
{
Write-Host "File Doesn't Exists"
exit
}
cd "C:\Users\$env:USERNAME\AppData\Local\my_app"
.\Update.exe --uninstall
Remove-Item -Path C:\Users\$env:USERNAME\AppData\Local\my_app -Force -Recurse
The actual error states
Remove-Item : Cannot remove the item at 'C:\Users\superuser\AppData\Local\my_app' because it is in use
At line:21 char:1
+ Remove-Item -Path C:\Users\$env:USERNAME\AppData\Local\my_app - ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Remove-Item], PSInvalidOperationException
+ FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.RemoveItemCommand
You change locations into the same directory you are trying to delete. You need to change out of that directory. You have a few options here:
The Obvious Solution (Once You Know the Issue)
Change out of the directory:
cd .. # any path that is not part of the directory tree you want to delete
But PowerShell has some more useful ways to traverse directories. Read on for more information.
Solution 2: Windows PowerShell - Use the Location Stack
Opt for using Push-Location and Pop-Location instead of cd (aliased to Set-Location).Push/Pop-Location use the location stack. Use Push-Location to change to new directories and Pop-Location to walk backwards. In your case, this would work:
Push-Location "C:\Users\$env:USERNAME\AppData\Local\my_app"
.\Update.exe --uninstall
Pop-Location # This will return to the previous directory
Remove-Item -Path C:\Users\$env:USERNAME\AppData\Local\my_app -Force -Recurse
Solution 3: PowerShell Core - Use cd -
If you can utilize PowerShell Core, the same concept applies but PowerShell Core supports the bash-like cd - and cd + since version 6.2. Similar to using Push/Pop-Location, you can walk backwards and forwards to the directories you've been to. In your case, cd - would work like so:
cd "C:\Users\$env:USERNAME\AppData\Local\my_app"
.\Update.exe --uninstall
cd - # This will return to the previous directory
Remove-Item -Path C:\Users\$env:USERNAME\AppData\Local\my_app -Force -Recurse
From the Set-Location documentation for PowerShell Core:
PowerShell 6.2 added support for - and + as a values for the Path parameter. PowerShell maintains a history of the last 20 locations that can be accessed with - and +. This list is independent from the location stack that is accessed using the StackName parameter.

Several folders into a zip with PowerShell

I have several folders dir_01, dir_02, dir_03 that I want to backup in a zip file, say, backup.zip. This has to be saved in a folder with today's date. I need to get a .bat file to do the job; no additional third party executables allowed.
Here I found how to create a folder with today's date, but I am having problems to pass $destination to -DestinationPath. I created a .bat that calls PowerShell. Code giving me problems:
powershell.exe $destination = New-Item -Path 'C:\path\to\destionation' -ItemType Directory -Name ("$(Get-Date -f yyyy-MM-dd)")
powershell.exe -nologo -noprofile -command Compress-Archive -Path 'C:\path\dir_01', 'C:\path\dir_02', 'C:\path\dir_03' -DestinationPath $destination\backup.zip -Force
The error message is the following:
New-Object : Exception calling ".ctor" with "2" argument(s): "Access to the path 'C:\backup.zip' is denied."
At
C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\Microsoft.PowerShell.Archive\Microsoft.PowerShell.Archive.psm1:729
char:30
+ ... ileStream = New-Object -TypeName System.IO.FileStream -ArgumentList $ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
However, the code works if I hard-code the path to destination, like this:
powershell.exe -nologo -noprofile -command Compress-Archive -Path 'C:\path\dir_01', 'C:\path\dir_02', 'C:\path\dir_03' -DestinationPath 'C:\whole\path\backup.zip' -Force
But doing so, I'm unable to save backup.zip in today's folder.
Question: How can I save backup.zip in the folder that I created with today's date?
You can perform both commands in the same PowerShell session by separating them with a semicolon.
powershell.exe $destination = New-Item -Path 'C:\path\to\destionation' -ItemType Directory -Name ("$(Get-Date -f yyyy-MM-dd)"); Compress-Archive -Path 'C:\path\dir_01', 'C:\path\dir_02', 'C:\path\dir_03' -DestinationPath $destination\backup.zip -Force
That will launch PowerShell and have it create the folder and then zip things into it in the same session, rather than create a session, in that session create a folder, close the session, start a new PowerShell session, zip things up, close the second session.

Powershell Remove-Item Cmdlet error

I'm using powershell to remove a directory with the command:
Remove-Item $pathAsString -Recurse -Force
However, it gives me the following error:
Remove-Item : Cannot remove the item at 'C:\Path' because it is in use.
At line:1 char:1
+ Remove-Item "C:\Path" -Recurse
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Remove-Item], PSInvalidOperationException
+ FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.RemoveItemCommand
I thought that was odd, because the directory shouldn't be in use. I can go into file explorer and delete the directory manually. I'm not really sure why this behavior is occurring. I'm fairly new to powershell, so don't understand exactly how it behaves.
My scripts interaction with the program includes:
Creating the folder
Downloading an MSI to the folder
Setting a variable to represent the MSI stored in the folder. Like so:
$MSIVariable = Get-ChildItem $Path | Where {&_.Name -eq "MSIName.msi"}
I'm assuming that something to do with the folder is within a stream of some sort, but don't know how I'd fix this issue.
EDIT:
Here is the code I use involving the folder:
Creating the Folder:
if(!(Test-Path $MSILocation))
{
New-Item $MSILocation -ItemType directory
}
Downloading the MSI:
$webClient = (New-Object System.Net.WebClient)
$downloadLocation = Join-Path $MSILocation $MSIName
$webClient.DownloadFile($downloadURL, $downloadLocation)

Delete broken link

I need to delete all the content of a folder which may include broken links among others. The folder path is provided by a variable. Problem is that PowerShell fails to remove the broken links.
$folderPath = "C:\folder\"
Attempt 1:
Remove-Item -Force -Recurse -Path $folderPath
Fails with error:
Remove-Item : Could not find a part of the path 'C:\folder\brokenLink'.
At line:1 char:1
+ Remove-Item -Force -Recurse -Path $folderPath
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (C:\folder\brokenLink:String) [Remove-Item], DirectoryNot
FoundException
+ FullyQualifiedErrorId : RemoveItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Attempt 2:
Start-Job { cmd /c rmdir $folderPath }
Fails because $folderPath gets passed as is instead of its value:
Start-Job { cmd /c rmdir $folderPath } | select command
Command
-------
cmd /c rmdir $folderPath
Any suggestion besides using the .NET framework?
EDIT
By broken link I'm referring to a folder which points to a previously mounted partition, that doesn't exist anymore. The folder is still available but when attempting to navigate into it this error occurs because the destination doesn't exist anymore:
Error:
C:\folder\brokenLink refers to a location that is unavailable. It
could be on a hard drive on this computer, or on a network. Check to
make sure that the disk is properly inserted, or that you are
connected to the Internet or your network, and then try again. If it
still cannot be located, the information might have been moved to a
different location.
This will work:
$folderPath = "C:\folderContaingBrokenSymlinks\";
$items = ls $folderPath -Recurse -ea 0;
foreach($item in $items){
if($item.Attributes.ToString().contains("ReparsePoint")){
cmd /c rmdir $item.PSPath.replace("Microsoft.PowerShell.Core\FileSystem::","");
}
else{
rm -Force -Recurse $item;
}
}

Parsing Shortcuts in Powershell

I have some code which is trying to make a copy of a directory which contains shortcuts:
# Create a directory to store the files in
mkdir "D:\backup-temp\website.com files\"
# Search for shortcuts so that we can exclude them from the copy
$DirLinks = Get-ChildItem "\\web1\c$\Web Sites\website\" -Recurse | ? { $_.Attributes -like "*ReparsePoint*" } | % { $_.FullName }
# Execute the copy
cp -recurse -Exclude $DirLinks "\\web1\c$\Web Sites\website\*" "D:\backup-temp\website.com files\"
But when I execute the script I get the following error:
Copy-Item : The symbolic link cannot be followed because its type is disabled.
At C:\scripts\backup.ps1:16 char:3
+ cp <<<< -recurse "\\web1\c$\Web Sites\website\*" "D:\backup-temp\website.com files\"
+ CategoryInfo : NotSpecified: (:) [Copy-Item], IOException
+ FullyQualifiedErrorId :
System.IO.IOException,Microsoft.PowerShell.Commands.CopyItemCommand
It seems the script is getting hung up on a symbolic link (I'm assuming the shortcut) that I'm trying to exclude in the fourth line of the script.
How can I tell powershell to ignore/exclude shortcuts?
Thanks,
Brad
If you are on V3 or higher you can eliminate the reparse points like so:
Get-ChildItem "\\web1\c$\Web Sites\website" -Recurse -Attributes !ReparsePoint |
Copy-Item -Dest "D:\backup-temp\website.com files"
On V1/V2 you can do this:
Get-ChildItem "\\web1\c$\Web Sites\website" |
Where {!($_.Attributes -bor [IO.FileAttributes]::ReparsePoint)} |
Copy-Item -Dest "D:\backup-temp\website.com files" -Recurse
So it turns out that the issue I faces is explained in this Microsoft Blog Post:
http://blogs.msdn.com/b/junfeng/archive/2012/05/07/the-symbolic-link-cannot-be-followed-because-its-type-is-disabled.aspx
Essentially on the server I am running the powershell script from I needed to run the following command:
fsutil behavior set SymlinkEvaluation R2R:1
This allows Remote to remote symbolic links. Once this is in place the above powershell commands run as expected without errors.