最終的に、VS 6 を Win 8 と Win 10 で動作させることができました。基本的な手順は次のとおりです。
\Windows に msjava.dll という名前のダミー ファイルを作成します。(例: "echo >msjava.dll") この手順がないと、VS 6 インストーラーはうまく機能しません。
VS 6 と SP 6 をインストールします。
MSDEV.EXE の名前を、MSDEVQ.EXE などの別の名前に変更します。
フォールト トレラントなヒープ shim を除外する MSDEVQ の互換性データベースを作成します。このステップがないと、HeapAlloc などを多用するプログラムのデバッグは、非常に遅くなります。
デバッグの場合、OLE32 への呼び出しが発生する前に、ブレークポイントがトリップされることを確認してください。メイン プログラムまたは (MFC アプリの場合) InitInstance 関数の早い段階で、次のヘッダーを含めます。
X64DebugHack.h:
#ifdef _DEBUG
// In order to be able to debug this application on x64, we need to single
// step across at least one statement before ole32.dll gets loaded. So
// always leave this breakpoint in place.
requiredbreakpoint:
int junkola = 42;
// Check to see that there was a breakpoint...
PUCHAR pjunk;
_asm lea eax, requiredbreakpoint
_asm mov pjunk, eax
if (*pjunk != 0xCC)
AfxMessageBox("Required breakpoint was not set prior to loading OLE32.DLL -- single stepping will not be possible during this debugging session.", MB_OK | MB_ICONHAND, 0);
LoadLibrary("OLE32");
#endif
- 「デバッグの停止」ボタンを提供する拡張 DLL を記述します。拡張機能は、Win64 と Win32 では異なるハンドル タイプを持つデバッグ ハンドルを検索して破棄する必要があります。拡張機能を記述するメカニズムは、このフォーラムの範囲を超えていますが、実際の作業を行うコードは次のとおりです。
CCommands::HelpAssistantKill:
typedef LONG NTSTATUS;
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
enum SYSTEM_INFORMATION_CLASS {
SystemHandleInformation = 16,
};
typedef NTSTATUS(NTAPI *PNTQUERYSYSTEMINFORMATION)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
typedef struct _SYSTEM_HANDLE_INFORMATION {
ULONG ProcessId;
UCHAR ObjectTypeNumber;
UCHAR Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
typedef struct _SYSTEM_HANDLE_INFORMATION_DATA {
ULONG HandleCount;
SYSTEM_HANDLE_INFORMATION HandleInformation[1];
} SYSTEM_HANDLE_INFORMATION_DATA, *PSYSTEM_HANDLE_INFORMATION_DATA;
#define HANDLE_TYPE_DEBUG_OBJECT 11 // correct value for Win8 x64
STDMETHODIMP CCommands::HelpAssistantKill()
{ // CCommands::HelpAssistantKill
AFX_MANAGE_STATE(AfxGetStaticModuleState());
BOOL didit = FALSE;
HMODULE hDll = NULL;
PSYSTEM_HANDLE_INFORMATION_DATA phi = NULL;
do { // do once
HRESULT hr;
// Locate NtQuerySystemInformation within NTDLL.DLL
hDll = LoadLibrary("NTDLL");
if (!hDll)
break;
PNTQUERYSYSTEMINFORMATION NtQuerySystemInformation = (PNTQUERYSYSTEMINFORMATION) GetProcAddress(hDll, "NtQuerySystemInformation");
if (!NtQuerySystemInformation)
break;
// Do an initial query to get the number of handles presently open in the system.
// This is a large number. The returned length value is meaningless for this query.
SYSTEM_HANDLE_INFORMATION_DATA hid;
DWORD junk;
NTSTATUS status = (*NtQuerySystemInformation)(SystemHandleInformation, &hid, sizeof(hid), &junk);
if (!NT_SUCCESS(status) && status != STATUS_INFO_LENGTH_MISMATCH)
break;
ULONG length = sizeof(SYSTEM_HANDLE_INFORMATION_DATA) + (hid.HandleCount - 1) * sizeof(SYSTEM_HANDLE_INFORMATION);
phi = (PSYSTEM_HANDLE_INFORMATION_DATA) new UCHAR[length];
if (!phi)
break;
// Get a list of all handles open in the system
status = (*NtQuerySystemInformation)(SystemHandleInformation, phi, length, &junk);
if (!NT_SUCCESS(status))
break;
// Find and close any debug objects that are open in this instance of Visual Studio.
DWORD pid = GetCurrentProcessId();
ULONG ihandle;
for (ihandle = 0; ihandle < hid.HandleCount; ++ihandle)
{ // for each open handle
PSYSTEM_HANDLE_INFORMATION p = phi->HandleInformation + ihandle;
if (p->ProcessId != pid || p->ObjectTypeNumber != HANDLE_TYPE_DEBUG_OBJECT)
continue;
if (CloseHandle((HANDLE) p->Handle))
didit = TRUE;
} // for each open handle
// Instruct DevStudio to stop
BSTR bsStopDebugging = SysAllocString(L"DebugStopDebugging");
if (!bsStopDebugging)
break;
hr = m_pApplication->ExecuteCommand(bsStopDebugging);
SysFreeString(bsStopDebugging);
if (hr != 0)
break;
} // do once
while (FALSE);
if (phi)
delete[] phi;
if (hDll)
FreeLibrary(hDll);
if (!didit)
{ // didn't do anything
MessageBox(NULL, "Unable to find and close any debug object handles", "HelpAssistant", MB_OK | MB_ICONINFORMATION);
} // didn't do anything
return S_OK;
} // CCommands::HelpAssistantKill
これはかなり勇敢な取り組みのように感じましたが、VS 6 でビルドされた約 100 万行のコードを作業し続ける必要がありました。VS 2015 用の実行可能なマクロ プロセッサを自分で作成したので、このアプリケーションの変換を行うことができます。