Can`t Load C++/CLI DLL resources - resources

I'm trying just to see resource names but nothing appears.
I've made and compiled a C++/CLI (Managed) DLL in Visual Studio 2010 and added some Resource files as a test (one icon and one bitmap). I've checked with PE Explorer and the resources definitely are there.
My simple code:
Assembly asm = Assembly.LoadFrom("C:\\test.dll");
String[] res = asm.GetManifestResourceNames();
I know that the DLL is loaded because when I debug i can see all the infos in the 'asm' variable. Also i can Import data (using MEF) from the DLL.
So, the DLL has the resources and the code IS loading the assembly for sure. But why my 'res' variable always returns empty string list?
EDIT:
I've created a C# Class Library (.dll) with a resource just for a test. Now it works!! But still in my C++/CLI DLL the resources do not appear. Somehow they are in the DLL but the code cant reach it (only in the C++ DLL). Maybe it would have something to do with managed/unmanaged code, but since i'm compiling it with CLR it does not seem to be the case. Any suggestions?
SOLUTION
I've got it! Just in case someone needs.
According to these topics:
Embedding resource in a C++/CLI project
and
http://bytes.com/topic/net/answers/571530-loading-markup-xamlreader-load-resource-file#post2240705
the problem is exactly the C++/CLI thing. You have to add it in Input item under Linker tab in Project Properties. Now it seems to work fine. Thanks

I have a similar problem and your question helps me to solve it.
my project platform is C++/CLI and my DLL platform is c#.
I want to pack DLL into my executive file, hence we should put DLL in the project resource file through below steps at first:
1.copy DLL in project path.
2.put DLL name(e.g. test.dll) in below place
properties->linker->input->Embeded Managed Resource File
then we should read and use embedded DLL:
Stream^ stream = Assembly::GetExecutingAssembly()->GetManifestResourceStream("test.dll");
array<unsigned char>^ dllRawBuffer = gcnew array<unsigned char>(stream->Length);
int res = stream->Read(dllRawBuffer, 0, stream->Length);
stream->Close();
Assembly^ dllAssembly = Assembly::Load(dllRawBuffer);
System::Type^ testclass = dllAssembly->GetType("TestNamespace.TestClass");
MethodInfo^ TestMethod = testclass->GetMethod("TestMethodName");
// Create an instance.
Object^ Testobj = Activator::CreateInstance(testclass);
// Execute the method.
array<Object^>^ params = gcnew array<Object^>(2);
params[0] = 2;
params[1] = 3;
Object^ result = TestMethod->Invoke(Testobj, params);
obviously, this solution only works for managed DLLs.

Related

Why cannot I use CString as return types or parameters in a MFC DLL made for windows CE?

I have got a library which was made for a desktop windows project. It is done in MFC VC++ by somebody else, and it works correctly. I will use one particular function from the library as an example for explaining the situation.
The example function goes like this:
CString GetFulPath(); // .h file
In the cpp file,
CString CwFolderBrowser::GetFullPath()
{
CString path;
if(this->M_pIDLIST!=NULL)
{
LPTSTR fullPath=path.GetBuffer(MAX_PATH);
::SHGetPathFromIDList(this->M_pIDLIST, fullPath); //ITEMIDLISTからパスを得る
path.ReleaseBuffer();
}
return path;
}
Now, I can include this library in my project and do something like:
CwFolderBrowser cFolderBrowser;
if(cFolderBrowser.ShowDialog() == TRUE)
cPath = cFolderBrowser.GetFullPath();
This will show a folder browser dialog and let me choose a folder. It works fine on desktop windows.
Currently, I am working on Windows CE device. We have converted the library for use with Windows CE by removing unsupported functions and stuff. The library compiles and builds correctly without errors.
Next, I create an MFC Smart Device project, include the converted library, its h file and lib files and set the proper directories for dlls. The project builds fine. I can #include the library's h file properly too.
The problem arises as soon as I call the GetFullPath function:
cPath = cFolderBrowser.GetFullPath();
It gives me an unresolved external link error! The Intellisense does show this function in its list and I can choose it and everything. But in vain.
Strangely, If I modify the library and change GetFullPath()'s signature as below,
LPCTSTR GetFulPath(); // .h file LPCTSTR instead of CString
In the cpp file,
LPCTSTR CwFolderBrowser::GetFullPath() // Return type changed to LPCTSTR
{ // instead of CString
... // Body modified accordingly
}
then, the unresolved external Link error disappears and it works!
I am stumped about this strange behaviour, because, I can use CString normally in the MFC Smart Device project and there are no errors. The link error shows up only when I try to call functions from the library (and other such libraries) dll. At the same time, BOOL, int etc. seems to have no problems as function return types.
Ofcourse, I can go through each library and change every instanceof a CString return to LPCTSTR, but that would be a very big change. I would like to know why CString works fine in project as well as dll when on desktop, while, on Win CE, it works in the project but not i the DLL (At the same time, the DLL itself compiles fine without errors wether it uses CString or LPCTSTR!).
So, basically, I would like to keep the function CString if possible, and would like to know the reason why this happens. The exact same error also happenes in other libraries too.
Any help is appreciated. Thank you.
UPDATE:
I saw a page on ATL & MFC 7.0 which said about using the /Zc:wchat_t option. I have checked the Dll project as well as my application. Both use the same option of 'Treat wchar_t as Built-in type' as Yes. So, that option matches up.
Further, as I mentioned above, changing the function return to LPCTSTR works. The error disappears. Everything is going fine until I convert the returned LPCTSTR back to CString. The CString turns out as empty/Null. This happens both inside the dll code itself, as well as in my application code too.
UPDATE2:
Thanks to Michael and Cody, I changed the function to LPCTSTR and made sure that the values were not going out of scope before I could use them like they suggested. Now the empty/Null problem is solved and I can get the path values properly.
The problem that remains is that I have to convert all the CString functions to LPCTSTR, which is not exactly feasible. I would like to keep the functions as CString.
This is a classic problem and has been asked often here on SO.
This cannot work:
LPCTSTR CwFolderBrowser::GetFullPath()
{
CString path;
if(this->M_pIDLIST!=NULL)
{
LPTSTR fullPath=path.GetBuffer(MAX_PATH);
::SHGetPathFromIDList(this->M_pIDLIST, fullPath);
path.ReleaseBuffer();
}
return (LPCTSTR)path; // << here you return a pointer to the zero
// terminated string in the path object,
} // but path will be deleted as soon as it goes
// out of scope
Maybe in some cases the function appears to work because the memory of the deleted CString object has not yet been overwritten.
You should do this (no error treatment here for simplicity):
LPCTSTR CwFolderBrowser::GetFullPath(TCHAR *pathbuffer)
{
if(this->M_pIDLIST!=NULL)
{
::SHGetPathFromIDList(this->M_pIDLIST, pathbuffer);
}
return (LPCTSTR)pathbuffer;
}
...
// call like this
TCHAR pathbuffer[MAX_PATH];
GetFullPath(pathbuffer);

T4 template shadow copy does not work

I'm using VS2012 and T4 templates and assemblies are supposed to be shadow copied, meaning that you can reference an assembly in a template and then recompile that assembly. But this simply doesn't work for me. When I try it, when I try to rebuild the assembly, I get errors like:
Unable to copy file "obj\Debug\xxx.dll" to "..\bin\xxx.dll".
The process cannot access the file '..\bin\xxx.dll' because it is being used by another process.
The only way around it is to restart Visual Studio, and this is so tedious that I'm ready to abandon T4 entirely. What could I be doing wrong?
So this isn't really an answer yet but hopefully we get there
Test ran the following in VS2013 (I realize you run VS2012)
<## assembly name = "$(SolutionDir)\TestProj\bin\Debug\TestProj.dll"#>
<## import namespace = "TestProj"#>
namespace ConsoleApplication1
{
class <#=Testing.Name#>
{
}
}
The TestProj contains the Testing class
namespace TestProj
{
public static class Testing
{
public static string Name
{
get { return "Tester" ;}
}
}
}
This did work very well in VS2013 and as far as I remember this worked in VS2012 as well.I will try to install VS2012 on one of my machines but do you mind testing this simple sample on your installation to validate it's not something in your solution that holds the dll?
In case you are interested in the project file you can find it here:
https://github.com/mrange/CodeStack/tree/master/q21118821
I work around similar issue. T4 design time template is processed in different App domain under the same process of visual studio. When rebuild the solution Visual Studio tries to replace the referenced DLL, and it cannot replace it because it is still in use.
I work around this issue by deleting the AppDomain in which T4 template is processed. See msdn

WPF Designer throws error when string resources are used in code behind

I have a wpf custom control (in AssemblyA) that references a string resource from an resx file in an external assembly (AssemblyB).
public override void OnApplyTemplate()
{
try
{
base.OnApplyTemplate();
// ...
// Do Stuff
// ...
}
catch (Exception ex)
{
Logger.Error(ExceptionCodes.Ex50000, ex);
}
}
When I add the custom control (in AssemblyA) via a dll reference to a page in another project (AssemblyC) in another solution, the control fails to display in the designer. Instead, the designer displays a nice big red cross with the message
FileNotFoundException: Could not load file or assembly 'AssemblyB'.
The AssemblyB was also added as a dll reference to AssemblyC.
Removing the the references to the string resource in AssemblyA removes the error and allows the control to display correctly in the designer. Unfortunately, this is not an option as the string resources are used throughout the application for support reasons.
Creating an resx file in AssemblyA also removes the error but decentralises the resources which is not an option for on going development.
Based on the above, the designer is obviously not loading the resource assembly. Any insights would be appreciated.
To Summarise
CustomControl in Assembly A in Solution 1 references a string resourced from a resx file in Assembly B in Solution 1. Assembly C in Solution 2 has a dll reference to both Assembly A and Assembly B. A UserControl in Assembly C uses CustomControl in Assembly A. The Visual Studio WPF designer throws a FileNotFound exception when displaying the UserControl.
Let it throw error, just check whether your are able to complie and run, the Make the assembly In Solution C as exe and try to run it. Because with Visual studio 10.0.4, i have see that exception many times, but if it is complied it doesn't give any compiler error, just try to compile and run it

Can you force MonoTouch to include an unreferenced assembly in its static compilation?

I have a MonoTouch app that dynamically instantiates a class (using Type.GetType()) at runtime. The class is in an assembly that is not referenced anywhere else in the app, so the MonoTouch static compiler thinks that the assembly isn't used and ignores the assembly when it compiles the app. If I add a reference to the class in the app, then the compiler includes the assembly and the call to Type.GetType() works fine:
MyAssembly a;
I would prefer to just tell the compiler to always include all the assemblies listed in the project's "References" when it compiles the app. Is this possible?
Thanks,
-Tom B.
You will have to change your project's Linker behavior from "Link all assemblies" to "Link SDK assemblies only".
The other solution, if you have the project code that assembly was created with, is to mark the class you want to use with the PreserveAttribute.
Were you able to figure this out yet? If not, I had a similar problem: Is there a way to force MonoDevelop to build/load an assembly?
As I understand it, that's just how the C# compiler works. I was able to get around this by adding a custom pre-build step that scripts a class into the referencing assembly that includes dummy references to the unreferenced assemblies, like so:
using System;
namespace MyNamespace
{
public static class Referencer
{
Type t;
//These lines are scripted one per class in the unreferenced assemblies
//You should only need one per assembly, but I don't think more hurts.
t = typeof(Namespace1.Class1);
t = typeof(Namespace2.Class2);
...
t = typeof(NamespaceN.ClassN);
}
}

Attempt to initialize the CRT more than once

I am using VS2008 to port code from VC6. When I ran the new build app, I get this error "R6031 Attemp to initialize the CRT more than once. This indicates a bug in your application".
There are a total of 21 dlls that are involve in the build this one app. Some DLL has .c files in them and explicitly calls _CRT_INIT() in DllMain. code below:
BOOL APIENTRY DllMain (HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
switch( dwReason)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
if(!_CRT_INIT( hModule, dwReason, lpReserved))
return FALSE;
break;
}
return TRUE;
}
I am not sure how to fix this problem. Do I need to comment out the call to _CRT_INIT()?
Thanks in advance.
Yes, you should not need to call _CRT_INIT() explicitly. It's probably being called by one or another DLLMain.
See MSDN for details.
Edit
I think you have misread MSDN:
When building a DLL which uses any of
the C Run-time libraries, in order to
ensure that the CRT is properly
initialized, either
the initialization function must be named DllMain() and the entry point
must be specified with the linker
option -entry:_DllMainCRTStartup#12 -
or -
You have named the init function DllMain(), so _CRT_INIT() is being called automatically. I think.
Why not simply comment out that line and see what happens?
This error code is specific to mixed-mode assemblies. Have you enabled the CLR during the port by mistake? You should not see this during a simple port from VC6 to a later Visual C++ revision.
This diagnostic indicates that MSIL
instructions were executing during
loader lock. For more information, see
Initialization of Mixed Assemblies.
You can check the project setting by right-clicking the project in Solution Explorer, then under Properties look at Configuration Properties -> General -> Common Language Runtime Support

Resources