NDF 도우미 클래스 확장
이 예제에서는 NDF 진단 및 복구 기능을 구현하는 방법을 보여 줍니다. 이 예제에서는 시스템이 정상 상태를 유지하려면 중요한 구성 파일이 있어야 합니다. 따라서 문제는 파일이 있는지 여부를 확인하는 것입니다. 그렇지 않으면 시스템이 비정상이며 NDF에서 문제를 진단합니다. 복구는 누락된 파일을 다시 만드는 것입니다.
문제를 진단하고 복구하려면 Initialize, LowHealth, GetRepairInfo 및 Repair의 네 가지 INetDiagHelper 메서드를 사용해야 합니다.
도우미 클래스 초기화
찾을 파일의 이름을 초기화하고 검색합니다. 이 파일 이름은 진단 중에 "filename"이라는 도우미 특성으로 전달됩니다.
#include <windows.h>
//utility function to simplify string allocation and copies, user throughout example
HRESULT
StringCchCopyWithAlloc (
PWSTR* Dest,
size_t cchMaxLen,
in PCWSTR Src)
{
if (NULL == Dest || NULL == Src || cchMaxLen > USHRT_MAX)
{
return E_INVALIDARG;
}
size_t cchSize = 0;
HRESULT hr = StringCchLength(Src, cchMaxLen - 1, &cchSize);
if (FAILED(hr))
{
return hr;
}
size_t cbSize = (cchSize + 1)*sizeof(WCHAR);
*Dest = (PWSTR) CoTaskMemAlloc(cbSize);
if (NULL == *Dest)
{
return E_OUTOFMEMORY;
}
SecureZeroMemory(*Dest, cbSize);
return StringCchCopy((STRSAFE_LPWSTR)*Dest, cchSize + 1, Src);
}
HRESULT SimpleFileHelperClass::Initialize(
/* [in] */ ULONG celt,
/* [size_is][in] */ HELPER_ATTRIBUTE rgAttributes[ ])
{
if(celt < 1)
{
return E_INVALIDARG;
}
if(rgAttributes == NULL)
{
return E_INVALIDARG;
}
else
{
//verify the attribute is named as expected
if (wcscmp(rgAttributes[0].pwszName, L"filename")==0)
{
//copy the attribute to member variable
return StringCchCopyWithAlloc(&m_pwszTestFile, MAX_PATH,
rgAttributes[0].PWStr);
} else {
//the attribute isn't named as expected
return E_INVALIDARG;
}
}
}
파일의 존재 확인
LowHealth 메서드는 파일의 존재를 검사 데 사용됩니다. 파일이 있는 경우 진단 상태 DS_REJECTED 설정됩니다. 이는 잘못된 것이 없음을 나타냅니다. 파일을 찾을 수 없는 경우 진단 상태 DS_CONFIRMED 설정됩니다.
#include <windows.h>
HRESULT SimpleFileHelperClass::LowHealth(
/* [unique][string][in] */ LPCWSTR pwszInstanceDescription,
/* [string][out] */ LPWSTR *ppwszDescription,
/* [out] */ long *pDeferredTime,
/* [out] */ DIAGNOSIS_STATUS *pStatus)
{
HANDLE hFile = NULL;
LPWSTR pwszDiagString=NULL;
// does the file already exist?
hFile = CreateFile(
m_pwszTestFile,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(INVALID_HANDLE_VALUE == hFile)
{
// alloc and set the diagnosis description and status
HRESULT hr = StringCchCopyWithAlloc(&pwszDiagString, MAX_PATH,
L"The file was deleted.");
if (FAILED(hr))
{
return hr;
}
*ppwszDescription = pwszDiagString;
*pStatus = DS_CONFIRMED;
return S_OK;
}
CloseHandle(hFile);
//the file exists
*pStatus = DS_REJECTED;
return S_OK;
}
복구 작업 결정
LowHealth가 DS_CONFIRMED 반환하면 GetRepairInfo가 구현되어 적절한 복구 작업을 결정합니다. 이 예제에서는 파일을 다시 만드는 것을 의미합니다.
#include <windows.h>
HRESULT
SimpleFileHelperClass::GetRepairInfo(
/* [in] */ PROBLEM_TYPE problem,
/* [out] */ ULONG *pcelt,
/* [size_is][size_is][out] */ RepairInfo **ppInfo)
{
HRESULT hr=S_OK;
RepairInfo* pRepair = (RepairInfo *)CoTaskMemAlloc(sizeof(RepairInfo));
if (pRepair == NULL) {
return E_OUTOFMEMORY;
}
SecureZeroMemory(pRepair,sizeof(RepairInfo));
// set the repair description and class name
hr = StringCchCopyWithAlloc(&pRepair->pwszClassName, MAX_PATH,
L"SimpleFileHelperClass");
if (FAILED(hr))
{
goto Error;
}
hr = StringCchCopyWithAlloc(&pRepair->pwszDescription, MAX_PATH,
L"Low Health Repair");
if (FAILED(hr))
{
goto Error;
}
// set the resolution GUID and cost
pRepair->guid = ID_LowHealthRepair;
pRepair->cost = 0;
// set repair status flags
pRepair->sidType = WinWorldSid;
pRepair->scope = RS_SYSTEM;
pRepair->risk = RR_NORISK;
pRepair->flags |= DF_IMPERSONATION; //impersonate the user when repairing
pRepair->UiInfo.type = UIT_NONE;
//pass back the repair
*ppInfo = pRepair;
*pcelt = 1; //number of repairs
return S_OK;
Error:
if(pRepair){
if(pRepair->pwszClassName){
CoTaskMemFree(pRepair->pwszClassName);
}
if(pRepair->pwszDescription){
CoTaskMemFree(pRepair->pwszDescription);
}
}
return hr;
}
문제 복구
복구 옵션이 하나만 없는 한 GetRepairInfo에서 반환된 수정 옵션이 사용자에게 제공됩니다. 이 경우 자동으로 실행됩니다. Repair 메서드는 구성 파일을 복원할 수 있도록 해당 RepairInfo 구조로 호출됩니다.
#include <windows.h>
HRESULT
SimpleFileHelperClass::Repair(
/* [in] */ RepairInfo *pInfo,
/* [out] */ long *pDeferredTime,
/* [out] */ REPAIR_STATUS *pStatus)
{
//verify expected repair was requested
if(IsEqualGUID(ID_LowHealthRepair, pInfo->guid)){
HANDLE hFile = NULL;
hFile = CreateFile(m_pwszTestFile,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(INVALID_HANDLE_VALUE == hFile)
{
// repair failed
*pStatus = RS_UNREPAIRED;
return HRESULT_FROM_WIN32(GetLastError());
}
CloseHandle(hFile);
// repair succeeded
*pStatus = RS_REPAIRED;
} else {
return E_INVALIDARG; //unkown repair passed in
}
return S_OK;
}