I'm having trouble calling unmanaged dll function from the windows win32 apis.
I've tried many ways, but the following was my first and what I think should work.

using System.Diagnostics;
using System.Runtime.InteropServices;

namespace Win32DllImports
{
    class Program
    {
        [DllImport("Urlmon", 
            EntryPoint = "ObtainUserAgentString",
            CallingConvention = CallingConvention.StdCall,
            CharSet = CharSet.Ansi)]
        private static extern uint ObtainUserAgentString(uint dwOption, 
            char[] userAgent, ref 
            uint length);

        static void Main(string[] args)
        {
            char[] buffer = new char[512];
            uint size = new uint();

            uint rtn = ObtainUserAgentString(0, buffer, ref size);

            string frombuffer = new string(buffer);
            Debug.WriteLine(rtn); // 2147942414 (E_OUTOFMEMORY)
            Debug.WriteLine(frombuffer); // prints nothing, not even new line char
            Debug.WriteLine(size); // 156
        }
    }
}

Of course it does not work, the comments show what the results are, an out of memory error, buffer not filled with what should be a 70 char user agent string.

Can anyone see what I'm doing wrong?

Recommended Answers

All 2 Replies

Really not my strong suit but I would try dumbing down the dllimport see if it works with the bare minimum.

So, removing the entrypoint since you arent renaming it anyways,
not specifying the char set, or using CharSet = CharSet.Auto.

The wrapper I am using for PCSC communication with a smartcard also uses in/out attributes perhaps try that on your "ref" parameter?

[DllImport(WINSCARD_DLL, CharSet = CharSet.Auto)]
        private static extern int SCardTransmit(
            [In] IntPtr hCard,
            [In] IntPtr pioSendPci,
            [In] byte[] pbSendBuffer,
            [In] int cbSendLength,
            [In, Out] IntPtr pioRecvPci,
            [Out] byte[] pbRecvBuffer,
            [In, Out] ref int pcbRecvLength);

Again, I understand it's not much of a lead but figured it was better than radio silence right? :)
Good luck!

Thank's.
I got it in the end.

Here it is for reference...

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace Win32DllImports
{
    class Program
    {
        [DllImport("urlmon", CharSet = CharSet.Ansi)]
        private static extern uint ObtainUserAgentString(uint dwOption, IntPtr szUAOut, ref uint dwSize);

        static void Main(string[] args)
        {

            Debug.WriteLine(GetCurrentUserAgent());

        }

        public static string GetCurrentUserAgent()
        {
            int ibufferlength = 512;
            IntPtr pUserAgent = Marshal.AllocHGlobal(ibufferlength);
            uint iDataSize = (uint)ibufferlength;

            ObtainUserAgentString(0, pUserAgent, ref iDataSize);

            string sUserAgent = Marshal.PtrToStringAnsi(pUserAgent);
            Marshal.FreeHGlobal(pUserAgent);

            return sUserAgent;
        }

    }
}
commented: Great! Glad you worked it out :) +5
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.