none
VB2008でOSが32bitか64bitなのかを判定するには? RRS feed

  • 質問

  • Win7上でVB2008を使用してアプリを作成していますが、作成したアプリが64bitOSのX86(32bit)で動作しているのか、それともはじめから32bitのOS上で動いているのかを調べたいのです。

    つまり、アプリを立ち上げたときに、OSの種類(32bitか64bitなのか)を判別したいのです。その方法はありますでしょうか?

    2013年8月3日 7:34

回答

  • こんなのはいかかでしょうか?

    C:\Program Files (x86) フォルダの有無で判断する。

    Dim pgf As String = System.Environment.GetEnvironmentVariable("SystemDrive") & "\Program Files (x86)"
    Dim isOS64 As Boolean = IIf(System.IO.Directory.Exists(pgf), True, False)
    VB2008SP1 OS:Win7 x64 で確認です。
    • 編集済み ShiroYuki_Mot 2013年8月4日 2:28 語句訂正
    • 回答としてマーク UPR 2013年8月4日 13:28
    2013年8月4日 2:02

すべての返信

  • > アプリを立ち上げたときに、OSの種類(32bitか64bitなのか)を判別し
    > たいのです。その方法はありますでしょうか?

    アプリが自身のコードの中で判別するのか、アプリを立ち上げたユーザーが判別するのか分かりませんがどちらですか?

    アプリを立ち上げたユーザーが、64 ビット OS 上で、64 ビットネイティブモード/32 ビット互換モードのどちらで動作しているのか判別するということなら、タスクマネージャーで可能です。

    Part 1. 64 ビット Windows OS の基本知識
    http://blogs.msdn.com/b/nakama/archive/2008/10/30/part-1-64-windows-os.aspx

    2013年8月3日 8:32
  • 私もそう考えたのですが、Environment.Is64BitOperatingSystemは.NET 4で追加されたプロパティであり、質問者さんの使われているVB2008(.NET 3.5以前)では使えません。結局Environment.Is64BitOperatingSystemが内部で行っている処理と同等のことを行う必要があります。

    具体的には、Windows APIのIsWow64Processを使います。しかしこのAPIはWindows XP SP2以降、Windows Server 2003 SP1以降にしか提供されていませんからまずはこのAPIが存在するかどうかの判定から必要があります。判定も含めてExamplesにかかれていますので、この処理をVBに移植することになります。

    ですが、新しいもの(64bit OS)に対応したいのであれば、新しいもの(VS2010 / .NET 4以降)を使うことで楽ができますので、VS2010以降に移行することをお勧めします。

    2013年8月3日 9:03
  • お返事ありがとうございます。

    >アプリが自身のコードの中で判別するのか、アプリを立ち上げたユーザーが判別するのか分かりませんがどちらですか

    使用ユーザーが選択するのではなく、アプリ自身が判断させたいのです。それによって処理を振り分けたいのです。何か方法がありますでしょうか。

    2013年8月3日 9:09
  • (追記の事情により前文削除)

    別の方法として、めんどくさい方法ですが、GetNativeSystemInfo を使えばわかりそうに見えます。
    pinvoke.net のコピペを交えたサンプルです。
    ※動作は保障しません。動作確認・検証・保障などは利用者の責任とします。

    private void button1_Click(object sender, EventArgs e)
    {
        SYSTEM_INFO systemInfo;
        GetNativeSystemInfo(out systemInfo);
        MessageBox.Show(systemInfo.processorArchitecture.ToString());
    }
    
    // pinvok.netより
    [StructLayout(LayoutKind.Sequential)]
    struct SYSTEM_INFO
    {
        public ProcessorArchitecture processorArchitecture;
        public ushort reserved;
        public uint pageSize;
        public IntPtr minimumApplicationAddress;
        public IntPtr maximumApplicationAddress;
        public IntPtr activeProcessorMask;
        public uint numberOfProcessors;
        public uint processorType;
        public uint allocationGranularity;
        public ushort processorLevel;
        public ushort processorRevision;
    }
    
    private enum ProcessorArchitecture : ushort
    {
        Amd64 = 9,
        Ia64 = 6,
        Intel = 0,
    }
    [DllImport("Kernel32.dll")]
    private static extern void GetNativeSystemInfo(out SYSTEM_INFO systemInfo);


    追記:

    あ、よく考えれば、IsWow64Process でも事足りるか。ごめんなさい。orz
    32bit OS なら false が得られそうですし…。

    2013年8月3日 10:14
    モデレータ
  • 皆さんのアドバイスありがとうございます。

    当方はVB初心者であり、C言語は全くといっていいほどわかりません。佐祐理さんやAzuleanさんのおっしゃっている内容もよくつかめないのが現状です。要するにVB2008で解決するというのは無理ということなのでしょうね。もしそういうことであればあきらめるしかなさそうです。VS2010にするしかないのかもしれません。

    2013年8月3日 10:58
  • VB だということを忘れていました。
    いろいろと割り切ったコードです。Windows XP の古いバージョンは関数が見つからないため、何らかの Exception が発生するはずですが、エラールートと共通化しています。
    Windows XP も含めて適切な判断をしたいのであれば、その環境で動かしてどのように動くか見極めるなど、対処してください。

    ※動作は保障しません。動作確認・検証・保障などは利用者の責任とします。

    Module Module1
    
        <DllImport("Kernel32.dll", SetLastError:=True, CallingConvention:=CallingConvention.Winapi)> _
        Private Function IsWow64Process(ByVal hProcess As IntPtr, ByRef wow64Process As Boolean) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        Sub Main()
            Try
                Dim isWow64 As Boolean
                Dim result As Boolean = IsWow64Process(Process.GetCurrentProcess().Handle, isWow64)
                If result Then
                    If isWow64 Then
                        ' WOW64で実行中
                        'つまり、64bit Windows で 32bit Process として実行されています
                    Else
                        ' WOW64ではない
                        ' 64bit Windows で 64bit Process として実行されているか、
                        ' 32bit Windows で 32bit Process として実行されている
                        ' x86 としてプログラムを作っているなら、32bit Windows ということが言えます
                    End If
                Else
                    ' 実行エラー
                End If
            Catch ex As Exception
                ' エラー or 古い Windows
                ' Windows XP の古いバージョンの場合はここに来ますので、32bit Windows の可能性があります
            End Try
        End Sub
    
    End Module

    2013年8月3日 11:18
    モデレータ
  • http://dobon.net/vb/dotnet/system/is64bit.html

    いちばん手軽なのはCLRレベルでよければIntPtr.Sizeではないでしょうか。

    2013年8月3日 13:28
  • いちばん手軽なのはCLRレベルでよければIntPtr.Sizeではないでしょうか。

    それはプロセスが32bitか64bitかを判断はできますが、OSが32bitなのか64bitなのかは判断できません。

    // 初めの私の回答は、開発環境の確認不足で申し訳ありませんでした。

    2013年8月3日 13:47
  • こんなのはいかかでしょうか?

    C:\Program Files (x86) フォルダの有無で判断する。

    Dim pgf As String = System.Environment.GetEnvironmentVariable("SystemDrive") & "\Program Files (x86)"
    Dim isOS64 As Boolean = IIf(System.IO.Directory.Exists(pgf), True, False)
    VB2008SP1 OS:Win7 x64 で確認です。
    • 編集済み ShiroYuki_Mot 2013年8月4日 2:28 語句訂正
    • 回答としてマーク UPR 2013年8月4日 13:28
    2013年8月4日 2:02
  • それはプロセスが32bitか64bitかを判断はできますが、OSが32bitなのか64bitなのかは判断できません。

    あ、32bitモードだとCLRも32bitで動きますね・・・

    先ほど書いたdobon.NETさんの方にIsWow64Processを使う方法やPROCESSOR_ARCHITECTURE、Win32_Processorの3つの方法でOSの判定方法も書いてあるのでそれが使えそうです。

    ちゃんとGetProcAdressを使ったりして非対応OSへの対策も行っているようです。

    2013年8月4日 3:43
  • Azulean 様

    ありがとうございました。大変参考になりました。しかしながらお示しいただいたコードで実行させたところOSが64bitであることの結果は得られませんでした。いつもisWow64の値はFalseとなって区別することができませんでした。当方のPC(Win7Pro、VB2008ProSP1)のせいかもしれません。お世話をおかけしました。

    2013年8月4日 13:14
  • Shiroyuki_Mot 様

    確かに”C:\Program Files (x86) フォルダの有無で判断する。”のが一番早そうですね。目から鱗のようです。お示しのコードできちんとOSが64bitであることの確認ができ、おかげで処理を振り分けることができました。

    ありがとうございました。

    2013年8月4日 13:19
  • お返事ありがとうございました。しかしながら「ご指定のページが見つかりません。」のため見ることはできませんでした。
    2013年8月4日 13:24
  • ting 様

    アドバイスありがとうございました。dobon.NETさんの情報大変勉強になりました。

    2013年8月4日 13:35
  • ありがとうございました。大変参考になりました。しかしながらお示しいただいたコードで実行させたところOSが64bitであることの結果は得られませんでした。いつもisWow64の値はFalseとなって区別することができませんでした。当方のPC(Win7Pro、VB2008ProSP1)のせいかもしれません。お世話をおかけしました。

    それは Any CPU で実行していませんか?

    私が示したコードで 64bit 判定が可能なのは、x86 としてビルド・実行しているときのみです。
    実験コードとして新しいプロジェクトに貼り付けていた場合、exe のプロジェクトが Any CPU になっている可能性があります。

    2013年8月4日 13:52
    モデレータ
  • Azuleanさんの推測が正しいとして、話を続けますと、

    このように深く理解していない開発者が意図せず64bitモードで動作させてしまうことを避けるために、新しいEXEプロジェクト作成時のデフォルト値がVisual Studio 2008まではAny CPUでしたが、Visual Studio 2010からx86に変更されています。

    # だから既に指摘しているように、時代に合わせたコンパイラを選択すべきです。

    ところでなぜ、64bit OSなのかを判定する必要があるのでしょうか? 何か無駄なことをしているのかもしれません。

    2013年8月4日 14:49
  • UPR さま お役に立てたようで。

    佐祐理 さまが投げ掛けられた 何か無駄なことをしているのかも に賛成です。
    UPR さまの前のスレッドを読ませて頂いたのですが、根本的な問題は別にありそうな気がしています。
    私はスキル不足で指摘出来ませんが、今回の件で取り敢えず表面的な対応を済ませた後で、再び、元の問題を考えて見る価値があると思っています。

    2013年8月4日 15:19
  • 各位

    皆様のアドバイスありがとうございます。なぜOSの種類を判別しなければならないのか?ということですが

    以前私が投稿しました「32bitのPCと64bitのPCでPrintdocumentを利用して印刷すると、印刷位置がずれてしまう」という現象のためです。アプリは32bitのPCで書いてあります。32bitPCではきちんと印刷位置もずれずに印刷できるのですが、64bitのPCにインストール(program Files(X86))すると大幅に印刷がずれてしまうのです。(縦横ともに縮んでしまう)Printdocumentでは固定ピッチのフォントを使用しそのフォントの高さを基準に罫線や印刷位置を指定しています。

     Hi = myFont.Height  としてこのHiを基準に位置決めをしています。しかし64bitのPCでは縦横ともに縮んでしまうのです。ところが64bitの場合このHiを

    Hi = myFont.Height *1.25

    としてやると正常に印刷できるのです。この理由がわからないためにOSの判定をして*1なのか*1.25なのか決めているわけです。この現象はどの64bitのPCでも同じでプリンターを変えても同じです。プログラムの書き方が悪いのかもしれませんが・・・

    ということで質問させていただきました。

    2013年8月5日 0:06
  • Azulean 様

    たびたびのお返事ありがとうございます。確かに Any CPU で実行していました。

    これからx86 としてビルド・実行するように試してみます。ご報告は後ほど・・・

    2013年8月5日 0:10
  • Shiroyuki_Mot 様

    ありがとうございました。取り敢えず表面的な対応ではありますが何とかなりそうです。しかし根本的な解決にはなっていないと思いますので、これから試行錯誤を繰り返してみたいと思います。

    2013年8月5日 0:13
  • 話題が本スレッドからはずれるので、Win7(32bit)上のVB2008(Pro)で作成したアプリをWin7(64bit)のPCで印刷させると位置がずれる側に返信しました。

    変な回避策を行うより、根本解決することをお勧めします。

    2013年8月5日 0:44
  • Azulean 様

    ご指摘ありがとうございました。

    x86 としてビルド・実行させたところきちんと判定ができました。不勉強なためお世話をかけました。
    2013年8月5日 0:58