Results 1 to 16 of 16

Thread: How to get the "User-Agent" when sending data with WinHttp.WinHttpRequest?

  1. #1

    Thread Starter
    Addicted Member Davor Geci's Avatar
    Join Date
    Sep 2009
    Posts
    222

    How to get the "User-Agent" when sending data with WinHttp.WinHttpRequest?

    Hello,
    I'm sending data to a server and need also to pass the User-Agent that identifies the windows version (I don't care about the browser version).

    I now have a static value for the "user-agent". Do you know how to get it from example a webbrowser or is there another way?

    My current code:

    Code:
        Dim winHttpReq As Object
        Dim myURL As String
        Dim postData As String
    
        Set winHttpReq = CreateObject("WinHttp.WinHttpRequest.5.1")
    
        myURL = "https://Someserver.com"
    
        postData = "my_data_for_sending"
    
        winHttpReq.Open "POST", myURL, False
        winHttpReq.SetRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
    
        winHttpReq.send (postData)
    How can I get the "User-Agent" from users machine to use it in SetRequestHeader?

    P.S.
    The company (google) says that we can't create some custom User-Agents but we need to use the ones that are already in circulation, because it could break something and the sever will stop accepting our data.

    Thanks,
    Davor
    Last edited by Davor Geci; Oct 14th, 2019 at 01:55 AM.
    My projects:
    Virtual Forms
    VBA Telemetry

  2. #2
    Addicted Member
    Join Date
    Aug 2019
    Posts
    194

    Re: How to get the "User-Agent" when sending data with WinHttp.WinHttpRequest?

    Quote Originally Posted by Davor Geci View Post
    Hello,
    I'm sending data to a server and need also to pass the User-Agent that identifies the windows version (I don't care about the browser version).

    I now have a static value for the "user-agent". Do you know how to get it from example a webbrowser or is there another way?

    My current code:

    Code:
        Dim winHttpReq As Object
        Dim myURL As String
        Dim postData As String
    
        Set winHttpReq = CreateObject("WinHttp.WinHttpRequest.5.1")
    
        myURL = "https://Someserver.com"
    
        postData = "my_data_for_sending"
    
        winHttpReq.Open "POST", myURL, False
        winHttpReq.SetRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
    
        winHttpReq.send (postData)
    How can I get the "User-Agent" from users machine to use it in SetRequestHeader?

    P.S.
    The company (google) says that we can't create some custom User-Agents but we need to use the ones that are already in circulation, because it could break something and the sever will stop accepting our data.

    Thanks,
    Davor
    Code:
    Set myMSXML = CreateObject("Microsoft.XmlHttp")
    myMSXML.Open "POST", "https://Someserver.com", False
    myMSXML.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded"
    myMSXML.SetRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
    myMSXML.SetRequestHeader "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
    myMSXML.SetRequestHeader "Accept-Language", "en-GB,en;q=0.5"
    myMSXML.SetRequestHeader "Accept-Encoding", "gzip, deflate, br"
    myMSXML.SetRequestHeader "Referer", "https://Someserver.com"
    myMSXML.Send "my_data_for_sending"

  3. #3

    Thread Starter
    Addicted Member Davor Geci's Avatar
    Join Date
    Sep 2009
    Posts
    222

    Re: How to get the "User-Agent" when sending data with WinHttp.WinHttpRequest?

    Thanks doberman2002,

    thanks for your reply, you are also using a static User-Agent in this code.
    How can we get the User-Agent from this code?
    Davor
    My projects:
    Virtual Forms
    VBA Telemetry

  4. #4
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,121

    Re: How to get the "User-Agent" when sending data with WinHttp.WinHttpRequest?

    Quote Originally Posted by Davor Geci View Post
    How can I get the "User-Agent" from users machine to use it in SetRequestHeader?r
    User-agent is not per machine but per browser. You can have two different versions of IE installed on the same machine (hard but doable) that send different headers.

    User-agent header design is one big ball of mud -- https://developer.mozilla.org/en-US/...the_user_agent

    cheers,
    </wqw>

  5. #5

    Thread Starter
    Addicted Member Davor Geci's Avatar
    Join Date
    Sep 2009
    Posts
    222

    Re: How to get the "User-Agent" when sending data with WinHttp.WinHttpRequest?

    Quote Originally Posted by wqweto View Post
    User-agent is not per machine but per browser. You can have two different versions of IE installed on the same machine (hard but doable) that send different headers.

    User-agent header design is one big ball of mud -- https://developer.mozilla.org/en-US/...the_user_agent

    cheers,
    </wqw>
    And how to get it from any browser within the VB6 or VBA?
    My projects:
    Virtual Forms
    VBA Telemetry

  6. #6
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,121

    Re: How to get the "User-Agent" when sending data with WinHttp.WinHttpRequest?

    Add cAsyncSocket class to an empty Std-EXE project, place a WebBrowser1 control to Form1 and try this code:

    thinBasic Code:
    1. Option Explicit
    2.  
    3. Private Const WM_USER                       As Long = &H400
    4. '--- for PeekMessage
    5. Private Const PM_REMOVE                     As Long = 1
    6.  
    7. Private Declare Function PeekMessage Lib "user32" Alias "PeekMessageA" (lpMsg As APIMSG, ByVal hWnd As Long, ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long, ByVal wRemoveMsg As Long) As Long
    8. Private Declare Function TranslateMessage Lib "user32" (lpMsg As APIMSG) As Long
    9. Private Declare Function DispatchMessage Lib "user32" Alias "DispatchMessageA" (lpMsg As APIMSG) As Long
    10.  
    11. Private Type APIPOINT
    12.     X                   As Long
    13.     Y                   As Long
    14. End Type
    15.  
    16. Private Type APIMSG
    17.     hWnd                As Long
    18.     lMessage            As Long
    19.     wParam              As Long
    20.     lParam              As Long
    21.     lTime               As Long
    22.     pt                  As APIPOINT
    23. End Type
    24.  
    25. Private WithEvents m_oListenSocket  As cAsyncSocket
    26. Private WithEvents m_oClientSocket  As cAsyncSocket
    27. Private m_sClientRequest            As String
    28.  
    29. Private Sub Form_Load()
    30.     Debug.Print pvGetBrowserHeader(WebBrowser1, "User-Agent")
    31. End Sub
    32.  
    33. Private Function pvGetBrowserHeader(oCtl As WebBrowser, sHeader As String) As String
    34.     Const LNG_LOCALPORT     As Long = 12349
    35.     Const DBL_TIMEOUT       As Double = 3
    36.     Const READYSTATE_COMPLETE As Long = 4
    37.     Const READYSTATE_INTERACTIVE As Long = 3
    38.     Dim dblTimer            As Double
    39.    
    40.     Set m_oListenSocket = New cAsyncSocket
    41.     If m_oListenSocket.Create(LNG_LOCALPORT) Then
    42.         If m_oListenSocket.Listen() Then
    43.             pvSpinThreadMessagePump FromMsg:=WM_USER + 1
    44.             m_sClientRequest = vbNullString
    45.             oCtl.Navigate "http://127.0.0.1:" & LNG_LOCALPORT
    46.             dblTimer = Timer
    47.             Do While Timer < dblTimer + DBL_TIMEOUT
    48.                 Select Case oCtl.ReadyState
    49.                 Case READYSTATE_COMPLETE, READYSTATE_INTERACTIVE
    50.                     Exit Do
    51.                 End Select
    52.                 pvSpinThreadMessagePump FromMsg:=WM_USER + 1
    53.             Loop
    54.             pvGetBrowserHeader = pvGetRequestHeader(m_sClientRequest, sHeader)
    55.         End If
    56.     End If
    57.     Set m_oListenSocket = Nothing
    58. End Function
    59.  
    60. Private Sub pvSpinThreadMessagePump(Optional ByVal hWnd As Long, Optional ByVal FromMsg As Long, Optional ByVal ToMsg As Long)
    61.     Dim uMsg                As APIMSG
    62.    
    63.     Do While PeekMessage(uMsg, hWnd, FromMsg, ToMsg, PM_REMOVE) <> 0
    64.         Call TranslateMessage(uMsg)
    65.         Call DispatchMessage(uMsg)
    66.     Loop
    67. End Sub
    68.  
    69. Private Function pvGetRequestHeader(sRequest As String, sHeader As String) As String
    70.     Dim vSplit          As Variant
    71.     Dim lIdx            As Long
    72.    
    73.     vSplit = Split(sRequest, vbCrLf)
    74.     For lIdx = 0 To UBound(vSplit)
    75.         If LCase$(Left$(vSplit(lIdx), Len(sHeader) + 1)) = LCase$(sHeader) & ":" Then
    76.             pvGetRequestHeader = Trim$(Mid$(vSplit(lIdx), Len(sHeader) + 2))
    77.         End If
    78.     Next
    79. End Function
    80.  
    81. Private Sub m_oListenSocket_OnAccept()
    82.     Set m_oClientSocket = New cAsyncSocket
    83.     m_oListenSocket.Accept m_oClientSocket
    84. End Sub
    85.  
    86. Private Sub m_oClientSocket_OnReceive()
    87.     Dim sBody           As String
    88.    
    89.     m_sClientRequest = m_sClientRequest & m_oClientSocket.ReceiveText
    90.     If InStr(m_sClientRequest, vbCrLf & vbCrLf) > 0 Then
    91.         sBody = pvGetRequestHeader(m_sClientRequest, "User-Agent")
    92.         '--- construct HTTP/1.0 response
    93.         m_oClientSocket.SendText "HTTP/1.0 200 OK" & vbCrLf & _
    94.             "Content-Type: text/html" & vbCrLf & _
    95.             "Content-Len" & "gth: " & Len(sBody) & vbCrLf & vbCrLf & _
    96.             sBody
    97.     End If
    98. End Sub
    cheers,
    </wqw>

  7. #7
    PowerPoster
    Join Date
    Feb 2017
    Posts
    4,997

    Re: How to get the "User-Agent" when sending data with WinHttp.WinHttpRequest?

    Quote Originally Posted by Davor Geci View Post
    I'm sending data to a server and need also to pass the User-Agent that identifies the windows version (I don't care about the browser version).
    Quote Originally Posted by Davor Geci View Post
    Do you know how to get it from example a webbrowser
    Why do you need that? If you need to identify the Windows version accurately, then you don't want the User Agent string that comes from the WebBrowser control, because it will be stuck in Windows 8.

    For example, I have Windows 10 64 bits, my User Agent string from FireFox is:
    Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0

    But the string that I get with wqweto's code is:
    Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; WOW64; Trident/7.0; .NET4.0C; .NET4.0E)

    You can use this site to analyze the strings.

    The part of the strings that identifies the Windows version is:
    • Windows NT 10.0; Win64; x64
    • Windows NT 6.2; WOW64


    Two options comes to mind to get the proper string.
    To use wqweto's code but to shell the default web browser instead of the WebBrowser control or to build the string yourself, by getting the Windows version with the APIs for that.

    Here there is information about how that string should be built.

    PS: I have Intel processor but it reports x64 instead of IA64.

  8. #8

    Thread Starter
    Addicted Member Davor Geci's Avatar
    Join Date
    Sep 2009
    Posts
    222

    Re: How to get the "User-Agent" when sending data with WinHttp.WinHttpRequest?

    Because I don't have a form in this project, just a class I can't use the code from wqweto, by the way, thanks wqweto for posting it.
    Eduardo I did some reading of the links from your post.
    I understand, and also it is in great detail, but didn't have any luck to implement it.
    Because I'm in VBA I was trying to midify the current User-Agent:

    Code:
    winHttpReq.SetRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
    with:

    Code:
    winHttpReq.SetRequestHeader "User-Agent", "Mozilla/4.0 (" & Application.OperatingSystem & ")"
    this was giving me the User-Agent:
    Code:
    Mozilla/4.0 (Windows (32-bit) NT 10.00)
    and another code has given me:
    Code:
    Mozilla/4.0 (Microsoft Windows 10 Home 10.0.17763)
    But in both cases Google Analytics doesn't recognize the Operating System or Operating System Version

    The original User-Agent:
    Code:
    Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)
    is reported as Windows 2000

    Hm, I was thinking that this would be a simple one, but it turns out that I was wrong.
    My projects:
    Virtual Forms
    VBA Telemetry

  9. #9
    Addicted Member
    Join Date
    Aug 2019
    Posts
    194

    Re: How to get the "User-Agent" when sending data with WinHttp.WinHttpRequest?

    Quote Originally Posted by Davor Geci View Post
    Because I don't have a form in this project, just a class I can't use the code from wqweto, by the way, thanks wqweto for posting it.
    Eduardo I did some reading of the links from your post.
    I understand, and also it is in great detail, but didn't have any luck to implement it.
    Because I'm in VBA I was trying to midify the current User-Agent:

    Code:
    winHttpReq.SetRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
    with:

    Code:
    winHttpReq.SetRequestHeader "User-Agent", "Mozilla/4.0 (" & Application.OperatingSystem & ")"
    this was giving me the User-Agent:
    Code:
    Mozilla/4.0 (Windows (32-bit) NT 10.00)
    and another code has given me:
    Code:
    Mozilla/4.0 (Microsoft Windows 10 Home 10.0.17763)
    But in both cases Google Analytics doesn't recognize the Operating System or Operating System Version

    The original User-Agent:
    Code:
    Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)
    is reported as Windows 2000

    Hm, I was thinking that this would be a simple one, but it turns out that I was wrong.
    you're trying to identify operating system by that, OK that's fine but sending a request to server and grabbing user agent can't be done, only server side can Se it.
    load combobox with lots of user-agents and send request with different combobox list items google will show each one.use mobile user agents to.
    are you creating a View Bot

  10. #10

    Thread Starter
    Addicted Member Davor Geci's Avatar
    Join Date
    Sep 2009
    Posts
    222

    Re: How to get the "User-Agent" when sending data with WinHttp.WinHttpRequest?

    I'm creating a class module that will allow us to send telemetric data to Google Analytics from VB6 or VBA.
    Data like Screenviews, Events, Exceptions (errors), Custom Metrics, Custom Dimensions, Timings,....
    My projects:
    Virtual Forms
    VBA Telemetry

  11. #11
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: How to get the "User-Agent" when sending data with WinHttp.WinHttpRequest?

    Module1.bas:

    Code:
    Option Explicit
    
    'Reference to: Microsoft HTML Object Library
    
    Private Sub Main()
        With New MSHTML.HTMLDocument
            MsgBox .parentWindow.navigator.userAgent
        End With
    End Sub
    Application.manifest (added as resource Type #24, Id #1):

    Code:
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" manifestVersion="1.0">
      <assemblyIdentity name="Your.Company.Here.Project1" processorArchitecture="X86" type="win32" version="1.0.0.0" />
      <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
        <security>
            <requestedPrivileges>
              <requestedExecutionLevel level="asInvoker" uiAccess="false" />
            </requestedPrivileges>
        </security>
      </trustInfo>
      <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> 
        <application> 
          <!-- WinVista --><supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> 
          <!-- Win7     --><supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
          <!-- Win8     --><supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
          <!-- Win8.1   --><supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
          <!-- Win10    --><supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
        </application> 
      </compatibility>
    </assembly>
    To embed this safely always pad it with spaces to a whole multiple of 4 bytes.

    Result from compiled EXE I get on one Win10 machine:

    Name:  sshot.png
Views: 4442
Size:  2.5 KB

  12. #12
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,121

    Re: How to get the "User-Agent" when sending data with WinHttp.WinHttpRequest?

    As simple as navigator.userAgent, doh!

    Well, at least the full mini-httpserver sample above can be used with Firefox and Chrome (or whatever browser can navigate localhost) too, not only IE.

    cheers,
    </wqw>

  13. #13
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: How to get the "User-Agent" when sending data with WinHttp.WinHttpRequest?

    Took me some digging to find it.

    Microsoft's online developer support site is almost worthless these days. I had to go back and look through MSDN CDs and didn't find it until I was all the way back to the October 2001 CDs. I should have known better and started there.

    It's like the company is already dead and being operated halfheartedly by incompetent liquidators desperate to wring out the last drops of value there. Look at all of the .Net pollution in that User-Agent string! When .Net sits around the house, .Net sits around the house.

  14. #14
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: How to get the "User-Agent" when sending data with WinHttp.WinHttpRequest?

    FYI, same scenario but some tweaks to create/remove a registry entry:

    Code:
    Option Explicit
    
    Private Const KEY_HKCU_FEATURE_BROWSER_EMULATION As String = _
        "HKCU\Software\Microsoft\Internet Explorer\Main\" _
      & "FeatureControl\FEATURE_BROWSER_EMULATION\"
    Private Const IE11_STANDARDS_MODE As Long = 11000
    
    Private IdeMode As Boolean
    
    Public Sub ClearIE11Mode()
        Dim Name As String
        Dim Value As Variant
        
        If IdeMode Then
            Name = KEY_HKCU_FEATURE_BROWSER_EMULATION & "VB6.EXE"
        Else
            Name = KEY_HKCU_FEATURE_BROWSER_EMULATION & App.EXEName & ".exe"
        End If
        With CreateObject("WScript.Shell")
            On Error Resume Next
            Value = .RegRead(Name)
            If Err.Number <> 0 Then
                On Error GoTo 0
                .RegDelete Name
            End If
        End With
    End Sub
    
    Private Sub SetIE11Mode()
        Dim Name As String
        Dim Value As Variant
    
        On Error Resume Next
        Debug.Assert 1 / 0
        IdeMode = Err.Number <> 0
        On Error GoTo 0
        If IdeMode Then
            Name = KEY_HKCU_FEATURE_BROWSER_EMULATION & "VB6.EXE"
        Else
            Name = KEY_HKCU_FEATURE_BROWSER_EMULATION & App.EXEName & ".exe"
        End If
        With CreateObject("WScript.Shell")
            On Error Resume Next
            Value = .RegRead(Name)
            If Err.Number <> 0 Or Value <> IE11_STANDARDS_MODE Then
                On Error GoTo 0
                .RegWrite Name, IE11_STANDARDS_MODE, "REG_DWORD"
            End If
        End With
    End Sub
    
    Private Sub Main()
        SetIE11Mode 'Normally you'd do this once on first run.  However that
                    'presumes your EXE name is pretty unique because the reg
                    'value's Name is a simple file name and not a full path.
        With New MSHTML.HTMLDocument
            MsgBox .parentWindow.navigator.userAgent
        End With
        ClearIE11Mode 'Since this is just a test program we'll clear the entry
                      'we made above.
    End Sub

    Name:  sshot.png
Views: 4444
Size:  2.4 KB

  15. #15

    Thread Starter
    Addicted Member Davor Geci's Avatar
    Join Date
    Sep 2009
    Posts
    222

    Re: How to get the "User-Agent" when sending data with WinHttp.WinHttpRequest?

    Thanks guys for your suggestions and solutions.
    Couldn't login to vbforms for a few days, so couldn't respond.
    I'm planing to use this within VBA (Excel VBA), dilettante do you maybe know if this will also work (the registry create) on machines where the user doesn't have the admin rights?
    My projects:
    Virtual Forms
    VBA Telemetry

  16. #16
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: How to get the "User-Agent" when sending data with WinHttp.WinHttpRequest?

    The value written to the registry is in HKCU so there shouldn't be any requirement for elevated runs.

    You can use API calls to verify/write the value, I just used WScript.Shell for a quick and dirty test.


    I also found:

    32-bit and 64-bit Complexities

    You have the option to add the browser emulation key to the current user (HKCU) or the local machine ((HKLM) hive. If you add to the current user HKCU hive, you don’t need to worry about “bitness” of your OS or application. However, if you add the key to the local machine hive, you need to consider the following complexities. Depending on the “bitness” of your application, you need to add the key to the correct registry location on a Windows 64-bit machine. On a 64-bit OS, 32-bit applications run in the WOW64 subsystem. For 32-bit apps, WOW64 redirects registry calls to a separate location for certain keys. The FEATURE_BROWSER_EMULATION key is redirected. Therefore, on a 64-bit OS, a 32-bit application’s value needs to be placed in HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION.

    It seems that the values must have simple names, not full paths, so you want to use unique names for such executables to avoid colliding with other programs using the same hack. They might be setting different emulation from what you need.
    Last edited by dilettante; Oct 19th, 2019 at 01:22 PM.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width