如何使用编程的方法开启远程桌面:
一、使用注册表,程序中自然可以使用修改注册表的方法
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\
将fDenyTSConnection (REG_DWORD) 从1改为0
1、表示禁用
0、表示启用
但这种方式有些限制,比如修改注册表需要管理员权限,修改后重启远程计算机等,还需要将远程桌面添加到防火墙例外。
二、使用wmi 脚本(交合时的方法)
查找当前设定:
wmic RDToggle get AllowTSConnections
设置Terminal Services 设定
wmic RDToggle where servername=”ServerName" call SetAllowTSConnections 1
远程计算机的设定:
wmic /node:"RemoteServer" /user:"domain\AdminUser" /password:"password"
RDToggle where servername="RemoteServer" get AllowTSConnections
开启远程计算机的设定:
wmic /node:"RemoteServer" /user:"domain\AdminUser" /password:"password"
RDToggle where servername="RemoteServer" call SetAllowTSConnections 1
wmic PATH win32_terminalservicesetting WHERE (__Class!="") CALL
SetAllowTSConnections 1
三、使用VC++
1) Header
You need to add the following references and #include statements to compile correctly.
#define _WIN32_DCOM #include using namespace std; #include # pragma comment(lib, "wbemuuid.lib")
2) Initialize COM
Because WMI is based on COM technology, you must perform calls to the CoInitializeExand CoInitializeSecurity functions to access WMI.
// Initialize COM. hr = CoInitializeEx(0, COINIT_MULTITHREADED); if (SUCCEEDED(hr)) { // Initialize Security hr = CoInitializeSecurity( NULL, -1, // COM negotiates service NULL, // Authentication services NULL, // Reserved RPC_C_AUTHN_LEVEL_PKT_PRIVACY, // authentication RPC_C_IMP_LEVEL_IMPERSONATE, // Impersonation NULL, // Authentication info EOAC_NONE, // Additional capabilities NULL // Reserved ); }
Note: To connect to the \root\CIMV2\TerminalServices namespace, the authentication level must include packet privacy. For C/C++ calls, this is an authentication level of RPC_C_AUTHN_LEVEL_PKT_PRIVACY.
3) Create a connection to a WMI namespace
By definition, WMI runs in a different process than your application. Therefore, you must create a connection between your application and WMI.
Note: To connect to a remote computer, for example Computer_B, use the following parameters:
_bstr_t(L"\\COMPUTER_B\ROOT\\CIMV2") // WMI namespace _bstr_t(L"DOMAIN\\MyUserName") // User name _bstr_t(L"MyPassword") // User password
Here is the main code:
IWbemLocator *pLocator = NULL; if (SUCCEEDED(hr)) { // Obtain the initial locator to Windows Management // on a particular host computer. hr = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLocator); } IWbemServices *pNamespace = NULL; _bstr_t sNamespace(L"ROOT\\CIMV2"); if (SUCCEEDED(hr)) { // Connect to the root\cimv2 namespace with the // current user and obtain pointer pSvc // to make IWbemServices calls. hr = pLocator->ConnectServer( sNamespace, // WMI namespace NULL, // User name NULL, // User password 0, // Locale NULL, // Security flags 0, // Authority 0, // Context object &pNamespace // IWbemServices proxy ); } if(SUCCEEDED(hr)) wprintf(L"Connected to %s WMI namespace.\n", static_cast(sNamespace));
Note: The code above works for Win2k3/XP, for Vista, just update the namespace from "root/cimv2" to "root/cimv2/TerminalServices".
4) Set the security levels on the WMI connection
To use the connection you create to WMI, you must set the impersonation and authentication levels for your application.
if (SUCCEEDED(hr)) { // Set the IWbemServices proxy so that impersonation // of the user (client) occurs. hr = CoSetProxyBlanket( pNamespace, // the proxy to set RPC_C_AUTHN_WINNT, // authentication service RPC_C_AUTHZ_NONE, // authorization service NULL, // Server principal name RPC_C_AUTHN_LEVEL_PKT_PRIVACY, // authentication level RPC_C_IMP_LEVEL_IMPERSONATE, // impersonation level NULL, // client identity EOAC_NONE // proxy capabilities ); }
5) Make the WMI Request
Locate Win32_TerminalServiceSettings using IWbemServices.
IEnumWbemClassObject* pEnumerator = NULL; if(SUCCEEDED(hr)) { hr = pNamespace->ExecQuery( bstr_t("WQL"), bstr_t("SELECT * FROM Win32_TerminalServiceSetting"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator); }
6) Check and Update TerminalServiceSettings
Check the current value of AllowTSConnection flag and call SetAllowTSConnection.
IWbemClassObject * pObject = NULL; ULONG uReturn = 0; while (pEnumerator) { hr = pEnumerator->Next(WBEM_INFINITE, 1, &pObject, &uReturn); if(0 == uReturn) { break; } if(SUCCEEDED(hr)) { // Get the current Value of AllowTSConnections VARIANT v; hr = pObject->Get(L"AllowTSConnections",0,&v,0,0); if (SUCCEEDED(hr) && (V_VT(&v) == VT_I4)) { wprintf(L"AllowTSConnections = %d.\n", V_I4(&v)); } else { wprintf(L"Error in getting specified object\n"); } VariantClear(&v); } if(SUCCEEDED(hr)) { // Call the method SetAllowTSConnections(1) _bstr_t sMethodName = L"SetAllowTSConnections"; _bstr_t sClassName = L"Win32_TerminalServiceSetting"; IWbemClassObject* pClass = NULL; hr = pNamespace->GetObject(sClassName, 0, NULL, &pClass, NULL); IWbemClassObject* pInParamsDefinition = NULL; hr = pClass->GetMethod(sMethodName, 0, &pInParamsDefinition, NULL); IWbemClassObject* pClassInstance = NULL; hr = pInParamsDefinition->SpawnInstance(0, &pClassInstance); // Create the values for the in parameters VARIANT v; V_VT(&v) = VT_I4; V_I4(&v) = 1; // Store the value for the in parameters hr = pClassInstance->Put(L"AllowTSConnections", 0, &v, 0); // Get the context from which to execute the method CIMTYPE pType; LONG pFlavor; VARIANT var; hr = pObject->Get(L"__PATH", 0, &var, &pType, &pFlavor); // Execute Method IWbemClassObject* pOutParams = NULL; hr = pNamespace->ExecMethod(var.bstrVal, sMethodName, 0, NULL, pClassInstance, &pOutParams, NULL); if (SUCCEEDED(hr)) { wprintf(L"SetAllowTSConnections(%d) OK.\n", V_I4(&v)); } else { wprintf(L"SetAllowTSConnections(%d) FAILED.\n", V_I4(&v)); } VariantClear(&v); VariantClear(&var); }
7) Cleanup and shutdown
Destroy all COM pointers and shut down your application correctly.
if(pLocator != NULL) pLocator->Release(); if(pNamespace != NULL) pNamespace->Release(); CoUninitialize();
Conclusion
Enabling Remote Desktop locally or remotely is of great use for administrators or to automate installers (NSIS for instance). But it needs to be done properly (not just with the registry settings). WMI is the best way to achieve this and you I have described how to achieve this in VC++. You can find attached the full .cpp file of the example I will probably be discussing here about a plugin for NSIS if people are interrested.
原文地址:
http://www.vedivi.com/support/blog/71-how-to-enable-remote-desktop-programmatically.html