- 記事一覧 >
- ブログ記事
C++ Visual Studio 2019でActiveXを作成
はじめに
以前書いたブログ記事「C++,C# WebBrowser コントロールで IE11 の ActiveX を延命」にて、「Hello world.」 とだけ表示する ActiveX を紹介しました。
今回、その ActiveX について、Visual Studio 2019 で実装、ビルドするところまで紹介したいと思います。
ActiveXは、IE11の拡張機能です。「C++,C# WebBrowserコントロールでIE11のActiveXを延命」または、Edge の IE11 モードで使い続けることはできると思います。正直、今更、ActiveX?という気がしないでもないですが、何かのお役に立てればと思います。
概要
ただ単に 「Hello world.」 と表示する ActiveX です。 (赤枠内が ActiveX です。)
以下の HTML で表示します。
<HTML>
<HEAD>
</HEAD>
<BODY>
<OBJECT CLASSID="CLSID:11b7ddbf-412b-45f5-accc-ab6d01ceb53e" WIDTH="200" HEIGHT="100">
<PARAM NAME="Caption" VALUE="Hello world.">
<EMBED TYPE="application/x-test-activex" WIDTH="200" HEIGHT="100" Caption="Hello world.">
</OBJECT>
</BODY>
</HTML>
IE11 モードではない Edge の場合は、以下のように起動しません。
ソースコード(C++)
ウィザードで生成されたソースコードを少し変更するのみです。ここでは、差分のみ示します。
SafeComp.cpp
SafeComp.h
の2つを追加し、
TestActiveX.cpp
の1つを変更します。
ここで、TestActiveX.cpp
について、
const GUID CDECL BASED_CODE _ctlid =
{ 0x11b7ddbf,0x412b,0x45f5,{0xac,0xcc,0xab,0x6d,0x01,0xce,0xb5,0x3e } };
0x11b7ddbf
...0x3e
部分は、
TestActiveXCtrl.cpp
の
IMPLEMENT_OLECREATE_EX(CTestActiveXCtrl, "MFCACTIVEXCONTRO.TestActiveXCtrl.1",
0x11b7ddbf,0x412b,0x45f5,0xac,0xcc,0xab,0x6d,0x01,0xce,0xb5,0x3e)
に合わせる必要があります。
@@ -0,0 +1,64 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
// Helper function to create a component category and associated
|
4
|
+
// description
|
5
|
+
HRESULT CreateComponentCategory(CATID catid, WCHAR* catDescription)
|
6
|
+
{
|
7
|
+
ICatRegister* pcr = NULL ;
|
8
|
+
HRESULT hr = S_OK ;
|
9
|
+
|
10
|
+
hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
|
11
|
+
NULL,
|
12
|
+
CLSCTX_INPROC_SERVER,
|
13
|
+
IID_ICatRegister,
|
14
|
+
(void**)&pcr);
|
15
|
+
if (FAILED(hr)) {
|
16
|
+
return hr;
|
17
|
+
}
|
18
|
+
|
19
|
+
// Make sure the HKCR\Component Categories\{..catid...}
|
20
|
+
// key is registered
|
21
|
+
CATEGORYINFO catinfo;
|
22
|
+
catinfo.catid = catid;
|
23
|
+
catinfo.lcid = 0x0409 ; // english
|
24
|
+
|
25
|
+
// Make sure the provided description is not too long.
|
26
|
+
// Only copy the first 127 characters if it is
|
27
|
+
int len = wcslen(catDescription);
|
28
|
+
if (len>127)
|
29
|
+
len = 127;
|
30
|
+
wcsncpy_s(catinfo.szDescription, sizeof(catinfo.szDescription), catDescription, len);
|
31
|
+
// Make sure the description is null terminated
|
32
|
+
catinfo.szDescription[len] = '\0';
|
33
|
+
|
34
|
+
hr = pcr->RegisterCategories(1, &catinfo);
|
35
|
+
pcr->Release();
|
36
|
+
|
37
|
+
return hr;
|
38
|
+
}
|
39
|
+
// Helper function to register a CLSID as belonging to a component
|
40
|
+
// category
|
41
|
+
HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid)
|
42
|
+
{
|
43
|
+
// Register your component categories information.
|
44
|
+
ICatRegister* pcr = NULL ;
|
45
|
+
HRESULT hr = S_OK ;
|
46
|
+
hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
|
47
|
+
NULL,
|
48
|
+
CLSCTX_INPROC_SERVER,
|
49
|
+
IID_ICatRegister,
|
50
|
+
(void**)&pcr);
|
51
|
+
if (SUCCEEDED(hr)) {
|
52
|
+
// Register this category as being "implemented" by
|
53
|
+
// the class.
|
54
|
+
CATID rgcatid[1] ;
|
55
|
+
rgcatid[0] = catid;
|
56
|
+
hr = pcr->RegisterClassImplCategories(clsid, 1, rgcatid);
|
57
|
+
}
|
58
|
+
|
59
|
+
if (pcr != NULL) {
|
60
|
+
pcr->Release();
|
61
|
+
}
|
62
|
+
|
63
|
+
return hr;
|
64
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
|
6
|
+
// Helper function to create a component category and associated
|
7
|
+
// description
|
8
|
+
HRESULT CreateComponentCategory(CATID catid, WCHAR* catDescription);
|
9
|
+
// Helper function to register a CLSID as belonging to a component
|
10
|
+
// category
|
11
|
+
HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid);
|
12
|
+
|
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
|
5
5
|
|
6
|
+
|
6
7
|
|
7
8
|
|
8
9
|
|
@@ -15,7 +16,13 @@
|
|
15
16
|
const WORD _wVerMajor = 1;
|
16
17
|
const WORD _wVerMinor = 0;
|
17
18
|
|
19
|
+
const CATID CATID_SafeForScripting =
|
20
|
+
{ 0x7dd95801,0x9882,0x11cf,{0x9f,0xa9,0x00,0xaa,0x00,0x6c,0x42,0xc4 } };
|
21
|
+
const CATID CATID_SafeForInitializing =
|
22
|
+
{ 0x7dd95802,0x9882,0x11cf,{0x9f,0xa9,0x00,0xaa,0x00,0x6c,0x42,0xc4 } };
|
18
23
|
|
24
|
+
const GUID CDECL BASED_CODE _ctlid =
|
25
|
+
{ 0x11b7ddbf,0x412b,0x45f5,{0xac,0xcc,0xab,0x6d,0x01,0xce,0xb5,0x3e } };
|
19
26
|
|
20
27
|
// CTestActiveXApp::InitInstance - DLL 初期化
|
21
28
|
|
@@ -56,6 +63,24 @@
|
|
56
63
|
if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE))
|
57
64
|
return ResultFromScode(SELFREG_E_CLASS);
|
58
65
|
|
66
|
+
if (FAILED(CreateComponentCategory(
|
67
|
+
CATID_SafeForScripting,
|
68
|
+
L"Controls that are safely scriptable")))
|
69
|
+
return ResultFromScode(SELFREG_E_CLASS);
|
70
|
+
|
71
|
+
if (FAILED(CreateComponentCategory(
|
72
|
+
CATID_SafeForInitializing,
|
73
|
+
L"Controls safely initializable from persistent data")))
|
74
|
+
return ResultFromScode(SELFREG_E_CLASS);
|
75
|
+
|
76
|
+
if (FAILED(RegisterCLSIDInCategory(
|
77
|
+
_ctlid, CATID_SafeForScripting)))
|
78
|
+
return ResultFromScode(SELFREG_E_CLASS);
|
79
|
+
|
80
|
+
if (FAILED(RegisterCLSIDInCategory(
|
81
|
+
_ctlid, CATID_SafeForInitializing)))
|
82
|
+
return ResultFromScode(SELFREG_E_CLASS);
|
83
|
+
|
59
84
|
return NOERROR;
|
60
85
|
}
|
61
86
|
|
セーフとしてマーク
マイクロソフトの
スクリプトと初期化 ActiveX MFC コントロールセーフとしてマークする
↑
こちらのサイトに、既定では、MFC ActiveXコントロールは、スクリプトおよび初期化セーフのセーフマークされません。
という記述があります。
これは、どういうことかと言うと、"セーフとしてマーク" しないと、ActiveX が起動しません。
これを回避するためには、
インターネットオプション - 信頼済みサイト(信頼済みサイト追加済み の場合) - このゾーンのセキュリティのレベル : 低
とするか、
インターネットオプション - セキュリティ - レベルのカスタマイズ で
スクリプトを実行しても安全だとマークされていない ActiveX コントロールの初期化とスクリプトの実行 : ダイアログを表示する(有効にする)
と設定しないといけません。
"セーフとしてマーク" しておけば、設定は必要無いため、今回、"セーフとしてマーク" したプログラム作成になります。
内容は、上記マイクロソフトのサイトに書いてある通り実装された SafeComp.cpp
、SafeComp.h
追加 + TestActiveX.cpp
に上記マイクロソフトのサイトに書いてある通りのプログラム追加です。
実は、Hello world
表示だけの場合、ソースコードの変更箇所は有りません。diff は、全てそのためです。
C++ 版ビルド手順
exe ビルド
Visual Studio 2019 は、インストールしたての状態が前提です。
プロジェクト作成準備
Visual Studio Installer
を起動します。
「変更」をクリックします。
「C++ によるデスクトップ開発」→ 右側の詳細部分の「最新の v142 ビルドツール C++ MFC (x86...」にチェックを入れ、「変更」をクリックします。
プロジェクト作成
Visual Studio Installer
を閉じて、Visual Studio 2019
を起動します。
「新しいプロジェクトの作成」をクリックします。
「MFC ActiveX コントロール」を選択して、「次へ」をクリックします。
プロジェクト名:TestActiveX
ソリューション名:TestActiveX
とし、(入力内容は任意です。)「作成」をクリックします。
次に基づいてコントールを作成:「STATIC」を選択し、「完了」をクリックします。
ソースコード編集
この時点で、リポジトリパスにある程度のプログラムが作成されていますので、
(リポジトリパス例:C:\Users\admin\source\repos\TestActiveX\TestActiveX
)
github リポジトリ(itc-lab/TestActiveX)
の
SafeComp.cpp
SafeComp.h
の2つを追加し、
ここで、TestActiveX.cpp
について、
const GUID CDECL BASED_CODE _ctlid =
{ 0x11b7ddbf,0x412b,0x45f5,{0xac,0xcc,0xab,0x6d,0x01,0xce,0xb5,0x3e } };
0x11b7ddbf
...0x3e
部分は、
TestActiveXCtrl.cpp
の
IMPLEMENT_OLECREATE_EX(CTestActiveXCtrl, "MFCACTIVEXCONTRO.TestActiveXCtrl.1",
0x11b7ddbf,0x412b,0x45f5,0xac,0xcc,0xab,0x6d,0x01,0xce,0xb5,0x3e)
に合わせる必要があります。
SafeComp.cpp
SafeComp.h
については、
ソリューションエクスプローラー
↓
ソース ファイル
↓
追加
↓
既存の項目
で追加の必要があります。
表示 - クラスビュー
↓TestActiveX
/ TestActiveXLib
/ _DTestActiveX
を右クリック
↓
追加
↓
プロパティの追加
プロパティー名 : Caption
(リストボックスで選択) とし、「OK」をクリックします。
ビルド実行
「ビルド」→「TestActiveX のビルド」をクリックします。
ここで、管理者権限が無い場合、以下のようなエラーになります。
その場合は、Visual Studio 2019 を "管理者として実行" で起動して、ビルドします。
1> ライブラリ C:\Users\admin\source\repos\TestActiveX\Debug\TestActiveX.lib とオブジェクト C:\Users\admin\source\repos\TestActiveX\Debug\TestActiveX.exp を作成中
1>TestActiveX.vcxproj -> C:\Users\admin\source\repos\TestActiveX\Debug\TestActiveX.ocx
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VC\v160\Microsoft.CppCommon.targets(2288,5): warning MSB3075: コマンド "regsvr32 /s "C:\Users\admin\source\repos\TestActiveX\Debug\TestActiveX.ocx"" はコード 5 で終了しました。このコマンドを実行するための十分な権限があるか確認してください。
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VC\v160\Microsoft.CppCommon.targets(2288,5): warning MSB4181: "Exec" タスクから false が返されましたが、エラーがログに記録されませんでした。
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VC\v160\Microsoft.CppCommon.targets(2300,5): error MSB8011: 出力の登録に失敗しました。ユーザーごとのリダイレクトを有効にするか、引き上げられたアクセス許可を使用して、コマンド プロンプトからコンポーネントを登録してください。
1>プロジェクト "TestActiveX.vcxproj" のビルドが終了しました -- 失敗。
========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========
⇒ Visual Studio 2019 を管理者として実行
ビルドに成功すると、C:\Users\admin\source\repos\TestActiveX\Release\TestActiveX.ocx
が作成されます。
msi ビルド
本ブログ別記事「カスタム URL スキームでエクスプローラーを起動してフォルダを開く msi ビルド全手順」「拡張機能インストール」の手順とほぼ同じですので、詳細は省略します。
概ね以下の手順になります。
拡張機能の Microsoft Visual Studio Installer Projects
をインストールします。
↓TestActiveX.sln
ソリューションを開きます。
↓
ファイル → 追加 → 新しいプロジェクト → 「Setup Project」選択し、「次へ」をクリックします。
↓
プロジェクト名:TestActiveXInstaller
とし、「作成」をクリックします。
↓
「Application Folder」をクリックして、DefaultLocation の値を [LocalAppDataFolder]TestActiveX
とします。
↓
「Application Folder」選択状態で、右ペインを右クリック →「Add」→「ファイル」をクリックします。
↓
ビルド済みの TestActiveX.ocx
例:C:\Users\admin\source\repos\TestActiveX\Release\TestActiveX.ocx
を追加します。
↓
「ビルド」→「TestActiveXInstaller のビルド」をクリックして、TestActiveXIntaller.msi
ができます。
(例:C:\Users\admin\source\repos\TestActiveX\TestActiveXInstaller\Release\TestActiveXIntaller.msi
)
動作例
「Hello world.」 と表示されれば、OKです。真っ白になっている場合、正常に動作していません。
↓
ヨシ!
その他、宣伝、誹謗中傷等、当方が不適切と判断した書き込みは、理由の如何を問わず、投稿者に断りなく削除します。
書き込み内容について、一切の責任を負いません。
このコメント機能は、予告無く廃止する可能性があります。ご了承ください。
コメントの削除をご依頼の場合はTwitterのDM等でご連絡ください。