-
Oct 14th, 2019, 01:52 AM
#1
Thread Starter
Addicted Member
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
-
Oct 14th, 2019, 02:16 AM
#2
Addicted Member
Re: How to get the "User-Agent" when sending data with WinHttp.WinHttpRequest?
Originally Posted by Davor Geci
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"
-
Oct 14th, 2019, 03:21 AM
#3
Thread Starter
Addicted Member
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
-
Oct 14th, 2019, 05:31 AM
#4
Re: How to get the "User-Agent" when sending data with WinHttp.WinHttpRequest?
Originally Posted by Davor Geci
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>
-
Oct 14th, 2019, 06:00 AM
#5
Thread Starter
Addicted Member
Re: How to get the "User-Agent" when sending data with WinHttp.WinHttpRequest?
Originally Posted by wqweto
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
-
Oct 14th, 2019, 06:49 AM
#6
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:
Option Explicit
Private Const WM_USER As Long = &H400
'--- for PeekMessage
Private Const PM_REMOVE As Long = 1
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
Private Declare Function TranslateMessage Lib "user32" (lpMsg As APIMSG) As Long
Private Declare Function DispatchMessage Lib "user32" Alias "DispatchMessageA" (lpMsg As APIMSG) As Long
Private Type APIPOINT
X As Long
Y As Long
End Type
Private Type APIMSG
hWnd As Long
lMessage As Long
wParam As Long
lParam As Long
lTime As Long
pt As APIPOINT
End Type
Private WithEvents m_oListenSocket As cAsyncSocket
Private WithEvents m_oClientSocket As cAsyncSocket
Private m_sClientRequest As String
Private Sub Form_Load()
Debug.Print pvGetBrowserHeader(WebBrowser1, "User-Agent")
End Sub
Private Function pvGetBrowserHeader(oCtl As WebBrowser, sHeader As String) As String
Const LNG_LOCALPORT As Long = 12349
Const DBL_TIMEOUT As Double = 3
Const READYSTATE_COMPLETE As Long = 4
Const READYSTATE_INTERACTIVE As Long = 3
Dim dblTimer As Double
Set m_oListenSocket = New cAsyncSocket
If m_oListenSocket.Create(LNG_LOCALPORT) Then
If m_oListenSocket.Listen() Then
pvSpinThreadMessagePump FromMsg:=WM_USER + 1
m_sClientRequest = vbNullString
oCtl.Navigate "http://127.0.0.1:" & LNG_LOCALPORT
dblTimer = Timer
Do While Timer < dblTimer + DBL_TIMEOUT
Select Case oCtl.ReadyState
Case READYSTATE_COMPLETE, READYSTATE_INTERACTIVE
Exit Do
End Select
pvSpinThreadMessagePump FromMsg:=WM_USER + 1
Loop
pvGetBrowserHeader = pvGetRequestHeader(m_sClientRequest, sHeader)
End If
End If
Set m_oListenSocket = Nothing
End Function
Private Sub pvSpinThreadMessagePump(Optional ByVal hWnd As Long, Optional ByVal FromMsg As Long, Optional ByVal ToMsg As Long)
Dim uMsg As APIMSG
Do While PeekMessage(uMsg, hWnd, FromMsg, ToMsg, PM_REMOVE) <> 0
Call TranslateMessage(uMsg)
Call DispatchMessage(uMsg)
Loop
End Sub
Private Function pvGetRequestHeader(sRequest As String, sHeader As String) As String
Dim vSplit As Variant
Dim lIdx As Long
vSplit = Split(sRequest, vbCrLf)
For lIdx = 0 To UBound(vSplit)
If LCase$(Left$(vSplit(lIdx), Len(sHeader) + 1)) = LCase$(sHeader) & ":" Then
pvGetRequestHeader = Trim$(Mid$(vSplit(lIdx), Len(sHeader) + 2))
End If
Next
End Function
Private Sub m_oListenSocket_OnAccept()
Set m_oClientSocket = New cAsyncSocket
m_oListenSocket.Accept m_oClientSocket
End Sub
Private Sub m_oClientSocket_OnReceive()
Dim sBody As String
m_sClientRequest = m_sClientRequest & m_oClientSocket.ReceiveText
If InStr(m_sClientRequest, vbCrLf & vbCrLf) > 0 Then
sBody = pvGetRequestHeader(m_sClientRequest, "User-Agent")
'--- construct HTTP/1.0 response
m_oClientSocket.SendText "HTTP/1.0 200 OK" & vbCrLf & _
"Content-Type: text/html" & vbCrLf & _
"Content-Len" & "gth: " & Len(sBody) & vbCrLf & vbCrLf & _
sBody
End If
End Sub
cheers,
</wqw>
-
Oct 14th, 2019, 08:01 AM
#7
Re: How to get the "User-Agent" when sending data with WinHttp.WinHttpRequest?
Originally Posted by Davor Geci
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).
Originally Posted by Davor Geci
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.
-
Oct 14th, 2019, 10:09 AM
#8
Thread Starter
Addicted Member
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
-
Oct 14th, 2019, 04:12 PM
#9
Addicted Member
Re: How to get the "User-Agent" when sending data with WinHttp.WinHttpRequest?
Originally Posted by Davor Geci
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
-
Oct 14th, 2019, 04:21 PM
#10
Thread Starter
Addicted Member
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
-
Oct 14th, 2019, 11:46 PM
#11
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:
-
Oct 15th, 2019, 12:45 AM
#12
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>
-
Oct 15th, 2019, 09:13 AM
#13
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.
-
Oct 15th, 2019, 01:52 PM
#14
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
-
Oct 19th, 2019, 08:33 AM
#15
Thread Starter
Addicted Member
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
-
Oct 19th, 2019, 01:11 PM
#16
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|