Переместить файлы PST на сервер через VB - PullRequest
0 голосов
/ 20 июня 2011

На работе мы подобрали новый сервер обмена, поэтому мой начальник попросил меня перейти на все наши компьютеры и вручную переместить все открытые файлы PST, которые были у людей, в их папку на новом сервере. Я по понятным причинам решил, что будет проще написать это. После небольшого исследования я натолкнулся на один такой скрипт, который нуждался лишь в небольшой настройке (он найден здесь http://halfloaded.com/blog/logon-script-move-local-pst-files-to-network-share/), но имел много других вещей, которые мне на самом деле не нужны (проверяет, работает ли он на ноутбуке) , затрагивая только локальные папки и т. д.), поэтому я перевел основную логику из нее в свою собственную версию без большинства этих проверок работоспособности. Проблема, с которой я сталкиваюсь, состоит в том, что у меня есть 2, казалось бы, идентичных цикла, повторяющих разное число раз, и это вызывает проблемы. Вот что у меня

Option Explicit
Const OverwriteExisting = True

' get username, will use later
Dim WshNetwork: Set WshNetwork = wscript.CreateObject("WScript.Network")
Dim user: user = LCase(WshNetwork.UserName)
Set WshNetwork = Nothing

' network path to write pst files to
Dim strNetworkPath : strNetworkPath = "\\server\folder\"
'Fix network path if forgot to include trailing slash...
If Not Right(strNetworkPath,1) = "\" Then strNetworkPath = strNetworkPath & "\" End If

' initiate variables and instantiate objects
Dim objOutlook, objNS, objFolder, objFSO, objFName, objTextFile, pstFiles, pstName, strPath
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.CreateTextFile("c:\My\Desktop\pst_script_log.txt " , True)
Set objOutlook = CreateObject("Outlook.Application")
Set objNS = objOutlook.GetNamespace("MAPI")
Dim count : count = -1

' Enumerate PST filesand build arrays
objTextFile.Write("Enumerating PST files" & vbCrLf)
For Each objFolder in objNS.Folders
    If GetPSTPath(objFolder.StoreID) <> "" Then
        pstFiles = GetPSTPath(objFolder.StoreID)
        pstName = objFolder.Name
        count = count + 1
        objTextFile.Write(count & "  " & pstFiles & vbCrLf)
        ReDim Preserve arrNames(count)
        arrNames(count) = pstName
        ReDim Preserve arrPaths(count)
        arrPaths(count) = pstFiles
        objOutlook.Session.RemoveStore objFolder
    End IF
Next

' closes the outlook session
objOutlook.Session.Logoff
objOutlook.Quit
Set objOutlook = Nothing
Set objNS = Nothing

' quits if no pst files were found
If count < 0 Then
    wscript.echo "No PST Files Found."
    wscript.Quit
End If

objTextFile.Write("moving them" & vbCrLf)

' moves the found pst files to the new location
Dim pstPath
For Each pstPath In arrPaths
    On Error Resume Next
        objTextFile.Write(pstPath & vbCrLf)
        objFSO.MoveFile pstPath, strNetworkPath
        If Err.Number <> 0 Then
            wscript.sleep 5000
            objFSO.MoveFile pstPath, strNetworkPath
        End If
    Err.Clear
    On Error GoTo 0
Next
Set objFSO = Nothing

' sleep shouldn't be necessary, but was having issues believed to be related to latency
wscript.sleep 5000
'Re-open outlook
Set objOutlook = CreateObject("Outlook.Application")
Set objNS = objOutlook.GetNamespace("MAPI")

'Re-map Outlook folders
For Each pstPath In arrPaths
    objTextFile.Write("Remapping " & pstPath & " to " & strNetworkPath & Mid(pstPath, InStrRev(pstPath, "\") + 1) & vbCrLf)
    objNS.AddStore strNetworkPath & Mid(pstPath, InStrRev(pstPath, "\") + 1)
Next

count = -1

For Each objFolder In objNS.Folders
    If GetPSTPath(objFolder.StoreID) <> "" Then
        count = count + 1
        objTextFile.Write("Renaming " & GetPSTPath(objFolder.StoreID) & " to " & arrNames(count) & vbCrLf)
        objFolder.Name = arrNames(count)
    End If
Next

objOutlook.Session.Logoff
objOutlook.Quit
objTextFile.Write("Closing Outlook instance and unmapping obj references...")
Set objFolder = Nothing
Set objTextFile = Nothing
Set objOutlook = Nothing
Set objNS = Nothing
wscript.echo "Done."
wscript.Quit

Private Function GetPSTPath(byVal input)
    'Will return the path of all PST files
    ' Took Function from: http://www.vistax64.com/vb-script/
    Dim i, strSubString, strPath
    For i = 1 To Len(input) Step 2
        strSubString = Mid(input,i,2)
        If Not strSubString = "00" Then
            strPath = strPath & ChrW("&H" & strSubString)
        End If
    Next

    Select Case True
        Case InStr(strPath,":\") > 0
            GetPSTPath = Mid(strPath,InStr(strPath,":\")-1)
        Case InStr(strPath,"\\") > 0
            GetPSTPath = Mid(strPath,InStr(strPath,"\\"))
    End Select
End Function

Неисправный цикл находится в строках 24 и 81. Специфическая ошибка заключается в том, что счетчик увеличивается во втором цикле больше, чем в первом, однако это связано с тем, что первый цикл заканчивается короткими циклами и пропускает последний файл PST. Люди с похожими проблемами на сайте, где я нашел большую часть этого кода, сказали, что добавление функций wscript.sleep в определенных местах им помогло, но мне не повезло в их рекомендуемых местах, и у меня сложилось впечатление, что их проблемы не такой как у меня.

Я был бы очень признателен за помощь в том, что идет не так в моем коде, и я открыт для предложений о способах исправления других проблем, которые я не вижу, и думаю, что есть лучший способ сделать что-то подобное.

EDI: После более подробного исследования моей проблемы, кажется, что, выполняя RemoveStore внутри цикла в строке 24, я изменяю значение objNS.Folders (что имеет смысл), и чтобы избежать этого, я должен сохранить Элементы objFolder мне нужно удалить и сделать это в другом цикле. Проблема в том, что я не знаю, как это сделать, я пытался

        [line 35]
        ReDim Preserve arrFolders(count)
        arrFolders(count) = objFolder
    End If
Next

For Each objFolder in arrFolders
    objOutlook.Session.RemoveStore objFolder
Next

Однако я получаю ошибки Несоответствия типов относительно RemoveStore, поэтому я думаю, что он не хранит объект так, как ему нужно. Есть идеи?

Ответы [ 2 ]

1 голос
/ 11 ноября 2011

FWIW - подключение к PST в сети не поддерживается. См http://support.microsoft.com/kb/297019/en-us и http://blogs.technet.com/b/askperf/archive/2007/01/21/network-stored-pst-files-don-t-do-it.aspx

0 голосов
/ 21 июня 2011

Итак, наконец-то все заработало правильно (или достаточно близко к праву).Как уже упоминалось в комментариях от Брэда, вы должны искать на вашем диске файлы PST, а также то, что у меня здесь.Этот метод влияет ТОЛЬКО на файлы PST, которые пользователь открыл в Outlook, а НЕ на все файлы PST на своем компьютере.То, что происходило, было, как я уже упоминал в своем редакторе, objOutlook.Session.RemoveStore изменял значение objNS.Folders, что нарушало мой первый цикл For.Вы должны сделать это вне вашего цикла enumartion, в противном случае он прерывается и пропускает некоторые (а также неправильно маркирует некоторые при переопределении их).Кроме того, за пределами этого цикла objFolder необходимо было переопределить как объект MAPIFolder, иначе вы получите ошибки несоответствия типов при попытке удалить рабочий образец:

' Enumerate PST filesand build arrays
objTextFile.Write("Enumerating PST files" & vbCrLf)
For Each objFolder in objNS.Folders
If GetPSTPath(objFolder.StoreID) <> "" Then
    count = count + 1
    pstFiles = GetPSTPath(objFolder.StoreID)
    pstName = objFolder.Name
    pstFolder = objFolder
    objTextFile.Write(count & "  " & pstFiles & vbCrLf)
    ReDim Preserve arrNames(count)
    arrNames(count) = pstName
    ReDim Preserve arrPaths(count)
    arrPaths(count) = pstFiles
    'objOutlook.Session.RemoveStore objFolder
End If
Next

For Each pstName in arrNames
set objFolder = objNS.Folders.Item(pstName)
objNS.RemoveStore objFolder
Next
set objFolder = Nothing
...