(VC++).Net Framework がインストールされているかどうかを調べる方法で書いてる要件を満たすため、過去4回いろいろ書いてきましたが、それらのまとめとして、実際の C++ のコードを載せておきます。
動きとしては、.Net Framework 2.0 がインストールされているかどうかの確認。
されていなければ、インターネットにつながるかどうかの確認。
つながらなければその旨を表示するというごくシンプルなものです。
(しかし、シンプルとはいえ文字列・ポインタ系ではまって時間を無駄にしてしまいましたが。。)
プロジェクトは Visual Studio 2008 で、ダイアログベースの MFC アプリケーション、CSocket を使うようウィザードでチェックを入れます。
プロジェクト名は CheckFramework とします。
■CheckFramework.cpp
// CheckFramework.cpp : アプリケーションのクラス動作を定義します。//
#include "stdafx.h"
#include "CheckFramework.h"
#include "CheckFrameworkDlg.h"
...省略
// 唯一の CCheckFrameworkApp オブジェクトです。
CCheckFrameworkApp theApp;
// CCheckFrameworkApp 初期化
BOOL CCheckFrameworkApp::InitInstance()
{
...省略
CString strTitle = _T(".Net Framework インストールチェック");
// .Net Framework 2.0 インストールチェック
bool bNetfx20Installed = IsNetfx20Installed();
if ( ! bNetfx20Installed ) {
// .Net がインストールされてないときは、MSのサイトにつながるかチェック
CString msg ;
if ( ! IsConnectNetwork( &msg ) ){
CString errMsg ;
errMsg ="インターネットに接続できないため、動作に必要な .Net Framework 2.0 をダウンロードできません。\n";
errMsg += "インタネットに接続するか、.Net Framework 2.0 をインストールしてから再度お試しください。\n";
MessageBox( NULL , errMsg + msg , strTitle , MB_OK | MB_ICONERROR );
return FALSE;
}
}
//setup.exeの存在確認
CFileFind find;
//自分のexeのパス確認
TCHAR path[_MAX_PATH];
::GetModuleFileName(NULL,path,sizeof path);
//自分のexeのパスから、ディレクトリ名までのインデックスを探す。
int i = 0;
for ( i = wcslen(path) ; i > 0 ; i--)
{
if ( path[i] == '\\' ){
break ;
}
}
TCHAR path2[sizeof path];
_tcsncpy( path2 , path , i + 1 );
path2[i + 1] = '\0';
//setup.exeのパスを生成
CString strFilePath = path2;
strFilePath += _T("setup.exe") ;
if( find.FindFile( strFilePath ) ){
//setup.exeを起動
ShellExecute( NULL , _T("open") , strFilePath , NULL , NULL , SHOW_OPENWINDOW );
}else{
CString msg = _T("インストールエラー: setup.exe が見つかりません。");
MessageBox( NULL , msg , strTitle , MB_OK | MB_ICONERROR );
}
...省略
// ダイアログは閉じられました。アプリケーションのメッセージ ポンプを開始しないで
// アプリケーションを終了するために FALSE を返してください。
return FALSE;
}
/******************************************************************
Function Name: IsConnectNetwork
Description: 指定されたホストにたいして通信ができるかどうかを判断
Inputs: CString *msg 参照渡の文字列。メッセージを返す
Results: true 指定されたURL、ポートのホストにアクセスできた。
false アクセスできなかった
******************************************************************/
bool IsConnectNetwork(CString *msg)
{
BOOL bret;
// ソケットを作成
CSocket socket;
bret = socket.Create();
if( bret == FALSE)
{
*msg = "\n詳細:ソケット作成に失敗しました。";
return false;
}
CString strSv ;
strSv = "www.microsoft.com";
// サーバーへ接続する(ローカルを指定しています。)
bret = socket.Connect( ( strSv ), 80);
if( bret == FALSE)
{
*msg = "\n詳細:";
*msg += strSv ;
*msg += " に接続できませんでした。";
return false;
}
socket.Close();
return true;
}
■IsInstalledFrameworkLib.cpp
#include "stdafx.h"
//MSのサンプル使用。詳細は http://jehupc.exblog.jp/9620350/
// Constants that represent registry key names and value names
// to use for detection
const TCHAR *g_szNetfx20RegKeyName = _T("Software\\Microsoft\\NET Framework Setup\\NDP\\v2.0.50727");
const TCHAR *g_szNetfxStandardRegValueName = _T("Install");
const TCHAR *g_szNetfxStandardSPxRegValueName = _T("SP");
const TCHAR *g_szNetfxStandardVersionRegValueName = _T("Version");
/******************************************************************
Function Name:IsNetfx20Installed
Description:Uses the detection method recommended at
http://msdn.microsoft.com/library/aa480243.aspx
to determine whether the .NET Framework 2.0 is
installed on the machine
Inputs: NONE
Results: true if the .NET Framework 2.0 is installed
false otherwise
******************************************************************/
bool IsNetfx20Installed()
{
bool bRetValue = false;
DWORD dwRegValue=0;
if (RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx20RegKeyName, g_szNetfxStandardRegValueName, NULL, (LPBYTE)&dwRegValue, sizeof(DWORD)))
{
if (1 == dwRegValue)
bRetValue = true;
}
return bRetValue;
}
/******************************************************************
Function Name:RegistryGetValue
Description:Get the value of a reg key
Inputs:HKEY hk - The hk of the key to retrieve
TCHAR *pszKey - Name of the key to retrieve
TCHAR *pszValue - The value that will be retrieved
DWORD dwType - The type of the value that will be retrieved
LPBYTE data - A buffer to save the retrieved data
DWORD dwSize - The size of the data retrieved
Results:true if successful, false otherwise
******************************************************************/
bool RegistryGetValue(HKEY hk, const TCHAR * pszKey, const TCHAR * pszValue, DWORD dwType, LPBYTE data, DWORD dwSize)
{
HKEY hkOpened;
// Try to open the key
if (RegOpenKeyEx(hk, pszKey, 0, KEY_READ, &hkOpened) != ERROR_SUCCESS)
{
return false;
}
// If the key was opened, try to retrieve the value
if (RegQueryValueEx(hkOpened, pszValue, 0, &dwType, (LPBYTE)data, &dwSize) != ERROR_SUCCESS)
{
RegCloseKey(hkOpened);
return false;
}
// Clean up
RegCloseKey(hkOpened);
return true;
}
■stdafx.h
...省略
/******** IsInstalledFrameworkLib.cpp 関連のヘッダファイル start ***********/
#include
#include
#include
#include
#ifndef SM_TABLETPC
#define SM_TABLETPC86
#endif
#ifndef SM_MEDIACENTER
#define SM_MEDIACENTER87
#endif
// Function prototypes
bool IsNetfx20Installed();
bool RegistryGetValue(HKEY, const TCHAR*, const TCHAR*, DWORD, LPBYTE, DWORD);
/******** IsInstalledFrameworkLib.cpp 関連のヘッダファイル end ***********/
/******** ネットワーク接続チェック関連のヘッダファイル start ***********/
bool IsConnectNetwork(CString *msg);
/******** ネットワーク接続チェック関連のヘッダファイル end ***********/
久しぶりの C++ なんで、文字列操作あたりは汚いかもしれませんが。。。
(余談:MCPのロゴ載せてみました。といっても、70-215の試験なんで今さらという感じですが。。アメリカのMCPメンバーサイトに登録してなかったんで、MSの日本法人に問い合わせて Access Code 再発行してもらいました。)