Get Version from SDK - like "10.8.5.410"  SOLVED

PDF-XChange Editor SDK for Developers

Moderators: PDF-XChange Support, Daniel - PDF-XChange, Chris - PDF-XChange, Sean - PDF-XChange, Paul - PDF-XChange, Vasyl - PDF-XChange, Ivan - Tracker Software, Stefan - PDF-XChange

Forum rules
DO NOT post your license/serial key, or your activation code - these forums, and all posts within, are public and we will be forced to immediately deactivate your license.

When experiencing some errors, use the IAUX_Inst::FormatHRESULT method to see their description and include it in your post along with the error code.
zarkogajic
User
Posts: 1549
Joined: Thu Sep 05, 2019 12:35 pm

Get Version from SDK - like "10.8.5.410"

Post by zarkogajic »

Hi Support,

I think this was maybe asked before, but just to be sure:

Is there a way to get the version number from SDK, some method to return something like "10.8.5.410"?

p.s.
If not, please include something if possible for future.

-žarko
User avatar
MishaH
User
Posts: 31
Joined: Wed Sep 11, 2024 1:43 pm

Re: Get Version from SDK - like "10.8.5.410"

Post by MishaH »

Hello, zarkogajic

You are probably looking for this topic: viewtopic.php?t=30712

Kind regards,
Misha
zarkogajic
User
Posts: 1549
Joined: Thu Sep 05, 2019 12:35 pm

Re: Get Version from SDK - like "10.8.5.410"

Post by zarkogajic »

Hi,

Yes, that should be it, tx.

User avatar
Daniel - PDF-XChange
Site Admin
Posts: 12856
Joined: Wed Jan 03, 2018 6:52 pm

Get Version from SDK - like "10.8.5.410"

Post by Daniel - PDF-XChange »

:)
Dan McIntyre - Support Technician
PDF-XChange Co. LTD

+++++++++++++++++++++++++++++++++++
Our Web site domain and email address has changed as of 26/10/2023.
https://www.pdf-xchange.com
[email protected]
zarkogajic
User
Posts: 1549
Joined: Thu Sep 05, 2019 12:35 pm

Re: Get Version from SDK - like "10.8.5.410"

Post by zarkogajic »

Hi Daniel,

Well .. not actually what I was looking for :(

The API Version cannot be used to get "10.8.5.410".

Atm, APIVersion returns "2020001" (or similar) - so not usable for what's needed.

Yes, I can get the file version from file - but that is the catch - I might not be certain what DLL was loaded to make Instance ... and that's what I wanted to be able to figure out via Get Version.

-žarko
User avatar
Daniel - PDF-XChange
Site Admin
Posts: 12856
Joined: Wed Jan 03, 2018 6:52 pm

Re: Get Version from SDK - like "10.8.5.410"

Post by Daniel - PDF-XChange »

Hello, zarkogajic

I am afriad that it does not seem as though there is a way to do such at the moment, Might i ask what precisely the reason you need to perform such a check and return the end user version number? Perhaps understanding the use case could help us to offer a better solution.

Kind regards,
Dan McIntyre - Support Technician
PDF-XChange Co. LTD

+++++++++++++++++++++++++++++++++++
Our Web site domain and email address has changed as of 26/10/2023.
https://www.pdf-xchange.com
[email protected]
zarkogajic
User
Posts: 1549
Joined: Thu Sep 05, 2019 12:35 pm

Re: Get Version from SDK - like "10.8.5.410"

Post by zarkogajic »

Hi Dan

I use the SDK's DLL in my code, which by design has the same build/version number as the EUEditor.

In my coding I use both the x86 and x64 version and also sometimes use it from the manifest file ("Registration-Free") and sometimes the registry registered version.

In my testings I then want to know what is the "version" of the dll - so to be sure I'm running my test code agains the version I wanted. As a "double check".

I hope this makes sense and a plausible cause ;)

p.s.
Like that IStream thingy (in a separate topic) - had to test over multiple sdk versions and wanted a way to be sure I'm using the "correct" version dll.

-žarko
User avatar
Daniel - PDF-XChange
Site Admin
Posts: 12856
Joined: Wed Jan 03, 2018 6:52 pm

Re: Get Version from SDK - like "10.8.5.410"

Post by Daniel - PDF-XChange »

Hello, zarkogajic

Thank you, I have added these details to the feature request for adding a way to fetch the "user visible" version number format of such items. I will let you know if anything comes about from this.

Kind regards,
Dan McIntyre - Support Technician
PDF-XChange Co. LTD

+++++++++++++++++++++++++++++++++++
Our Web site domain and email address has changed as of 26/10/2023.
https://www.pdf-xchange.com
[email protected]
User avatar
Vasyl - PDF-XChange
Site Admin
Posts: 2488
Joined: Thu Jun 30, 2005 4:11 pm

Re: Get Version from SDK - like "10.8.5.410"

Post by Vasyl - PDF-XChange »

Hi Zarko.

Unfortunately, but the APIVersion cannot be converted to that user-readable representation. You need something like this:

Code: Select all

struct FILEVERSION
{
	DWORD	v[4] = {0};
};

bool ReadVersion(const wchar_t* sValue, FILEVERSION& ver)
{
	if (!sValue || (sValue[0] == '\0'))
		return false;
	DWORD nIndex = 0;
	DWORD val = 0;
	const wchar_t* p = sValue;
	do
	{
		if ((*p == L'.') || (*p == L'\0'))
		{
			ver.v[nIndex] = val;
			val = 0;
			nIndex++;
			if ((nIndex == 4) || (*p == L'\0'))
				break;
		}
		else if ((*p >= L'0') && (*p <= '9'))
		{
			val *= 10;
			val += (*p - L'0');
		}
		else
		{
			break;
		}
		p++;
	} while (true);
	return (ver.v[0] > 0);
}

struct LANGANDCODEPAGE
{
	WORD	wLanguage;
	WORD	wCodePage;
};

void GetVersionNumber(const wchar_t* sFileName, int& dwMajor, int& dwMinor, int& dwBuild, int& dwSubBuild, std::wstring& sSpecialBuild)
{
	sSpecialBuild.clear();
	UINT nHandle = 0;
	DWORD dwSize = ::GetFileVersionInfoSizeW(sFileName, (LPDWORD)&nHandle);
	byte* pData = (byte*)_alloca(dwSize);
	::GetFileVersionInfoW(sFileName, 0, dwSize, pData);
	LANGANDCODEPAGE* pTransl = nullptr;
	::VerQueryValueW(pData, L"\\VarFileInfo\\Translation", (void**)&pTransl, &nHandle);
	wchar_t buf[128];
	wsprintf(buf, L"\\StringFileInfo\\%04x%04x\\FileVersion", pTransl[0].wLanguage, pTransl[0].wCodePage);
	wchar_t* p = nullptr;
	::VerQueryValueW(pData, (LPWSTR)buf, (void**)&p, &nHandle);
	FILEVERSION fv;
	ReadVersion(p, fv);
	dwMajor = (int)fv.v[0];
	dwMinor = (int)fv.v[1];
	dwBuild = (int)fv.v[2];
	dwSubBuild = (int)fv.v[3];
	wsprintf(buf, L"\\StringFileInfo\\%04x%04x\\SpecialBuild", pTransl[0].wLanguage, pTransl[0].wCodePage);
	p = nullptr;
	nHandle = 0;
	::VerQueryValueW(pData, (LPWSTR)buf, (LPVOID*)&p, &nHandle);
	if ((p != nullptr) && (p[0] != '\0') && (nHandle > 0))
		sSpecialBuild = (LPCWSTR)p;
}
While the sFileName - is the full path to the PDFXEditCore.<platform>.dll

HTH.
PDF-XChange Co. LTD (Project Developer)

Please archive any files posted to a ZIP, 7z or RAR file or they will be removed and not posted.
zarkogajic
User
Posts: 1549
Joined: Thu Sep 05, 2019 12:35 pm

Re: Get Version from SDK - like "10.8.5.410"  SOLVED

Post by zarkogajic »

Hi Vasyl,

Thanks. The need to know/specify the path ("sFileName") of the dll is what I wanted to not play a role.

If no go, ok.

I'll try with GetModuleFileName...

-žarko
zarkogajic
User
Posts: 1549
Joined: Thu Sep 05, 2019 12:35 pm

Re: Get Version from SDK - like "10.8.5.410"

Post by zarkogajic »

Hi,

For future readers:

Here's the implementation of "Get SDK version, from PXV_Instance" (both in Delphi and C#):

Delphi code:

Code: Select all

uses
  Winapi.Windows, System.SysUtils;

function GetComDllPath(const Unk: IUnknown): string;
var
  VTable : PPointer;
  FnPtr  : Pointer;
  MBI    : TMemoryBasicInformation;
  Path   : array[0..MAX_PATH] of Char;
begin
  Result := '';
  if Unk = nil then Exit;

  // Dereference the interface pointer to get the vtable pointer,
  // then grab the first entry (any address inside the DLL will do)
  VTable := PPointer(Unk)^;
  FnPtr  := VTable^;

  // Map that code address back to its hosting module
  if VirtualQuery(FnPtr, MBI, SizeOf(MBI)) = 0 then Exit;

  if GetModuleFileName(HMODULE(MBI.AllocationBase), Path, MAX_PATH) = 0 then Exit;

  Result := string(Path);
end;

function GetDllFileVersion(const FilePath: string): string;
var
  Dummy   : DWORD;
  Size    : DWORD;
  Buf     : array of Byte;
  pInfo   : PVSFixedFileInfo;
  InfoLen : UINT;
begin
  Result := '';

  Size := GetFileVersionInfoSize(PChar(FilePath), Dummy);
  if Size = 0 then Exit;

  SetLength(Buf, Size);
  if not GetFileVersionInfo(PChar(FilePath), 0, Size, Buf) then Exit;

  if not VerQueryValue(Buf, '\', Pointer(pInfo), InfoLen) then Exit;

  Result := Format('%d.%d.%d.%d', [
    HiWord(pInfo.dwFileVersionMS),
    LoWord(pInfo.dwFileVersionMS),
    HiWord(pInfo.dwFileVersionLS),
    LoWord(pInfo.dwFileVersionLS)
  ]);
end;
Delphi usage:

Code: Select all

pxvInst : IPXV_Inst;

//obtain pxvInst say from PXV_Control.Inst (where PXV_Control is your TPXV_Control)

sdkDLLPath := GetComDllPath(pxvInst);
sdkDLLVersion := GetDllFileVersion(sdkDLLPath);

C# code

Code: Select all

using System;
using System.Runtime.InteropServices;
using System.Text;

public static class ComDllInfo
{
    #region P/Invoke declarations

    [StructLayout(LayoutKind.Sequential)]
    private struct MEMORY_BASIC_INFORMATION
    {
        public IntPtr  BaseAddress;
        public IntPtr  AllocationBase;
        public uint    AllocationProtect;
        public IntPtr  RegionSize;
        public uint    State;
        public uint    Protect;
        public uint    Type;
    }

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern int VirtualQuery(
        IntPtr lpAddress,
        ref MEMORY_BASIC_INFORMATION lpBuffer,
        int dwLength);

    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern uint GetModuleFileName(
        IntPtr hModule,
        StringBuilder lpFilename,
        int nSize);

    [DllImport("version.dll", CharSet = CharSet.Unicode)]
    private static extern int GetFileVersionInfoSize(
        string lptstrFilename,
        out uint lpdwHandle);

    [DllImport("version.dll", CharSet = CharSet.Unicode)]
    private static extern bool GetFileVersionInfo(
        string lptstrFilename,
        uint dwHandle,
        int dwLen,
        byte[] lpData);

    [DllImport("version.dll", CharSet = CharSet.Unicode)]
    private static extern bool VerQueryValue(
        byte[] pBlock,
        string lpSubBlock,
        out IntPtr lplpBuffer,
        out uint puLen);

    [StructLayout(LayoutKind.Sequential)]
    private struct VS_FIXEDFILEINFO
    {
        public uint dwSignature;
        public uint dwStrucVersion;
        public uint dwFileVersionMS;
        public uint dwFileVersionLS;
        public uint dwProductVersionMS;
        public uint dwProductVersionLS;
        public uint dwFileFlagsMask;
        public uint dwFileFlags;
        public uint dwFileOS;
        public uint dwFileType;
        public uint dwFileSubtype;
        public uint dwFileDateMS;
        public uint dwFileDateLS;
    }

    #endregion

    /// <summary>
    /// Given any COM interface, returns the full path of the DLL hosting it.
    /// Works for both regsvr32-registered and registration-free (manifest) COM.
    /// </summary>
    public static string GetComDllPath(object comObject)
    {
        if (comObject == null)
            throw new ArgumentNullException(nameof(comObject));

        // Get a raw COM interface pointer (AddRef is called automatically)
        IntPtr pUnk = Marshal.GetIUnknownForObject(comObject);
        try
        {
            // Read the vtable pointer (first pointer-sized slot of the object)
            IntPtr vTable = Marshal.ReadIntPtr(pUnk);

            // Read the first vtable entry (QueryInterface) — any address
            // inside the DLL is sufficient to identify the module
            IntPtr fnPtr = Marshal.ReadIntPtr(vTable);

            // Ask Windows which module owns that code address
            var mbi = new MEMORY_BASIC_INFORMATION();
            if (VirtualQuery(fnPtr, ref mbi, Marshal.SizeOf(mbi)) == 0)
                throw new InvalidOperationException(
                    "VirtualQuery failed: " + Marshal.GetLastWin32Error());

            var sb = new StringBuilder(260);
            if (GetModuleFileName(mbi.AllocationBase, sb, sb.Capacity) == 0)
                throw new InvalidOperationException(
                    "GetModuleFileName failed: " + Marshal.GetLastWin32Error());

            return sb.ToString();
        }
        finally
        {
            // Balance the AddRef from GetIUnknownForObject
            Marshal.Release(pUnk);
        }
    }

    /// <summary>
    /// Reads the FileVersion from the Win32 version resource of any file.
    /// Returns a Version object (Major.Minor.Build.Revision).
    /// </summary>
    public static Version GetDllFileVersion(string filePath)
    {
        if (string.IsNullOrEmpty(filePath))
            throw new ArgumentNullException(nameof(filePath));

        int size = GetFileVersionInfoSize(filePath, out _);
        if (size == 0)
            throw new InvalidOperationException(
                $"GetFileVersionInfoSize failed for: {filePath}");

        byte[] buf = new byte[size];
        if (!GetFileVersionInfo(filePath, 0, size, buf))
            throw new InvalidOperationException(
                $"GetFileVersionInfo failed for: {filePath}");

        if (!VerQueryValue(buf, @"\", out IntPtr pInfo, out uint len))
            throw new InvalidOperationException("VerQueryValue failed.");

        var info = Marshal.PtrToStructure<VS_FIXEDFILEINFO>(pInfo);

        return new Version(
            (int)((info.dwFileVersionMS >> 16) & 0xFFFF),  // Major
            (int)( info.dwFileVersionMS        & 0xFFFF),  // Minor
            (int)((info.dwFileVersionLS >> 16) & 0xFFFF),  // Build
            (int)( info.dwFileVersionLS        & 0xFFFF)   // Revision
        );
    }
}
C# usage:

Code: Select all

// Create your COM object however you normally would
var comObj = new YourComObject();   // or Activator.CreateInstance(type)

string path    = ComDllInfo.GetComDllPath(comObj);
Version ver    = ComDllInfo.GetDllFileVersion(path);

Console.WriteLine($"DLL Path : {path}");
Console.WriteLine($"Version  : {ver}");
-žarko
User avatar
Sean - PDF-XChange
Site Admin
Posts: 1032
Joined: Wed Sep 14, 2016 5:42 pm

Re: Get Version from SDK - like "10.8.5.410"

Post by Sean - PDF-XChange »

That's great zarkogajic, thank you kindly.

Best regards,
Sean Godley
Technical Writer
PDF-XChange Co LTD
Sales: +1 (250) 324-1621
Fax: +1 (250) 324-1623