2010-05-22 2 views
5

작은 VBScript를 작성하여 .zip 파일을 만든 다음 지정된 폴더의 내용을 .zip 파일에 복사합니다.WScript.Sleep을 사용하지 않고 CopyHere를 사용하여 파일에 쓰기

이유가있어 하나씩 파일을 복사합니다 (한꺼번에 많은 작업을 수행 할 수 있음을 알고 있습니다). 그러나 내 문제는 각 루프 반복간에 WScript.Sleep없이 하나씩 복사하려고 할 때 "파일을 찾을 수 없거나 읽기 권한이 없습니다."입니다. 오류; 각 쓰기 후에 WScript.Sleep 200을 배치하면 작동하지만 100 %는 작동하지 않습니다. 파일 크기에 따라이 때문에 쓰는 데 시간이 오래 걸릴 수 있기 때문에

꽤 많이 나는 200 밀리 초

등이 충분하지 않을 수 있습니다 절전 기능을 제거하고에 의존하지 좀하고 싶습니다 당신이 할 수 그들이 확장 일치하는 경우 다음 내가 한 .zip으로 그들을 배치 파일을 통해 I 루프 아래 코드의 작은 조각으로 참조 (ZipFile를) 나는 슬립 기능에 의존 막을 수있는 방법에

For Each file In folderToZip.Items 
    For Each extension In fileExtensions 
     if (InStr(file, extension)) Then 
      zipFile.CopyHere(file) 
      WScript.Sleep 200 
      Exit For 
     End If 
    Next 
Next 

어떤 제안 ?

감사

+0

내가 생각하는 다른 방법은 배열을 만들고 필터를 통과 한 모든 파일을 배치하는 것이지만 ... CopyHere 함수에서 배열을 사용할 수 있습니다. 어떻게 알 수 있습니까? – mlevit

+0

아니, 당신은 그것을 반복하고 기본적으로 똑같은 방식으로 배열을 사용할 수 없다. 전달 된 파일을 임시 폴더에 복사하고 거기에서 모두 한 번에 추가하는 것은 어떻습니까? – Tomalak

+0

@Tomalak 그것이 변화를 가져올 지 모른다. 파일에 복사하는 것과 같은 오류가 발생할 수 있다고 생각합니다. 그래도 한 번에 모두 어떻게 추가 하시겠습니까? – mlevit

답변

0

당신은 "존재"로, 예를 들어, 방금 복사 한 파일을 액세스 해보십시오 확인할 수 있습니다

For Each file In folderToZip.Items 
    For Each extension In fileExtensions 
     If LCase(oFSo.GetExtensionName(file)) = LCase(extension) Then 
      zipFile.CopyHere(file) 
      Dim i: i = 0 
      Dim target: target = oFSO.BuildPath(zipFile, oFSO.GetFileName(file)) 
      While i < 100 And Not oFSO.FileExists(target) 
       i = i + 1 
       WScript.Sleep 10 
      Wend 
      Exit For 
     End If 
    Next 
Next 

잘 모르겠어요 target이 사용하기 위해 올바르게 계산되는 경우 컨텍스트,하지만 당신은 아이디어를 얻을. 나는이 오류가 첫번째 장소에서 발생한다는 것에 놀랍니다 ... FileSystemObject은 엄격히 동기화되어야합니다.

모든 것이 실패하면, 이렇게 : CopyHere는 비동기

For Each file In folderToZip.Items 
    For Each extension In fileExtensions 
     If LCase(oFSo.GetExtensionName(file)) = LCase(extension) Then 
      CompressFailsafe zipFile, file 
      Exit For 
     End If 
    Next 
Next 

Sub CompressFailsafe(zipFile, file) 
    Dim i: i = 0 
    Const MAX = 100 

    On Error Resume Next 
    While i < MAX 
    zipFile.CopyHere(file) 
    If Err.Number = 0 Then 
     i = MAX 
    ElseIf Err.Number = xxx ''# use the actual error number! 
     Err.Clear 
     WScript.Sleep 100 
     i = i + 1 
    Else 
     ''# react to unexpected error 
    End Of 
    Wend 
    On Error GoTo 0 
End Sub 
+0

코드를 사용해 보았습니다. FileExists = true이므로 루프가 실행되지 않습니다. 나는 그것이 무엇인지는 모르지만, 파일이 존재하지 않는 것처럼 보이지는 않습니다. 그러나 이전 파일이 복사를 완료하지 않았기 때문에 스크립트가 누군가에게 쓰기 위해 액세스 할 수 없습니다. 당신이 말했듯이, 나는 복사가 엄격하게 동기식이라고 가정했을 것이다. – mlevit

+0

@mlevit : 어쩌면 파일 크기를 비교하는 것이 최선의 방법일까요? – Tomalak

+0

@Tomalak 나는 그 아이디어를 좋아해서 그것을 시도했지만, 약 20KB 이상의 파일에 도달하면 문제가 분명해진다. 파일을 ZIP 파일에 저장하기 때문에 파일 크기가 줄어들어 ZIP 파일 크기가 계산되지 않으므로 루프가 무한대가됩니다. – mlevit

1

당신이 올바른지이다. 내가 VBScript로이 작업을 수행 할 때 , 나는 우편에있는 파일의 수까지에 복사 된 파일의 수보다 크거나 같은 잔다.

Sub NewZip(pathToZipFile) 

    WScript.Echo "Newing up a zip file (" & pathToZipFile & ") " 

    Dim fso 
    Set fso = CreateObject("Scripting.FileSystemObject") 
    Dim file 
    Set file = fso.CreateTextFile(pathToZipFile) 

    file.Write Chr(80) & Chr(75) & Chr(5) & Chr(6) & String(18, 0) 

    file.Close 
    Set fso = Nothing 
    Set file = Nothing 

    WScript.Sleep 500 

End Sub 



Sub CreateZip(pathToZipFile, dirToZip) 

    WScript.Echo "Creating zip (" & pathToZipFile & ") from (" & dirToZip & ")" 

    Dim fso 
    Set fso= Wscript.CreateObject("Scripting.FileSystemObject") 

    If fso.FileExists(pathToZipFile) Then 
     WScript.Echo "That zip file already exists - deleting it." 
     fso.DeleteFile pathToZipFile 
    End If 

    If Not fso.FolderExists(dirToZip) Then 
     WScript.Echo "The directory to zip does not exist." 
     Exit Sub 
    End If 

    NewZip pathToZipFile 

    dim sa 
    set sa = CreateObject("Shell.Application") 

    Dim zip 
    Set zip = sa.NameSpace(pathToZipFile) 

    WScript.Echo "opening dir (" & dirToZip & ")" 

    Dim d 
    Set d = sa.NameSpace(dirToZip) 

    ' for diagnostic purposes only 
    For Each s In d.items 
     WScript.Echo s 
    Next 


    ' http://msdn.microsoft.com/en-us/library/bb787866(VS.85).aspx 
    ' =============================================================== 
    ' 4 = do not display a progress box 
    ' 16 = Respond with "Yes to All" for any dialog box that is displayed. 
    ' 128 = Perform the operation on files only if a wildcard file name (*.*) is specified. 
    ' 256 = Display a progress dialog box but do not show the file names. 
    ' 2048 = Version 4.71. Do not copy the security attributes of the file. 
    ' 4096 = Only operate in the local directory. Don't operate recursively into subdirectories. 

    WScript.Echo "copying files..." 

    zip.CopyHere d.items, 4 

    Do Until d.Items.Count <= zip.Items.Count 
     Wscript.Sleep(200) 
    Loop 

End Sub 
0

우리는 많은 디버깅 및 품질 보증에 후 사용 솔루션 고속 및 저속 컴퓨터와 CPU 부하가 많은 컴퓨터를 비롯한 다양한 Windows의 맛은 다음과 같습니다.

비평 및 개선을 환영합니다.

우리는 루프없이이 작업을 수행 할 수 없습니다. 즉, 유효성 검사를 수행하거나 압축 작업을 게시하려는 경우입니다.

목표는 최대한 많은 창 풍미에서 안정적으로 실행되는 무언가를 만드는 것이 었습니다. 가능한 한 네이티브 적으로도 이상적입니다.

이 코드는 여전히 100 % 신뢰도가 아니지만 ~ 99 % 인 것으로 보입니다. 가능한 안정적인만큼 우리는 dev 및 QA 시간을 사용할 수 있습니다. 그것의 가능한 iSleepTime 증가는 그것을 100 % 노트의

포인트를 만들 수 :

  • 무조건 잠은은 iSleepTime이 감소되어서는 안된다 우리는
  • 를 볼 수있는 가장 신뢰할 수 있고 호환 방법이 될 것 같다 반복 횟수가 많을수록 오류가 발생할 확률이 높습니다. zip/copy 프로세스의 내부 작업과 관련이있는 것 같습니다.
  • iFiles은 소스 파일 수입니다.
  • 루프가 더 단순할수록 루프에서 oZippp.Items().Count을 출력하는 것과 같이 파일 액세스/공유/잠금 위반과 관련 될 수있는 것처럼 보이지 않는 오류가 발생했습니다. 우리는 추적하기 위해 시간을 소비하지 않았습니다.
  • Windows 7에서 압축 처리 과정의 내부가 압축 된 zip 폴더의 cwd에있는 임시 파일을 사용하는 것으로 보입니다.이 파일은 장기 실행 zip 중에 탐색기 창을 새로 고침하거나 cmd와 함께 dir을 나열하여 볼 수 있습니다
  • 우리는 윈도우 2000, XP, 2003, Vista에서이 코드를 사용하여 성공을 거두었, 7 당신은 아마 루프에 시간 제한을 추가 할 것
  • , 피하기 무한 루프

    'Copy the files to the compressed folder 
    oZippp.CopyHere oFolder.Items() 
    iSleeps = 0 
    iSleepTime = 5 
    On Error Resume Next 
    Do 
        iSleeps = iSleeps + 1 
        wScript.Sleep (iSleepTime * 1000) 
    Loop Until oZippp.Items().Count = iFiles 
    On Error GoTo 0 
    
    
    If iFiles <> oZippp.Items().Count Then 
        ' some action to handle this error case 
    Else 
        ' some action to handle success 
    End If 
    
+0

항목이 폴더 안에 있으면이 작업은 실패합니다. 원본 폴더가 20 개의 항목을 포함하고 있다면 네임 스페이스는 20을보고하지만 zip 네임 스페이스는 폴더 1 개만보고합니다. –

3

이것이 VB6에서 우리가하는 방법입니다. 도우미 기능이 보이는 곳

Private Function pvCanOpenExclusive(sFile As String) As Boolean 
    Dim nFile  As Integer 

    nFile = FreeFile 
    On Error GoTo QH 
    Open sFile For Binary Access Read Lock Write As nFile 
    Close nFile 
    pvCanOpenExclusive = True 
QH: 
End Function 

니스 부작용이을 압축이 실패하는 경우에도이 끝나지 않을 것입니다 같은 우편에 CopyHere를 호출 한 후 우리는이

Call Sleep(100) 
    Do 
     Do While Not pvCanOpenExclusive(sZipFile) 
      Call Sleep(100) 
     Loop 
     Call Sleep(100) 
    Loop While Not pvCanOpenExclusive(sZipFile) 

같은 완료 비동기 압축 기다립니다 무한 루프.

zipfldr.dll로 닫을 때 zip 파일에 액세스 할 때 문제가 발생합니다. 즉, pvCanOpenExclusive가 true를 반환 할 때입니다.

+0

이것은 이것을 확인하는 정말 우아한 방법처럼 보입니다 ... – tobriand

+0

셸이 어떤 일을하는지 꽤 많이 추측하고 있습니다. 파일을 한 번만 열어서 복사본을 시작하면 바로 그 일을 할 것이라고 가정하고 있습니다. (예를 들어, 소스 디렉토리 속성을 평가 한 후 0.5 초가 지나지 않았습니다.) – EFraim

+0

@EFraim 네, 이것은 완전히 해킹 된 것입니다. 일반적으로 작동 방식이 아닙니다. [IDropTarget] 인터페이스를 사용하여 [this]와 같은 파일을 동 기적으로 압축 할 수 있습니다 (http://www.vbforums.com/showthread.php?808681-VB6-Create-a-ZIP-file-without-any-DLL-depends IStorage 및 IDropTarget 사용). – wqw

0

여기 VB에서 사용 된 속임수입니다. 변경 전에 Zip 파일의 길이를 가져 와서 변경 될 때까지 기다린 다음 다른 두 번째 또는 두 번째를 기다리십시오. 두 개의 특정 파일 만 필요했지만이 파일을 만들 수는 있습니다.

Dim s As String 
Dim F As Object 'Shell32.Folder 
Dim h As Object 'Shell32.Folder 
Dim g As Object 'Shell32.Folder 
Dim Flen As Long, cntr As Long, TimerInt As Long 
Err.Clear 
s = "F:\.zip" 
NewZipFolder s 
Flen = FileLen(s) 
Set F = CreateObject("Shell.Application").namespace(CVar(s)) 
TimerInt = FileLen("F:\MyBigFile.txt")/100000000 'set the loop longer for bigger files 
F.CopyHere "F:\DataSk\DemoData2010\Test.mdf" 
Do 
    cntr = Timer + TimerInt 
    Do 
     DoEvents: DoEvents 
    Loop While cntr > Timer 
    Debug.Print Flen 
Loop While Flen = FileLen(s) 
    cntr = Timer + (TimerInt/2) 
    Do 
     DoEvents: DoEvents 
    Loop While cntr > Timer 
Set F = Nothing 
Set F = CreateObject("Shell.Application").namespace(CVar(s)) 


F.CopyHere "F:\MynextFile.txt" 

MsgBox "Done!" 
관련 문제