Мне нужно было это для работы с более старой версией VS-компилятора и более в рамках Qt. Вот как я это сделал.
Добавьте этот файл GetWinVersion.h
в свой проект Qt:
#ifndef GETWINVERSION
#define GETWINVERSION
#include
#ifdef Q_OS_WIN
#include
#include
float GetWinVersion()
{
OSVERSIONINFO osvi;
ZeroMemory( &osvi, sizeof(OSVERSIONINFO) );
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
return GetVersionEx( &osvi ) ?
(float)osvi.dwMajorVersion +
((float)osvi.dwMinorVersion/10) :
0.0 ;
}
#endif //Q_OS_WIN
#endif // GETWINVERSION
Добавьте необходимую ссылку в файл pro или pri qmake:
msvc: LIBS += -lKernel32
Реализовать вспомогательную функцию следующим образом (обратите внимание, что SystemInfo, используемая здесь, является моим собственным классом, но вы получаете идею ...):
#include "GetWinVersion.h"
SystemInfo info;
#ifdef Q_OS_WIN
info.setPlatform( SystemInfo::WINDOWS );
switch(QSysInfo::windowsVersion())
{
case QSysInfo::WV_32s: info.setOsName( L"3.1" ); info.setOsVersion( 3.1 ); break;
case QSysInfo::WV_95: info.setOsName( L"95" ); info.setOsVersion( 4.0 ); break;
case QSysInfo::WV_98: info.setOsName( L"98" ); info.setOsVersion( 4.1 ); break;
case QSysInfo::WV_Me: info.setOsName( L"Me" ); info.setOsVersion( 4.9 ); break;
case QSysInfo::WV_NT: info.setOsName( L"NT" ); info.setOsVersion( 4.0 ); break;
case QSysInfo::WV_2000: info.setOsName( L"2000" ); info.setOsVersion( 5.0 ); break;
case QSysInfo::WV_XP: info.setOsName( L"XP" ); info.setOsVersion( 5.1 ); break;
case QSysInfo::WV_2003: info.setOsName( L"2003" ); info.setOsVersion( 5.2 ); break; // Windows Server 2003, Windows Server 2003 R2, Windows Home Server, Windows XP Professional x64 Edition
case QSysInfo::WV_VISTA: info.setOsName( L"Vista" ); info.setOsVersion( 6.0 ); break; // Windows Vista, Windows Server 2008
case QSysInfo::WV_WINDOWS7: info.setOsName( L"7" ); info.setOsVersion( 6.1 ); break; // Windows 7, Windows Server 2008 R2
case QSysInfo::WV_WINDOWS8: info.setOsName( L"8" ); info.setOsVersion( 6.2 ); break; // Windows 8, Windows Server 2012
// These cases are never reached due to Windows api changes
// As of Qt 5.5, this not accounted for by QSysInfo::windowsVersion()
//case QSysInfo::WV_WINDOWS8_1: info.setOsName( L"8.1" ); info.setOsVersion( 6.3 ); break; // Windows 8.1, Windows Server 2012 R2
//case QSysInfo::WV_WINDOWS10: info.setOsName( L"10" ); info.setOsVersion( 10.0 ); break; // Windows 10, Windows Server 2016
default:
// On Windows 8.1 & 10, this will only work when the exe
// contains a manifest which targets the specific OS's
// you wish to detect. Else 6.2 (ie. Win 8.0 is returned)
info.setOsVersion( GetWinVersion() );
if( info.osVersion() == 6.3f ) // Windows 8.1, Windows Server 2012 R2
info.setOsName( L"8.1" );
else if( info.osVersion() == 10.0f ) // Windows 10, Windows Server 2016
info.setOsName( L"10" );
else
info.setOsName( L"UNKNOWN" );
}
info.setOsBits( IsWow64() ? 64 : 32 );
#else
...
Теперь вот реальный ключ. Вам нужно прикрепить файл манифеста к вашему exe, который будет «нацелен» на последние версии Windows, иначе вы не сможете их обнаружить (см. Документы MS: https://msdn.microsoft.com/en-us/ библиотека / окно / настольный / ms724451% 2 = vs.85% 29.aspx ). Вот пример манифеста, чтобы сделать это:
И вот несколько пакетов для прикрепления манифеста:
set exeFile=MyApp.exe
set manifestFile=MyApp.manifest
set manifestExe=C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\x64\mt.exe
"%manifestExe%" -manifest "%manifestFile%" -outputresource:"%exeFile%"
В теории вы можете использовать qmake для запуска этого последнего бита манифест. Мне не повезло с примерами, которые я нашел, и просто «обманул» эту партию на данный момент ...
Я первоначально использовал некоторый код VBScript от Antonin Foller: Base64 Кодируют Функцию VBS и , Base64 Декодируют Функцию VBS .
сайт Ищущего Antonin, я видел, что у него был некоторый код для , заключил печатаемое кодирование в кавычки, с помощью объекта CDO.Message , таким образом, я попробовал это.
Наконец, я портировал код, упомянутый в ответе Mark's на VBScript (также использовал некоторый код от это ТАК вопрос), и использовал поток ___ StringToBinary и функции Stream_BinaryToString от сайта Antonin для получения функций, которые использовали кодирование MSXML.
я запустил быстрый тест для измерения времени кодирования для 1 500 символьных сообщений (средний размер сообщения, который я должен отправить в свой веб-сервис) через все четыре метода:
Вот результаты:
Iterations : 10,000 Message Size : 1,500 +-------------+-----------+ + Method | Time (ms) + +-------------+-----------+ | VBScript | 301,391 | +-------------+-----------+ | QP | 12,922 | +-------------+-----------+ | QP (Binary) | 13,953 | +-------------+-----------+ | MSXML | 3,312 | +-------------+-----------+
я также контролировал использование памяти (Использование мадам для процесса cscript.exe в Windows Task Manager), в то время как тест работал. У меня нет необработанных чисел, но использование памяти и для заключенных в кавычки печатаемых и для решений MSXML были ниже решения для VBScript (7,000K для первого, вокруг 16,000K для VBScript).
я решил пойти с решением MSXML для моего драйвера. Для заинтересованных, вот код, который я использую:
base64.vbs
Function Base64Encode(sText)
Dim oXML, oNode
Set oXML = CreateObject("Msxml2.DOMDocument.3.0")
Set oNode = oXML.CreateElement("base64")
oNode.dataType = "bin.base64"
oNode.nodeTypedValue =Stream_StringToBinary(sText)
Base64Encode = oNode.text
Set oNode = Nothing
Set oXML = Nothing
End Function
Function Base64Decode(ByVal vCode)
Dim oXML, oNode
Set oXML = CreateObject("Msxml2.DOMDocument.3.0")
Set oNode = oXML.CreateElement("base64")
oNode.dataType = "bin.base64"
oNode.text = vCode
Base64Decode = Stream_BinaryToString(oNode.nodeTypedValue)
Set oNode = Nothing
Set oXML = Nothing
End Function
'Stream_StringToBinary Function
'2003 Antonin Foller, http://www.motobit.com
'Text - string parameter To convert To binary data
Function Stream_StringToBinary(Text)
Const adTypeText = 2
Const adTypeBinary = 1
'Create Stream object
Dim BinaryStream 'As New Stream
Set BinaryStream = CreateObject("ADODB.Stream")
'Specify stream type - we want To save text/string data.
BinaryStream.Type = adTypeText
'Specify charset For the source text (unicode) data.
BinaryStream.CharSet = "us-ascii"
'Open the stream And write text/string data To the object
BinaryStream.Open
BinaryStream.WriteText Text
'Change stream type To binary
BinaryStream.Position = 0
BinaryStream.Type = adTypeBinary
'Ignore first two bytes - sign of
BinaryStream.Position = 0
'Open the stream And get binary data from the object
Stream_StringToBinary = BinaryStream.Read
Set BinaryStream = Nothing
End Function
'Stream_BinaryToString Function
'2003 Antonin Foller, http://www.motobit.com
'Binary - VT_UI1 | VT_ARRAY data To convert To a string
Function Stream_BinaryToString(Binary)
Const adTypeText = 2
Const adTypeBinary = 1
'Create Stream object
Dim BinaryStream 'As New Stream
Set BinaryStream = CreateObject("ADODB.Stream")
'Specify stream type - we want To save binary data.
BinaryStream.Type = adTypeBinary
'Open the stream And write binary data To the object
BinaryStream.Open
BinaryStream.Write Binary
'Change stream type To text/string
BinaryStream.Position = 0
BinaryStream.Type = adTypeText
'Specify charset For the output text (unicode) data.
BinaryStream.CharSet = "us-ascii"
'Open the stream And get text/string data from the object
Stream_BinaryToString = BinaryStream.ReadText
Set BinaryStream = Nothing
End Function
Итак, у меня есть другой полный пример кодировщика и декодера:
Кодировщик:
' This script reads jpg picture named SuperPicture.jpg, converts it to base64
' code using encoding abilities of MSXml2.DOMDocument object and saves
' the resulting data to encoded.txt file
Option Explicit
Const fsDoOverwrite = true ' Overwrite file with base64 code
Const fsAsASCII = false ' Create base64 code file as ASCII file
Const adTypeBinary = 1 ' Binary file is encoded
' Variables for writing base64 code to file
Dim objFSO
Dim objFileOut
' Variables for encoding
Dim objXML
Dim objDocElem
' Variable for reading binary picture
Dim objStream
' Open data stream from picture
Set objStream = CreateObject("ADODB.Stream")
objStream.Type = adTypeBinary
objStream.Open()
objStream.LoadFromFile("SuperPicture.jpg")
' Create XML Document object and root node
' that will contain the data
Set objXML = CreateObject("MSXml2.DOMDocument")
Set objDocElem = objXML.createElement("Base64Data")
objDocElem.dataType = "bin.base64"
' Set binary value
objDocElem.nodeTypedValue = objStream.Read()
' Open data stream to base64 code file
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFileOut = objFSO.CreateTextFile("encoded.txt", fsDoOverwrite, fsAsASCII)
' Get base64 value and write to file
objFileOut.Write objDocElem.text
objFileOut.Close()
' Clean all
Set objFSO = Nothing
Set objFileOut = Nothing
Set objXML = Nothing
Set objDocElem = Nothing
Set objStream = Nothing
Декодер:
' This script reads base64 encoded picture from file named encoded.txt,
' converts it in to back to binary reprisentation using encoding abilities
' of MSXml2.DOMDocument object and saves data to SuperPicture.jpg file
Option Explicit
Const foForReading = 1 ' Open base 64 code file for reading
Const foAsASCII = 0 ' Open base 64 code file as ASCII file
Const adSaveCreateOverWrite = 2 ' Mode for ADODB.Stream
Const adTypeBinary = 1 ' Binary file is encoded
' Variables for reading base64 code from file
Dim objFSO
Dim objFileIn
Dim objStreamIn
' Variables for decoding
Dim objXML
Dim objDocElem
' Variable for write binary picture
Dim objStream
' Open data stream from base64 code filr
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFileIn = objFSO.GetFile("encoded.txt")
Set objStreamIn = objFileIn.OpenAsTextStream(foForReading, foAsASCII)
' Create XML Document object and root node
' that will contain the data
Set objXML = CreateObject("MSXml2.DOMDocument")
Set objDocElem = objXML.createElement("Base64Data")
objDocElem.DataType = "bin.base64"
' Set text value
objDocElem.text = objStreamIn.ReadAll()
' Open data stream to picture file
Set objStream = CreateObject("ADODB.Stream")
objStream.Type = adTypeBinary
objStream.Open()
' Get binary value and write to file
objStream.Write objDocElem.NodeTypedValue
objStream.SaveToFile "SuperPicture.jpg", adSaveCreateOverWrite
' Clean all
Set objFSO = Nothing
Set objFileIn = Nothing
Set objStreamIn = Nothing
Set objXML = Nothing
Set objDocElem = Nothing
Set objStream = Nothing