実行環境
Windows 10
プログラムの概要
仮想メモリの情報をVBSから取得して、あらかじめどのような結果になるか確認しておきます。
VBS
1Dim WMILocator, WMIService, QfeSet, QfeSet2 2 3Set WMILocator = WScript.CreateObject("WbemScripting.SWbemLocator") 4Set WMIService = WMILocator.ConnectServer 5Set QfeSet = WMIService.ExecQuery("SELECT TotalVirtualMemorySize FROM Win32_OperatingSystem") 6Set QfeSet2 = WMIService.ExecQuery("SELECT FreeVirtualMemory FROM Win32_OperatingSystem") 7 8Dim Qfe, Qfe2 9 10for each Qfe in QfeSet 11 ' MB換算で表示 12 WScript.Echo Qfe.Properties_.Item("TotalVirtualMemorySize").Value / 1024 13Next 14 15for each Qfe2 in QfeSet2 16 ' MB換算で表示 17 WScript.Echo Qfe2.Properties_.Item("FreeVirtualMemory").Value / 1024 18Next
結果を控え、今度はC++のプログラムから仮想メモリの情報を取得するため下記を実装しました。
開発環境はVisualStudio 2013です。
C++
1void GetMemoryInf() 2{ 3 // 初期化処理 4 MEMORYSTATUSEX msex = { sizeof(MEMORYSTATUSEX) }; 5 6 // メモリ情報を取得 7 GlobalMemoryStatusEx(&msex); 8} 9
このコードの後で「msex.ullTotalVirtual」と「msex.ullAvailVirtual」の値をMBに換算(byte ⇒ MB)して確認しました。
すると単位がずれているとかそういうことではなく、結果的に全く異なる結果になってしまいました。
おそらくある意味ではどちらも正しい値ではあると思うのですが、こちらが期待していたのは「VBSで取得していた方の値」です。
なるべく内部のコードで完結できるような形で仮想メモリ情報を取得する実装をしたいのですが、どういうことなのかわからず実現方法がわかっていない状況です。
ご教示頂けませんでしょうか。
【補足】
最悪上記で使ったVBSを呼び出すこともできるのですが、最終手段としたいです。
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
下記のような質問は推奨されていません。
- 質問になっていない投稿
- スパムや攻撃的な表現を用いた投稿
適切な質問に修正を依頼しましょう。
回答3件
3
ベストアンサー
比較する対象を間違えていませんか?
ullTotalVirtual は多くの 64bit 環境では、搭載メモリにかかわらず 約128TiByte になると思われます。
ullTotalVirtual は仮想アドレス空間のサイズですから、仮想メモリのサイズは ullTotalPageFile を参照すべきではないでしょうか?
当方の環境 (Windows10 Home 64bit) では、vbs の結果とほぼ一致しました。
投稿2020/01/20 04:13
総合スコア986
2
ネイティブのWin32 APIであるGlobalMemoryStatusEx
は、以下のリファレンスの説明を真に受けて解釈すると、
GlobalMemoryStatusEx function - Microsoft Docs
You can use the GlobalMemoryStatusEx function to determine how much memory your application can allocate without severely impacting other applications.
「このAPIを使っているアプリケーション(実行ファイル)自体が使えるメモリ量を取得できる」です。実際、このAPI自体を実行するアプリケーションが32ビット版である場合は実メモリがどんなに大きくてもullTotalVirtual
メンバーの値は最大でおよそ2GBになります。質問者さんが対象としたい構造体メンバーはそれとは違うullTotalVirtual
とullAvailVirtual
ですが、もともとkernel32が有するネイティブAPIであるGlobalMemoryStatusEx
とWindows管理用インターフェースのWMIとでは用途が違うと言えるため、取得できる値が違ったとしてもそれは仕方が無い(Windows自体の仕様)と少なくとも個人的には考えます。
VBScriptで実行した値をご所望なのであれば、C++とWindowsのCOMインターフェースを使用して同等の操作を行うことができます。
以下は Example: Getting WMI Data from the Local Computer でのサンプルコードをほとんどそのままに、質問者さんが提示したVBScriptと同じような操作をC++で行い、WMIでのTotalVirtualMemorySize``FreeVirtualMemory
を取得する例です。(※尚、実際にこのコードを使われる場合はエラー処理やエラー時に抜ける場合の後処理などを適切に行ってください)
C++
1#define _WIN32_DCOM 2#include <iostream> 3using namespace std; 4#include <comdef.h> 5#include <Wbemidl.h> 6 7#pragma comment(lib, "wbemuuid.lib") 8 9/* 10https://docs.microsoft.com/ja-jp/windows/win32/wmisdk/example--getting-wmi-data-from-the-local-computer 11*/ 12int main() 13{ 14 HRESULT hres; 15 16 // Step 1: -------------------------------------------------- 17 // Initialize COM. ------------------------------------------ 18 19 hres = CoInitializeEx(0, COINIT_MULTITHREADED); 20 if (FAILED(hres)) 21 { 22 wcout << L"Failed to initialize COM library. Error code = 0x" 23 << hex << hres << endl; 24 return 1; // Program has failed. 25 } 26 27 // Step 2: -------------------------------------------------- 28 // Set general COM security levels -------------------------- 29 30 hres = CoInitializeSecurity( 31 NULL, 32 -1, // COM authentication 33 NULL, // Authentication services 34 NULL, // Reserved 35 RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication 36 RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation 37 NULL, // Authentication info 38 EOAC_NONE, // Additional capabilities 39 NULL // Reserved 40 ); 41 42 if (FAILED(hres)) 43 { 44 wcout << L"Failed to initialize security. Error code = 0x" 45 << hex << hres << endl; 46 CoUninitialize(); 47 return 1; // Program has failed. 48 } 49 50 // Step 3: --------------------------------------------------- 51 // Obtain the initial locator to WMI ------------------------- 52 53 IWbemLocator *pLoc = NULL; 54 55 hres = CoCreateInstance( 56 CLSID_WbemLocator, 57 0, 58 CLSCTX_INPROC_SERVER, 59 IID_IWbemLocator, (LPVOID *)&pLoc); 60 61 if (FAILED(hres)) 62 { 63 wcout << L"Failed to create IWbemLocator object." 64 << L" Err code = 0x" 65 << hex << hres << endl; 66 CoUninitialize(); 67 return 1; // Program has failed. 68 } 69 70 // Step 4: ----------------------------------------------------- 71 // Connect to WMI through the IWbemLocator::ConnectServer method 72 73 IWbemServices *pSvc = NULL; 74 75 // Connect to the root\cimv2 namespace with 76 // the current user and obtain pointer pSvc 77 // to make IWbemServices calls. 78 hres = pLoc->ConnectServer( 79 _bstr_t(L"ROOT\CIMV2"), // Object path of WMI namespace 80 NULL, // User name. NULL = current user 81 NULL, // User password. NULL = current 82 0, // Locale. NULL indicates current 83 NULL, // Security flags. 84 0, // Authority (for example, Kerberos) 85 0, // Context object 86 &pSvc // pointer to IWbemServices proxy 87 ); 88 89 if (FAILED(hres)) 90 { 91 wcout << L"Could not connect. Error code = 0x" 92 << hex << hres << endl; 93 pLoc->Release(); 94 CoUninitialize(); 95 return 1; // Program has failed. 96 } 97 98 wcout << L"Connected to ROOT\CIMV2 WMI namespace" << endl; 99 100 // Step 5: -------------------------------------------------- 101 // Set security levels on the proxy ------------------------- 102 103 hres = CoSetProxyBlanket( 104 pSvc, // Indicates the proxy to set 105 RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx 106 RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx 107 NULL, // Server principal name 108 RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx 109 RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx 110 NULL, // client identity 111 EOAC_NONE // proxy capabilities 112 ); 113 114 if (FAILED(hres)) 115 { 116 wcout << L"Could not set proxy blanket. Error code = 0x" 117 << hex << hres << endl; 118 pSvc->Release(); 119 pLoc->Release(); 120 CoUninitialize(); 121 return 1; // Program has failed. 122 } 123 124 // Step 6: -------------------------------------------------- 125 // Use the IWbemServices pointer to make requests of WMI ---- 126 127 // For example, get the name of the operating system 128 IEnumWbemClassObject* pEnumerator = NULL; 129 hres = pSvc->ExecQuery( 130 bstr_t(L"WQL"), 131 bstr_t(L"SELECT TotalVirtualMemorySize, FreeVirtualMemory FROM Win32_OperatingSystem"), 132 WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 133 NULL, 134 &pEnumerator); 135 136 if (FAILED(hres)) 137 { 138 wcout << L"Query for operating system name failed." 139 << L" Error code = 0x" 140 << hex << hres << endl; 141 pSvc->Release(); 142 pLoc->Release(); 143 CoUninitialize(); 144 return 1; // Program has failed. 145 } 146 147 // Step 7: ------------------------------------------------- 148 // Get the data from the query in step 6 ------------------- 149 150 IWbemClassObject *pclsObj = NULL; 151 ULONG uReturn = 0; 152 153 while (pEnumerator) 154 { 155 HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, 156 &pclsObj, &uReturn); 157 158 if (0 == uReturn) 159 { 160 break; 161 } 162 163 VARIANT vtProp; 164 165 // Get the value of the properties 166 hr = pclsObj->Get(L"TotalVirtualMemorySize", 0, &vtProp, 0, 0); 167 if (SUCCEEDED(hr)) { 168 wcout << L"OS TotalVirtualMemorySize: " << vtProp.bstrVal << endl; 169 } 170 VariantClear(&vtProp); 171 172 hr = pclsObj->Get(L"FreeVirtualMemory", 0, &vtProp, 0, 0); 173 if (SUCCEEDED(hr)) { 174 wcout << L"OS FreeVirtualMemory: " << vtProp.bstrVal << endl; 175 } 176 VariantClear(&vtProp); 177 178 pclsObj->Release(); 179 } 180 181 // Cleanup 182 // ======== 183 184 pSvc->Release(); 185 pLoc->Release(); 186 pEnumerator->Release(); 187 CoUninitialize(); 188 189 return 0; // Program successfully completed. 190}
質問者さんご提示のVBScriptをメガバイト換算せずにオリジナルの値を表示するよう少し修正し、実行して比較した例を以下に示します。t2.vbsが質問者さんのVBScriptで、ConApp1.exeが上記C++コードの実行ファイルの32ビット版、64ビット版です。FreeVirtualMemory
の値が実行ごとに少し変化してしまうのは仕方ないですが、TotalVirtualMemorySize
の値は常に同じであることが分かります。
CMD
1C>cscript /Nologo t2.vbs 2-- TotalVirtualMemorySize: 319140808 4-- FreeVirtualMemory 512523004 6 7C>Release\ConApp1.exe 8Connected to ROOT\CIMV2 WMI namespace 9OS TotalVirtualMemorySize: 19140808 10OS FreeVirtualMemory: 12522928 11 12C>x64\Release\ConApp1.exe 13Connected to ROOT\CIMV2 WMI namespace 14OS TotalVirtualMemorySize: 19140808 15OS FreeVirtualMemory: 12524372
投稿2020/01/20 02:50
総合スコア9159
下記のような回答は推奨されていません。
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
このような回答には修正を依頼しましょう。
回答へのコメント
0
1024 で割っていますか?オペレーティングシステムから見るメモリサイズと、ハードウエアから見るメモリサイズは違います。オペレーティングシステムでは、BIOS の使用サイズが含まれていません。どちらか目的を合わせて、同じデータを使用することをお薦めします。
投稿2020/01/20 01:03
総合スコア269
下記のような回答は推奨されていません。
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
このような回答には修正を依頼しましょう。
回答へのコメント
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
関連した質問
Q&A
受付中
Accessデータ連携のVBAによるファイル名変更
回答2
クリップ0
更新
2023/04/27
Q&A
解決済
URLのリダイレクトのフラグとは、詳しくお願いします
回答1
クリップ0
更新
2023/06/07
Q&A
解決済
VBAでウェブサイトのテーブルの1要素をクリックする方法をご教示ください。
回答1
クリップ0
更新
2023/06/06
Q&A
解決済
AtcoderのEducational DP Contestの問題 I - Coins を動的計画で解いた場合とメモ化再帰で解いた場合の実行時間の違いについて
回答1
クリップ0
更新
2023/06/02
Q&A
受付中
Access2010+Windows11+SQLServer2008 R2で環境依存文字が文字化けします
回答1
クリップ0
更新
2023/06/07
Q&A
解決済
Python tkinterでボタンが表示されません。
回答1
クリップ0
更新
2023/05/30
Q&A
受付中
64ビットエクセルのVBAプログラム 止まる箇所についてご教授願う(32はOK
回答2
クリップ0
更新
2023/06/06
Q&A
解決済
プルダウンリストで選択された名前の図を表示したい
回答1
クリップ0
更新
2023/06/07
下記のような回答は推奨されていません。
このような回答には修正を依頼しましょう。
2020/01/20 04:33 編集
2020/01/20 06:16