回答編集履歴

1 参考ソースを追加

atata0319

atata0319 score 625

2018/05/11 02:49  投稿

管理者権限がないユーザーで ActiveX をインストールするには以下の方法があります。
上からおすすめ順になります。
1.Active Directory
#1.Active Directory
組織内で Active Directory が有効であれば、Active Directory で配信するように設定してください。
2.Per User ActiveX
CAB ファイルをダウンロードしてインストールするように構成している場合、
INF ファイルに Per User ActiveX の設定を実施すれば、
各ユーザーがインストール可能な CAB を作成することができます。
#2.Per User ActiveX
CAB ファイルをダウンロードしてインストールするように構成している場合、INF ファイルに Per User ActiveX の設定を実施すれば、各ユーザーがインストール可能な CAB を作成することができます。
詳しくは以下のページを参照ください。
https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/dd433049(v=vs.85)
ただし、IE8 以降が必須です。
mike2mike4 さんが言われてたサーバ側の設定というのはおそらくこの方法だと思います。
3.Per User Registration
#3.Per User Registration
REGSVR32.EXE を直接起動してインストールしている場合、
ActiveX 側で Per User Registration をサポートしていれば、
REGSVR32.EXE に追加の引数を渡すことによりユーザー毎にインストールすることができます。
・ATL DLL
デフォルトでサポートされています。以下のコマンドラインを使用します。
REGSVR32 対象のActiveX.DLL /i:user /n
Per User Registration を使用してインストールした場合、アンインストール時には /i:user /n /u を指定します。
・ATL EXE
多分、デフォルトでサポートされていたと思いますが、確認していません。
起動引数に /RegServerPerUser を指定します。
/RegServerPerUser でインストールした場合、アンインストール時は /UnregServerPerUser となります。
・MFC DLL
めんどくさいので ATL にしませんか?
ATL の動作に合わせる必要はありませんが、 DllInstall を実装して def ファイルでエクスポートすることにより可能です。App Wizard でそんなオプションがあれば良いのですが、私は以下のように実装しています。
```C++
STDAPI DllInstall(BOOL bInstall, _In_opt_ PCWSTR pszCmdLine)
{
   AFX_MANAGE_STATE(_afxModuleAddrThis);
   HRESULT hr;
   HKEY hkeyRedirected;
   LSTATUS lstatus = RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Classes", 0, KEY_ALL_ACCESS, &hkeyRedirected);
   if (lstatus != NOERROR)
       return HRESULT_FROM_WIN32(lstatus);
   lstatus = RegOverridePredefKey(HKEY_CLASSES_ROOT, hkeyRedirected);
   if (lstatus != NOERROR)
   {
       RegCloseKey(hkeyRedirected);
       return HRESULT_FROM_WIN32(lstatus);
   }
   if (bInstall)
   {
       // 本来は直接呼び出せるように RegOverridePredefKey でいろいろマッピングするが、めんどくさいのでパス。
       // hr = DllRegisterServer();
       ITypeLib* plib;
       wchar_t dllpath[MAX_PATH];
       GetModuleFileName(AfxGetInstanceHandle(), dllpath, _countof(dllpath));
       hr = LoadTypeLib(dllpath, &plib);
       if (SUCCEEDED(hr))
       {
           hr = RegisterTypeLibForUser(plib, dllpath, NULL);
           if (SUCCEEDED(hr))
           {
               if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE))
                   hr = ResultFromScode(SELFREG_E_CLASS);
           }
       }
   }
   else
   {
       // 本来は直接呼び出せるように RegOverridePredefKey でいろいろマッピングするが、めんどくさいのでパス。
       // hr = DllUnregisterServer();
       UnRegisterTypeLibForUser(_tlid, 1, 0, 0, SYS_WIN32);
       if (!COleObjectFactoryEx::UpdateRegistryAll(FALSE))
           hr = ResultFromScode(SELFREG_E_CLASS);
       else
           hr = S_OK;
   }
   RegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
   RegCloseKey(hkeyRedirected);
   return hr;
}
```
さらにプロジェクトの DEF ファイルに以下のように DllInstall を追加します。
```DEF
EXPORTS
   DllCanUnloadNow    PRIVATE
   DllGetClassObject  PRIVATE
   DllRegisterServer  PRIVATE
   DllUnregisterServer PRIVATE
   DllInstall         PRIVATE
```
これによって ATL と同様に /i:user /n で個別ユーザーでインストールが可能になります。
・MFC EXE
めんどくさいので ATL にしませんか?
MFC DLL の例に合わせて実装してください。多分、関係ないと思うので解説は省略します。
MFC DLL の例に合わせて実装してください。多分、関係ないと思うので解説は省略します。
---
>2.
Githubにサンプルを追加しました。
https://github.com/atata0319/teratail125280/tree/master/PUAxControlTest1/makecab
test.html で管理者権限のないユーザーでもインストールできることを確認しています。(Windows 10 Pro 64bits 上の IE11)

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る