MyMSDN

MyMSDN记录开发新知道

2010年9月6日 #

IsWow64并不能用来检测是否是Windows 32bit系统还是64bit系统

如何当前操作系统是不是64位?如何判断当前应用程序是否在Wow64下运行?

首先什么是Wow64?很多朋友一看到64就认为这个方法是判断当前系统是否是64bit的,其实不然。Wow64是Windows-On-Windows64的意思,它是指在64位的操作系统上(不是指64位的CPU)运行32位应用程序的兼容平台。

下面是MSDN中一段IsWow64的应用程序:

BOOL IsWow64() 
{ 
    typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); 
    LPFN_ISWOW64PROCESS fnIsWow64Process; 
    BOOL bIsWow64 = FALSE; 
    fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress( GetModuleHandle(_T("kernel32")), "IsWow64Process"); 
    if (NULL != fnIsWow64Process) 
    {
        fnIsWow64Process(GetCurrentProcess(),&bIsWow64); 
    } 
    return bIsWow64; 
}

下面的代码用来检测这个程序的结果:

if( IsWow64() == TRUE )
{
    _tprintf(_T("IsWow64() == TRUE\n"));
}
else
{
    _tprintf(_T("IsWow64() == FALSE\n"));
}

让我们编译一下这个程序。

我们需要的是64位的操作系统,比如XP64bit,Windows 2008 R2等都是64bit操作系统。

在64位的操作系统上运行的kernel32.dll中,将会实现IsWow64Process方法,而在32位系统中提供的kernel32.dll中则没有提供相关函数的实现。

比较迷惑人的则是bIsWow64,其实仔细看MSDN中的Remark,会发现:

If the application is a 64-bit application running under 64-bit Windows, the Wow64Process parameter is set to FALSE.也就是说64位应用程序跑在64位的操作系统上,bIsWow64的值将是FALSE而不是TRUE。

因此我们需要分别将我们的程序编译成Win32平台和x64平台的,如果你用Visual Studio进行编译,默认安装则只包含32位的编译器/链接器,即便你是在64位操作系统上安装,也是一样的。你需要在VC++节点下勾选x64选项才可以,Itanium则需要在Server平台下安装才可勾选。然后在编译的时候,分别选择Win32和x64进行编译。

image

编译后,运行,结果如我们分析的一样:

在64位系统上运行Win32编译配置的结果是IsWow64() == TRUE,而x64编译配置的结果是IsWow64() == FALSE。

如果想要知道当前系统是否是64位的,则可以通过下面的方法:

BOOL Is64bitSystem()
{
    SYSTEM_INFO si;
    GetNativeSystemInfo(&si);

    if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ||    
        si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64 )
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    } 
}

注意:需要注意是GetNativeSystemInfo  函数从Windows XP 开始才有, 而 IsWow64Process  函数从 Windows XP with SP2 以及 Windows Server 2003 with SP1 开始才有。

posted @ 2010-09-06 02:06 volnet 阅读(901) | 评论 (7)编辑 收藏

2010年9月5日 #

英特尔® 多线程应用开发指南

     摘要: http://software.intel.com/zh-cn/articles/intel-guide-for-developing-multithreaded-applications/ 英特尔® 多线程应用开发指南 提交新文章 Published On :  2010年02月25日 20:00 评级 请登录后评级!当前分数: 0 由 0 用户 请登录后评级!当前分数: 0 ...  阅读全文

posted @ 2010-09-05 02:20 volnet 阅读(51) | 评论 (0)编辑 收藏

2010年9月4日 #

关于宏MAX_PATH与文件名长度的关系

目的:测试MAX_PATH路径与文件名的关系。

结论:MAX_PATH代表从盘符开始到文件名结尾的C字符串长度(长度+1)的最大长度。也就是假设C:\a.txt共8个字符,长度为9,MAX_PATH通常为260,其中这个文件全名的长度不能大于260。

测试代码:

image

#include "stdafx.h"
#include <atlbase.h>
#include <windows.h>
#include <atlfile.h>
#include <atlstr.h>
#include <iostream>
#include <string>

BOOL IsFileExist( LPCTSTR lpszFileName )
{
    DWORD dwAttr = ::GetFileAttributes( lpszFileName );
    if ( dwAttr == 0xFFFFFFFF )
    {
        return FALSE;
    }
    if ( ( dwAttr & FILE_ATTRIBUTE_DIRECTORY ) > 0 )
    {
        return FALSE;
    }
    return TRUE;
}

BOOL DeleteFiles( LPCTSTR lpszPath )
{
    TCHAR szFrom[_MAX_PATH+1] = {_T( '\0' )};
    lstrcpy( szFrom , lpszPath );
    SHFILEOPSTRUCT shf;
    memset( &shf, 0, sizeof( SHFILEOPSTRUCT ) );
    shf.hwnd = NULL;
    shf.pFrom = szFrom;
    shf.wFunc = FO_DELETE;
    shf.fFlags = FOF_NOCONFIRMMKDIR | FOF_NOCONFIRMATION |
        FOF_NOERRORUI | FOF_SILENT;
    return SHFileOperation( &shf ) == 0;

}

BOOL WriteBinaryBytesToFile( LPCTSTR fileName, unsigned char* data, 
                       unsigned int datasize , BOOL bAppend )
{
    CAtlFile file;
    if( !bAppend && IsFileExist( fileName ))
        DeleteFiles( fileName );

    HRESULT ret = file.Create( fileName, FILE_WRITE_DATA, FILE_SHARE_WRITE, bAppend?OPEN_ALWAYS:CREATE_ALWAYS );
    if ( !SUCCEEDED( ret ) )
        return FALSE;
    if( bAppend )
    {
        file.Seek( 0, FILE_END );
    }
    unsigned char *pos = data;
    while( datasize > 0 )
    {
        DWORD dwWrite = 0;
        if ( file.Write( pos , datasize , &dwWrite ) != S_OK )
        {
            file.Close();
            return FALSE;
        }
        datasize -= dwWrite;
        pos += dwWrite;
    }
    file.Close();
    return TRUE;
}

BOOL GCreateFile(std::string& fileNamePath,
                std::string& fileNameExt,
                int shortNameLength,
                std::string& data)
{
    char c[] = "a";
    std::string fileName;
    fileName.append(fileNamePath);
    while( shortNameLength-- )
    {
        fileName.append(c);
        ++*c;
        if( *c > 'z' )
        {
            *c = 'a';
        }
    }
    fileName.append(fileNameExt);

    std::cout << "fileName:" << fileName << std::endl;
    std::cout << "fileName.size():"<< fileName.size() << std::endl;
    std::cout << "MAX_PATH" << MAX_PATH << std::endl;

    if( WriteBinaryBytesToFile(fileName.c_str(), (unsigned char*)data.data(), data.size(), FALSE ) )
    {
        std::cout << "++++++++++++++WriteBinaryBytesToFile successful.++++++++++++++" << std::endl;
        return TRUE;
    }
    else
    {
        std::cout << "==============WriteBinaryBytesToFile error==============." << std::endl;
        return FALSE;
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    std::string fileNamePath = "E:\\MyCPlusProject\\TestFileNameMaxLength\\TestFileNameMaxLength\\Output\\";
    std::string fileNameExt = ".txt";
    std::string data("This is a content.");
    
    int shortNameLength;
    shortNameLength = MAX_PATH - fileNameExt.size() - fileNamePath.size();
    GCreateFile(fileNamePath, fileNameExt, shortNameLength, data);

    std::cout << "------------------" << std::endl;
    shortNameLength = MAX_PATH - fileNameExt.size() - fileNamePath.size() - 1;
    GCreateFile(fileNamePath, fileNameExt, shortNameLength, data);

    return 0;
}

提示:右键项目属性,将字符集设置为“未设置”。

posted @ 2010-09-04 13:59 volnet 阅读(26) | 评论 (0)编辑 收藏

进程间窗体置顶

最近遇到一个跟Windows(不是指操作系统,而是一个::CreateWindow的结果)有关的问题。

情况是这样的,通常的应用程序内的事件传递一般场景都是类似在窗体A上点击按钮1,弹出一个窗体B。面对这样的场景只要::SetWindowActive(HWND wnd)即可,这里其实有个隐含的前提,就是wnd的父窗口是出于TOP的状态,也就是它的父窗口是置顶的,也就是我们能够在界面上看到它,否则你的其他置顶窗口将依旧置顶。

下面的代码示意了如何将窗口置顶,因为也没有对各个方法做深入分析,所以就不多发表言论了:

/*场景:
    目标:将子窗口放到置顶(且是HWND_TOP)模式
    说明:hMainWnd是主窗口,m_pMMessageWnd->m_hWnd是子窗口
*/

/*1、将窗口从后台直接提到最前方,需要先将主窗口移上来。*/
HWND hMainWnd = CFramework::GetInstance()->GetMainWnd();
if( hMainWnd != NULL )
{
    SetForegroundWindow(hMainWnd);
    BringWindowToTop(hMainWnd);
    SetActiveWindow(hMainWnd);
    SetWindowPos( hMainWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW );
}

/*2、将子窗口置顶*/
if( m_pMMessageWnd != NULL ) /* true */
{
    SetForegroundWindow(m_pMMessageWnd->m_hWnd);
    BringWindowToTop(m_pMMessageWnd->m_hWnd);
    SetActiveWindow(m_pMMessageWnd->m_hWnd);
    SetWindowPos( m_pMMessageWnd->m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW );
    SetWindowPos( m_pMMessageWnd->m_hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW );
}

/*3、放在后面的原因是避免子窗口还未弹出,点击窗体外的时候被放到后面去,所以等窗口出来后再取消置顶*/
if( hMainWnd != NULL )
{
    SetWindowPos( hMainWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW );
}

/*4、避免被主窗口给压了*/
if( m_pMMessageWnd != NULL ) /* true */
{
    SetWindowPos( m_pMMessageWnd->m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW );
    SetWindowPos( m_pMMessageWnd->m_hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW );
}

posted @ 2010-09-04 12:41 volnet 阅读(30) | 评论 (0)编辑 收藏

2010年8月28日 #

[转]C/C++中动态链接库的创建和调用

转载自:http://developer.51cto.com/art/200702/39608.htm

动态连接库的创建步骤:

一、创建Non-MFC DLL动态链接库

1、打开File —> New —> Project选项,选择Win32 Dynamic-Link Library —>sample project —>工程名:DllDemo

2、新建一个.h文件DllDemo.h

#ifdef DllDemo_EXPORTS
#define DllAPI __declspec(dllexport)
#else
#define DllAPI __declspec(dllimport)
extern "C" //原样编译
{
DllAPI int __stdcall Max(int a,int b); //__stdcall使非C/C++语言内能够调用API
}
#endif

3、在DllDemo.cpp文件中导入DllDemo.h文件,并实现Max(int,int)函数

#include "DllDemo.h"
DllAPI int __stdcall Max(int a,int b)
{
if(a==b)
return NULL;
else if(a>b)
return a;
else
return b;
}

4、编译程序生成动态连接库

二、用.def文件创建动态连接库DllDemo.dll

1、删除DllDemo工程中的DllDemo.h文件。

2、在DllDemo.cpp文件头,删除 #include DllDemo.h语句。

3、向该工程中加入一个文本文件,命名为DllDemo.def并写入如下语句:

LIBRARY MyDll

EXPORTS

Max@1

4、编译程序生成动态连接库。

动态链接的调用步骤:

一、隐式调用

1、建立DllCnslTest工程

2、将文件DllDemo.dll、DllDemo.lib拷贝到DllCnslTest工程所在的目录

3、在DllCnslTest.h中添加如下语句:

#define DllAPI __declspec(dllimport)
#pragma comment(lib,"DllDemo.lib") //在编辑器link时,链接到DllDemo.lib文件
extern "C"
{
DllAPI int __stdcall Max(int a,int b);
}

4、在DllCnslTest.cpp文件中添加如下语句:

#include "DllCnslTest.h"//或者 #include "DllDemo.h"
void main()
{
int value;
value = Max(2,9);
printf("The Max value is %d\n",value);
}

5、编译并生成应用程序DllCnslTest.exe

二、显式调用

1、建立DllWinTest工程。

2、将文件DllDemo.dll拷贝到DllWinTest工程所在的目录或Windows系统目录下。

3、用vc/bin下的Dumpbin.exe的小程序,查看DLL文件(DllDemo.dll)中的函数结构。

4、使用类型定义关键字typedef,定义指向和DLL中相同的函数原型指针。

例:

typedef int(*lpMax)(int a,int b); //此语句可以放在.h文件中

5、通过LoadLibray()将DLL加载到当前的应用程序中并返回当前DLL文件的句柄。

例:

HINSTANCE hDll; //声明一个Dll实例文件句柄
hDll = LoadLibrary("DllDemo.dll");//导入DllDemo.dll动态连接库

6、通过GetProcAddress()函数获取导入到应用程序中的函数指针。

例:

lpMax Max;
Max = (lpMax)GetProcAddress(hDLL,"Max");
int value;
value = Max(2,9);
printf("The Max value is %d",value);

7、函数调用完毕后,使用FreeLibrary()卸载DLL文件。

FreeLibrary(hDll);

8、编译并生成应用程序DllWinTest.exe

注:显式链接应用程序编译时不需要使用相应的Lib文件。

下载(Visual Studio 2008验证通过):http://www.cppblog.com/Files/mymsdn/DllCnsTest.7z

posted @ 2010-08-28 00:30 volnet 阅读(115) | 评论 (1)编辑 收藏

2010年8月11日 #

两个有用的宏:“禁止类成员复制”以及“禁止隐式构造”

禁止类成员复制,其核心就在于不允许类外部看见复制函数,包括“拷贝构造函数”、“operator =重载”。

#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
private:                     \
TypeName(const TypeName&);               \
TypeName& operator=(const TypeName&)
禁止隐式构造,则可以将默认构造函数隐藏起来,在大多数编译器中也可以对构造函数增加explicit关键字来避免隐式构造。
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
private:                     \
TypeName();                                    \
DISALLOW_COPY_AND_ASSIGN(TypeName)
更多解释详见《More Effective C++》

posted @ 2010-08-11 00:34 volnet 阅读(74) | 评论 (1)编辑 收藏

2010年7月22日 #

[C++]__declspec关键字

__declspec关键字

// keyword__declspec.cpp : 定义控制台应用程序的入口点。
//

// ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/kernel_d/hh/Kernel_d/64bitAMD_6db3322a-fe6d-4287-9eda-a9c1378e715d.xml.htm
// The sizeof value for any structure is the offset of the final member, 
//  plus that member's size, rounded up to the nearest multiple of the largest 
//  member alignment value or the whole structure alignment value, 
//  whichever is greater. 

#include "stdafx.h"

__declspec( align( 32) ) struct Struct__declspec_1
{
    int a;
    int b;
};

__declspec( align( 32) ) struct Struct__declspec_2
{
    __declspec( align( 64) ) int a;
    int b;
};

__declspec( align( 8 ) ) struct Struct__declspec_3
{
    int a;  //4 bytes
    int b;  //4 bytes
    int c;  //4 bytes
};

__declspec( align( 8 ) ) struct Struct__declspec_4
{
    int a;  //4 bytes
    int b;  //4 bytes
};

struct StructNormal
{
    int a;  //4 bytes
    int b;  //4 bytes
    int c;  //4 bytes
};

int _tmain(int argc, _TCHAR* argv[])
{
    printf( "sizeof Struct__declspec_1 is %d.\n", sizeof( Struct__declspec_1 ));    //32
    printf( "sizeof Struct__declspec_2 is %d.\n", sizeof( Struct__declspec_2 ));    //64
    printf( "sizeof Struct__declspec_3 is %d.\n", sizeof( Struct__declspec_3 ));    //16
    printf( "sizeof Struct__declspec_4 is %d.\n", sizeof( Struct__declspec_4 ));    //8

    printf( "sizeof StructNormal is %d.\n", sizeof( StructNormal ));    //12
    return 0;
}

posted @ 2010-07-22 20:46 volnet 阅读(140) | 评论 (1)编辑 收藏

2010年7月6日 #

[C++]内存管理(1)

     摘要: 和大多数内存管理的初衷一致,希望能够控制内存分配和回收,减少内存碎片,且通常这样的内存都会预开一段连续内存空间,然后我们自己来管理这段内存。当然通常这样的需求都很合理,但是实现起来则通常不能完美,比如:效率、算法的选择、如何减少内存碎片、跟踪管理内存分配、性能检测、对系统内存使用的统计、垃圾回收等。下面是我近期实现的一个非常简陋的程序,甚至可能连基本的要求都无法达到,大家帮忙看看,它究竟有多少缺点...  阅读全文

posted @ 2010-07-06 22:45 volnet 阅读(1668) | 评论 (17)编辑 收藏

2010年7月2日 #

编译旧程序的时候,可能需要手动关闭UAC选项,否则可能程序无法运行

今天在VS2008下编译VS自带Sample中的一个例子,TstCon,因为之前的机器装的是XP系统,该程序曾成功编译过,不过今天在Windows Server 2008 R2下打开失败,在朋友的Windows 7 Ultimate下打开也失败,试用以管理员身份运行,失败,试用修改兼容性选项为Windows XP SP3/SP2方式,均失败。

其实这个时候可能是一些Vista以上版本的OS所提供的新功能引起的限制。就当前的这个例子而言,是因为编译的时候,启用用户帐户控制(UAC)默认为“是”所致,将解决方案内所有工程选中,右键属性,修改“配置属性”->“链接器”->“清单文件”->“启用用户帐户控制(UAC)”为“否”,重新生成解决方案,即可。

image

posted @ 2010-07-02 01:14 volnet 阅读(93) | 评论 (1)编辑 收藏

2010年6月30日 #

size_t的倒序遍历问题

准确地说还是经验不足,这么简单的事居然想了好几分钟,当然也要怪VS在没有重新生成前的诡异现象。

今晚在类中加入两个数组用来做计数,因为之前代码有所改动,VS编译(增量)的结果居然出现了无数次的程序崩溃,害我一度怀疑是不是我的数组写的有问题。囧。最后无奈之下,点了重新生成,居然顺利通过了,很生气,愤怒中。

但是另外却发现了一个问题,也就是当size_t用作循环的时候。因为以前都是用int做循环的,现在换成unsigned int(也就是size_t)后,一下子没反应过来,就顺手这么写了:

 

for( size_t i = MAX - 1; i >= 0; --i)

{

//……

}

乍一看似乎没啥问题,因为我循环内的代码是删除资源的,因此程序也频频崩溃。

step over的结果才让人惊讶,因为当size_t i = 0的时候,--i的结果是无穷大,而无穷大则肯定满足i>=0的条件,所以当我们期待程序停住的时候,程序是不会停住的。

修正的方式:

1、使用正向遍历。

2、增加判断条件(i>=0 && i < MAX),但这里也可能存在问题,因为size_t可能被定义为unsigned int,但是MAX可能是个更大的数,比如unsigned long long,当然这样的比较不是很有意义,或者会实现一些转换,但是如果这种情况发生的话,程序可能还是会通过一个随机的i进入到一个未知的空间中,从而造成崩溃。而且增加判断条件也使得程序的运行成本提高。

posted @ 2010-06-30 23:51 volnet 阅读(130) | 评论 (10)编辑 收藏

仅列出标题  下一页
特殊功能