Powershell ZIP CopyHere 抵消异步行为
Powershell ZIP CopyHere counteracting asynchronous behavior
在 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"))
这会返回以下错误:
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
我是否滥用了这个特定包的 Item 方法?我很困惑,为什么 "appears" 要整齐地完成的事情不起作用。我还尝试了提供的代码片段 Here。它还抱怨在这种特殊情况下的 .Item 方法。
我 运行 遇到的问题是试图找到检查 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"
在 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"))
这会返回以下错误:
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
我是否滥用了这个特定包的 Item 方法?我很困惑,为什么 "appears" 要整齐地完成的事情不起作用。我还尝试了提供的代码片段 Here。它还抱怨在这种特殊情况下的 .Item 方法。
我 运行 遇到的问题是试图找到检查 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"