コマンドプロンプトでネットをつなぎなおす（2） Get-NetIPConfiguration

テラテイルの方で質問をさせていただき
https://teratail.com/questions/kyd6j0rngr5zxf

以下のご意見をいただきました。

>**<font color="red">バッチファイルをpowershellとして実行するときに、結構トリッキーな技を使っているの>で、管理者権限で実行しなおすというのが困難になっているように見えます。</font>**

私の理解力が足りず、「どの部分」が「トリッキー」で、<font color="blue" >**「管理者権限で実行しなおすのが困難」**</font>になっているのかがきちんと理解がおいついていないですが、

ご指摘によれば

>順番として、

>①バッチファイルを実行
>（そのバッチファイルを管理者権限で実行）
>②管理者権限を持ったまま)そのバッチファイルを powershell で実行

とのこと

:::note info
以下のコードはスタートアップフォルダから毎朝起動しているので、使ってもらって大丈夫です。
:::


```network.bat

<# :
@echo off
openfiles >nul 2>&1
if errorlevel 1 (
  powershell start-process "'%~f0'" -verb runas
  goto :EOF
)
powershell -noprofile -command "invoke-expression (get-content '%~f0' -raw)"
goto :EOF
#>

# 以下 powershell スクリプト
$adapter = Get-NetAdapter | Where-Object {$_.InterfaceAlias -eq "Wi-Fi"}

 
# アダプターのコンフィグを取得
$conf = $adapter | Get-NetIPConfiguration
 
# IPアドレスが設定されている場合
If ($conf.IPv4Address.IPAddress) {
 
    # IPアドレス設定を削除する
    $adapter | Remove-NetIPAddress -AddressFamily "IPv4" -Confirm:$false
}
 
# デフォルトゲートウェイが設定されている場合
If ($conf.Ipv4DefaultGateway) {
 
    # デフォルトゲートウェイ設定を削除する
    $adapter | Remove-NetRoute -AddressFamily "IPv4" -Confirm:$false
}

$adapter | New-NetIPAddress `
 -AddressFamily "IPv4" `
 -IPAddress "172.17.2.XXX" `
 -PrefixLength 24 `
 -DefaultGateway "172.17.2.XXX"
 
 $adapter | Set-DnsClientServerAddress -ServerAddresses "211.129.XX.XX,211.129.XX.XXX"
```

# 逐次解説（自分用の振り返りでだらだら書いています）
+ **<# :**
cmd的にはスルー。なんの意味もなく実行されない行です。
powershellにとって **<#** はコメント行の始まと判定しています。
powershell的には **:** は無視か？？？（今は不明）
※（参考）
PowerShellのスクリプト内でコメントアウトするには、#を使います。
単一文なら先頭に#をつけるだけでよいです。
複数にわたるコメント文なら<#...#>を使います。



+ **@echo off**
これをつけないと出力結果にいろんな情報が記載され、出力結果がわかりにくい。

>https://qiita.com/Sanada-code/items/5d21d885b732e6fb0d03
実際に例示されてわかりやすい
出典：@Sanada-code

+ **openfiles**
実際にcmdに入力して実行してみると（管理者権限でなく）
```実例.btat
エラー：ログインしているユーザーは管理者権限をもっていません
```
とでる。これがerrorlevel 1のエラーのようだ。
⇒このコマンドは管理者権限がないと実行できない。NUL(空のファイル)[にリダイレクト（出力）させているので何も起きません。

+ **if errorlevel 1** 
これはopenfilesで出た結果「errorlevel」の値が０ならば管理者、１なら一般ユーザーとなるので一般ユーザーの場合は以下のことを行えと条件分岐させている。

 + **2>&1**
 「エラー出力」を「標準出力」にリダイレクトする

 ①＞② 2＞&1
①の結果を＞&1で処理して「標準エラー出力」⇒「標準出力」し
①の結果を今度はnulに出力している

>https://qiita.com/uhooi/items/b8b25761a5c4efe9025a
>https://rainbow-engine.com/batch-redirect-howto/
上は２＞＆１についてかなり詳しく考察しています。

 + **GOTO**

|GOTO (ラベル)|ラベルまで移動|
|:-:|:-:|
| (ラベル)|ラベルの明示|

+ EOF
end of fileの略

>https://www.javadrive.jp/command/bat/index11.html

+ **powershell start-process 起動したいバッチファイル  -verb runas**
powershellを管理権限で実行

+ **%~f0** 
バッチファイルの自体の名前を絶対パスを取得する（このバッチファイルのフルパス）

+ **-NoProfile**
まず-NoProfileはPowershell実行時に読み込む環境情報を読み込まないという設定です。今回想定している利用場面では無くても大丈夫そうなパラメータですが、念のための記述。


+ **Invoke-Expression**
変数に格納した文字列を **コマンドとして実行する** には、「Invoke-Expression」コマンドレットを使用できます。


powershell -command｛　　｝コマンドを実行する

+ **command**
command の値には、スクリプト ブロック、または文字列を指定できます。
powershell実行する内容を指定しています。
※commandの後の”　　”　”　”内で文字列指定しています。

+ **(get-content '対象ファイル' -raw)**
ファイルの中身の一括取得
Get-Contentコマンドレットは、-RAWオプションをつけることで全ての行を1つの変数に丸ごと格納することが出来ます。

>https://qiita.com/daifukusan/items/fcc0f8c9ee0c47c68a72


```例.bat
PS> $p="ping 127.0.0.1"
PS> Invoke-Expression $p

127.0.0.1 に ping を送信しています 32 バイトのデータ:
127.0.0.1 からの応答: バイト数 =32 時間 <1ms TTL=64
127.0.0.1 からの応答: バイト数 =32 時間 <1ms TTL=64
127.0.0.1 からの応答: バイト数 =32 時間 <1ms TTL=64
127.0.0.1 からの応答: バイト数 =32 時間 <1ms TTL=64

127.0.0.1 の ping 統計:
    パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 0ms、最大 = 0ms、平均 = 0ms
```
出典
> https://pg-note.com/archives/155




+ **Get-NetAdapter**
オプションを指定せずにGet-NetAdapterコマンドレットを実行すると、コンピュータに接続されたネットワークアダプターが表示されます
実際の自分の仕事PCで実施
```
Name                      InterfaceDescription                    ifIndex Status       MacAddress             LinkSpeed
----                      --------------------                    ------- ------       ----------             ---------
Bluetooth ネットワーク... Bluetooth Device (Personal Area Netw...      19 Disconnected XX-X3-BC-C0-XX-XX         3 Mbps
Wi-Fi                     Intel(R) Wireless-AC 9560 160MHz             16 Up           XX-X3-BC-C0-XX-XX       780 Mbps
イーサネット              Intel(R) Ethernet Connection (6) I219-V       3 Disconnected XX-22-7A-6A-XX-XX          0 bps

```

+ **-InterfaceAlias**
	インターフェースのエイリアス名を指定する。Wi-FiかEthernetかbluetoohなど


Get-NetIPAddress
これも自分の仕事PCで実施
まわりのスマホの電波も拾っている感じ
```
IPAddress         : fe80::9820:XXaX:5XXX:7cXX%X
InterfaceIndex    : 15
InterfaceAlias    : ローカル エリア接続* 12
AddressFamily     : IPv6
Type              : Unicast
PrefixLength      : 64
PrefixOrigin      : WellKnown
SuffixOrigin      : Link
AddressState      : Deprecated
ValidLifetime     :
PreferredLifetime :
SkipAsSource      : False
PolicyStore       : ActiveStore

IPAddress         : fe80::5ba:2b9b:XX9X:Xf%X0
InterfaceIndex    : 20
InterfaceAlias    : ローカル エリア接続* 3
AddressFamily     : IPv6
Type              : Unicast
PrefixLength      : 64
PrefixOrigin      : WellKnown
SuffixOrigin      : Link
AddressState      : Deprecated
ValidLifetime     :
PreferredLifetime :
SkipAsSource      : False
PolicyStore       : ActiveStore

IPAddress         : fe80::6ca5:10be:XXXX:XXe9%XX
InterfaceIndex    : 19
InterfaceAlias    : Bluetooth ネットワーク接続
AddressFamily     : IPv6
Type              : Unicast
PrefixLength      : 64
PrefixOrigin      : WellKnown
SuffixOrigin      : Link
AddressState      : Deprecated
ValidLifetime     :
PreferredLifetime :
SkipAsSource      : False
PolicyStore       : ActiveStore

IPAddress         : fe80::29c7:6020:bXXX:XXfX%XX
InterfaceIndex    : 16
InterfaceAlias    : Wi-Fi
AddressFamily     : IPv6
Type              : Unicast
PrefixLength      : 64
PrefixOrigin      : WellKnown
SuffixOrigin      : Link
AddressState      : Preferred
ValidLifetime     :
PreferredLifetime :
SkipAsSource      : False
PolicyStore       : ActiveStore

IPAddress         : ::1
InterfaceIndex    : 1
InterfaceAlias    : Loopback Pseudo-Interface 1
AddressFamily     : IPv6
Type              : Unicast
PrefixLength      : 128
PrefixOrigin      : WellKnown
SuffixOrigin      : WellKnown
AddressState      : Preferred
ValidLifetime     :
PreferredLifetime :
SkipAsSource      : False
PolicyStore       : ActiveStore

IPAddress         : 169.XXX.XX.XXX
InterfaceIndex    : 15
InterfaceAlias    : ローカル エリア接続* 12
AddressFamily     : IPv4
Type              : Unicast
PrefixLength      : 16
PrefixOrigin      : WellKnown
SuffixOrigin      : Link
AddressState      : Tentative
ValidLifetime     :
PreferredLifetime :
SkipAsSource      : False
PolicyStore       : ActiveStore
```


-InterfaceIndexと択一

+ **-eq**
比較演算子です。等しいという意味を持ちます。

|PowerShell|C/C++|意味|
|:-:|:-:|:-:|
|-eq|==|等しい|
|-ne|!=|等しくない|
|-gt|>|より大きい|
|-ge|>=||以上|
|-lt|<|より小さい|
|-le|<=|以下|
|-like|N/A|ワイルドカードと等しい|
|-notlike|N/A|ワイルドカードと等しくない|
|-match	N/A正規表現と等しい|
-notmatch|N/A||正規表現と等しくない|

+ **Get-NetIPConfiguration**
実際に仕事で使っているPCで実行
以下のような実行結果
```
InterfaceAlias       : Wi-Fi
InterfaceIndex       : 16
InterfaceDescription : Intel(R) Wireless-AC 9560 160MHz
NetProfile.Name      : dowatec-wifi 2
IPv4Address          : 172.17.2.XXX
IPv6DefaultGateway   :
IPv4DefaultGateway   : 172.17.2.XXX
DNSServer            : 211.129.12.XXX
                       211.129.14.XXX

InterfaceAlias       : Bluetooth ネットワーク接続
InterfaceIndex       : 19
InterfaceDescription : Bluetooth Device (Personal Area Network)
NetAdapter.Status    : Disconnected

InterfaceAlias       : イーサネット
InterfaceIndex       : 3
InterfaceDescription : Intel(R) Ethernet Connection (6) I219-V
NetAdapter.Status    : Disconnected

```

+ **参考(Get-NetIPConfiguration).IPv4Address**
上だとIPv4でつながっているWi-Fi,イーサネット,bluetoothがすべて取り出される
```例.bat
IPAddress         : 172.17.2.XXX
InterfaceIndex    : 16
InterfaceAlias    : Wi-Fi
AddressFamily     : IPv4
Type              : Unicast
PrefixLength      : 24
PrefixOrigin      : Manual
SuffixOrigin      : Manual
AddressState      : Preferred
ValidLifetime     :
PreferredLifetime :
SkipAsSource      : False
PolicyStore       : ActiveStore
PSComputerName    :

IPAddress         : 169.254.XX.XX
InterfaceIndex    : 19
InterfaceAlias    : Bluetooth ネットワーク接続
AddressFamily     : IPv4
Type              : Unicast
PrefixLength      : 16
PrefixOrigin      : WellKnown
SuffixOrigin      : Link
AddressState      : Tentative
ValidLifetime     :
PreferredLifetime :
SkipAsSource      : False
PolicyStore       : ActiveStore
PSComputerName    :

IPAddress         : 169.254.74.XXX
InterfaceIndex    : 3
InterfaceAlias    : イーサネット
AddressFamily     : IPv4
Type              : Unicast
PrefixLength      : 16
PrefixOrigin      : WellKnown
SuffixOrigin      : Link
AddressState      : Tentative
ValidLifetime     :
PreferredLifetime :
SkipAsSource      : False
PolicyStore       : ActiveStore
PSComputerName    :
```
+ **参考(Get-NetIPConfiguration).IPv4Address.IPAddress**
だと、その中でipだけ抜き出してくれる
```例
172.17.2.XXX
169.254.XX.XX
169.254.74.XXX
```


+**Remove-NetIPAddress -AddressFamily "IPv4" -Confirm:$false**


|オプション|説明|
|:-:|:-:|
|-AddressFamily|IPアドレスのタイプを指定する。"IPv4" or "IPv6"|
|-Confirm|コマンドレット実行前にプロンプトで確認するかどうか|
>https://qiita.com/Kirito1617/items/aed439bcb66c63489337



+ **PrefixLength 24**

|サブネットマスク|サブネットプレフィックス長|利用できるIP数|
|:-:|:-:|:-:|
|255.0.0.0|/8|16,777,216|
|255.128.0.0|/9|8,388,608|
|255.192.0.0|/10|4,194,304|
|255.224.0.0|/11|2,097,152|
|255.240.0.0|/12|1,048,576|
|255.248.0.0|/13|524,288|
|255.252.0.0|/14|262,144|
|255.254.0.0|/15|131,072|
|255.255.0.0|/16|65,536|
|255.255.128.0|/17|32,768|
|255.255.192.0|/18|16,384|
|255.255.224.0|/19|8,192|
|255.255.240.0|/20|4,096|
|255.255.248.0|/21|2,048|
|255.255.252.0|/22|1,024|
|255.255.254.0|/23|512|
|255.255.255.0|/24|256|
|255.255.255.128|/25|128|
|255.255.255.192|/26|64|
|255.255.255.224|/27|32|
|255.255.255.240|/28|16|
|255.255.255.248|/29|8|
|255.255.255.252|/30|4|
|255.255.255.254|/31|2|
|255.255.255.255|/32|1|

>https://www.ipentec.com/document/network-ip-address-correspondence-subnet-mask-and-subnet-prefix-length

自分用の解説がながすぎて、でもまあ今の自分は知らないことが多いからこんなものか。。。