2

I've been using some code I've found on the net to query the GAC using the fusion.dll however I've recently been getting a few error reports back complaining of an OverflowException.

    // If assemblyName is not fully qualified, a random matching may be returned!!!!
    public static String QueryAssemblyInfo(String assemblyName)
    {
        ASSEMBLY_INFO assembyInfo = new ASSEMBLY_INFO();
        assembyInfo.cchBuf = 512;
        assembyInfo.currentAssemblyPath = new String('\0',
        assembyInfo.cchBuf);
        IAssemblyCache assemblyCache = null;
        // Get IAssemblyCache pointer
        IntPtr hr = GacApi.CreateAssemblyCache(out assemblyCache, 0);
        if (hr == IntPtr.Zero)
        {
            hr = assemblyCache.QueryAssemblyInfo(1, assemblyName, ref assembyInfo);
            if (hr != IntPtr.Zero)
                Marshal.ThrowExceptionForHR(hr.ToInt32());
        }
        else
            Marshal.ThrowExceptionForHR(hr.ToInt32());
        return assembyInfo.currentAssemblyPath;
    }

The offending code is when its trying to convert the IntPtr to a Int32 when its actually an Int64, but the problem is the Marshal.ThrowExceptionForHR only accepts an Int32 so I'm a bit stuck for what to do. At the moment I'm just handling the exception but I'd like to know what is the correct way of doing it?

Marlon

Marlon
  • 2,129
  • 3
  • 21
  • 40

2 Answers2

5

Check the signature on your DllImport for CreateAssemblyCache. It looks like it should be int, not IntPtr

[DllImport("fusion.dll")]
internal static extern int CreateAssemblyCache(
    out IAssemblyCache ppAsmCache, int reserved);
Phil Hunt
  • 8,404
  • 1
  • 30
  • 25
  • 2
    thanks, I've just checked the definitions of both the Create and Query methods and your correct they both return ints. – Marlon Dec 09 '10 at 17:27
4

Why are you using an IntPtr to hold the value of an HRESULT? The size of an HRESULT is not platform dependent, it is always 32 bits, so you should use either int or uint to hold the value. Change the code to use one of these instead, and the problem will go away.

Greg Beech
  • 133,383
  • 43
  • 204
  • 250
  • assemblyCache.QueryAssemblyInfo() returns an IntPtr. My basic type knowledge is rusty, if I convert it to an uInt would that mean I'll have twice the range (positive) and it wont overflow? -- Just tried, unfortunately the Marshal method expects an Int32 – Marlon Dec 09 '10 at 17:12
  • @Marlon - that's my point; it shouldn't because that's the wrong type to represent an HRESULT. You should change it so it is correct. – Greg Beech Dec 09 '10 at 17:13
  • sorry for being slow, its late in the day - I can change the interface to return a int32, that's fine. But wouldn't that still overflow as the COM object I'm interacting with is returning something that a int32 can't store. – Marlon Dec 09 '10 at 17:19
  • The result values of these methods are HRESULTs, which are 32 bit values. They can be stored in a 32 bit integer (int or uint) without any problem. – Greg Beech Dec 09 '10 at 17:25
  • just checked the msdn docs and it is indeed returning an int, no idea why it would be returning a value greater than what a int can handle but I guess I'll soon find out if it still isn't working – Marlon Dec 09 '10 at 17:27
  • The reason would most likely be that you're running on a 64-bit platform, and thus attempting to initialize a 64 bit IntPtr with the 32 bit return value from the P/Invoke method. I'm amazed it actually runs at all to be honest, but the net result will be that the contents of the IntPtr are most likely garbage. – Greg Beech Dec 09 '10 at 17:30