こんにちは、情シス担当のますいです。

弊社では社内のPCは4年(開発チームは2年)を目安に交換することになっており、新人入社や突発的な故障による交換の分も合わせると、年間60台程度の新規PCをセットアップしています。  
使用しているPCは、Windows10 Proがプリインストールされたごく普通のメーカー法人モデルで、オンプレミスのActive Directoryで管理しています。
 
PCはドメイン参加やソフトウェアインストール等の初期セットアップを行ってユーザーに渡しますが、作業が繁雑なため各種操作を極力自動で実行できるようスクリプトを組んでいます。  
ここではスクリプトの細部については解説せず、どのような処理をどういうコマンドで実行しているかの概略を説明します。

1.事前準備

スクリプトを実行する前に手動でやらなければならないことを実行します。

初回起動

初期状態のWindowsを起動すると青い画面が出て、ユーザーアカウントなどいくつかの入力を求められます。Out-Of-Box Experience (OOBE) というものですが、これは手入力で普通に処理します。

PC名の変更

Windows8.1まではOOBEの段階でPC名を付けられたのですが、Windows10では初期名称を勝手に命名されてしまうので、起動後にログインしてから変更しなければなりません。
変更コマンドをバッチにして、PC名だけ入力すれば良いようにしています。

rename.bat

@echo off
set /p newname=PC name :
wmic computersystem where name="%computername%" call rename name="%newname%"
変更を確定するために一回再起動します。Windows8.1以前に比べて無駄な再起動が1回増えてしまいました。

2. スクリプトによる自動設定

ここから自動スクリプトの出番です。ネットワークへの接続やドメイン参加などを行うスクリプト1と、ソフトウェアのインストールやOSの設定を行うスクリプト2に分割してあります。
言語はJScriptを使用していますが、VBSやPowerShellなどでも可能でしょう。
(スクリプト例はWindowsコマンドとJScriptのメソッドが混在していますが、WindowsコマンドはWScript.Shellのexecまたはrunメソッドで実行しています。)
一連の操作は管理者権限を求められるものが多いので、いちいちUACによって中断されることがないよう、コマンドプロンプトを「管理者として実行」で開いてからスクリプトを実行します。

スクリプト1

ネットワーク接続

弊社ではDHCPサーバにMACアドレスを登録してIPアドレスを固定で割り当てるので、この段階ではネットワークに繋がっていません。
割り当てるIPアドレスは別途管理表に記録しています。
手動で登録するにはipconfigでMACアドレスを調べてDHCPサーバ(Windows Server 2012 R2)にリモデで入って予約して…と煩雑な手順が必要になりますが、スクリプトから下記手順で登録しています。

1. 割り当てるIPアドレスを自己のNICに固定で設定する

IPアドレスを設定するには、対象のイーサネットアダプタ名を指定する必要がありますが、Windows7以前では「ローカル エリア接続」、Windows8以降は「イーサネット」と名称が異なるので、スクリプト内でOSバージョンをチェックして指定先を設定しています。
OSバージョンを取得する関数
function getOsVersion() {
// 戻り値は win7:6.1, win8:6.2, win8.1:6.3, win10:10.0
 var objWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\\\.\\root\\cimv2");
 var e = new Enumerator(objWMI.ExecQuery("Select * from Win32_OperatingSystem"));
 var item = e.item();
 return(item.Version.substr(0, item.Version.lastIndexOf(".")));
}
NICにIPアドレスを固定する
netsh interface ip set address [イーサネットアダプタ名] static [IPアドレス] [ネットマスク] [ゲートウェイ] 1
この後、DHCPサーバにPINGを打って疎通を確認しています(スクリプト省略)。

2. 自己のMACアドレスをDHCPサーバに予約する

DHCPサーバは Windows Server なので netsh dhcp server コマンドでIPアドレスを予約することができます。このコマンドを、PsExecを用いて遠隔でDHCPサーバに実行させます。
※ PsExec:Microsoftが公開しているWindows管理ツール群[PsTools]の1つで、遠隔PCにコマンドを実行させることができる。
MACアドレスの取得にはWMIのWin32_NetworkAdapterConfigurationクラスを使用します(スクリプト省略)。
psexec \\[DHCPサーバ名] -u [管理者ユーザ名] -p [管理者パスワード] netsh dhcp server \\[DHCPサーバ名] scope [DHCPスコープ] add reservedip [IPアドレス] [MACアドレス] [PC名]

3. NICのIPアドレス設定をDHCP取得に変更し、取得しなおす

netsh interface ip set dns [イーサネットアダプタ名] dhcp
netsh interface ip set address [イーサネットアダプタ名] dhcp
無線LANを搭載している場合は上記2と同じ手順で無線LANのIPアドレスも予約しておきます。

ドメインへの参加

ドメインの参加にはWMIのWin32_ComputerSystemクラスでJoinDomainOrWorkgroupメソッドを使用します。
var objNetWork = WScript.CreateObject("WScript.Network");
var objComputer = GetObject("winmgmts:{impersonationLevel=impersonate}!\\\\" + objNetWork.ComputerName + "\\root\\cimv2:Win32_ComputerSystem.Name='" + objNetWork.ComputerName + "'");
var result = objComputer.JoinDomainOrWorkgroup([ドメイン], [管理者パスワード], [ドメイン管理者ID], [登録先OU], 3);

スクリプト2

ソフトウェアインストール

部署により異なりますがインストールするソフトウェアは20本程度あります。
ソフトウェアのインストール方式は下記のように大別されますのでそれぞれについて解説します。
  • msi形式
  • サイレントオプションのあるexe
  • ファイルをコピーするだけ
  • 対話式インストーラ

msi形式

MSI(Microsoft Windows Installer)形式のファイルはそのまま実行することはできず、msiexec.exe のパラメータとしてファイルを指定してインストールします。
サイレントモードのオプションがあるので、カスタマイズする必要がなければ簡単にインストールできます。
msiexec /i [ファイル名] /qn 


サイレントオプションのあるexe

これも各ソフトウェアの指定に従い実行します。
MS Officeもボリュームライセンス版を利用しているので Config.xml にサイレントインストールオプションを指定してインストールします。


ファイルをコピーするだけ

一部のフリーウェアや社内アプリはローカルの所定の場所にコピーし、デスクトップにショートカットを作成します。
var objFileSys = WScript.CreateObject("Scripting.FileSystemObject");
objFileSys.CopyFolder(copyFrom, copyTo);
var objShortCut = objShell.CreateShortcut(objFileSys.BuildPath(objShell.SpecialFolders("Desktop"), "[ソフト名].lnk"));
objShortCut.TargetPath = [実行ファイルのパス];
objShortCut.WorkingDirectory = [実行ファイルのあるディレクトリ];
objShortCut.Save();


対話式インストーラ

これが一番やっかいです。GUIを操作しなければインストールできないのですが手動ではやりたくない。
そこで SendKeys メソッドを使用してGUIに対して所定の順番でキー入力を行うという、かなり無理矢理な方法をとります。
キー入力時に、対象ウィンドウがアクティブになっていない可能性があるので、1入力ごとにウィンドウをアクティブにする処理を入れます。
objShell.AppActivate([ウィンドウ名]);
ここで、例えば[次へ(N)]というボタンを押す操作の場合、仮にデフォルトでそのボタンにフォーカスが当たっているとしてもエンターキーを送信することはお勧めしません。何らかの影響でフォーカスがずれている可能性があるので必ず[Alt+n]を送信します。
objShell.SendKeys("%n");
画面遷移に時間がかかる箇所は適宜スリープを挟みますが、遷移状況をスクリプト側から把握できないため、遷移タイミングが予定より遅いと失敗するのが難点です。

ソフトウェアの初期設定

メーラーなど初期設定が必要なものについては、あらかじめ設定済みのconfを置いたり、レジストリに書き込んだりして可能な限り自動化します。

プリンタインストール

プリントサーバを使っても良いのですが、慣習で弊社では各PCにプリンタドライバを直接インストールしています。
プリンタをインストールするには、まずWindowsに用意されているprnport.vbsというスクリプトを使ってポートを作成し、次に printui.dll を使ってドライバのインストールとプリンタの登録を行います。
インストールには、プリンタドライバのインストーラに含まれるinfファイルのパスと、そこに記述されたプリンタ名、IPアドレス、表示名といった情報が必要になります。
ポートの作成
cscript %windir%\system32\Printing_Admin_Scripts\ja-JP\prnport.vbs -a -r [ポート名] -h [プリンタのIPアドレス] -o raw

プリンタの登録
rundll32.exe printui.dll,PrintUIEntry /if /f [infファイルのパス] /m [プリンタ名] /r [ポート名] /b [表示名]
インストール後、通常使うプリンタの選択やプリンタのプロパティ設定は手動で行います。

その他の設定

業務能率を上げるため、Windowsの標準設定から変更する部分を設定します。
大抵はレジストリの操作で可能です。

フォルダオプション

  • 拡張子を表示する
  • 開いているフォルダまで展開する
  • 常にメニューを表示する

視覚効果

  • アニメーションやフェードを全て停止する

リモートデスクトップの許可

  • Remote Desktop Users グループにユーザを追加する

IE初期設定

  • ホームページを about:blank にする
  • 社内標準ブックマークを設定する
  • イントラネットサイト互換表示をオフにする

Windows10 特有の設定

  • 検索結果にWeb検索結果を含めない
  • タスクバーに検索窓を表示しない
  • エクスプローラーからOneDriveを削除する
  • OneDriveをスタートアップから削除する
  • スタートメニューからおすすめを削除する

3.おわりに

ここまで自動化しても手作業の部分は多く残っており、効率化を日々模索しています。
もっと会社の規模が大きくなってPC台数が増えてきたら、VDIの導入など抜本的な改善も検討したいと思っています。