Feeds:
Posts
Comments

Archive for the ‘Visual Studio’ Category

After I added a Split Page to a Windows Store app that was created with the Blank App template, I got the error mentioned in the title whenever I opened the xaml file of the split page.

I got rid of it by deleting the .suo file of the Visual Studio solution.

 

Advertisements

Read Full Post »

In one of my applications, I need to use some DLLs. There may be several versions of those DLLs installed in different directories, and I need to dynamically decide which version of the DLLs to be loaded (assuming that all versions of the DLLs export the same functions, interfaces, and/or classes). What should I do?

For the DLLs that export simple C functions, I can call LoadLibrary() to load them by specifying the full path of the DLLs and then call GetProcAddress() to get the addresses of the functions I want to call. What if I want to use the exported classes of the DLL?

It would be very tedious to get the addresses of the methods of the exported classes by calling GetProcAddress() by ourselves. Fortunately, Visual Studio allows us to specify which DLLs to be delay loaded. The delay loaded DLLs won’t be loaded when the application starts up. Rather, they will be loaded just before the first function of the DLL is called. This is done automatically by the “delay loaded DLLs” feature, which load the DLLs by calling LoadLibrary() and GetProcAddress() for us.

But how do we control from which directory the DLLs should be loaded? The answer is: before any function of the DLLs is called, call SetDllDirectory() by passing the directory from where you want the DLLs to be loaded.

Read Full Post »

In one of my C++/CLI projects, I need to use a class exported from a unmanaged DLL. When I build the C++/CLI project, I get two linking errors: LNK2028 and LNK2029. The linker cannot find the GetObject() method of a class.

First, I made sure that the export library of the unmanaged DLL was linked with the managed DLL.

Then I used the dumpbin tool to dump the exports of the unamanged DLL, I found that the GetObject() method was renamed as GetObjectW(), and the linker tries to look for GetObject() when linking the managed project, hence the errors.

We know that Microsoft implemented two sets of Win32 functions, one set for ANSI with the function names postfixed with A, one set for Unicode with function names postfixed with W. We call the functions without specifying which version we want to use, the compiler will figure it out depending on whether the UNICODE macro is defined. Here is an example (copied from wingdi.h)

WINGDIAPI int   WINAPI GetObjectA(__in HANDLE h, __in int c,
        __out_bcount_opt(c) LPVOID pv);
WINGDIAPI int   WINAPI GetObjectW(__in HANDLE h, __in int c,
        __out_bcount_opt(c) LPVOID pv);
#ifdef UNICODE
#define GetObject  GetObjectW
#else
#define GetObject  GetObjectA
#endif // !UNICODE
#if defined(_M_CEE)
#undef GetObject
__inline
int
GetObject(
    HANDLE h,
    int c,
    LPVOID pv
    )
{
#ifdef UNICODE
    return GetObjectW(
#else
    return GetObjectA(
#endif
        h,
        c,
        pv
        );
}
#endif  /* _M_CEE */

If the UNICODE macro is defined, GetObject will be replaced with GetObjectW regardless whether it is used as a member method name or a function name. That is why the GetObject() method gets renamed as GetObjectW.

However, when compiling a C++/CLI project, the _M_CEE macro is defined, causing the GetObject macro to be undefined, and an inline function GetObject() defined. And that is why the linker looks for GetObject() instead of GetObjectW().

There isn’t a clean solution when you have a method whose name conflicts with a Win32 function. You can use the push_macro/pop_macro directives to temporarily undefine the macro defined for the Win32 function, to prevent the method name from being changed:

class __declspec (dllexport) UnmanagedClass
{
public:

#pragma push_macro("GetObject")
#undef GetObject
	std::wstring GetObject();
#pragma pop_macro("GetObject")

	void CallGetObject();
};

The problem is whenever you want to call this method in a unmanaged project, you have to undefine the macro, making the code quite messy.

To avoid these kind of linking errors in C++/CLI projects, 1) make sure the export library of unmanaged DLLs are added to the C++/CLI projects, 2) avoid naming a method with the same name of a Win32 system function.

Here is the code that I used to reproduce the issue.

1. The header file of the unamanged class.

#pragma once

#include "string"

class __declspec (dllexport) UnmanagedClass
{
public:

#pragma push_macro("GetObject")
#undef GetObject
	std::wstring GetObject();
#pragma pop_macro("GetObject")

	void CallGetObject();
};

2. The cpp file of the unmanaged class.

#include "stdafx.h"

#include "UnmanagedClass.h"

#pragma push_macro("GetObject")
#undef GetObject

std::wstring UnmanagedClass::GetObject()
{
	return L"GetObject() is called";
}

void UnmanagedClass::CallGetObject()
{
	// The GetObject macro must remain to be undefined here.
	this->GetObject();
}

#pragma pop_macro("GetObject")

3. The cpp file in the managed project that calls the UnmangedClass::GetObject() method.

UnmanagedClass uc;
std::wstring str = uc.GetObject();

String^ mstr = System::Runtime::InteropServices::Marshal::PtrToStringAuto(
		System::IntPtr::IntPtr((void*)str.c_str()));

Console::WriteLine(mstr);

Read Full Post »

Just published an article on the CodeProject Web site about the design of the Mastermind game I wrote. You can get the latest source code from http://code.google.com/p/mobilemastermind/.

Mastermind For Windows Mobile

Mastermind For Windows Mobile

Read Full Post »

I am developing a tool in C# with Visual Studio 2008. There are two C# files that are generated based on some data files, which are also used at runtime. There are multiple sets of the data files, each of them stored in in different folder. For different purpose, I need to use the data files from different folder. A data file, once defined, will never be changed or removed. When a data file needs to be changed, a new revision of it will be created and co-exist with the older ones. So if the number of files of two folders are different, we can safely say that the two sets of data files are different.

So, how can we automate the build process of the project?

First, I create an environment variable, XXX_DataFiles, indicating the folder of the data files. We can then use this variable in the project settings. When we want to use the data files from another folder, we can simply change the value of the environment variable, without having to change the project settings.

In the Build Event tab of the project properties dialog, I add the script something as follows:

echo OFF

IF NOT EXIST "$(SolutionDir)$(ProjectName)\A.cs" GOTO generate
IF NOT EXIST "$(SolutionDir)$(ProjectName)\B.cs" GOTO generate

for /F %%j in ('dir /A /B "$(TargetDir)Data\*.dat" ^| find /C /V ""') do set Count1=%%j

for /F %%j in ('dir /A /B "$(XXX_DataFiles)*.dat" ^| find /C /V ""') do set Count2=%%j

if %Count1% == %Count2% GOTO end

:generate

IF EXIST "$(TargetDir)Data" GOTO start_del

mkdir  "$(TargetDir)Data"
GOTO start_copy

:start_del
del /Q "$(TargetDir)Data\*.*"

:start_copy
xcopy "$(XXX_DataFiles)*.dat" "$(TargetDir)Data" /Q

MyCodeGenerator "$(TargetDir)Data" "$(SolutionDir)$(ProjectName)"

:end

First, if any of the generated C# files doesn’t exist, we go ahead to the generate. If both of them exist, we check whether the target folder and source folder of the data files have the same number of files. If the numbers are the same, we terminate the process. Otherwise, we create the target folder if it doesn’t exist yet and start copy the files. If the target folder exists, we delete all files inside the folder and copy data files from the source folder. Finally we invoke the MyCodeGenerator to generate the two C# files.

The script

for /F %%j in ('dir /A /B "$(TargetDir)Data\*.dat" ^| find /C /V ""') do set Count1=%%j

finds the number of .dat files in the “$(TargetDir)Data” folder and saves the number in the Count1 environment variable.

Read Full Post »

I am writing a small compiler using ANTLR 3.0. When I debug it, I get numerous first chance exceptions. With each exception, a messages is displayed in the Output window and the program breaks into the source code, which becomes quite annoying and time-consuming. The exceptions are thrown and handled by ANTLR to detect which branch of the lexer or parse rule to proceed. In most cases, I don’t need to worry about them.

How can I get rid of the messages and prevent the control from breaking into the code?

To get rid of the messages while debugging, right click in the Output window, and in the context menu, uncheck in the menu item “Exception Messages”.

Context Menu of Popup Window

Context Menu of Popup Window

To prevent the control from breaking into the source code when an exception  is thrown, open the Exceptions dialog by selecting the Debug – Exceptions menu item, add the exception types to the Exceptions dialog, make sure the Thrown and User-unhandled flags for the exceptions are unchecked. In the screen shot below, two exceptions that are thrown by ANTLR are added under the Common Language Runtime Exceptions.

Exceptions Dialog

Exceptions Dialog

Read Full Post »