我正在调试部署Windows Metro App Package的示例应用程序(" .Appx"文件)。它称为WinRT方法" PackageManager.AddPackageAsync"失败并显示详细的错误代码文本(在操作完成后从调用返回值中检索):
错误0x80070002:由于Windows无法注册Windows 内部错误或内存不足。
我的目标是找到WinRT调用中出现此错误的位置。我认为实现这一目标的最佳方法是找到错误代码的设置位置。我之前使用旧的简单Win32 API完成了这项工作,但现在使用这个新的基于com的复杂异构接口,我完全迷失了。
可以找到示例项目文件at。它的主要功能如下:
[MTAThread]
int __cdecl main(Platform::Array<String^>^ args)
{
wcout << L"Copyright (c) Microsoft Corporation. All rights reserved." << endl;
wcout << L"AddPackage sample" << endl << endl;
if (args->Length < 2)
{
wcout << "Usage: AddPackageSample.exe packageUri" << endl;
return 1;
}
HANDLE completedEvent = nullptr;
int returnValue = 0;
String^ inputPackageUri = args[1];
try
{
completedEvent = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
if (completedEvent == nullptr)
{
wcout << L"CreateEvent Failed, error code=" << GetLastError() << endl;
returnValue = 1;
}
else
{
auto packageUri = ref new Uri(inputPackageUri);
auto packageManager = ref new PackageManager();
auto deploymentOperation = packageManager->AddPackageAsync(packageUri, nullptr, DeploymentOptions::None);
deploymentOperation->Completed =
ref new AsyncOperationWithProgressCompletedHandler<DeploymentResult^, DeploymentProgress>(
[&completedEvent](IAsyncOperationWithProgress<DeploymentResult^, DeploymentProgress>^ operation, AsyncStatus)
{
SetEvent(completedEvent);
});
wcout << L"Installing package " << inputPackageUri->Data() << endl;
wcout << L"Waiting for installation to complete..." << endl;
WaitForSingleObject(completedEvent, INFINITE);
if (deploymentOperation->Status == AsyncStatus::Error) //Here I decided to track "deploymentOperation->Status"
{
auto deploymentResult = deploymentOperation->GetResults();
wcout << L"Installation Error: " << deploymentOperation->ErrorCode.Value << endl;
wcout << L"Detailed Error Text: " << deploymentResult->ErrorText->Data() << endl;
}
else if (deploymentOperation->Status == AsyncStatus::Canceled)
{
wcout << L"Installation Canceled" << endl;
}
else if (deploymentOperation->Status == AsyncStatus::Completed)
{
wcout << L"Installation succeeded!" << endl;
}
}
}
catch (Exception^ ex)
{
wcout << L"AddPackageSample failed, error message: " << ex->ToString()->Data() << endl;
returnValue = 1;
}
if (completedEvent != nullptr)
CloseHandle(completedEvent);
return returnValue;
}
由于操作(PackageManager.AddPackageAsync)应该是异步的并且我不确定如何跟踪新线程中执行的代码我决定搜索&#34; deploymentOperation-&gt; Status&#34;变量被设置(看起来这实际上是一个函数调用)到#34; AsyncStatus :: Error&#34; (或整数3)。在我经历了大量的代码和函数调用之后,我理解无论何时设置此变量或不设置(看起来它并不重要但确定此函数检索操作错误数据)取决于由未记录的ntdll函数调用初始化的变量成员,名为&#34; NtGetCompleteWnfStateSubscription&#34;通过它的指针。它也是从ntdll调用的。我提到的变量成员的结构如下:
struct Unknown
{
AsyncStatus /*? 32bit long*/ dw0; // it was set to '3' during the current operation as the AsyncStatus::error enum value so I think it should belong to it
DWORD dw4; //was set to 0x5F
DWORD dw8; //was set to 0x80073CF6 (some generic error)
} ;
ntdll中的代码,其中&#34; NtGetCompleteWnfStateSubscription&#34;函数被调用,初始化变量哪个成员具有这种结构类型(在汇编中,生成IDA PRO):
ntdll.dll:77906200 loc_77906200: ; CODE XREF: ntdll.dll:ntdll_strncpy_s+1A3j
ntdll.dll:77906200 push 1030h
ntdll.dll:77906205 push esi ; the variable pointer
ntdll.dll:77906206 push edi
ntdll.dll:77906207 push eax
ntdll.dll:77906208 lea eax, [ebp-0Ch]
ntdll.dll:7790620B push eax
ntdll.dll:7790620C push ebx
ntdll.dll:7790620D call near ptr ntdll_NtGetCompleteWnfStateSubscription
ntdll.dll:77906212 test eax, eax ; now "[esi+2Ch] + esi" contains data from the "Unkown" structure and contains the operation error data
ntdll.dll:77906214 jns short loc_7790623F
上面的代码实际上被调用了3次但是使用相同的&#34; esi&#34;指针。所以现在我的问题是如何找到使用此函数设置错误代码的位置。我尝试捕获ntdll中的大部分功能看起来像这样但没有成功。出于某种奇怪的原因,我无法调试NtGetCompleteWnfStateSubscription。任何建议都会有所帮助。我使用的是IDA PRO 6.5,VS 2013 U1,Windows 8.1 x64 U1。
编辑:如果您不想打扰问题特定的详细信息,我的一般性问题是如何找到WinRT异步方法设置&#34; IAsyncInfo :: Status&#34;属性或在执行错误时出现错误时调用的函数或方法。