I have C# windows form project on VS2013.
my graphic support by MFC C++ project through dll.
when I use 32 bit dll and 32bit C# project it's work fine.
but when use 64bit dll and 64bit C# project only work with .net framework 4 client profile and not work on .net framework 4.5 and get access violation error when use dll.
code that throw access violation error on C++ dll.
BOOL ImportElevation( CString &csFileName )
{
CString csTmpPath = GetTempFolderName(csFileName.GetBuffer());
int iResult = vtCreateDir(csTmpPath);
if (iResult == 0 && errno != EEXIST)
{
MessageBox(NULL,_T("Couldn't create temporary directory to hold contents of archive."),
_T("Error"),MB_ICONERROR);
return FALSE; // no layers created
}
CString csUnzipPath = csTmpPath + _T("/");
iResult = ExpandZip(csFileName, csUnzipPath, ProgressCallback);
if (iResult == 1)
{
// the archive contained a single file
std::string strPathName = (const char *) csUnzipPath;
for (dir_iter it(strPathName); it != dir_iter(); ++it)//at this line throw exception
{
if (it.is_directory())
continue;
csUnzipPath += it.filename().c_str();
break;
}
CElevLayer* pLayer = new CElevLayer(csFileName);
if(pLayer->ImportElevation(csUnzipPath,TRUE,ProgressCallback))
{
m_vecElevLayer.push_back(pLayer);
m_iActiveLayerIdx = m_vecElevLayer.size()-1;
pLayer->CreateMap(ProgressCallback);
return TRUE;
}
else
SAFE_DELETE(pLayer);
return FALSE;
}
// clean up after ourselves
csTmpPath = GetTempFolderName(csUnzipPath);
vtDestroyDir(csTmpPath);
return TRUE;
}
I run this dll on 3 different projects and get this error.
Related
I read a lot of stackoverflow post, but there was no solution for my problem.
I want to get the version number of the running Windows 10 installation (e.g. 1809 or 1909) in C# or WinJS
I develop an UWP app with Cordova (Javascript) and I have also a Cordova plugin (winmd) in C# which I can use, but there is no api to get this 4 digit version number.
I have a WinJS/Javascript code which was working fine till version 1903:
var ApiInformation = Windows.Foundation.Metadata.ApiInformation;
if (ApiInformation.isApiContractPresent("Windows.Foundation.UniversalApiContract", 9)) {
return 9999; // TODO: fix this build number, when it is released
} else if (ApiInformation.isApiContractPresent("Windows.Foundation.UniversalApiContract", 8)) {
return 1903;
} else if (ApiInformation.isApiContractPresent("Windows.Foundation.UniversalApiContract", 7)) {
return 1809;
} else if (ApiInformation.isApiContractPresent("Windows.Foundation.UniversalApiContract", 6)) {
return 1803;
} else if (ApiInformation.isApiContractPresent("Windows.Foundation.UniversalApiContract", 5)) {
return 1709
} else if (ApiInformation.isApiContractPresent("Windows.Foundation.UniversalApiContract", 4)) {
return 1703;
} else if (ApiInformation.isApiContractPresent("Windows.Foundation.UniversalApiContract", 3)) {
return 1607;
} else if (ApiInformation.isApiContractPresent("Windows.Foundation.UniversalApiContract", 2)) {
return 1511;
} else if (ApiInformation.isApiContractPresent("Windows.Foundation.UniversalApiContract", 1)) {
return 1507;
} else {
return 0;
}
But because Windows 10 1909 is only a bugfix version with no own SDK, there is also no new UniversalApiContract version. So on a Windows 1909 installation the check for UniversalApiContract "9" returns "false" and so it returns "1903" instead "1909".
Are there some developers out there, who find out something in version 1909, which is new or unique to 1909, so we can check for this and say that this is version 1909?
Important: I am developing an UWP app and Windows has a sandbox concept for UWP apps, so there are some limitations, e.g. UWP apps cannot access the registry or the whole filesystem.
[UPDATE]
Thanks Peter! It works now.
I use it in UWP Cordova WinJS/Javascript with this code:
var v = Windows.System.Profile.AnalyticsInfo.versionInfo.deviceFamilyVersion;
var major = (v & 0xFFFF000000000000) >> 48;
var minor = (v & 0x0000FFFF00000000) >> 32;
var build = (v & 0x00000000FFFF0000) >> 16;
var release = v & 0x000000000000FFFF;
if (build == 18363)
return 1909;
if (build == 18362)
return 1903;
I had to use Windows.System.Profile.AnalyticsInfo.versionInfo.deviceFamilyVersion, because Windows.System.Profile.AnalyticsVersionInfo.deviceFamilyVersion was "undefined" with the hint "Permission denied"? But the code above works.
You can use AnalyticsInfo.VersionInfo.DeviceFamilyVersion to get the version number.
The property is a string which contains some digits. Parse the string into a 32-bit number, and then each byte of that 32-bit number forms part of a standard A.B.C.D version.
It looks like most of the information is available from Environment.OSVersion, except for the release number. Adapting technique from the other answers and combining, you can do this:
using System;
using Windows.System.Profile;
public static Version GetWindowsVersion()
{
var v = Environment.OSVersion.Version;
var release = (int) ulong.Parse(AnalyticsInfo.VersionInfo.DeviceFamilyVersion) & 0xffff;
return new Version(v.Major, v.Minor, v.Build, release);
}
I have two project, say named CPPDLLProject and CSharpProject.
Here in CPPDLLProject, there are few dllexport functions which can be called from CSharpProject and that calling is working fine.
But here I want to call CSharpProject's functions from CPPDLLProject so that can propagate data from C++ DLL to C# project.
Just for more explanation, Would like to add below code example.
Below is the function in the C++ DLL from which would like to call C# functions.
void __stdcall CPPDLLApp::PumpMessageData(int aCode, int aType)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (aCode == PUMP_UPDATE_MSG && aData != NULL)
{
switch (aType)
{
case MSG_ADD:
{
// Call the C# function to send the added msg to C# project
GetCPPDLLAppMsg("MSG added");
break;
}
case MSG_DELETE:
{
// Call the C# function to send the deleted msg to C# project
GetCPPDLLAppMsg("MSG deleted");
break;
}
case MSG_UPDATE:
{
// Call the C# function to send the updated msg to C# project
GetCPPDLLAppMsg("MSG updated");
break;
}
}
}
if (aCode == PUMP_STOP_MSG)
{
// Call the C# function to send the stop msg to C# project
break;
}
if (aCode == PUMP_START_MSG)
{
// Call the C# function to send the start msg to C# project
break;
}
}
Below is the C# project's function.
public void GetCPPDLLAppMsg(string aMessage)
{
Console.WriteLine(aMessage);
}
Please suggest how to achieve this goal.
I have done few googling but no luck.
My question might not be clear but any kind of help is appreciated.
I don't really understand your question, but you can use a intermediate dll and the following C++ method:
void *p = (void *)wglGetProcAddress(name);
if (p == 0 ||
(p == (void*)0x1) || (p == (void*)0x2) || (p == (void*)0x3) ||
(p == (void*)-1))
{
HMODULE module = LoadLibraryA("dllname.dll");
p = (void *)GetProcAddress(module, name);
}
name = name of the function
dllname = name of your dll
with this you will be able to load a dll and get the function pointer to wichever function you need, but you may need to compile a C# dll to use this, you can make a bridge or something
I've downloaded the latest compiled version of FreeImage, then build FreeImageNet wrapper. Put FreeImage.dll and FreeImageNet.dll on the same folder as my executable (the sample code). But everytime I run it, it says freeimage.dll is missing. I modified the code on FreeImageWrapper.cs and remove the exception handler
public static bool IsAvailable()
{
/*try
{*/
// Call a static fast executing function
Version nativeVersion = new Version(GetVersion());
Version wrapperVersion = GetWrapperVersion();
// No exception thrown, the library seems to be present
return
(nativeVersion.Major > wrapperVersion.Major) ||
((nativeVersion.Major == wrapperVersion.Major) && (nativeVersion.Minor > wrapperVersion.Minor)) ||
((nativeVersion.Major == wrapperVersion.Major) && (nativeVersion.Minor == wrapperVersion.Minor) && (nativeVersion.Build >= wrapperVersion.Build));
}
/*catch (DllNotFoundException)
{
return false;
}
catch (EntryPointNotFoundException)
{
return false;
}
catch (BadImageFormatException)
{
return false;
}*/
}
It always throws BadImageFormatException. It seems the problem is on the native dll (freeimage.dll) ?
How do I fix it ?
Thanks in advance.
I'm using Visual C# 2010 Express
This happens very often if you try to load a unmanaged 32bit dll into a 64bit process. To get around this problem open the properties of your startup project and change under Built - PlatformTarget the type from Any CPU to x86.
I am trying to host CLR in my native Win32 C++ application.
CLR loading works okay, but when i try to execute a method in the assembly, then ExecuteInDefaultAppDomain returns 0x8013101B, and bails out.
Here is the code snippet:
// Managed Code
namespace ManagedLibrary
{
public class LibraryBootstrapper
{
static LibraryBootstrapper()
{
MessageBox.Show("Static LibraryBootsrapper");
}
public LibraryBootstrapper()
{
}
public static int Initialize(String str)
{
MessageBox.Show("Hi " + str + ", Library Bootsrapped");
return 0;
}
}
// Native Code
int tmain()
{
// Bind to the runtime.
ICLRRuntimeHost *pClrHost = NULL;
HRESULT hrCorBind = CorBindToRuntimeEx(
NULL, // Load the latest CLR version available
L"wks", // Workstation GC ("wks" or "svr" overrides)
0, // No flags needed
CLSID_CLRRuntimeHost,
IID_ICLRRuntimeHost,
(PVOID*)&pClrHost);
// Now, start the CLR.
HRESULT hrStart = pClrHost->Start();
DWORD result = 0;
// Load an assembly and execute a method in it.
HRESULT hrExecute = pClrHost->ExecuteInDefaultAppDomain(L"C:\\KIRAN\\Workspaces\\VS 2010\\HostCLR\\ManagedLibrary\\bin\\Debug\\ManagedLibrary.dll", L"ManagedLibrary.LibraryBootstrapper", L"Initialize", L"Kiran", &result);
//HRESULT hrStop = pClrHost->Stop();
return;
}
I figured it out!
The problem was that the versions of .NET frame that was being referenced by native and managed projects were different. Syncing that up worked.
And, btw, the error code 0x8013101B, corresponds to COR_E_NEWER_RUNTIME (see corerror.h), which helped me figure out the problem.
The error codes are explained here: http://blogs.msdn.com/b/yizhang/archive/2010/12/17/interpreting-hresults-returned-from-net-clr-0x8013xxxx.aspx
How can I programmatically tell in C# if an unmanaged DLL file is x86 or x64?
Refer to the specifications. Here's a basic implementation:
public static MachineType GetDllMachineType (string dllPath)
{
// See http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
// Offset to PE header is always at 0x3C.
// The PE header starts with "PE\0\0" = 0x50 0x45 0x00 0x00,
// followed by a 2-byte machine type field (see the document above for the enum).
//
using (var fs = new FileStream (dllPath, FileMode.Open, FileAccess.Read))
using (var br = new BinaryReader (fs))
{
fs.Seek (0x3c, SeekOrigin.Begin);
Int32 peOffset = br.ReadInt32();
fs.Seek (peOffset, SeekOrigin.Begin);
UInt32 peHead = br.ReadUInt32();
if (peHead != 0x00004550) // "PE\0\0", little-endian
throw new Exception ("Can't find PE header");
return (MachineType)br.ReadUInt16();
}
}
The MachineType enum is defined as:
public enum MachineType : ushort
{
IMAGE_FILE_MACHINE_UNKNOWN = 0x0,
IMAGE_FILE_MACHINE_AM33 = 0x1d3,
IMAGE_FILE_MACHINE_AMD64 = 0x8664,
IMAGE_FILE_MACHINE_ARM = 0x1c0,
IMAGE_FILE_MACHINE_EBC = 0xebc,
IMAGE_FILE_MACHINE_I386 = 0x14c,
IMAGE_FILE_MACHINE_IA64 = 0x200,
IMAGE_FILE_MACHINE_M32R = 0x9041,
IMAGE_FILE_MACHINE_MIPS16 = 0x266,
IMAGE_FILE_MACHINE_MIPSFPU = 0x366,
IMAGE_FILE_MACHINE_MIPSFPU16 = 0x466,
IMAGE_FILE_MACHINE_POWERPC = 0x1f0,
IMAGE_FILE_MACHINE_POWERPCFP = 0x1f1,
IMAGE_FILE_MACHINE_R4000 = 0x166,
IMAGE_FILE_MACHINE_SH3 = 0x1a2,
IMAGE_FILE_MACHINE_SH3DSP = 0x1a3,
IMAGE_FILE_MACHINE_SH4 = 0x1a6,
IMAGE_FILE_MACHINE_SH5 = 0x1a8,
IMAGE_FILE_MACHINE_THUMB = 0x1c2,
IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169,
IMAGE_FILE_MACHINE_ARM64 = 0xaa64
}
I only needed three of these, but I included them all for completeness. Final 64-bit check:
// Returns true if the dll is 64-bit, false if 32-bit, and null if unknown
public static bool? UnmanagedDllIs64Bit(string dllPath)
{
switch (GetDllMachineType(dllPath))
{
case MachineType.IMAGE_FILE_MACHINE_AMD64:
case MachineType.IMAGE_FILE_MACHINE_IA64:
return true;
case MachineType.IMAGE_FILE_MACHINE_I386:
return false;
default:
return null;
}
}
Using a Visual Studio command prompt, dumpbin /headers dllname.dll works too. On my machine the beginning of the output stated:
FILE HEADER VALUES
8664 machine (x64)
5 number of sections
47591774 time date stamp Fri Dec 07 03:50:44 2007
Even easier: check out the System.Reflection.Module class. It includes the GetPEKind method, which returns 2 enums that describe the type of code and the CPU target. No more hex!
(the rest of this very informative post was copied shamelessly from http://www.developersdex.com/vb/message.asp?p=2924&r=6413567)
Sample code:
Assembly assembly = Assembly.ReflectionOnlyLoadFrom(#"<assembly Path>");
PortableExecutableKinds kinds;
ImageFileMachine imgFileMachine;
assembly.ManifestModule.GetPEKind(out kinds, out imgFileMachine);
PortableExecutableKinds can be used to check what kind of the assembly. It
has 5 values:
ILOnly: The executable contains only Microsoft intermediate language
(MSIL), and is therefore neutral with respect to 32-bit or 64-bit
platforms.
NotAPortableExecutableImage: The file is not in portable executable (PE)
file format.
PE32Plus: The executable requires a 64-bit platform.
Required32Bit: The executable can be run on a 32-bit platform, or in the
32-bit Windows on Windows (WOW) environment on a 64-bit platform.
Unmanaged32Bit: The executable contains pure unmanaged code.
Following are the links:
Module.GetPEKind Method:
http://msdn.microsoft.com/en-us/library/system.reflection.module.getpekind.aspx
PortableExecutableKinds Enumeration:
http://msdn.microsoft.com/en-us/library/system.reflection.portableexecutablekinds(VS.80).aspx
ImageFileMachine Enumeration:
http://msdn.microsoft.com/en-us/library/system.reflection.imagefilemachine.aspx
Instead of Assembly.LoadFile, use Assembly.ReflectionOnlyLoadFrom. This will let you work around the "Bad Image Format" exceptions.
I know it has been a while since this was updated. I was able to get away with the "Bad Image Format" exceptions by loading the file into it's own AppDomain.
private static (string pkName, string imName) FindPEKind(string filename)
{
// some files, especially if loaded into memory
// can cause errors. Thus, load into their own appdomain
AppDomain tempDomain = AppDomain.CreateDomain(Guid.NewGuid().ToString());
PEWorkerClass remoteWorker =
(PEWorkerClass)tempDomain.CreateInstanceAndUnwrap(
typeof(PEWorkerClass).Assembly.FullName,
typeof(PEWorkerClass).FullName);
(string pkName, string imName) = remoteWorker.TryReflectionOnlyLoadFrom_GetManagedType(filename);
AppDomain.Unload(tempDomain);
return (pkName, imName);
}
At this point, I do the following:
public (string pkName, string imName) TryReflectionOnlyLoadFrom_GetManagedType(string fileName)
{
string pkName;
string imName;
try
{
Assembly assembly = Assembly.ReflectionOnlyLoadFrom(assemblyFile: fileName);
assembly.ManifestModule.GetPEKind(
peKind: out PortableExecutableKinds peKind,
machine: out ImageFileMachine imageFileMachine);
// Any CPU builds are reported as 32bit.
// 32bit builds will have more value for PortableExecutableKinds
if (peKind == PortableExecutableKinds.ILOnly && imageFileMachine == ImageFileMachine.I386)
{
pkName = "AnyCPU";
imName = "";
}
else
{
PortableExecutableKindsNames.TryGetValue(
key: peKind,
value: out pkName);
if (string.IsNullOrEmpty(value: pkName))
{
pkName = "*** ERROR ***";
}
ImageFileMachineNames.TryGetValue(
key: imageFileMachine,
value: out imName);
if (string.IsNullOrEmpty(value: pkName))
{
imName = "*** ERROR ***";
}
}
return (pkName, imName);
}
catch (Exception ex)
{
return (ExceptionHelper(ex), "");
}
}
Running this against my Widows\Assembly directory gives me zero errors with over 3600 files processed.
note: I use a dictionary to load the values being returned.
I hope it helps. YMMV