Получение имени локального компьютера или IP-адреса изнутри SQL CLR в сеансе RDP

У меня есть C# (.NET 4.5) SQL CLR (SQL Server 2012, Windows Server 2008 R2). Пользователи входят в систему через RDP для запуска приложения, которое, в свою очередь, вызывает эту среду CLR.

Я пытаюсь узнать либо имя локального компьютера, либо локальный IP-адрес из среды CLR.

Я сбросил всю среду в файл журнала из CLR, и переменная CLIENTNAME не установлена ​​(неудивительно, поскольку это, скорее всего, среда процесса SQL, а не пользовательская), поэтому я не могу это использовать.

Я попытался импортировать Cassia DLL и использовать ее, но ClientIPAddress класса TerminalServicesManager имеет значение null, так что это тоже не работает.

Есть ли способ получить имя или IP-адрес локального компьютера из SQL CLR?


person Jim Balo    schedule 17.11.2015    source источник
comment
Когда вы говорите «локальный», вы имеете в виду клиентскую часть, а не серверную, верно? Местный кажется немного двусмысленным термином здесь;). И да, SQLCLR работает внутри узла CLR SQL Server, следовательно, на самом сервере.   -  person Solomon Rutzky    schedule 17.11.2015
comment
@srutzky Да, я имею в виду на стороне клиента.   -  person Jim Balo    schedule 17.11.2015


Ответы (2)


Похоже, вы используете «локальный» для обозначения IP-адреса клиента (то есть конечного пользователя, который использует удаленный рабочий стол для доступа к серверу). Это определенно интересная (и сложная) проблема для решения, учитывая, что подключение к SQL Server осуществляется с локальной машины из-за использования RDP. И если вы выходите из процесса SQL Server либо через xp_cmdshell, либо через SQLCLR, вы теперь находитесь в подпроцессе, который возник из процесса на сервере, а не на клиентской машине. Практически нет связи между клиентской машиной и SQL Server.

К счастью, есть способ получить эту информацию, ЕСЛИ каждый пользователь подключается со своим собственным логином (логином Windows или логином SQL Server) вместо общего (общий логин с большей вероятностью произойдет при использовании логинов SQL Server).

Если у каждого свой индивидуальный Логин, то можно сделать следующее:

  1. Create a table to hold fields such as:
    • [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 при использовании олицетворения, но, похоже, это не работает.

person Solomon Rutzky    schedule 17.11.2015
comment
Интересный подход! Сегодня постараюсь протестировать и сообщу. - person Jim Balo; 17.11.2015
comment
Я протестировал ваше решение, и оно отлично сработало! Одно замечание: мне не нужно было настраивать приложение для использования входа в систему Windows — оно отлично работало и с входом в SQL. Большое спасибо за твою помощь!! - person Jim Balo; 18.11.2015
comment
@JimBalo Рад, что это сработало. Спасибо, что сообщили мне, что входы в SQL Server также работают :-). Я думаю, что сказал, что они не будут, так как моя первая попытка была для переменной среды пользователя, и я думал, что маршрут потребует использования олицетворения в SQLCLR. Но когда олицетворение не переключало контекст реестра, я не проводил переоценку. Но теперь я обновил ответ, чтобы он был более точным. - person Solomon Rutzky; 18.11.2015

Попробуйте.. Надеюсь, получится 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;
    }
person Moumit    schedule 17.11.2015
comment
Moumit, оператору нужен не IP-адрес машины, на которой работает SQL Server, а IP-адрес или имя хоста/машины клиентского компьютера, который выполняет подключение к удаленному рабочему столу к серверу. на котором работает SQL Server. - person Solomon Rutzky; 18.11.2015