远程 WMI 连接

10

我想从另一台PC使用ManagementScope连接到运行Windows 7的远程PC,这两台计算机都在本地网络中。在远程PC上,我已创建了一个名为"Samuel"的新用户账户,没有设置密码并将其设置为管理员。

ConnectionOptions options = new ConnectionOptions();
options.Username = "Samuel";
options.Password = "";

ManagementScope scope = new ManagementScope("\\\\192.168.0.2\\root\\cimv2", options);          
scope.Connect();

我收到的错误信息:

拒绝访问。(来自 HRESULT: 0x80070005 (E_ACCESSDENIED) 的异常)

更新:
在为用户设置密码后,我收到了新的错误信息:

RPC 服务器不可用。(来自 HRESULT: 0x800706BA 的异常)


如果您进入“服务”,WMI服务是否正在运行?如果是的话,如果您在目标Windows 7 PC上运行上述代码,您能否连接到WMI? - etoisarobot
WMI服务正在运行。关于在目标上运行此代码,您是指在本地运行吗?如果是的话,我无法在该机器上执行代码(没有VS或框架)。 - shlomjmi
Samuel 是域账户还是本地账户? - Helen
Samuel本地账户,域名为mshome。 - shlomjmi
有没有关于此的完整源代码的最终解决方案? - Kiquenet
为了调试和故障排除,请下载http://servicesplus.codeplex.com/,这是一个.exe文件,然后右键单击该文件并选择“以Samuel身份运行”,以查看是否可以访问远程PC。如果成功,您可以下载其源代码。 - Sameh
9个回答

9
也许是缺少了“EnablePrivileges”:
scope.Options.EnablePrivileges = true;

来自MSDN (ConnectionOptions.EnablePrivileges Property):

获取或设置一个值,指示连接操作是否需要启用用户权限。仅在执行的操作需要启用某个特定用户权限时才应使用此属性(例如,机器重启)。

编辑: 如果不起作用,请尝试将模拟级别设置为“模拟”:

scope.Options.Impersonation = System.Management.ImpersonationLevel.Impersonate;

模拟级别 Impersonate: 模拟级别 COM 模拟,允许对象使用调用者的凭据。这是 WMI 调用的推荐模拟级别。


1
试图理解“需要启用特定用户权限”的含义。对我来说,任何WMI连接都需要某种特权。是否有人可以提供有关哪些操作需要设置此属性的进一步信息? - Shannon Wagner
Authority更改为我的域名而不是“DOMAIN”对我有用。 - Maslow

7
  • According to the WMI FAQ on TechNet, the 0x80070005 error indicates a DCOM issue:

    0x80070005 (DCOM ACCESS_DENIED)
    This error occurs when the connected user is not recognized or is restricted in some fashion by the remote server (for example, the user might be locked out). This happens most often when accounts are in different domains. Recent changes to WMI security can also cause this error to occur:

    • Blank passwords, formerly permitted, are not allowed in Windows XP and Windows Server 2003.

    • WMI does not allow asynchronous callbacks to a Windows 98 client. A call like SWbemServices.ExecNotificationQueryAsync from a Windows 98 computer to a Windows XP computer will result in an Access Denied error returned to the Windows 98 machine.

    • The DCOM configuration access setting might have been changed.

    • If the target computer is running Windows XP, the Forceguest value under the registry key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa might be set to force the Guest account off (value is zero).

    (Although Windows XP is mentioned, this may be applied to Windows 7 as well.)

  • The 0x800706BA error, in its rurn, indicates a firewall issue:

    0x800706xx (DCOM RPC error)
    This often occurs when a firewall is configured on the remote computer. You will need to open the appropriate ports on the firewall to permit remote administration using DCOM.

    Try enabling the Remote administration exception in Windows Firewall on the remote computer and see if it helps. To do this from the command line, run the following command in the elevated command prompt:

    netsh advfirewall firewall set rule group="remote admin" new enable=yes
    


    You can also find the DCOM, UAC, Windows Firewall and other settings required for remote WMI access in the Connecting to WMI Remotely Starting with Windows Vista article on MSDN.


  • Also, since Samuel is a nondomain account, you need to grant this account DCOM Remote Access, Remote Launch and Remote Activation permissions on the remote computer as described here.


正如我在之前的回答中所评论的: 设置密码后,我收到了以下错误信息:“RPC 服务器不可用。(HRESULT 异常: 0x800706BA)” - shlomjmi
尝试在远程计算机的Windows防火墙中启用“远程管理”异常,看看是否有帮助。 (请参见更新的答案。) - Helen

5
您之所以收到“访问被拒绝”的错误提示是因为您仅使用用户名查询范围连接。您有两个选项:将用户名和密码设置为空或输入用户名和密码。
您之所以收到“RPC服务器不可用”的错误提示是因为防火墙不允许您查询该计算机。您有两个选项:禁用防火墙或将其添加到远程管理例外中。
您可以在cmd中像这样添加防火墙例外:
旧版本的Windows: netsh firewall set service type=remoteadmin mode=enable 较新版本的Windows: netsh advfirewall firewall set rule group="Windows Remote Management" new enable=yes
如果您尝试使用域用户登录,请将用户名更改为domainName\username或设置连接属性connection.Authority = "ntlmdomain:domainName"。

1

不确定是因为远程机器上的WMI引擎没有监听,还是您有其他登录/连接问题导致被拒绝。

这是我用来连接到远程机器的代码,它完美地工作。也许它能帮到你:

ConnectionOptions oConn = new ConnectionOptions();
ManagementScope oScope = null;

oConn.Username = txtLogin;
oConn.Password = txtPassword;
oConn.Authority = "ntlmdomain:" + txtDomain;

oScope = new ManagementScope("\\\\" + txtHostName + "\\root\\CIMV2", oConn);

oScope.Connect();

如果我的域/登录/密码三元组被接受,那么Connect()函数将会工作。否则,Connect()函数将抛出一个异常。只要指定的凭据在该计算机上具有权限,你就可以开始运行了。

3
我有两个问题:1) 我复制了Microsoft的示例,将"ntlmdomain:DOMAIN"放在了代码中,但我没有意识到需要将我的域名替换进去(呃)。2) 我把我的域名放在了用户名那里,但这是不被允许的。我原本写成了user="mydomain\myuser",但正确方式应该是user="myuser"。 - NealWalters

1
你确定可以使用没有密码的账户进行远程WMI连接吗?
这样做有很多限制,比如无法共享文件、远程桌面等。建议设置密码,看看是否会有所改善。

设置密码后,我收到了这个错误消息:“RPC 服务器不可用。(HRESULT 异常:0x800706BA)” - shlomjmi

1
您可能需要检查远程 Windows 7 PC 上的 WMI 安全设置。 右键单击计算机 > 管理 > 服务和应用程序 > WMI 控制 > 安全选项卡, 并确保您正在使用的用户帐户具有必要的权限。

0

我也遇到了这个问题。我试图编写C#代码来获取远程PC的WMI信息和文件。但是遇到了两个访问被拒绝错误:

长话短说,我不得不对远程PC进行更改。请参见下文:

  • 0x80070005: 访问被拒绝:https://social.msdn.microsoft.com/Forums/vstudio/en-US/6229334e-d5ef-4016-9e7e-1c8718be8d43/access-is-denied-exception-from-hresult-0x80070005-eaccessdenied-in-vbnet?forum=netfxbcl

  • System.Management:访问被拒绝:“使用 System.Management 和 WMI”https://support.microsoft.com/en-us/help/317012/process-and-request-identity-in-asp.net


  • 0

    使用“net view \\服务器名”的解决方案

    我知道使用控制台命令并对输出进行一些字符串操作并不是很理想,但另一方面它确实有效,并且对我来说,也不太希望去搞乱DCOM默认设置以使WMI方式工作(至少在Win7上)。

    已在Win7和XP客户端以及MS和Linux服务器上进行了测试。

    Function GetShares(ServerName As String) As List(Of String)
        Try
            Dim P As New Process
            Dim Read As Boolean = False
            Dim Str As String
            Dim Shares As New List(Of String)
    
            With P.StartInfo
                .FileName = "net"
                .Arguments = "view " & ServerName
                .RedirectStandardOutput = True
                .RedirectStandardError = True
                .CreateNoWindow = True
                .UseShellExecute = False
            End With
            P.Start()
            P.WaitForExit()
    
            If P.ExitCode <> 0 Then
                MsgBox(P.StandardError.ReadToEnd, MsgBoxStyle.OkOnly, "Error")
            Else
                Do Until P.StandardOutput.EndOfStream = True
                    If Read = True Then
                        Str = P.StandardOutput.ReadLine
                        If Str = "The command completed successfully." Then Exit Do
                        Str = Strings.RTrim(Str) 'Removes any trailing spaces
                        Str = Strings.Mid(Str, 1, Strings.InStrRev(Str, " ")) 'remove Type
                        Str = Strings.RTrim(Str) ''Removes any trailing spaces
                        Shares.Add(Str)
                    Else
                        If Strings.Left(P.StandardOutput.ReadLine, 10) = "----------" Then Read = True
                    End If
                Loop
            End If
            Return Shares
        Catch ex As Exception
            MsgBox("Error in """ & System.Reflection.MethodInfo.GetCurrentMethod.Name & """: " & vbCr & ex.Message, MsgBoxStyle.OkOnly, "Runtime error")
            Debug.Print("--------------------------" & vbCr & "Error: " & ex.Message & vbCr & ex.StackTrace)
            Return Nothing
        End Try
    End Function
    

    0
    尝试在用户名之前添加域名或计算机名称(例如 @"mshome\Samuel")。

    看看Jerry的回答和下面的评论。 - prabhakaran
    @prabhakaran:这是一个相当老的问题,但我记得我曾经通过在用户名前添加域名来解决类似的问题,但那只是我的特殊情况。 - SKINDER

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接