【问题标题】:Getting local computer name or IP address from inside of a SQL CLR in RDP Session从 RDP 会话中的 SQL CLR 内部获取本地计算机名称或 IP 地址
【发布时间】:2016-02-18 09:50:51
【问题描述】:

我有一个 C# (.NET 4.5) SQL CLR(SQL Server 2012、Windows Server 2008 R2)。用户通过 RDP 登录以运行应用程序,该应用程序又调用此 CLR。

我正在尝试从 CLR 内部找出本地计算机名称或本地 IP 地址。

我已将整个环境从 CLR 转储到日志文件中,并且没有设置 CLIENTNAME 变量(这并不奇怪,因为它可能是 SQL 进程的环境而不是用户的环境),所以我不能使用它。

我尝试导入 Cassia DLL 并使用它,但是 TerminalServicesManager 类的 ClientIPAddress 为空,所以这似乎也不起作用。

有没有办法从 SQL CLR 获取本地计算机名称或 IP?

【问题讨论】:

  • 当您说“本地”时,您的意思是客户端,而不是服务器端,对吗?这里的“本地”一词似乎有点模棱两可;)。是的,SQLCLR 在 SQL Server 的 CLR 主机内部运行,因此在服务器本身上运行。
  • @srutzky 是的,我的意思是客户端。

标签: c# .net sql-server clr sqlclr


【解决方案1】:

听起来您使用“本地”来表示客户端(即最终用户;使用远程桌面访问服务器的用户)的 IP 地址。考虑到由于使用 RDP,与 SQL Server 的连接是从本地计算机建立的,这绝对是一个需要解决的有趣(且棘手)的问题。如果您通过xp_cmdshell 或SQLCLR 退出SQL Server 的进程,那么您现在处于源自服务器上的进程而不是客户端计算机上的子进程中。客户端机器和 SQL Server 之间几乎没有连接。

幸运的是,如果每个用户都使用自己的登录名(Windows 登录名或 SQL Server 登录名)而不是共享登录名(使用 SQL Server 登录名时更可能发生共享登录名),则有一种方法可以获取此信息.

如果每个人都有自己的登录名,那么您可以执行以下操作:

  1. 创建一个表来保存以下字段:
    • [Login] NVARCHAR(50) NOT NULL
    • ClientName NVARCHAR(50) NOT NULL
    • CreateDate DATETIME NOT NULL CONSTRAINT [DF_TableName_CreateDate] DEFAULT (GETDATE())
  2. 创建一个登录脚本(.cmd 脚本),如果不在其 Active Directory 漫游配置文件中(如果您使用 AD),则至少在该服务器上与他们的配置文件相关联。
  3. 登录脚本将简单地调用 SQLCMD 将环境变量 CLIENTNAME 插入到表中:

    SQLCMD -Q "INSERT INTO dbo.ClientHostNames (fields) VALUES (ORIGINAL_LOGIN(), N'%CLIENTNAME%');"
    

    这是因为 DOS 变量在命令执行之前被替换。

  4. 在您的 SQLCLR 代码中,使用进程内的"Context Connection = true;" ConnectionString 建立连接,因为这将作为运行 SQLCLR 代码的登录名执行。
  5. 使用类似于以下内容的查询获取主机名:

    SELECT HostName
    FROM   dbo.ClientHostNames
    WHERE  WindowsLogin = ORIGINAL_LOGIN()
    ORDER BY CreateDate DESC;
    
  6. 您可以只使用SqlCommand.ExecuteScalar() 来获取HostName 值。

这不是最直接的方法,但到目前为止我找不到任何其他可行的方法。我尝试设置一个用户环境变量,然后在使用模拟时尝试在 SQLCLR 中获取它,但这似乎不起作用。

【讨论】:

  • 有趣的方法!我今天会尝试测试它并让你知道。
  • 我测试了您的解决方案,效果很好!注意事项:我不必将应用程序设置为使用 Windows 登录 - 它也适用于 SQL 登录。非常感谢您的帮助!!
  • @JimBalo 很高兴它成功了。感谢您让我知道 SQL Server 登录也可以工作 :-)。我想我说过他们不会,因为我的第一次尝试是针对用户环境变量,并且认为走这条路需要在 SQLCLR 中使用模拟。但是当 Impersonation 没有切换注册表上下文时,我没有重新评估。但是我现在已经更新了答案以更准确。
【解决方案2】:

试试吧.. 希望它会work

    public string GetIPAddress()
    {
        System.Net.IPHostEntry ipHostInfo = System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName()); // `Dns.Resolve()` method is deprecated.

        string tempIp = string.Empty;
        foreach (var item in ipHostInfo.AddressList)
        {
            tempIp = item.ToString();
            //Make your comparison here
        }
        return tempIp;
    }

【讨论】:

  • Moumit,OP 不是要获取运行 SQL Server 的机器的 IP,而是要获取正在建立远程桌面连接的客户端计算机的 IP 或主机名/机器名 运行 SQL Server 的服务器。
猜你喜欢
  • 2011-06-14
  • 1970-01-01
  • 2010-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-25
  • 2011-06-23
  • 1970-01-01
相关资源
最近更新 更多