2016-10-11 27 views
0

Я пытаюсь создать сценарий, который добавляет (или создает, а затем добавляет) в существующий файл. Этот файл сопряжен с другой системой, поэтому, чтобы избежать ситуации, когда файл читается, пока я добавляю его, я создаю для него блокировку без доступа. Сценарий отлично работает с одним исключением, которое я не могу понять. Вот пример кода:Неожиданное поведение при открытии потока файлов в сценарии PowerShell

$ErrorActionPreference = "Stop" 
try 
{ 
    [System.IO.FileStream]$file1 = [System.IO.File]::Open("test.txt", [System.IO.FileMode]::Append,[System.IO.FileAccess]::Write, [System.IO.FileShare]::None) 
} 
catch 
{ 
    Write-Host "Unable to create a lock on this file" 
} 

Там одно условия, которое не приводит к срабатыванию блока поймать - если файл уже заблокирован через консоль Powershell И если этот код бежал из сценария и непосредственно не введенные в окне. Если я сначала открою файл в Excel, блок catch всегда будет работать. Если я выполню этот код, введя его в консоль, он также всегда работает. Но если я сначала заблокирую файл, введя его в консоль, а затем запустив скрипт, который пытается сделать то же самое, нет никакого исключения, и блок catch не запускается.

Что мне здесь не хватает?

Обновление: я сделал дополнительную диагностику, и вот мои выводы. Во-первых, как воспроизвести это:

  • Создайте файл с именем test.txt
  • Создать скрипт под названием test1.ps1, поместите код выше в нем
  • Выполнить эту команду в консоли:

    [System.IO.FileStream]$file2 = [System.IO.File]::Open("test.txt", [System.IO.FileMode]::Append,[System.IO.FileAccess]::Write, [System.IO.FileShare]::None) 
    
  • Теперь выполните test1.ps1 скрипт

И блок catch скрипта не срабатывает ... в моей рабочей среде! Я тестировал дома, и он работает так, как ожидалось. Поэтому я вернулся к работе и протестировал его снова, на этот раз используя файл на локальном диске ПК, и он сработал. Единственное отличие, которое сделало его неработоспособным, было то, что файл, над которым я работал, находился в пространстве имен DFS моей компании. Я попробовал его на диске локальной сети, сопоставленном на моем ПК, и он работал нормально.

По какой бы то ни было причине PowerShell не реагирует на файлы, заблокированные PowerShell в пространстве имен DFS, как это предполагается. Каждое другое приложение, которое я пробовал, обнаруживает блокировку: «Блокнот» и «Excel» отказались прочитать файл, и когда я протестировал его в документе PDF, Acrobat также не открыл его. Но PowerShell не жалуется и даже обрабатывает все последующие методы без ошибок - которые не имеют никакого эффекта; CopyTo() и Flush() методы не прерываются, но файл не изменяется.

+0

И еще один комментарий: если я заменю метод Append либо Open, CreateNew или усечения, это вызовет блок улова. У приложений Append, Create и OpenOrCreate нет. – Cpu1

ответ

1

При запуске вышеуказанного кода в качестве скрипта файл/дескриптор автоматически закрывается, когда завершается сценарий (или, точнее, процесс PowerShell). Вам нужно, чтобы скрипт работал, чтобы держать ручку открытой, например. добавив бесконечный цикл после Open() вызова:

$ErrorActionPreference = "Stop" 
try { 
    $writeStream = [IO.File]::Open($FilePath,[IO.FileMode]::Append,[IO.FileAccess]::Write, [IO.FileShare]::None) 
    do { 
     Start-Sleep -Milliseconds 100 
    } while ($true) 
} catch { 
    Write-Host "Unable to create a lock on this file" 
} 
+0

Извините, это мой первый скрипт, так что, возможно, я не понимаю ваш ответ ... Моя проблема не в сохранении блокировки файла, проблема в том, что если файл уже заблокирован powershell, экземпляр скрипта не обнаруживать его. Оператор Open не работает, как я ожидаю. – Cpu1

+0

Невозможно воспроизвести. Пожалуйста, опишите, что * точно * вы делаете, и как * точно * вы это делаете. –

+0

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