2017-02-20 21 views
0

С 2013 года (более 3 лет) я использовал http://www.useragentstring.com/ в своем основном проекте VB.Net, чтобы получить имя/версию браузера и имя/версию ОС из строки пользовательского агента, чтобы добавить статистику для моего локального веб-приложения.Использование browscap.ini с VB.Net

Но недавно, в последние месяцы, этот веб-сайт был ненадежным с большим количеством времени простоя. Поэтому, чтобы избежать отсутствия данных в моей статистике, я искал локальное решение, а не онлайн. Я нашел http://browscap.org/ - это старый веб-сайт (с 1998 года), который по-прежнему загружает обновленную информацию агента пользователя по сей день (browscap.ini). Он предназначен для PHP, но я нашел там реализацию C#: https://www.gocher.me/C-Sharp-Browscap.

Но как разработчик VB.Net, я не нашел для него никакой реализации VB. Я много гулял, но безуспешно. Кто-нибудь получает его для VB.NET?

ответ

0

Я, наконец, получаю, чтобы преобразовать решение C# в VB.NET с некоторой царапиной головы.

Public Class CompareByLength 
Implements IComparer(Of String) 
    Private Function Compare(ByVal x As String, ByVal y As String) as Integer _ 
     Implements IComparer(Of String).Compare 
      If x Is Nothing Then 
       If y Is Nothing Then 
        Return 0 
       Else 
        Return 1 
       End If 
      Else 
       If y Is Nothing Then 
        Return -1 
       Else 
        Dim retval As Integer = x.Length.CompareTo(y.Length) 
        If retval <> 0 Then 
         Return -retval 
        Else 
         return -x.CompareTo(y) 
        End If 

       End If 
      End If 
     End Function 
End Class 

Public Class BrowsCap 
    Private Declare Function GetPrivateProfileSectionNames Lib "kernel32.dll" Alias "GetPrivateProfileSectionNamesA" (ByVal lpReturnedString As Byte(), ByVal nSize As Integer, ByVal lpFileName As String) As Integer 
    Private Declare Function GetPrivateProfileSection Lib "kernel32.dll" Alias "GetPrivateProfileSectionA" (ByVal lpAppName As String, ByVal lpReturnedBuffer As Byte(), ByVal nSize As Integer, ByVal lpFileName As String) As Integer 
    Private Declare Function GetPrivateProfileString Lib "kernel32.dll" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As String, ByVal lpDefault As String, ByVal lpReturnedBuffer As String, ByVal nSize As Integer, ByVal lpFileName As String) As Integer 

    Private path As String 
    Private sections As String() 

    Private Function GetSectionNames() As String() 
     Dim maxsize As Integer = 500 
     Do 
      Dim bytes(maxsize) As Byte 
      Dim size As Integer = GetPrivateProfileSectionNames(bytes, maxsize, path) 
      If size < maxsize - 2 Then 
       Dim Selected As String = Encoding.ASCII.GetString(bytes, 0, size - (IIf(size > 0, 1, 0))) 
       Return Selected.Split(New Char() {ControlChars.NullChar}) 
      End If 
      maxsize = maxsize * 2 
     Loop 
    End Function 

    Public Sub IniFileName(ByVal INIPath As String) 
     path = INIPath 
     sections = GetSectionNames() 
     Array.Sort(sections, New CompareByLength()) 
    End Sub 

    public Function IniReadValue(ByVal Section As String, ByVal Key As String) As String 
     Dim temp As New StringBuilder(255) 
     Dim i As Integer = GetPrivateProfileString(Section, Key, "", temp.ToString(), 255, path) 
     Return temp.ToString() 
    End Function 

    Private Function findMatch(ByVal Agent As String) As String 
     If sections IsNot Nothing Then 
     For Each SecHead As String In sections 
      If (SecHead.IndexOf("*", 0) = -1) And (SecHead.IndexOf("?", 0) = -1) And (SecHead = Agent) Then 
      If IniReadValue(SecHead, "parent") <> "DefaultProperties" Then 
       Return SecHead 
      End If 
      End If 
     Next 
     For Each SecHead As String In sections 
      Try 
      If (SecHead.IndexOf("*", 0) > -1) Or (SecHead.IndexOf("?", 0) > -1) Then 
       if Regex.IsMatch(Agent, "^" + Regex.Escape(SecHead).Replace("\*", ".*").Replace("\?", ".") + "$") Then 
       Return SecHead 
       End If 
      End If 
      Catch ex As Exception 
      'Console.WriteLine(ex) 
      End Try 
     Next 
     Return "*" 
     End If 
     Return "" 
    End Function 

    Public Function getValues(ByVal Agent As String) As NameValueCollection 
     Dim match As String = findMatch(Agent) 
     Dim col As NameValueCollection = New NameValueCollection() 
     Do 
     Dim entries() As string 
     Dim goon As Boolean = true 
     Dim maxsize As Integer = 500 
     While goon 
      Dim bytes(maxsize) As Byte 
      Dim size As Integer = GetPrivateProfileSection(match, bytes, maxsize, path) 
      If size < maxsize - 2 
      Dim section As String = Encoding.ASCII.GetString(bytes, 0, size - IIf(size > 0, 1, 0)) 
      entries = section.Split(New Char() {ControlChars.NullChar}) 
      goon = False 
      End If 
      maxsize = maxsize * 2 
     End While 
     match = "" 
     If entries.Length > 0 Then 
      For Each entry As String In entries 
      Dim ent As String() = entry.Split(New Char() {"="C}) 
      If ent(0) = "Parent" Then 
       match = ent(1) 
      else if col(ent(0)) is nothing Then 
       col.Add(ent(0), ent(1)) 
      End If 
      Next 
     End If 
     Loop While match <> "" 
     Return col 
    End Function 
End Class 

А вот как его использовать:

Dim dict As Dictionary(Of String, Object) = New Dictionary(Of String, Object) 
Dim bc As New BrowsCap 
bc.IniFileName(Server.MapPath("/App_Data/lite_asp_browscap.ini")) 
Dim Entry As NameValueCollection = bc.getValues(Request.UserAgent) 
For Each s As String In Entry.AllKeys 
    dict.Add(s, Entry(s)) 
Next 
' dict("Browser") will contains browser name like "IE" or "Chrome". 
' dict("Version") will contains browser version like "11.0" or "56.0". 
' dict("Platform") will contains OS name and version like "Win7". 

Единственное, что осталось сделать, это обновить свой Browscap.ini (или lite_asp_browscap.ini) иногда (например, один раз в неделю).

+1

Вы должны знать, что примерно в 6 раз быстрее читать и разбирать INI самостоятельно, чем использовать PInvoke. Может быть, и проще. – Plutonix

+0

Вы должны быть правы, и я понял, что видел это в другом месте, но у меня нет времени, чтобы написать собственную парсинг + сравнить + регулярное выражение/логику совпадения. Все было написано на C#. Кроме того, мой код выполняется только 100-200 раз в день. Для меня это не проблема. Но если у вас есть такая логика, уже написанная без PInvoke, не стесняйтесь публиковать ее. Спасибо, что указали на это. –

 Смежные вопросы

  • Нет связанных вопросов^_^