web-dev-qa-db-ja.com

PowershellとOpenfilesを使用してWindows共有でロックされたファイルを閉じる

多くのフォルダ共有を使用していますが、他のプロセスによって開かれたロックされたファイルがたくさんあります。

それらのファイルを閉じる必要があります。これまでのところ、MMC-システムツール-共有フォルダ-開いているファイルを使用しています。

PowerShellを使用してOpenFiles.exeによって取得されたリスト/テーブルをフィルタリングでき、ファイルIDを取得したらnet file/closeで閉じると、はるかに便利です。 、または他のいくつかのPSネイティブは、同様の効果を意味します。

PowerShellは初めてなので、ファイルのパスを受け取り、ファイルIDを使用してそのファイルを閉じるPSスクリプトを作成する方法はあるのでしょうか。

4
Renato Reyes

Get-SmbOpenFileおよびClose-SmbOpenFileは、ジョブを実行します。

ファイルサーバーにログインし、PowerShellを起動します。 Get-SmbOpenFileを使用して、ファイルサーバーで開いているすべてのファイルを表示します。ファイルは次のテーブルヘッダーとともに表示されます

FileId                  SessionId               Path           ShareRelativePath      ClientComputerName     ClientUserName

Close-SmbOpenFileを使用してファイルを閉じます。

Close-SmbOpenFile -FileId 4415226383589

Excelファイルが問題であることがわかっている場合は、.XLSX拡張子が付いた開いているすべてのファイルの検索を絞り込むことができます。

Get-SmbOpenFile | Where-Object -Property sharerelativepath -match ".XLSX"

結果から問題のファイルを見つけたら、fileIDでファイルを閉じることができます。

ファイルサーバーで開いているすべてのファイルを閉じる場合:

Get-SmbOpenFile | Close-SmbOpenFile

開いていて、ファイル拡張子「.XLSX」と一致する1つ以上のファイルを閉じる場合。

Get-SmbOpenFile | Where-Object -Property sharerelativepath -match ".XLSX" | Close-SmbOpenFile -Force

****注**** TechNetの記事「TheClose-SMBOpenFilecmdletによると、ファイルを強制的に閉じますサーバーメッセージブロック(SMB)サーバーのいずれかのクライアントによって開かれているこのコマンドレットは、データが失われる可能性があるため、注意して使用する必要がありますファイルが閉じられる前にクライアントがすべてのファイル変更をサーバーにフラッシュバックしていない場合に、ファイルが閉じられているクライアントに対して。

CMDletの詳細について

Get-SmbOpenFile https://technet.Microsoft.com/en-us/library/jj635701(v = wps.620).aspx

Close-SmbOpenFile https://technet.Microsoft.com/en-us/library/jj635721(v = wps.620).aspx

5
Art.Vandelay05

openfiles.exeandnet fileの両方を使用する必要がある理由はありますか?
以下は、net fileのみを使用し、PowerShellスクリプトで囲む関数です。

これを使用するには、コード全体をコピーして、PowerShellセッションに貼り付けます。補足として、net fileおよびopenfilesを使用するには管理者権限が必要です。

セッションに貼り付けると、関数Close-OpenFileを使用できるようになります。使い方はとても簡単です。ファイルパスを関数にパイプするか、ファイルパスをパラメーターとして指定できます。

そのまま貼り付けた場合は、Get-Help Close-OpenFile -Exampleを使用して例を表示すると、実際にヘルプを利用できます。以下は、参考までに同じ例です。

# Method 1 : Pipeline
@("file\path\1", "file\path\2") | Close-OpenFile
"file\path\1" | Close-OpenFile

# Method 2 : Parameter
Close-OpenFile @("file\path\1", "file\path\2")
Close-OpenFile "file\path\2"

ここで、PowerShellを開くたびにこれを使用するとします。この回答の最後に、これを行う基本的な方法を示しました(他の方法もあります)。

<#
.Synopsis
   Closes Files Opened in Network Share
.EXAMPLE
   @("file\path\1", "file\path\2") | Close-OpenFile
   Attempts to close "file\path\1" and "file\path\2" if they are open.
.EXAMPLE
   Close-OpenFile @("file\path\1", "file\path\2")
   Attempts to close "file\path\1" and "file\path\2" if they are open.
.EXAMPLE
   "file\path\1" | Close-OpenFile
   Attempts to close "file\path\1" if it is open.
.EXAMPLE
   Close-OpenFile "file\path\2"
   Attempts to close "file\path\2" if it is open.
#>
function Close-OpenFile {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory=$true,
                   ValueFromPipeline = $true,
                   ValueFromPipelineByPropertyName=$true,
                   Position=0)]
        [String[]]$filesToClose
    )
    Begin {
        $netFile = net file
        if($netFile.length -lt 7) { Throw "No Files are Open" }
        $netFile = $netFile[4..($netFile.length-3)]
        $netFile = $netFile | ForEach-Object {
            $column = $_ -split "\s+", 4
            New-Object -Type PSObject -Property @{
                ID = $column[0]
                FilePath = $column[1]
                UserName = $column[2]
                Locks = $column[3]
            }
        }
        $count = 0
    } Process {
        ForEach ($file in $filesToClose) {
            ForEach ($openFile in $netFile) {
                if($openFile.FilePath -eq $file) {
                    $count++
                    net file $openfile.ID /close > $null
                }
            }
        }
    } End { Write-Output "Closed $count Files" }
}

以下は、PowerShellを開くたびにこの関数を使用する基本的な方法を示しています。

  1. $env:homepath\Documents\WindowsPowerShellに移動します(ない場合は作成します)。
    これは通常、C:\Users\<username>\Documents\WindowsPowerShellに解決されます。
  2. profile.ps1(またはMicrosoft.PowerShell_profile.ps1)というファイルを作成します。
  3. Close-OpenFiles関数全体をコピーして貼り付け、保存します。
1
nehcsivart

以下は、CMDとOpenFiles.exeを使用した簡単な方法です。これは必要に応じてすぐにPoSHに変換できると思います。これをCloseFile.cmdとして保存し、パス上のフォルダーに配置します。

    @echo off
    if "%1" == "" goto SYNTAX
    if "%2" == "" goto SYNTAX
    goto RUNIT

    :SYNTAX
        echo Use:
        echo    CloseFile.cmd ^<server^> ^<file^>
        goto :EOF

    :RUNIT
        set _server=%1
        set _file=%2
        openfiles /query /s %_server% /fo csv | findstr /i /c:"%_file%" > _filelist.txt
        for /f "tokens=1,4 delims=," %%a in (_filelist.txt) do (
            openfiles /disconnect /s %_server% /op %%b /id %%a
        )

        if exist _filelist.txt del _filelist.txt
0
Tim