Hey, Scripting Guy!

Scripting Guys が皆さんの質問にお答えします

Hey, Scripting Guy!

TechNet コラムへようこそ。このコラムでは、よく寄せられるシステム管理スクリプトに関する質問に Scripting Guys がお答えします。システム管理スクリプトについて質問がある場合は、scripter@microsoft.com (英語のみ) までお送りください。すべての質問に回答することはできないかもしれませんが、可能な限り対応いたします。

詳細情報

Hey, Scripting Guy!カテゴリ別アーカイブ

Hey, Scripting Guy!日付別アーカイブ

Hey, Scripting Guy!ダウンロード (英語)

Spacer

*

コンピュータの IP アドレスごとに通常使うプリンタを設定する方法はありますか

Hey, Scripting Guy! Question

Scripting Guy さん、よろしくお願いします。コンピュータの IP アドレスごとに通常使うプリンタを設定する方法はありますか。

-- TT

SpacerHey, Scripting Guy! AnswerScript Center

TT さん、おはようございます。今朝は少し脱線するかもしれませんが、TT さんはお許しくださるでしょう。このコラムを執筆している Scripting Guy は昨夜、16 才の息子とジムに行きました。息子は生まれて初めて父親より多くの回数のベンチ プレスをこなすことができました。確かに、Scripting Guy はレスリングではまだまだ息子に負けませんが、息子は次のように指摘します。「父さんがレスリングの技を全部知っているというだけのことだよ。僕の体がこれからも成長し続けて、もっと強くなれば、そんな小技は僕には効かなくなるよ。そうしたら、僕は父さんをつまみ上げて、叩きのめしてしまうだろうね」

息子はいつかそうすることでしょう。

言うまでもなく Scripting Guy が息子とレスリングできる日々、つまり、少なくとも息子とレスリングをして勝てる日々はもう残り少ないということです。そのため、Scripting Guy は新しく取り組む (闘う) ことのできる何かを探し始めています。たとえば、コンピュータの IP アドレスごとに通常使うプリンタを変更する問題に取り組むことです。

注 : まぁ、そうですね。この問題に取り組むことがこれまでで一番興奮したレスリングの埋め合わせになることはないでしょう。ただ、今このときは Scripting Guy は挑戦を求めているのではなく、打ち勝つことのできる何かを求めているのです。

電子メールに書かれているように、TT さんは複数のサブネットを使用しており、それらのサブネットの 2 番目のオクテットごとに通常使うプリンタを設定したいのですね。たとえば、コンピュータがサブネット 192.1.x.x 上にある場合は、通常使うプリンタを割り当て、192.2.x.x 上にある場合は、別の通常使うプリンタを割り当てるということですね。

難しそうですね。でも実際は、簡単です。少なくとも息子さんより強い父親にとっては。

幸い、息子さんより強い父親でなくともそれほど難しくはありません。

strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colItems = objWMIService.ExecQuery _
    ("Select * from Win32_NetworkAdapterConfiguration Where IPEnabled = True")

For Each objItem in colItems
    strIPAddress = objItem.IPAddress(0)
    arrIPAddress = Split(strIPAddress, ".")

    If arrIPAddress(0) = "192" Then

    Select Case arrIPAddress(1)
        Case 1 
            Set colInstalledPrinters =  objWMIService.ExecQuery _
                ("Select * from Win32_Printer Where Name = '\\\\atl-ps-01\\printer1'")
            For Each objPrinter in colInstalledPrinters
                objPrinter.SetDefaultPrinter()
                Exit For
            Next
        Case 2 
            Set colInstalledPrinters =  objWMIService.ExecQuery _
                ("Select * from Win32_Printer Where Name = '\\\\atl-ps-01\\printer2'")
            For Each objPrinter in colInstalledPrinters
                objPrinter.SetDefaultPrinter()
                Exit For
            Next
        End Select
    End If
Next

いくつか注意点があります。第 1 に、必要なプリンタはすべてコンピュータにインストール済みであると想定しています。インストール済みでない場合は、コードを変更して特定のプリンタの存在を確認し、プリンタが存在しない場合は、インストールを行うようにする必要があります。第 2 に、通常使うプリンタの構成には WMI を使用しました。その長所とはなんでしょうか。これにより、ローカル (おそらく、ログオン スクリプトとして) とリモートの "どちらでも" 実行できるスクリプトが提供されます。では、短所はなんでしょうか。それは、上記のようなスクリプトは Windows XP または Windows Server 2003 が動作しているコンピュータでのみ動作するということです。

注 : 今でも Windows 2000 を使用しているユーザーのために解決策はないのでしょうか。もちろんあります。Windows Script Host 5.6 で SetDefaultPrinter メソッドを使用すると同じ処理を実行することができます。このアプローチの唯一の欠点は、スクリプトをローカルに実行する必要があるということですが、言うまでもなく、このスクリプトをログオン スクリプトとして "実行している" 場合、どのみちこれは当然のことです。詳細については、「Microsoft Windows 2000 Scripting Guide」(英語) を参照してください。

いい考えがあります。Windows 2000 上で機能させるための方法が理解できない場合は、お知らせください。お役に立てる方法を何とか考えてみます。

さて、どこまで説明したでしょうか。ああ、そうでした。スクリプトについて説明していたところでしたね。ご覧のように、最初はいつものマンネリなコードで始まります。続いて、次の 2 行のコードを使用して、ローカル コンピュータの WMI サービスに接続します。

strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

接続を作成後、次のクエリを発行して、コンピュータ上で見つかった IP 対応のネットワーク アダプタのコレクションを返します。

Set colItems = objWMIService.ExecQuery _
    ("Select * From Win32_NetworkAdapterConfiguration Where IPEnabled = True")

ちなみに、この Where 句である Where IPEnabled = True は重要です。この句により、IP アドレスを持たない (または取得することのできない) すべての "ネットワーク アダプタ" を除外できます。馬鹿げているように思えるかもしれませんが、WMI はバーチャル マシン ドライバ、パケット スケジューラなどのものをすべてネットワーク アダプタであると見なします。"実際の" ネットワーク アダプタに的を絞るために IPEnabled = True を使用する習慣をつけることをお勧めします (ただし、実際はこのスクリプトは Where 句がなくてもうまく機能します)。

コレクションを取得したら、For Each ループを設定してそのコレクションのすべてのネットワーク アダプタを順に処理します。ループ内で実行していることは、実際はとても簡単ですが、少し説明が必要です。

まず、次のコードを使用して、コレクションの最初のネットワーク アダプタに割り当てられている最初の IP アドレスを取得します。

strIPAddress = objItem.IPAddress(0)

確かに、1 つのネットワーク アダプタが複数の IP アドレスを持つことがあります。ログオン スクリプトの一部としてプリンタをマッピングする場合、おそらくクライアント ワークステーションを処理対象としていることが想定されますが、その場合は、"マルチホーム" アダプタについて心配する必要はありません。リスクを承知で、(すべてではないけれども) ほとんどのネットワーク カードは IP アドレスを 1 つしか持たないと見なし、ここでは手を抜いて、最初の IP アドレスだけを取得します。

それでは、たとえば、192.2.168.1 という IP アドレスを使用しているとしましょう。ここで関心があるのは、2 番目のオクテット、つまりこの場合は 2 だけです。どうやってその値を分離させるのでしょうか。まず、Split 関数を使用して、この IP アドレスを配列に分割します。

arrIPAddress = Split(strIPAddress, ".")

IP アドレスをピリオドで区切ると、(この例では) 以下の項目で構成される配列になります。

192

2

168

1

次の手順では、最初のオクテット (つまり、配列内の項目 0) が 192 に等しいことを検証します。

If arrIPAddress(0) = "192" Then

ネットワーク セットアップによりますが、これはあまり重要ではないでしょう。つまり、おそらくお使いのすべての IP アドレスは 192 で始まります。この行は念のために作成しました。

次に、Select Case ステートメントを使用して、2 番目のオクテット (配列内の項目 1) の値を確認します。

Select Case arrIPAddress(1)

次に、この 2 番目のオクテットの取り得る値をチェックする一連の Case ステートメントを使用します。たとえば、2 番目のオクテットは 2 であるため、次の Case ステートメントが使用されます。

Case 2 
    Set colInstalledPrinters =  objWMIService.ExecQuery _
       ("Select * from Win32_Printer Where Name = '\\\\atl-ps-01\\printer2'")
        For Each objPrinter in colInstalledPrinters
            objPrinter.SetDefaultPrinter()
            Exit For
        Next

ご覧のとおり、ここでの処理は、WMI クエリを使用して \\atl-ps-01\printer2 という Name を持つすべてのプリンタを選択します。ただし、プリンタ名は一意である必要があるため、最大でも、1 つのプリンタで構成されるコレクションが返されます。いいえ、違います。プリンタ名を入力するときに \ キーを押したまま居眠りをしたのではありません。

\\\\atl-ps-01\\printer2

ご存知かも知れませんが、\ は WMI の予約文字です。つまり、Where 句に \ を使用する場合は必ず、\ をもう 1 つその前に挿入して \ 文字を "エスケープ" する必要があります。つまり、\ を二重にする必要があるのです。そのため文字列の先頭に \\ と 2 つある場合は、\\\\ と 4 つ入力します。

馬鹿げているように思えますか。

次に、For Each ループを設定してコレクション内のすべての項目を順に処理します。ループ内では、SetDefaultPrinter メソッドを使用して \\atl-ps-01\printer2 を通常使うプリンタに設定します。

objPrinter.SetDefaultPrinter()

その後、For Each ループを終了します。なぜですって。そうですね。通常使うプリンタを既に割り当てたので、通常使うプリンタをもう一度割り当てる理由がないからです (192 で始まる IP アドレスを持つ別のネットワーク アダプタがあることを想定しています)。もちろん、もう一度通常使うプリンタを割り当てる理由がある場合は、単に Exit For ステートメントを削除してかまいません。

その場合、同じような Case ステートメント (または何らかの関数) を設定して、2 番目のオクテットのその他の取り得る値をすべて明らかにする必要があります。そのためには、Case ステートメントの一部としてそのオクテットの値を指定し (Case 3 など)、そのサブネットに該当するプリンタを割り当てるコードを含めるだけです。全体的には、簡単ですね。ベンチ プレスよりはるかに簡単です (考えてみると、ちょっと馬鹿げていますね。というのも、重い重量を持ち上げることができるということと、その人がどのくらい強いかということは無関係なのではないでしょうか)。

TT さんのお役に立てばと思います。Scripting Guys は、帰宅して息子とのレスリング マッチに取り組まなければなりません。できるだけ多くの勝利を息子から勝ち得るようにしなければなりません。どのみち、一度息子に負けてしまったら、もう二度と息子に勝つことはできなくなると落ち込んでいるのです。

そうそう、以下が Windows 2000 で機能するバージョンのスクリプトです。誰かを打ち負かすことを心の支えにできなくなったので、打ち負かすのではなく親切にし始めた方がいいということがわかってきたものですから。

strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colItems = objWMIService.ExecQuery _
    ("Select * from Win32_NetworkAdapterConfiguration Where IPEnabled = True")

Set objNetwork = CreateObject("Wscript.Network")

For Each objItem in colItems
    strIPAddress = objItem.IPAddress(0)
    arrIPAddress = Split(strIPAddress, ".")

    If arrIPAddress(0) = "192" Then

    Select Case arrIPAddress(1)
        Case 1 
            Set colInstalledPrinters =  objWMIService.ExecQuery _
                ("Select * from Win32_Printer Where Name = '\\\\atl-ps-01\\printer1'")
            For Each objPrinter in colInstalledPrinters
                objNetwork.SetDefaultPrinter objPrinter.Name
                Exit For
            Next
        Case 2 
            Set colInstalledPrinters =  objWMIService.ExecQuery _
                ("Select * from Win32_Printer Where Name = '\\\\atl-ps-01\\printer2'")
            For Each objPrinter in colInstalledPrinters
                objNetwork.SetDefaultPrinter objPrinter.Name
                Exit For
            Next
        End Select
    End If
Next

ページのトップへページのトップへ