ネットワーク設定を1つのbatファイルで設定する

# はじめに

ネットワーク設定を変えることが増えて、いちいちインターフェースを右クリックしてプロパティ開いて、、という作業を減らしたかった。

batの知識はほぼゼロからでした。

## 参考
ほとんどこちらのコピペです。ありがとうございます。

[管理者権限でbatを実行したい時にやッた事](https://qiita.com/resolver/items/7187bd6ee8016ee5c741)

# 設定するネットワーク環境
「ワイヤレス ネットワーク接続」に
IPアドレス：192.168.11.90
マスク：255.255.255.0
GW：192.168.11.1
DNS1：192.168.11.1
と設定することにする。

# 追記していく方法
参考元の例では渡す処理が1つのコマンド（mkdir)だけだが、複数のコマンドを渡すときには工夫が必要になる。

複数コマンドを&で並べずに、一行ずつsyori.batに追記していく方法だと遅延環境変数とかエスケープとか考えずにすむ。

```
set syori_1=netsh interface ipv4 set address %IFNAMEWL% static %IPADDR% %MASK% %GW% 
set syori_2=netsh interface ipv4 set dnsservers %IFNAMEWL% %DNS1%

rem セットしたコマンドをbatに出力する。2行目は「>>」で追記する
echo %syori_1% >syori.bat
echo %syori_2% >>syori.bat
```
が、2行程度ならまだしももっと増えた場合めんどくさすぎるので、以下の方法をとった。

# 最終的なソースコード
```
@echo off

rem 日時を取得する
set now_date=%DATE: =0%
    set now_date=%now_date:~0,4%%now_date:~5,2%%now_date:~8,2%

set now_time=%time: =0%
    set now_time=%now_time:~0,2%%now_time:~3,2%%now_time:~6,2%

set now_dt=%now_date%%now_time%

rem 場所の移動する
cd /d "%~dp0"

rem ネットワーク設定
set IFNAMEWL="ワイヤレス ネットワーク接続"
set IPADDR=192.168.11.90
set MASK=255.255.255.0
set GW=192.168.11.1
set DNS1=192.168.11.1

rem 実行したい処理をセットする。& で複数コマンド。&をリテラルで渡すには^& と書いて渡す。
setlocal ENABLEDELAYEDEXPANSION
set syori_1=netsh interface ipv4 set address %IFNAMEWL% static %IPADDR% %MASK% %GW% ^& netsh interface ipv4 set dnsservers %IFNAMEWL% %DNS1%

rem セットしたコマンドをbatに出力する。出力直前に変数を展開する
echo !syori_1!>syori.bat
						   
rem デバッグ用
type syori.bat

rem エラーが起きた時の為にエラーレベルを出力する
set syori_err_l=echo %%errorlevel%%
echo %syori_err_l% ^>"%~dp0"err_%now_dt%.log >>syori.bat

rem powershellで管理者権限で出来たbatを実行する
powershell start-process syori.bat -verb runas

rem 処理が終わるまでちょい待つ。自分に2回pingして結果を出力しない。
@ping localhost -n 2 > nul

rem 出力されたエラーレベルを取得する
set /p err_l_get=<./err_%now_dt%.log

rem エラーレベルで処理の成否を判定
if %err_l_get% == 0 (
    echo 処理完了!!!
) else (
    echo 処理エラー　ヘルプに問い合わせて
    goto err_go
)

rem 使い終わったbatとlogを消す
del syori.bat

del err_%now_dt%.log

echo キーボードをどれか押すと閉じる

@pause  > nul

exit


:err_go
rem  エラー時の処理

rem 使い終わったbatを消す
del syori.bat

echo キーボードをどれか押すと閉じる

@pause > nul

exit

```

## ハマリポイント1：&のエスケープ

set syori_1= の行で複数のコマンドを変数に格納するとき、コマンドを&で並べるときに^&と書かないとダメ。
&をリテラルで書くときの注意点。

```
set syori_1=netsh interface ipv4 set address %IFNAMEWL% static %IPADDR% %MASK% %GW% ^& netsh interface ipv4 set dnsservers %IFNAMEWL% %DNS1%
```
このエスケープについては割とすぐに気づいた。

## ハマリポイント2：遅延環境変数
syori.batにコマンドを出力するとき、はじめはこう書いていた。

```
echo &syori_1&>syori.bat
```
文頭の `@echo off`をonにして実行時ログを見ると
> 
echo netsh interface ip set address "ワイヤレス ネットワーク接続" static 192.168.11.90 255.255.255.0 192.168.11.1 & netsh interface ip add dns "ワイヤレス ネットワーク接続" 192.168.11.1  1>syori.bat
netsh interface ip set address "ワイヤレス ネットワーク接続" static 192.168.11.90 255.255.255.0 192.168.11.1 // なぜか1つ目のnetshが実行される。
>
type syori.bat
要求された操作には、権限の昇格が必要です。管理者として実行してください。
// 1つ目のnetshの実行結果が出力されている


調べてみると
[Windowsバッチファイル変数](http://capm-network.com/?tag=Windows%E3%83%90%E3%83%83%E3%83%81%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%A4%89%E6%95%B0)
> 環境変数の展開方法には「%変数%」と「!変数!」の二通りがあります。「%」は構文解析時に環境変数の展開を行い、「!」はコマンド実行の直前に（つまり遅延して）環境変数の展開を行います。

どうやら今回の場合は、変数`&syori_1&`が展開するときになんかうまくいかなかったっぽい。
batchの詳しい処理順序とか理解できていませんが。

遅延環境変数を使えばうまくいきました。

```
setlocal ENABLEDELAYEDEXPANSION
set syori_1=netsh interface ip set address %IFNAMEWL% static %IPADDR% %MASK% %GW% ^& netsh interface ip add dns %IFNAME% %DNS1%

echo !syori_1!>syori.bat
```
>実行時ログ
echo !syori_1! 1>syori.bat
//echo実行時では変数は格納されたまま、出力直前で展開される。
>
type syori.bat
netsh interface ip set address "ワイヤレス ネットワーク接続" static 192.168.11.90 255.255.255.0 192.168.11.1 & netsh interface ip add dns "ワイヤレス ネットワーク接続" 192.168.11.1

# おわり

素直に右クリックメニューから管理者として実行すればいいんだけどね。