更新服務 連線 點
下列程式代碼範例示範如何更新服務連接點。 此程式代碼通常會在服務啟動時執行。
這個範例會擷取服務安裝程式在登錄中快取的SCP GUID系結字串。 它會使用此字串系結至 SCP 物件上的 IDirectoryObject 指標,然後呼叫 IDirectoryObject::GetObjectAttributes 方法來取得 SCP 的 serviceDNSName 和 serviceBindingInformation 属性。 請注意,您的服務可能需要驗證並更新其他屬性。
程式代碼會將 serviceDNSName 值與 GetComputerNameEx 函式所傳回的 DNS 名稱進行比較。 它也會比較服務的目前埠號碼與儲存在 serviceBindingInformation 屬性中的埠號碼。 如果其中一個值已變更,程式代碼會呼叫 IDirectoryObject::SetObjectAttributes 方法來更新 SCP 屬性。
DWORD
ScpUpdate(USHORT usPort)
{
DWORD dwStat, dwType, dwLen;
BOOL bUpdate=FALSE;
HKEY hReg;
TCHAR szAdsPath[MAX_PATH];
TCHAR szServer[MAX_PATH];
TCHAR szPort[8];
TCHAR *pszAttrs[]={
{TEXT("serviceDNSName")},
{TEXT("serviceBindingInformation")},
};
HRESULT hr;
IDirectoryObject *pObj;
DWORD dwAttrs;
int i;
PADS_ATTR_INFO pAttribs;
ADSVALUE dnsname,binding;
ADS_ATTR_INFO Attribs[]={
{TEXT("serviceDnsName"),ADS_ATTR_UPDATE,ADSTYPE_CASE_IGNORE_STRING,&dnsname,1},
{TEXT("serviceBindingInformation"),ADS_ATTR_UPDATE,ADSTYPE_CASE_IGNORE_STRING,&binding,1},
};
// Open the service registry key.
dwStat = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
TEXT("Software\\Microsoft\\Windows 2000 Auth-O-Matic"),
0,
KEY_QUERY_VALUE,
&hReg);
if (dwStat != NO_ERROR)
{
ReportServiceError("RegOpenKeyEx failed", dwStat);
return dwStat;
}
// Get the GUID binding string used to bind to the service SCP.
dwLen = sizeof(szAdsPath);
dwStat = RegQueryValueEx(hReg, TEXT("GUIDBindingString"), 0, &dwType,
(LPBYTE)szAdsPath, &dwLen);
if (dwStat != NO_ERROR) {
ReportServiceError("RegQueryValueEx failed", dwStat);
return dwStat;
}
RegCloseKey(hReg);
// Bind to the SCP.
hr = ADsGetObject(szAdsPath, IID_IDirectoryObject, (void **)&pObj);
if (FAILED(hr))
{
char szMsg1[1024];
sprintf_s(szMsg1,
"ADsGetObject failed to bind to GUID (bind string: %S): ",
szAdsPath);
ReportServiceError(szMsg1, hr);
if(pObj)
{
pObj->Release();
}
return dwStat;
}
// Retrieve attributes from the SCP.
hr = pObj->GetObjectAttributes(pszAttrs, 2, &pAttribs, &dwAttrs);
if (FAILED(hr)) {
ReportServiceError("GetObjectAttributes failed", hr);
pObj->Release();
return hr;
}
// Get the current port and DNS name of the host server.
_stprintf_s(szPort,TEXT("%d"),usPort);
dwLen = sizeof(szServer);
if (!GetComputerNameEx(ComputerNameDnsFullyQualified,szServer,&dwLen))
{
pObj->Release();
return GetLastError();
}
// Compare the current DNS name and port to the values retrieved from
// the SCP. Update the SCP only if nothing has changed.
for (i=0; i<(LONG)dwAttrs; i++)
{
if ((_tcscmp(TEXT("serviceDNSName"),pAttribs[i].pszAttrName)==0) &&
(pAttribs[i].dwADsType == ADSTYPE_CASE_IGNORE_STRING))
{
if (_tcscmp(szServer,pAttribs[i].pADsValues->CaseIgnoreString) != 0)
{
ReportServiceError("serviceDNSName being updated", 0);
bUpdate = TRUE;
}
else
ReportServiceError("serviceDNSName okay", 0);
}
if ((_tcscmp(TEXT("serviceBindingInformation"),pAttribs[i].pszAttrName)==0) &&
(pAttribs[i].dwADsType == ADSTYPE_CASE_IGNORE_STRING))
{
if (_tcscmp(szPort,pAttribs[i].pADsValues->CaseIgnoreString) != 0)
{
ReportServiceError("serviceBindingInformation being updated", 0);
bUpdate = TRUE;
}
else
ReportServiceError("serviceBindingInformation okay", 0);
}
}
FreeADsMem(pAttribs);
// The binding data or server name have changed,
// so update the SCP values.
if (bUpdate)
{
dnsname.dwType = ADSTYPE_CASE_IGNORE_STRING;
dnsname.CaseIgnoreString = szServer;
binding.dwType = ADSTYPE_CASE_IGNORE_STRING;
binding.CaseIgnoreString = szPort;
hr = pObj->SetObjectAttributes(Attribs, 2, &dwAttrs);
if (FAILED(hr))
{
ReportServiceError("ScpUpdate: Failed to set SCP values.", hr);
pObj->Release();
return hr;
}
}
pObj->Release();
return dwStat;
}