Powershell ZIP CopyHere counteracting asynchronous behavior

0

Within Powershell, the CopyHere method for the Shell-Application Namespace is asynchronous. My main goal with this is to convert a KML file to a KMZ file. The process of doing this is to create a ZIP file with the same name, copy the KML into the KMZ (compresses the file) and then rename the ZIP to KMZ. Unfortunately, being asynchronous means the rename function is being called before the CopyHere method is completed. I have found many examples of solving this. The cleanest one I found is below:

$kmlPath = $global:directoryPath + "Test.kml"
$zip = $global:directoryPath + "Test.zip"
New-Item $zip -ItemType file
$shellApplication = new-object -com shell.application
$zipPackage = $shellApplication.NameSpace($zip)
$zipPackage.CopyHere($kmlPath, 16)

while($zipPackage.Items().Item($zip.Name) -Eq $null)
{
    start-sleep -seconds 1
    write-host "." -nonewline
}
write-host "."
Rename-Item -Path $zip -NewName $([System.IO.Path]::ChangeExtension($zip, ".kmz"))

This responds with the following error:

Exception calling "Item" with "1" argument(s): "Not implemented (Exception from HRESULT: 0x80004001 (E_NOTIMPL))" + while($zipPackage.Items().Item($zip.Name) -Eq $null) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : ComMethodTargetInvocation

Am I misusing the Item method for this particular package? I am confused why something that "appears" to be neatly done is not working. I have also tried the snippet of code provided Here. It also complains about the .Item method in this particular situation.

powershell
namespaces
zip
kmz
asked on Stack Overflow Dec 15, 2017 by Chris Moretti

1 Answer

1

The issue i ran into was trying to find away to check on zip status.

So instead i did a trigger for a while that would fire ...If the Zipfile was openable and the File name was inside.

function kml_to_kmz([string]$kmlPath){
    [Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem')
    $kmlInfo = Get-ChildItem -Path $kmlPath
    $zipLocation = ($kmlInfo.Directory.FullName + '\' + $kmlInfo.Name.Remove($kmlInfo.Name.LastIndexOf('.')) + '.zip')
    New-item $zipLocation
    ((new-object -com shell.application).NameSpace($zipLocation)).CopyHere($kmlPath, 16)
    $trigger = $false
    while ($trigger -eq $false){
        try{
            $zip = [IO.Compression.ZipFile]::OpenRead($zipLocation)
            If(($zip.Entries | %{$_.Name}) -contains $kmlInfo.Name){
                $zip.Dispose();
                $trigger = $true
                break;
            }

        }catch{}
        start-sleep -seconds 1
        write-host "." -nonewline
    }
    [IO.Compression.ZipFile]::OpenRead($zipLocation).Dispose()
    Rename-Item -Path $zipLocation -NewName $([System.IO.Path]::ChangeExtension($zipLocation, '.kmz'))
}

kml_to_kmz -kmlPath "C:\Users\Default\Desktop\Test.kml"
answered on Stack Overflow Dec 15, 2017 by ArcSet • edited Dec 15, 2017 by ArcSet

User contributions licensed under CC BY-SA 3.0