タグ「Windows」が付けられているもの

How to use Microsoft Account on Windows 10 on Azure

Now we can create "Windows 10 Enterprise" virtual machines on Microsoft Azure in case that you have MSDN subscription. if you're the subscriber, you'll try it so easy. I recommend this way for persons and/or companies who hesitate to upgrade from Windows 7.

Well, when we create Windows 10 VM on Azure, we notice that the first user is a local account with administrators privileges. Then, we may not find to change it to Microsoft Account. It's reason that the first user is assumed by one of built-in local administrator (well-known named 'Administrator') and it must be the local account.

If we use Microsoft Account on Windows 10 on Microsoft Azure, we use following steps. At least I make well on my environment.

  1. Create a new account as a local account.
  2. Once log out and log on as the new account.
  3. Change to the account to Microsoft Acconut. If you don't have Microsoft Account, create it.
  4. Log out and log on as Microsoft Account. If you have already the account and enable sync settings, it shows your avator, desktop theme, etc.
  5. Adjust your preference of language, keyboard, display, etc.
  6. Install your applications and make your desktop readiness.

When you buy a Windows 10 PC (on-premises) and set it up, Windows 10 may suggest to use Microsoft Account. Because Windows 10 and Microsoft Account collaborate well each other. (e.g. Single sign-on, OneDrive, Office Online.) However, Windows 10 VM on Azure is different from Windows 10 PC about some initial settings.

今回は、Windowsのシステムが保持している HTTP プロキシ設定を Java のコードで取得する方法について考えます。

java.net.HttpURLConnectionjavax.ws.rs.client.Client、あるいは Apache HttpComponents (Apache HTTP Client を含むスイート) などを用いて HTTP 通信を行う際、通信の相手方によっては (企業システムではかなりの高確率で) 別途プロキシの設定を行う必要があります。プロキシの設定は各 HTTP クライアントによって異なりますが、いずれも当該の Java アプリケーションが独自に管理するパラメータとなります。

一方で、現在の OS ではシステム側で HTTP プロキシの情報を保持しています。例えば Windows は Internet Explorer と共通でコントロール パネルの「インターネット オプション」、Mac OS X であれば「システム環境設定」、Linux であれば GNOME や KDE などのウィンドウ・マネージャ指定の設定ファイルまたは環境変数、といったようにです。これらを Java のアプリケーションで取得して利用するにはどうすれば良いでしょうか?今回は Windows について検証してみました。

本来は Mac OS X でも検証した上でこの記事を書くつもりだったのですが、諸事情により検証することなく前日に MacBook Air (11 inch) を手放してしまったので、Windows だけを取り上げます。

Windows のシステムが保持しているプロキシ情報は、他の設定同様レジストリに存在しています。このことから、何通りかの取得方法が考えられます。

  • JNI 経由で Win32 API のレジストリ周りにアクセスし、直接レジストリ値を読み取る。
  • 外部プロセスとして reg コマンドを実行し、実行結果の出力を解析する。
  • Applet の API 実装が持っているらしい、コントロール パネル周りの隠し API を呼び出す。

結論としては、今回は上記 3 つは採用しませんでした。理由は以下の通りです。

  • JNI は手順としては理想に近いが、ビルド過程で地獄を見る。C ならまだしも、C++ でコンパイルしようものなら、コンパイラによるマーシャリングの相違からリンクできないケースが多々ある。しかも JNI はダイナミック・リンクになるため、実行するまでリンクの成否が分からない。
  • 外部プロセス呼び出しは同期が取れないと悲惨な目に遭うからできるだけ使いたくない。reg コマンドは同期実行だからまだ救いはあるものの、GlassFish の asadmin や Java DB のネットワーク・リスナーなどは非同期実行なので手に負えない。
  • Applet は Java 7 時代に散々評判を落としており、javapackager でネイティブ・パッケージを作成すると当該 API が含まれているはずの deploy.jar が埋め込まれなかったりする。また、そもそも Server JRE には含まれていない。

一時は JNI で頑張ろうとも思ったのですが、JNI よりは JNA (Java Native Access) を使った方がいいだろうという判断から、久しく見ていなかった JNA を覗いてみました。

以前筆者が JNA を利用しようとしたときは、 Felica SDK を Java から直接叩こうと試行して大失敗した時期で、もう 4~5 年くらい前の話になります。その当時は C/C++ と Java の IN/OUT をマッピングするだけのライブラリだという認識でした (それだけでもプログラミングはとても楽になるのですが)。現在の JNA には、JNA 本体だけでなく、有志の手で作成された各プラットフォーム向けのユーティリティが多数含まれています。Win32 API の主要な API を呼び出すユーティリティも揃っていて、C や C++ のコードを一切書かなくても Win32 API を呼び出すことが可能になりました。もちろん、レジストリもこれらのユーティリティだけで操作可能です。これで道具は揃いました。

前置きが長くなりました。ここからが本題です。

Windows のシステムが保持するプロキシ設定は、下記のレジストリ・キーに含まれています。

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings

この下にいくつかの値があり、それが「インターネット オプション」の設定値と対応しています。

AutoConfigURL - REG_SZ 型 (文字列)
「自動構成スクリプトを使用する」のチェックボックスとテキストフィールドに対応。チェックボックス ON かつテキストフィールドに値が設定されている場合に、テキストフィールドの値が設定される。チェックボックス OFF またはテキストボックスが空の場合には、このエントリ自体が存在しない。

proxyEnable - REG_DWORD (数値)
「LAN にプロキシ サーバーを使用する」のチェックボックスに対応。チェックボックス ON が 1、OFF が 0 となる。このエントリは必ず存在する。

proxyServer - REG_SZ (文字列)
「プロキシ・サーバー」および詳細設定:「サーバー」の「アドレス」「ポート」テキストフィールドと詳細設定:「すべてのプロトコルに同じプロキシ サーバーを使用する」チェックボックスに対応。アドレスの設定方法により値の形式が異なる (下記参照)。すべてのアドレスが空の場合、このエントリは存在しない。
「すべてのプロトコルに同じプロキシ サーバーを使用する」チェックボックス ON の場合、'アドレス:ポート' または 'アドレス' (ポート省略時) がレジストリの値となる。
同チェックボックス OFF の場合、'スキーマ=アドレス:ポート' または 'スキーマ=アドレス' (ポート省略時) のセットをスキーマの数だけ (最大 4) セミコロンで連結したものがレジストリの値となる。スキーマは HTTP → 'http'、Secure → 'https'、FTP → 'ftp'、Socks → 'socks' となる。

proxyOverride - REG_SZ (文字列)

「ローカル アドレスにはプロキシ サーバーを使用しない」チェックボックスと詳細設定:「次で始まるアドレスにはプロキシを使用しない」に対応。基本的には詳細設定:「次で始まるアドレスにはプロキシを使用しない」の値が設定されるが、「ローカル アドレスにはプロキシ サーバーを使用しない」チェックボックス ON の場合には、アドレス一覧の最後に '<local>' という特殊なアドレスが付加される。「次で始まるアドレスにはプロキシを使用しない」に値が設定されておらず、かつ「ローカル アドレスにはプロキシ サーバーを使用しない」チェックボックス OFF の場合には、このエントリは存在しない。

2016-04-03 補足 :
環境によっては proxyOverride の既定値として '*.local' が設定されます。

Win32 API のレジストリ操作系は、com.sun.jna.platform.win32.Advapi32Util クラス経由で呼び出すことができます。ただし、レジストリ・キーを指定するにはさらに com.sun.jna.platform.win32.WinReg インタフェースが必要です。

単純にレジストリを読み取るだけであれば、Advapi32Util クラスの registryGetStringValue メソッド (REG_SZ 型) または registryGetStringValue メソッド (REG_DWORD 型) の呼び出しだけで完結します。ただし、今回のように条件によってはレジストリ・エントリが存在しない場合には、事前に registryValueExists メソッドでエントリの存在を確認し、存在しない場合には registryGetStringValue 等を呼び出さないようにする必要があります。

ここまでの範囲で筆者が作成したサンプルは GitHub にあります

最後に、今後の展望と今回の調査に至った経緯についてお話しておきます。

まず、他の OS への展開ですが、Mac OS X についてはそれほど難しくはないと考えています。Mac OS X の「システム環境設定」の各種設定値を保持しているファイル (確か XML ファイルだったと記憶しています) の構成を把握し、かつネットワーク設定を保持するファイルの書式を押さえていれば、値の読み取りに関しては問題ないでしょう (Mac OS X の場合、値の変更は Windows 以上のリスクを伴います)。Linux については、厳密に言うと、Windows や Mac のようなシステムが保持する設定はありません。ただし、GNOME や KDE などのウィンドウ・マネージャが自身の HTTP 通信機能向けにプロキシ設定を保持しています。とは言うものの、ウィンドウ・マネージャは人気のあるものだけでも数種類存在し、それらの派生を含めると相当数に上るため、それらを網羅しきれないと思われます。

今回のお話は、このブログでは珍しく筆者が会社で経験したことが発端となっています。現在、筆者が開発に深く関わっている自社製品 (JavaFX 8 のアプリです) があり、その体験版の配布先からのフィードバックとして「ネットワークのプロキシ設定を Windows と共通にできないか?」という意見がありました。コンピューター・リテラシーがそれほど高くないユーザーにとっては、プロキシ設定だけでも結構なハードルになるのだそうです。その場では「Java からネイティブ・コードにアクセスすることになるので、不可能ではないけれど、難しいですねぇ...」と受け流しておいたのですが、ユーザー視点からは出てきて当然の意見だと思いまして、技術的な担保だけでも取れないかと裏でこっそりやった結果なのです。