【问题标题】:Powershell ZIP CopyHere counteracting asynchronous behaviorPowershell ZIP CopyHere 抵消异步行为
【发布时间】:2017-12-15 15:50:09
【问题描述】:

在 Powershell 中,Shell-Application 命名空间的 CopyHere 方法是异步的。我的主要目标是将 KML 文件转换为 KMZ 文件。这样做的过程是创建一个同名的 ZIP 文件,将 KML 复制到 KMZ(压缩文件),然后将 ZIP 重命名为 KMZ。不幸的是,异步意味着重命名函数在 CopyHere 方法完成之前被调用。我找到了很多解决这个问题的例子。我找到的最干净的一个如下:

$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"))

这会响应以下错误:

使用“1”个参数调用“项目”的异常:“未实现 (来自 HRESULT 的异常:0x80004001 (E_NOTIMPL))” + while($zipPackage.Items().Item($zip.Name) -Eq $null) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : ComMethodTargetInvocation

我是否误用了这个特定包的 Item 方法?我很困惑为什么“看起来”整齐地完成的事情不起作用。我还尝试了Here 提供的代码的 sn-p。它还抱怨在这种特殊情况下的 .Item 方法。

【问题讨论】:

    标签: powershell namespaces zip kmz


    【解决方案1】:

    我遇到的问题是试图找到检查 zip 状态的方法。

    所以我做了一段时间的触发器,它会触发......如果 Zipfile 是可打开的并且文件名在里面。

    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"
    

    【讨论】:

    • 这实际上工作得很好。我确实必须将“-ItemType 文件”添加到 New-item 实例化中,但这是一个快速修复(否则它会提示我输入类型)。我确实注意到 ISE 中的输出现在吐出了一系列全局配置(CodeBase、FullName、EntryPoint、DefinedTypes 和其他 40 个)。我不确定哪一段代码会吐出所有这些输出,但这肯定会分散注意力。有什么想法吗?
    • 行 '[Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem')' 正在将程序集参数的详细输出转储到控制台。我通过添加 '| 对其进行了修改Out-Null' 到末尾以屏蔽输出。一切正常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-13
    • 2021-12-10
    • 2023-01-03
    • 2014-12-08
    相关资源
    最近更新 更多