🐿️

PowerShellでネットワークドライブ(NAS等)を接続・切断

2024/12/16に公開

本記事は、TechCommit AdventCalendar 2024 の16日目の記事です。

はじめに

自宅PCのWindowsでNASとして運用しているサーバのWindows上のPowerShellから接続したり取り外したりということを時々やります。と言うのも、常時接続してなかったりするストレージを右クリックしてウィザード起動したりなんだりが面倒なのでターミナルでやっちゃいたい為。
その時に私が個人用で使ってるスクリプトの事例を小ネタとして紹介します。

記載する事例は完全に私の自宅環境での運用事例なのですが、ご自宅などの小規模なネットワークの作業などの参考にしてみてください。

要約すると

ネットワークの場所の追加ウィザード」等と同じような操作をPowerShellでやる方法を私の自宅流で解説しています。

ローカルネットワークにあるデバイスIPを取得

Get-NetNeighborを使うとローカルネットワークのデバイスのIPを取れます。
これでよく家のNASのアドレスなどをチェックしたりしています。例えば192.168.0.3みたいなヤツです。

Get-NetNeighbor -InterfaceIndex 4 -AddressFamily IPv4 -State Stale, Reachable

ドライブのリスト

Get-PSDriveで見れます。Linuxなどでのdfみたいなものです。

Get-PSDrive -PSProvider FileSystem

ドライブの接続

New-PSDriveを使うと(今回の文脈ではネットワーク)ドライブの接続を行います。

ポイントとしては-Persist -Scope Globalを指定する所で、ドライブを強制的に無期限に保持することを有効化します。これを使うことで「エクスプローラ」などでドライブの接続が永続化されます。

私の家でのNASではユーザ名とパスワードを必要とする一般的なタイプですが、これはSystem.Management.Automation.PSCredentialを使ってクレデンシャルのオプションとして与えます。

以下ではローカルNASのアドレス・ユーザ・パスワードを入力させ、
D..Zの適当なドライブ名を割り当てて接続を確立させる例を示します。

$addr = (Read-Host "Enter the IP address of the server").Trim()
$user = (Read-Host "Enter username").Trim()
$password = Read-Host "Enter password" -AsSecureString

$credential = New-Object System.Management.Automation.PSCredential($user, $password)

if ($addr.Length -eq 0 -or $user.Length -eq 0 -or $password.Length -eq 0) {
  Write-Error "Please enter all the required fields."
  exit 1
}

# Normalize the address
if (!$addr.StartsWith("\\")) {
  $addr = "\\" + $addr
}
$addr = $addr.Replace("/", "\")

$used_drive_names = Get-PSDrive -PSProvider FileSystem | Select-Object -ExpandProperty Name
$available_drive = "D" .. "Z" | Where-Object { $_ -notin $used_drive_names } | Select-Object -First 1
if ($available_drive) {
  try {
    New-PSDrive -Name $available_drive -PSProvider FileSystem -Root $addr -Credential $credential -Persist -Scope Global -ErrorAction Stop
  }
  catch {
    Write-Error "$_"
  }
}

上手くいくと以下のようにエクスプローラで表示されます。

ドライブの取り外し

Remove-PSDriveというコマンドレットがあるのですが、困ったことにこのコマンドレットはポンコツで、ネットワークドライブを外すのに私の環境だと動作しないので、ここはnetコマンドで切ってます。

以下ではドライブ名を入力するプロンプトを表示・入力させ、「G」ドライブなどのネットワークドライブを接続していた場合(DisplayRootで判定)、指定したドライブをnet /deleteによって切断する例を示します。

$drive_name = Read-Host "Enter the drive name to remove"
if ($drive_name.EndsWith(":")) {
  $drive_name = $drive_name.Substring(0, $drive_name.Length - 1)
}
if ($drive_name.Length -eq 0) {
  Write-Error "Please provide the drive name to remove."
  exit 1
}
$drive = Get-PSDrive -Name $drive_name -PSProvider FileSystem
if ($drive -and $drive.DisplayRoot.StartsWith("\\")) {
  try {
    $_drive = $drive.Name + ":"
    net use $_drive /delete
  }
  catch {
    Write-Error "$_"
  }
}

参考文献

Discussion