3流プログラマのメモ書き

元開発職→現社内SEの三流プログラマのIT技術メモ書き。 このメモが忘れっぽい自分とググってきた技術者の役に立ってくれれば幸いです。(jehupc.exblog.jpから移転中)

(VC++).Net Framework対応アプリインストール前に動かすチェックツール作ってみた

(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 再発行してもらいました。)