是否有可能使用不同的凭据读取/写入远程计算机的registry?

我正在使用Delphi来远程读取和写入远程计算机的registry。 当我的计算机上的帐户具有对远程计算机的pipe理访问权限时,此function正常

但是,我希望能够在连接时读取registry时指定用户名/密码,以便可以使用备用凭证进行连接。

通过文件系统,我调用了以下(使用用户名和密码),并能够build立到远程系统的连接并执行与文件系统相关的function。 但是,这似乎不适用于registry。

var netResource : TNetResource; begin FillChar(netResource, SizeOf(netResource), 0); netResource.dwScope := RESOURCE_GLOBALNET; netResource.dwType := RESOURCETYPE_DISK; netResource.dwDisplayType := RESOURCEDISPLAYTYPE_SHARE; netResource.dwUsage := RESOURCEUSAGE_CONNECTABLE; netResource.lpRemoteName := PChar('\\192.168.1.105\IPC$'); WNetAddConnection2(netResource, PChar(password), PChar(username), 0); end; 

以下是我希望能够调用的函数的示例,但指定可以访问远程计算机的凭证:

 procedure TForm1.SetWallpaperKey() ; var reg:TRegistry; begin reg:=TRegistry.Create; with reg do begin try if RegistryConnect('192.168.1.105') then if OpenKey('\Control Panel\desktop', False) then begin //change wallpaper and tile it reg.WriteString ('Wallpaper','c:\windows\CIRCLES.bmp') ; reg.WriteString ('TileWallpaper','1') ; //disable screen saver//('0'=disable, '1'=enable) reg.WriteString('ScreenSaveActive','0') ; end finally reg.Free; end; end; end; 

Solutions Collecting From Web of "是否有可能使用不同的凭据读取/写入远程计算机的registry?"

米克,我无法拒绝给你一个WMI解决方案给你的问题;),WMI有一个名为StdRegProv类,它允许您访问本地和远程机器的注册表。 关键点是类所在的命名空间,取决于安装在远程机器上的Windows版本。 所以对于Windows server 2003,Windows XP,Windows 2000,Windows NT 4.0和Windows Me / 98/95, StdRegProv类在root\default命名空间中可用,而对于其他版本(如Windows Vista / 7),命名空间是root\CIMV2

现在要配置凭据来访问注册表,您必须以这种方式在SWbemLocator.Connectserver方法中设置这些值:

 FSWbemLocator.Connectserver(server, 'root\default', User, Pass); 

另一个重要的是,这个类只是公开方法访问注册表不是属性,所以你不能使用wmi查询,而是你必须执行wmi方法。

检查下一个样本,看看它是如何工作的。

检查您是否拥有通过密钥的权限

 uses Windows, SysUtils, ActiveX, ComObj; // The CheckAccess method verifies that the user possesses the specified // permissions. The method returns a uint32 which is 0 if successful or some other // value if any other error occurred. procedure Invoke_StdRegProv_CheckAccess; const server = '192.168.52.128'; User = 'Administrator'; Pass = 'password'; var FSWbemLocator : OLEVariant; FWMIService : OLEVariant; FWbemObjectSet : OLEVariant; FInParams : OLEVariant; FOutParams : OLEVariant; begin FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator'); //http://msdn.microsoft.com/en-us/library/aa393664%28v=vs.85%29.aspx //StdRegProv is preinstalled in the WMI namespaces root\default and root\cimv2. //Windows server 2003, Windows XP, Windows 2000, Windows NT 4.0, and Windows Me/98/95: StdRegProv is available only in root\default namespace. FWMIService := FSWbemLocator.Connectserver(server, 'root\default', User, Pass); //For Windows Vista or Windows 7 you must use the root\CIMV2 namespace //FWMIService := FSWbemLocator.Connectserver(server, 'root\CIMV2', User, Pass); FWbemObjectSet:= FWMIService.Get('StdRegProv'); FInParams := FWbemObjectSet.Methods_.Item('CheckAccess').InParameters.SpawnInstance_(); FInParams.hDefKey:=HKEY_LOCAL_MACHINE; FInParams.sSubKeyName:='SYSTEM\CurrentControlSet'; FInParams.uRequired:=KEY_QUERY_VALUE; FOutParams := FWMIService.ExecMethod('StdRegProv', 'CheckAccess', FInParams); Writeln(Format('bGranted %s',[FOutParams.bGranted])); Writeln(Format('ReturnValue %s',[FOutParams.ReturnValue])); end; 

读取一个字符串值

 // The GetStringValue method returns the data value for a named value whose data // type is REG_SZ. procedure Invoke_StdRegProv_GetStringValue; const server = '192.168.52.128'; User = 'Administrator'; Pass = 'password'; var FSWbemLocator : OLEVariant; FWMIService : OLEVariant; FWbemObjectSet : OLEVariant; FInParams : OLEVariant; FOutParams : OLEVariant; begin FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator'); //http://msdn.microsoft.com/en-us/library/aa393664%28v=vs.85%29.aspx //StdRegProv is preinstalled in the WMI namespaces root\default and root\cimv2. //Windows server 2003, Windows XP, Windows 2000, Windows NT 4.0, and Windows Me/98/95: StdRegProv is available only in root\default namespace. FWMIService := FSWbemLocator.Connectserver(server, 'root\default', User, Pass); //For Windows Vista or Windows 7 you must use the root\CIMV2 namespace //FWMIService := FSWbemLocator.Connectserver(server, 'root\CIMV2', User, Pass); FWbemObjectSet:= FWMIService.Get('StdRegProv'); FInParams := FWbemObjectSet.Methods_.Item('GetStringValue').InParameters.SpawnInstance_(); FInParams.hDefKey:=HKEY_LOCAL_MACHINE; FInParams.sSubKeyName:='SOFTWARE\Borland\Delphi\5.0'; FInParams.sValueName:='App'; FOutParams := FWMIService.ExecMethod('StdRegProv', 'GetStringValue', FInParams); Writeln(Format('sValue %s',[FOutParams.sValue])); Writeln(Format('ReturnValue %s',[FOutParams.ReturnValue])); end; 

写一个字符串值

 // The SetStringValue method sets the data value for a named value whose data type // is REG_SZ. procedure Invoke_StdRegProv_SetStringValue; const server = '192.168.52.128'; User = 'Administrator'; Pass = 'password'; var FSWbemLocator : OLEVariant; FWMIService : OLEVariant; FWbemObjectSet : OLEVariant; FInParams : OLEVariant; FOutParams : OLEVariant; begin FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator'); FWMIService := FSWbemLocator.Connectserver(server, 'root\default', User, Pass); FWbemObjectSet:= FWMIService.Get('StdRegProv'); FInParams := FWbemObjectSet.Methods_.Item('SetStringValue').InParameters.SpawnInstance_(); FInParams.hDefKey:=HKEY_LOCAL_MACHINE; FInParams.sSubKeyName:='SOFTWARE\Borland\Delphi\5.0'; FInParams.sValueName:='Dummy'; FInParams.sValue:='ADummyValue'; FOutParams := FWMIService.ExecMethod('StdRegProv', 'SetStringValue', FInParams); Writeln(Format('ReturnValue %s',[FOutParams.ReturnValue])); end; 

对于更多的选项,你必须检查关于这个类的文档 。

我希望这可以帮助你。

现在使用windows API, TRegistry.RegistryConnect函数在内部调用RegConnectRegistry窗口函数,文档说:

如果当前用户对远程计算机没有适当的访问权限,则对RegConnectRegistry的调用将失败。 要连接到远程注册表,请在调用RegConnectRegistry之前使用LOGON32_LOGON_NEW_CREDENTIALS和ImpersonateLoggedOnUser调用LogonUser。

 Windows 2000: One possible workaround is to establish a session 

到一个管理共享如IPC $使用一组不同的凭据。 要指定不同于当前用户的证书,请使用WNetAddConnection2函数连接到共享。 当您完成访问注册表时,取消连接。

 Windows XP Home Edition: You cannot use this function to connect to 

运行Windows XP Home Edition的远程计算机。 此功能可以使用本地计算机的名称,即使它正在运行Windows XP Home Edition,因为它绕过了身份验证层。

检查下一个样品

使用windows api注册表功能

 uses Windows, Registry, SysUtils; procedure AccessRemoteRegistry(const lpMachineName, lpszUsername , lpszPassword: PChar); const LOGON32_LOGON_NEW_CREDENTIALS = 9; REG_OPTION_OPEN_LINK = $00000008; var netResource : TNetResource; dwFlags : DWORD; dwRetVal : DWORD; phToken : THandle; phkResult : HKEY; phkResult2 : HKEY; lpType : DWORD; lpData : PByte; lpcbData : DWORD; begin ZeroMemory(@netResource, SizeOf(netResource)); netResource.dwType := RESOURCETYPE_ANY; netResource.lpLocalName := nil; netResource.lpRemoteName:= lpMachineName; netResource.lpProvider := nil; dwFlags := CONNECT_UPDATE_PROFILE; dwRetVal := WNetAddConnection2(netResource, lpszPassword, lpszUsername, dwFlags); if dwRetVal=NO_ERROR then begin try Writeln('Connected'); if LogonUser(lpszUsername, nil, lpszPassword, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50,phToken) then begin try if ImpersonateLoggedOnUser(phToken) then begin try dwRetVal:=RegConnectRegistry(lpMachineName,HKEY_LOCAL_MACHINE,phkResult); if dwRetVal = ERROR_SUCCESS then begin dwRetVal:=RegOpenKeyEx(phkResult,PChar('SOFTWARE\Borland\Delphi\5.0'), REG_OPTION_OPEN_LINK, KEY_QUERY_VALUE, phkResult2); if dwRetVal = ERROR_SUCCESS then begin try lpType:=REG_SZ; //get the size of the buffer dwRetVal:=RegQueryValueEx(phkResult2, PChar('App'), nil, @lpType, nil, @lpcbData); if dwRetVal = ERROR_SUCCESS then begin GetMem(lpData,lpcbData); try dwRetVal:=RegQueryValueEx(phkResult2, 'App', nil, @lpType, lpData, @lpcbData); if dwRetVal = ERROR_SUCCESS then WriteLn(PChar(lpData)) else Writeln(Format('RegQueryValueEx error %d',[dwRetVal])); finally FreeMem(lpData); end; end else Writeln(Format('RegQueryValueEx error %d',[dwRetVal])); finally RegCloseKey(phkResult2); end; end else Writeln(Format('RegOpenKeyEx error %d',[dwRetVal])); end else Writeln(Format('RegConnectRegistry error %d',[dwRetVal])); finally RevertToSelf; end; end else RaiseLastOSError; finally CloseHandle(phToken); end; end else RaiseLastOSError; finally dwRetVal:=WNetCancelConnection2(netResource.lpRemoteName, CONNECT_UPDATE_PROFILE, false); if dwRetVal<>NO_ERROR then Writeln(Format('WNetCancelConnection2 error %d',[dwRetVal])); end; end else Writeln(Format('WNetAddConnection2 Connection error %d',[dwRetVal])); end; 

以这种方式使用

 AccessRemoteRegistry('\\192.168.52.128','NormalUser','password'); 

使用TRegistry的delphi类

 procedure AccessRemoteRegistry2(const lpMachineName, lpszUsername , lpszPassword: PChar); const LOGON32_LOGON_NEW_CREDENTIALS = 9; REG_OPTION_OPEN_LINK = $00000008; var netResource : TNetResource; dwFlags : DWORD; dwRetVal : DWORD; phToken : THandle; Reg : TRegistry; begin ZeroMemory(@netResource, SizeOf(netResource)); netResource.dwType := RESOURCETYPE_ANY; netResource.lpLocalName := nil; netResource.lpRemoteName:= lpMachineName; netResource.lpProvider := nil; dwFlags := CONNECT_UPDATE_PROFILE; dwRetVal := WNetAddConnection2(netResource, lpszPassword, lpszUsername, dwFlags); if dwRetVal=NO_ERROR then begin try Writeln('Connected'); if LogonUser(lpszUsername, nil, lpszPassword, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50,phToken) then begin try if ImpersonateLoggedOnUser(phToken) then begin try reg:=TRegistry.Create; try reg.RootKey:=HKEY_LOCAL_MACHINE; if reg.RegistryConnect(lpMachineName) then if reg.OpenKey('SOFTWARE\Borland\Delphi\5.0',False) then WriteLn(reg.ReadString('App')); finally reg.CloseKey; reg.Free; end; finally RevertToSelf; end; end else RaiseLastOSError; finally CloseHandle(phToken); end; end else RaiseLastOSError; finally dwRetVal:=WNetCancelConnection2(netResource.lpRemoteName, CONNECT_UPDATE_PROFILE, false); if dwRetVal<>NO_ERROR then Writeln(Format('WNetCancelConnection2 error %d',[dwRetVal])); end; end else Writeln(Format('WNetAddConnection2 Connection error %d',[dwRetVal])); end; 

以这种方式使用

 AccessRemoteRegistry2('\\192.168.52.128','NormalUser','password'); 

也许你需要WNetAddConnection3 ? 我不认为它启用远程注册表,但。

就个人而言,我会考虑WMI和网络命名管道,它们是Windows支持的远程注册表访问方法。

另外,你知道TRegistry.RegistryConnect。 它似乎没有用户名/密码,你想要的东西,但我还不清楚为什么这是不够的。