必ず成功する！VC++2022(cl.exe)をコマンドラインから実行する方法

※ この記事で紹介しているスクリプトを文字コードUTF-8で保存してしまうと実行がエラーになりますので、必ず Shift-JISで保存してご利用ください。

※ Visual Studio の更新をするとバイナリ(プログラム)のパスが変更されて見つからなくなる(実行できなくなる)場合があります。その際は上書きでスクリプトを再実行してください。

**この記事はVC++2017用に書いた以下の記事をVC++2022用に手直ししたものです。**

> [Visual C++ 実行に必要な環境変数をいつでも使えるように予め設定しておく方法 (vcvarsall.bat で設定される変数をユーザー環境変数に自動反映するツールを作りました！【完璧バージョン】) - Qiita](https://qiita.com//javacommons/items/9c97d68218c9c5831846)

# 早速ツールを使ってみる

## 前提事項

Visual Studio Community 2022 (C++デスクトップ) がインストール済の環境を想定しています。

## バッチファイルの実行

添付したバッチファイルを実行(エクスプローラーからダブルクリックしてください)するとユーザー環境変数に、INCLUDE LIB LIBPATH PATH が自動的に設定されます(一度実行しておけば設定が残りますので、ログアウトやOSの再起動しても再実行する必要がありません。このバッチファイルを実行した後に、Cygwin や MSYS2、またはコマンドプロンプト等を起動すればvcvarsall.batの実行なしで VC++のコマンド(CL CMAKE NMAKE 等)が使えるようになります)。

「希望する操作を数字で選択してください ⇒ 0=環境変数を消去  32=32bit環境を設定  64=64bit環境を設定  空文字=何もしない」
「数字(0 or 32 or 64)を入力: 」
と表示されますので、キーボードから 0 32 64 入力せずにENTER のいずれかを選択します。

すでに 32bit環境を設定 を実行した後であっても(消去処理が自動的に行われますので) そのまま(上書きで) 64bit環境を設定 を実行してかまいません。64bit環境から32bit環境に切り替える場合にも、わざわざ 環境変数を消去 を呼び出す必要はありません(上書きで実行してください)。実行に時間がかかる場合がありますが、以下のようなメッセージボックスが出るまでウィンドウを閉じずにお待ちください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/140610/8304c35d-2780-4c15-704f-ef87be245c11.png) ![image.png](https://qiita-image-store.s3.amazonaws.com/0/140610/cdd30b7d-974c-8e56-885c-05c5cf20760c.png) ![image.png](https://qiita-image-store.s3.amazonaws.com/0/140610/137e8087-9cc9-d744-e802-d766ee952ef9.png) ![image.png](https://qiita-image-store.s3.amazonaws.com/0/140610/8ad5e143-b12b-dbcc-164b-7431ed5c6b8d.png)

```text:vc2022-env.bat（必ず Shift-JISで保存してご利用ください）
@if(0)==(0) echo off
setlocal enabledelayedexpansion
set VCVARSALL=C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat

set INCLUDE=
set LIB=
set LIBPATH=
set PATH=%SystemRoot%\System32;%SystemRoot%\System32\Wbem
call "%VCVARSALL%" x86
set INCLUDE32=%INCLUDE%
set LIB32=%LIB%
set LIBPATH32=%LIBPATH%
echo [INCLUDE32]
for %%A in ("%INCLUDE32:;=";"%") do (if not "%%~A"=="" echo %%~A)
echo [LIB32]
for %%A in ("%LIB32:;=";"%") do (if not "%%~A"=="" echo %%~A)
echo [LIBPATH32]
for %%A in ("%LIBPATH32:;=";"%") do (if not "%%~A"=="" echo %%~A)
echo [VCPATH32]
set VCPATH32=
for %%A in ("%PATH:;=";"%") do (
  if /i "%%~A" neq "%SystemRoot%\System32" (
    if /i "%%~A" neq "%SystemRoot%\System32\Wbem" (
      echo %%~A
      if "!VCPATH32!" equ "" (set VCPATH32=%%~A) else (set VCPATH32=!VCPATH32!;%%~A)
    )
  )
)
::echo %VCPATH32%

set INCLUDE=
set LIB=
set LIBPATH=
set PATH=%SystemRoot%\System32;%SystemRoot%\System32\Wbem
call "%VCVARSALL%" amd64
set INCLUDE64=%INCLUDE%
set LIB64=%LIB%
set LIBPATH64=%LIBPATH%
echo [INCLUDE64]
for %%A in ("%INCLUDE64:;=";"%") do (if not "%%~A"=="" echo %%~A)
echo [LIB64]
for %%A in ("%LIB64:;=";"%") do (if not "%%~A"=="" echo %%~A)
echo [LIBPATH64]
for %%A in ("%LIBPATH64:;=";"%") do (if not "%%~A"=="" echo %%~A)
echo [VCPATH64]
set VCPATH64=
for %%A in ("%PATH:;=";"%") do (
  if /i "%%~A" neq "%SystemRoot%\System32" (
    if /i "%%~A" neq "%SystemRoot%\System32\Wbem" (
      echo %%~A
      if "!VCPATH64!" equ "" (set VCPATH64=%%~A) else (set VCPATH64=!VCPATH64!;%%~A)
    )
  )
)
::echo %VCPATH64%

set INCLUDE=
set LIB=
set LIBPATH=
set PATH=%SystemRoot%\System32;%SystemRoot%\System32\Wbem
cscript.exe //nologo //E:JScript "%~f0"
endlocal
exit /b
goto :EOF
@end

if (!Array.prototype.contains) {
  Array.prototype.contains = function(x) {
    for (var i=0; i<this.length; i++) {
      if (this[i]==x) return true;
    }
    return false;
  };
}

if (!Array.prototype.remove) {
  Array.prototype.remove = function(x) {
    var result = [];
    for (var i=0; i<this.length; i++) {
      if (this[i]==x) continue;
      result.push(this[i]);
    }
    return result;
  };
}

if (!Array.prototype.removeAll) {
  Array.prototype.removeAll = function(a) {
    var result = [];
    for (var i=0; i<this.length; i++) {
      if (a.contains(this[i])) continue;
      result.push(this[i]);
    }
    return result;
  };
}

var opts = {};
opts.penv         = new ActiveXObject("WScript.Shell").Environment("PROCESS");
opts.uenv         = new ActiveXObject("WScript.Shell").Environment("USER");
opts.include32    = opts.penv.item("INCLUDE32").split(";").remove("");
opts.include64    = opts.penv.item("INCLUDE64").split(";").remove("");
opts.lib32        = opts.penv.item("LIB32").split(";").remove("");
opts.lib64        = opts.penv.item("LIB64").split(";").remove("");
opts.libpath32    = opts.penv.item("LIBPATH32").split(";").remove("");
opts.libpath64    = opts.penv.item("LIBPATH64").split(";").remove("");
opts.path32       = opts.penv.item("VCPATH32").split(";").remove("");
opts.path64       = opts.penv.item("VCPATH64").split(";").remove("");

var selectOk = false;
var num;
while(!selectOk) {
  WScript.StdOut.WriteLine("希望する操作を数字で選択してください ⇒ 0=環境変数を消去  32=32bit環境を設定  64=64bit環境を設定  空文字=何もしない");
  WScript.StdOut.Write("数字(0 or 32 or 64)を入力: ");
  var line = WScript.StdIn.ReadLine();
  num = line.replace(/(^\s+)|(\s+$)/g, ""); // トリム
  switch(num) {
    case '0': case '32': case '64': case '':
      selectOk = true;
      break;
  }
}
switch(num) {
  case '0':
    clearEnv(opts);
    msgbox("環境変数を消去しました");
    break;
  case '32':
    clearEnv(opts);
    put32Env(opts);
    msgbox("32bit環境を設定しました");
    break;
  case '64':
    clearEnv(opts);
    put64Env(opts);
    msgbox("64bit環境を設定しました");
    break;
  default:
    msgbox("何もしませんでした");
    break;
}
WScript.Quit();
function msgbox(msg) {
  var shell = new ActiveXObject("WScript.Shell");
  shell.Popup(msg, 0, "Windows Script Host", 0);
}
function initEnv(opts) {
  opts.include = opts.uenv.item("INCLUDE").split(";").remove("");
  opts.lib     = opts.uenv.item("LIB").split(";").remove("");
  opts.libpath = opts.uenv.item("LIBPATH").split(";").remove("");
  opts.path    = opts.uenv.item("PATH").split(";").remove("");
}
function clearEnv(opts) {
  initEnv(opts);
  opts.uenv.item("INCLUDE") = opts.include.removeAll(opts.include32).removeAll(opts.include64).join(";");
  if (opts.uenv.item("INCLUDE") == "") opts.uenv.remove("INCLUDE");
  opts.uenv.item("LIB") = opts.lib.removeAll(opts.lib32).removeAll(opts.lib64).join(";");
  if (opts.uenv.item("LIB") == "") opts.uenv.remove("LIB");
  opts.uenv.item("LIBPATH") = opts.libpath.removeAll(opts.libpath32).removeAll(opts.libpath64).join(";");
  if (opts.uenv.item("LIBPATH") == "") opts.uenv.remove("LIBPATH");
  opts.uenv.item("PATH") = opts.path.removeAll(opts.path32).removeAll(opts.path64).join(";");
  if (opts.uenv.item("PATH") == "") opts.uenv.remove("PATH");
}
function put32Env(opts) {
  initEnv(opts);
  opts.uenv.item("INCLUDE") = opts.include.concat(opts.include32).join(";");
  opts.uenv.item("LIB") = opts.lib.concat(opts.lib32).join(";");
  opts.uenv.item("LIBPATH") = opts.libpath.concat(opts.libpath32).join(";");
  opts.uenv.item("PATH") = opts.path.concat(opts.path32).join(";");
}
function put64Env(opts) {
  initEnv(opts);
  opts.uenv.item("INCLUDE") = opts.include.concat(opts.include64).join(";");
  opts.uenv.item("LIB") = opts.lib.concat(opts.lib64).join(";");
  opts.uenv.item("LIBPATH") = opts.libpath.concat(opts.libpath64).join(";");
  opts.uenv.item("PATH") = opts.path.concat(opts.path64).join(";");
}
```
スクリプトを実行して「64」を入力した後でパスが通っていることを確認しているところ(スクリーンショット)。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140610/a08ac23c-03f3-6e5f-5fff-11e2c224b83e.png)

ご不明な点がありましたら、コメントでお知らせください。