お世話になっております。
また(個人的に)難問にぶち当たってしまい投稿させていただきます。
お知恵を戴けますようお願いします。
開発環境
VS2013 VC++ 共通言語ランタイムを使用しない、スタティックライブラリでMFCを使用
する。です。
今後、GetVersionExW()関数が使われなくなる傾向にあるとのことで、今まで
GetVersionExで取得していた、OSVERSIONINFOEXW構造体の内容を全て別方法で取得しなく
てはならなくなりました。
マニフェストするという回避方法はNGです。
細かい情報が欲しいため、Version Helper functionsも役に立ちません。
VerifyVersionInfo()関数を利用する事にして、OSのマイナー、メジャーバージョンを調
べて、やっとdwMajorVersion,dwMinorVersion,wProductType までは埋めることができま
した。
wServicePackMajorも、OSごとに調べればなんとか力技でセットできそうです。
ですが、存在するOSのエディション(wSuiteMask)やら、ビルド番号(dwBuildNumber),
サービスパックの慣用名(szCSDVersion),dwPlatFormIdなど、どのように取得したら良い
のか分かりません。
良い方法があったらアドバイス戴けますようお願いします。
また、絶対無理だという確実な情報があればそれも教えていただけたら断念する理由にな
るので助かります。
GetVersionEx関数に代わるOSバージョン情報取得は、
プログラマのブログとか色々見ていると、最近は
PEBから情報を取ってくる方法が薦められています。
PEBからバージョン情報を取るNative APIもあります。
↓にPEBとOSバージョン情報取得のことが書かれています。
http://hp.vector.co.jp/authors/VA028184/OllyDbgQA.htm#B110
32ビットだとMajorVersionとかはPEB+0xA4以下にあります
BuildNumberはPEB+0xAC
CSDVersion(番号)はPEB+0xAE
CSDVersion(名前のポインタ)はPEB+0x1F4
PlatFormIdはPEB+0xB0
SuiteMaskの情報は分かりませんが、GetProductInfo関数で代用
できるかもしれません。
GetVersionEx() がダメなら RtlGetVersion() を使えば… とはいかないんでしょうね。
では、 WMI の Win32_OperatingSystem とか。
Win32_OperatingSystem class (Windows)
https://msdn.microsoft.com/ja-jp/library/windows/desktop/aa394239.aspx
PowerShell で
> Get-WmiObject Win32_OperatingSystem | Select-Object *
とでもしてみると、一覧が取得できます。
wSuiteMask や dwBuildNumber や szCSDVersion は、そのものっぽいものがあります。
dwPlatFormId は OSType から判断するしか無いでしょうか。
WMI なので、C++ からは COM を使わないといけないのが面倒といえば面倒です。
しかし dwPlatFormId の VER_PLATFORM_WIN32s とか VER_PLATFORM_WIN32_WINDOWS とか、
まだ対応の必要ありますか??
VerifyVersionInfo() は Win9x 系では使えない気がしますし。
サポート対象OSをどうするのか、OSVERSIONINFOEXWを埋めてどうしたいのかというのが、
今回必要な情報だったと思います。
そもそもの話ですが、OSVERSIONINFOEXWはGetVersionExW()のために作られた構造体だっ
たと思いますので、これにこだわるならGetVersionExW()以外の選択は厳しいのではない
でしょう。
個人的には、DllGetVersion()やGetFileVersionInfo()などを、サポート対象OSや環境に
よって使い分けてOSを識別してますが、OSVERSIONINFOEXWを埋める用途には使えませんし
ねぇ。
うーーん、
>細かい情報が欲しいため、Version Helper functionsも役に立ちません。
まず、
WIN7以降ならまだ専用関数があるけれども、XP以前はなくなっていく傾向
だと思います。
WIN8.1,WIN10を前提に考えていくしかないような気がします。
WIN7、XP、8.1,10の違いをレジストリ-でチェックして、
XP以前はサポ-ト外、
WIN7は詳細はサポ-ト外、
WIN8,8.1はサポ-ト対象、
win10はバージョンアップによるサポ-ト対象
にするしかないような気がしますね。
もう、マイクロソフトからサポ-トきってきているので詳細となると難しいと思います。
いまの現状を維持できればいいとなると、
KさんのWMIがいいと思います。
ソフトの難易度がかなり高いですがサ-ビスソフトとして作るとWMIは作りやすいと
思います。
みなさん、アドバイスありがとうございます。
>ARさま
>サポート対象OSをどうするのか、OSVERSIONINFOEXWを埋めてどうしたいのかというのが、
>今回必要な情報だったと思います。
現状(Win8.0未対応)のプログラムではOSVERSIONENFOEXWの構造体情報をログファイルに
出力しているだけです。
ログ解析の際に、どのようなシステムで動かしたかを判断するための情報という扱いのよ
うです。
今後のOS(Win8.0以降)についても同様の情報を出力するように。という要求なので、対
応するしかない状態です。
ログだけであれば、そこまで細かい情報を出力することが本当に必要かどうか、再検討し
てみてもよいのではないでしょうか。
そのために PEB のような Undocumented な関数を使ったり、これまで使っていない WMI
に手を出したりすることが、コスト/リスクに見合う要求かどうか。
その判断次第では、VerifyVersionInfo をパラメーターを変えながら繰り返し呼び出すこ
とで取得できる情報でも十分だったということもあるかもしれません。
ただ、
> マニフェストするという回避方法はNGです。
というのは気になるところです。
GetVersionEx でも VerifyVersionInfo でも Version Helper Functions でも、マニフェ
ストを設定しておかないと古いバージョンと判断されてしまいます。
何かマニフェストを使えない事情があるのでしょうか?
以下ひとりごと。
どうして GetVersionEx を Deprecated にしちゃうんですかね…。
Windows 10 以降、メジャーバージョンが 10 より上がることがあるのかどうかわかりませ
んが、今後はビルド番号単位で新機能が増えることもあるはず。
Version Helper API では機能として粗いのではないかという気がします。
こちら、綺麗にまとめられてるので紹介させていただきます。
http://yamatyuu.net/computer/program/vc2013/osver4/index.html
一つ情報を足しておきます。
Windows10の最新のInsiderPreview、RedStone1ですが、今まで大丈夫であった
DllGetVersion()を使ってるとOSのバージョンが10.4で返ってくるという現象も出ています。
こういった情報は、いつまでも大丈夫とは限らないので、ログ程度ならあまりこだわり
過ぎないように柔軟な対応を検討した方が良いと思います。
アドバイスありがとうございました。
ログ出力する情報に関してはできる限り集めて対応したいと思います。
とりあえずこれにてCLOSE致します。
一応、現在出ているWin10までのものをマニフェストして作成し、
GetProductInfo(10, 0, 0, 0, &dwReturnedProductType);
関数も使ってエディションの番号(?)を求めるようなこともしてみました。
クローズし忘れました…。