• VS2008编译的程序在某些机器上运行提示“由于应用程序配置不正确,应用程序未能启动”的问题


      使用VS2008编译了一个程序,使用到自己编译的DLL,丢到某些机子上无法运行,提示“由于应用程序配置不正确,应用程序未能启动”的错误,装了vcredist_x86也没有用,开始以为是DLL的问题,后来换个简单的程序,仍然不行,百撕不得其解,后来上网找,下面有说了很多解决办法。
            我最终的解决办法是复制本机中的.manifest文件,修改里面的版本号,复制到提示错误的机子上,与可执行程序放在同一目录就可以了。在计算机中管理的系统工具,事件查看器可以查看应用程序的消息,找到“由于应用程序配置不正确,应用程序未能启动”相关的错误,有那个版本号。
    修改.manifest文件中version的版本号:
    <assemblyIdentity type="win32" name="Microsoft.VC90.MFC" version="9.0.30729.1" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
    根据事件查看器里面的信息看支持的版本是哪个,对应修改即可(有好多.manifest文件,不记得具体是哪个了),下面的文章有详细的说明~~~


    VC9编译的程序在没有装过VC9(确切的说是.Net Framework3.5)的机器上运行时,如果提示“由于应用程序配置不正确,应用程序未能启动。重新安装应用程序可能会纠正这个问题。”这个错误,那 么就说明该程序动态链接了VC9的运行时库,(如果还用到了MFC,那么可能动态链接了VC9的MFC库,同理还有ATL库),以及缺少对应的 manifest文件,程序在目标机器上没有找到这些库和配置文件,因此导致了这个错误。出现这种情况的VC9编译器可能存在3个版本,接下来分别阐明:

    1、没有打过任何补丁的VS2008

    该版本对应的CRT/MFC/ATL库的版本号为9.0.21022.8,这个版本号在后面 会用到。这个版本的程序部署比较简单,直接把VC安装目录下的redist目录(C:\Program Files\Microsoft Visual Studio 9.0\VC\redist)中需要的库以及对应的manifest文件拷贝到执行程序同目录下,这样程序到任何机器上都能够正常运行了。

    2、打过SP1补丁的VS2008

    打过该补丁后,系统中存在着两个版本的CRT/MFC/ATL库,版本号分别为 9.0.21022.8和9.0.30729.1,这导致了manifest文件中记录的版本号和实际库的版本号不一致(程序要求它们的版本号一致才能运 行)。这个版本的程序部署需要两个步骤,首先要使manifest文件中依赖项的版本号与实际库的版本号一致,均为9.0.30729.1,方法是在工程 设置中增加一个宏定义_BIND_TO_CURRENT_VCLIBS_VERSION,该宏定义于C:\Program Files\Microsoft Visual Studio 9.0\VC\include\crtassem.h文件中,然后重新编译程序。接下来还是将VC安装目录下的redist目录(C:\Program Files\Microsoft Visual Studio 9.0\VC\redist)中需要的库以及对应的manifest文件拷贝到执行程序同目录下,然后修改manifest文件中依赖项的版本号为 9.0.21022.8,这样使得程序误以为该目录下库的版本号为9.0.21022.8(实际上是9.0.30729.1版本),这样程序到任何机器上 都能够正常运行了。

    3、打过SP1补丁与SP1 ATL 安全更新 (KB973675)的VS2008

    这是最新的更新。在SP1补丁之后,微软又于近日发布了一个用于智能设备的 Microsoft Visual Studio 2008 Service Pack 1 ATL 安全更新 (KB973675), 该补丁又将CRT/MFC/ATL库的版本号升级,为9.0.30729.4148,这次升级比较好,manifest文件与库的版本号一致了,不像 SP1一样升级的不彻底。这样只需要在工程设置中增加一个宏定义_BIND_TO_CURRENT_VCLIBS_VERSION,接下来重新编译程序, 然后直接把VC安装目录下的redist目录中需要的库以及对应的manifest文件拷贝到执行程序同目录下,这样程序到任何机器上都能够正常运行了。

    顺便提一下,如果不想在发布程序时带上这些库和manifest文件(如果没有必要的话), 那么可以采用静态编译CRT和MFC,然后把manifest文件添加到资源中,这样编译出的程序只要一个exe就可以在任何机器上直接运行了。

    参考文章:

    1、“应用程序配置不正确,程序无法启动”的解决方法资料收集:

    有的时候,你在Visual C++上面经过好几个月的辛勤努力,终于将程序编写完成并且测试完毕,然而当你试图在客户的发布机上运行刚写好的程序时,有可能会碰到类似下面的错误,操 作系统告诉你“由于应用程序配置不正确,应用程序未能启动。重新安装应用程序可能会纠正这个问题”.

    一般情况下,这个问题都是由于程序不能找到所需要的C运行库(CRT)而引起的。

     

    在Windows XP SP2以后,Windows引入了Side-by-Side执行的概念,这个概念本来是.NET提出来的,但是Windows后来将这个概念集成到操作系 统层面上来了。大家都应该知道Dll Hell的问题,为了解决Dll Hell的问题,Side-By-Side提出不同版本的dll文件可以同时 存在于同一个系统里面,而且依赖于不同版本dll的应用程序在运行的时候可以使用到它当初被编译生成的dll。前面的话,有点绕,举个例子:

    1.         假定你编写了一个C++程序A,是使用MFC 8.0(这个版本是随着Visual Studio 2005)发布的。

    2.         之后你的机器升级了Visual Studio的版本,从2005升级到2008,2008的MFC库是9.0版本的,这个时候你的操作系统里面安装了两个版本的MFC,分别是8.0和 9.0。

    3.         你在Visual Studio 2008编写了另外一个C++程序B,B依赖与MFC 9.0。

    4.         如果你运行程序A的话,操作系统会将MFC 8.0加载到A的进程里面。

    5.         如果你这时同时运行程序B,操作系统会将MFC 9.0加载到B的进程里面。这就是Side-by-side的执行概念。

     

    操作系统之所以能够这样做,是因为它在加载程序A和B之前,除了查看PE格式里面A和B所依 赖的Dll信息,都会查看A和B的manifest文件。Manifest文件保存了Windows可执行文件(包括exe和dll文件)要运行起来的环 境设置信息,文件名一般是可执行文件的文件全名加上.manifest。例如notepad.exe的manifest文件就应该是 notepad.exe.manifest。例外有的程序将manifest文件直接嵌入到可执行文件的资源里面了,这也就是为什么有的时候你看不到程序 的manifest文件的原因。通常来说,一个manifest文件的内容如下(test.exe.manifest文件):

    <?xml version='1.0' encoding='UTF-8' standalone='yes'?>

    <assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>

    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">

        <security>

          <requestedPrivileges>

            <requestedExecutionLevel level='asInvoker' uiAccess='false' />

          </requestedPrivileges>

        </security>

    </trustInfo>

    <dependency>

        <dependentAssembly>

          <assemblyIdentity type='win32' name='Microsoft.VC90.DebugCRT' version='9.0.21022.8'

                            processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />

        </dependentAssembly>

    </dependency>

    </assembly>

    上面的例子里面,就说明这个程序依赖于CRT 9.0,而且是调试版的,CPU架构是32位的CPU。对于将manifest文件嵌入到资源文件的程序我们也有办法看到manifest的信息。

    1.         一种是使用mt.exe(Visual Studio自带的manifest处理程序):

    mt -inputresource:test.exe;#1 /out:test.manifest

    2.         另外一种是使用dumpbin程序将整个exe的内容打印到一个文件,然后用文本编辑器打开,搜索Assem字符串样式就能找到manifest信息:

    VS2008编译的程序在某些机器上运行提示由于应用程序配置不正确,应用程序未能启动的问题 - tangxingqt -doomgnu的博客

    解决方案

    知道了程序依赖于具体哪一个dll以后,你可以将所依赖的dll拷贝到程序的安装文件夹里 面,以CRT库绑定失败为例,介绍解决步骤:

    1.从上例中我们知道程序依赖的Microsoft.VC90.DebugCRT库,版本号 是9.0.21022.8,需要32位机器版本的CRT。这个依赖项一般是因为你的程序是调试版,所以Visual Studio在编译的时候,将调试版的CRT加入程序的依赖项。

    2.从Visual Studio的安装文件夹里面将D:"Program Files"Microsoft Visual Studio 9.0"VC"redist"Debug_NonRedist"x86中的Microsoft.VC90.DebugCRT整个文件夹拷贝到应用程序所在 的文件夹里面,注意:

    a)如果你的程序依赖的是32位的CRT,则要拷贝x86文件夹里面的 Microsoft.VC90.DebugCRT文件夹,如果是先x64程序,则要拷贝x64文件夹里面。

    b)你需要确定Microsoft.VC90.DebugCRT文件夹里面的 Microsoft.VC90.DebugCRT.manifest文件里面保存的版本信息而你程序依赖的版本信息匹 配,Microsoft.VC90.DebugCRT.manifest里面的版本信息大版本号一定要一致,小版本号一定要等于或者大于你程序依赖的 CRT的小版本号。比如上例中,我们的程序是依赖于CRT 9.0.21022.8,而我们的Microsoft.VC90.DebugCRT.manifest的版本是9.0.30729.1,这样是可以的;而 8.0.30729.1就会有问题。如果大版本号一样,小版本号不一致的话,一个比较简单的方案就是修改程序的manifest文件,使其互相匹配就可以 了。

    3.如果你的程序不是依赖调试版本的CRT,而是release版本的CRT,直接去微软的 官方网站下载一个crt redist包安装上就可以了。

     

    附:解决方案参考:

    方案一:


    方法一:
    在C:\Program Files\Microsoft Visual Studio 8\VC\redi
    st\Debug_NonRedist\x86 \Microsoft.VC80.DebugCRT 下找到了下列文件:

    msvcm80d.dll
    msvcp80d.dll
    msvcr80d.dll
    Microsoft.VC80.DebugCRT.manifest

    把这几个文件拷贝到目标机器上,与运行程序同一文件夹或放到system32下,就可以运行那个程序了。

    其他release版,MFC程序什么的都是拷redist下相应文件夹下的文件就可以了,文件夹后都有标识!

    方法二:
    修改编译选项,将/MD或/MDd 改为 /MT或/MTd,这样就实现了对VC运行时库的静态链接,在运行时就不再需要VC的dll了。

    方法三:

    工程-》属性-》配置属性-》常规-》MFC的使用,选择"在静态库 中使用mfc"
    这样生成的exe文件应该就可以在其他机器上跑了。

    方法四:

    你的vc8安装盘上找到再分发包vcredist_xxx.exe和你的程序捆绑安装

     

    我逐一测试下来,直到第三个方法才成功.第二个方法不知道在哪里修改编译选项所以放弃了,第四个方法不喜欢,这跟直接安装.net framework 2.0 有什么区别吗?还不如直接安装.net framework 2.0 呢.

     

         方案二:

    最早出现这个错误我和许多人认为的一样 
    认为是缺乏DLL库文件导致.但是在测试机复制了DLL甚至安装了.net framework 2.0以后 
    都无法解决问题,最后确认不是由缺乏DLL所致 
    因为程序是纯win32的应用程,非托管代码,所以也无需.net framework 

    Visual C++2003/2005默认的MFC程序是使用动态MFC库(Use MFC in a Shared DLL)来链接的 
    而动态MFC库使用 的是Multi-threaded DLL (/MD) 
    由于XP对于PE文件格式监测更加严格. 
    就会导致部分使用多线程DLL的可执 行文件在调用的时候出错 
    修改项目属性的编译开关 
    Project->Property->configuration Properties->C/C++->Code Generation->Runtime Library 
    修改成 Multi-threaded (/MT) 
    修改了Runtime类型以后 
    需要将MFC的编译类型也改成静态库 
    Project->Property->configuration Properties->General->Use of MFC 
    修改成Use MFC in a Static Library 

    一部分情况下在这步就能解决问题 
    另外一部分情况会遇见如下情况 
    编译器报错 



    CODE: 
    nafxcw.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new[](unsigned int)" (??_U@YAPAXI@Z) already defined in libcpmt.lib(newaop.obj) 
    [Copy to clipboard] 


    产生这个问题的原因是库依 赖关系 
    在Project->Property->configuration Properties->Linker->Command Line 
    加入编译开关/verbose:lib可以显示详细的库链接顺 序 
    CODE: 

    ------ Build started: Project: PerfMonDemo, Configuration: Release Win32 ------ 
    Linking... 
    Searching libraries 
    Searching d:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\lib\pdh.lib: 
    Searching d:\Program Files\Microsoft Visual Studio 8\VC\lib\DelayImp.lib: 
    .................
    Searching d:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\lib\nafxcw.lib: 
    Finished searching libraries 
    .\Release/PerfMonDemo.exe : fatal error LNK1169: one or more multiply defined symbols found 
    Build log was saved at "file://d:\Dev\Performance Monitor\Release\BuildLog.htm" 
    PerfMonDemo - 2 error(s), 0 warning(s) 
    ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== 

    [Copy to clipboard] 

    我 们发现在libcpmt.lib声明过的operator new在nafxcw.lib中再次定义 
    解决方法如下 
    Project->Property->configuration Properties->Linker->Input->Additional Dependencies 
    加入 
    nafxcw.lib 
    libcpmt.lib 
    Project->Property->configuration Properties->Linker->Input->Ignore Specific Library 
    加入 
    nafxcw.lib 
    libcpmt.lib 
    这样链接程序就不会先按照默认顺序来连接这两个库文件 
    而是在最后在加入对他们的引用.这样就避免了 这个问题 
    下面是一张可能发生冲突的列表 
    若要使用此运行时库 请忽略这些库 
    单线程 (libc.lib) libcmt.lib、msvcrt.lib、libcd.lib、libcmtd.lib、msvcrtd.lib 
    多线程 (libcmt.lib) libc.lib、msvcrt.lib、libcd.lib、libcmtd.lib、msvcrtd.lib 
    使 用 DLL 的多线程 (msvcrt.lib) libc.lib、libcmt.lib、libcd.lib、libcmtd.lib、msvcrtd.lib 
    调试单线程 (libcd.lib) libc.lib、libcmt.lib、msvcrt.lib、libcmtd.lib、msvcrtd.lib 
    调 试多线程 (libcmtd.lib) libc.lib、libcmt.lib、msvcrt.lib、libcd.lib、msvcrtd.lib 
    使 用 DLL 的调试多线程 (msvcrtd.lib) libc.lib、libcmt.lib、msvcrt.lib、libcd.lib、libcmtd.lib


    这里还有一篇

    转载于:http://blog.csdn.net/feng_enlove/article/details/5917903

    vs2008发布c编写的dll程序 初始化失败-0xc0150002

    用VC2005编译的程序,编译时没有任何错误,但是运行时就是提示“应用程序正常初始化失败”!! 查找了各方面资料,做了各种尝试,网上说什么的都有:有让安装vc2005 sp1补丁的;有让安装vcredist_x86.exe的; 有让把CRT库的dll直接拷贝到程序目录的; 有让清理注册表的;有让装.NetFramework新版本的;有让查manifest的; 

      结果我尝试了半天,几乎都是浪费时间。上面最后一条说的还算正确,只是作者把事情描述得太繁琐了。。现在把处理的方法说一下,省得大家再走弯路: 

      1. VC2003、VC2005、VC2008及其后续版本,对底层最基本的CRT、MFC、ATL库都进行了重构,为了避免不同版本的库引起冲突,重构后的库文件一般放在 C://windows/WinSxS 文件夹中,并用特定的文件夹/文件名称进行标识; 

      2. 与VC6不同, VC2003、VC2005、VC2008及其后续版本,引入了manifest清单的概念,即应用程序编译后会同时生成对应的.manifest文件,并将该.manifest文件作为资源编译到dll或者exe中去。.manifest文件实际上是一个XML格式的文本文件,里面记录了dll或exe中要引用的CRT、MFC、ATL库的版本和名称。VC6编译的应用程序对CRT、MFC、ATL的dll都是直接调用,而VC2003、VC2005、VC2008编译的程序都是先查询编译到资源中的manifest中的记录,然后按照记录提供的版本和名称去搜寻对应的CRT、MFC、ATL库以及随库发布的.manifest文件,搜寻的路径包括当前目录、C://windows/WinSxS 等等,如果没有找到对应的库文件,则提示“应用程序正常初始化失败”; 

      3.因此解决这个问题的办法就是:(a)用文本编辑器打开exe或dll对应的.manifest文件,查看它引用的CRT、MFC、ATL库的版本;或者,用UltraEdit直接打开exe或者dll,从资源区中找到编译进去的.manifest信息,找到它引用的CRT、MFC、ATL库的版本;或者,运行程序,当程序弹出“应用程序正常初始化失败”对话框时,在桌面上右键点击“我的电脑”-“管理”-“事件查看器”-“系统”,双击查看其中的记录,可以看到出错的原因是因为缺少了某某版本的CRT、MFC、ATL库,记录下这个版本信息;(b)记录到的库的版本信息一般类似于“Microsoft.VC90.DebugCRT”,之后到C://windows/WinSxS 或者VC200X的安装文件夹中搜索包含这个字符串的文件夹和文件,将搜索到的dll和.manifest文件都拷贝到应用程序所在的文件夹中,其中,.manifest文件必须重命名为“Microsoft.VC90.DebugCRT.manifest”(这里以Microsoft.VC90.DebugCRT为例),这样应用程序就可以正常运行了;(c)注意:库的.manifest文件和dll要一同拷贝到应用程序根目录去,因为应用程序会将编译到内部的manifest信息与外部的.manifest文件进行对比,之后才会对库的dll进行调用。如果只拷贝库的dll文件是没有用的; 

      4.如果本机编译和运行程序都ok,但是将编译好的程序拿到其它机器上确无法运行,则多半也是这个原因。另外,如果提示"应用程序配置不正确",大多也是因为上面所说的CRT、MFC、ATL库版本与应用程序不匹配导致的,可以如法炮制进行解决;

    (原文http://microblue.com.cn/it/8823.html

    把VS安装目录下的Microsoft Visual Studio 9.0/VC/redist/Debug_NonRedist/x86/Microsoft.VC90.DebugCRT下的
    msvcm90d.dll
    msvcp90d.dll
    msvcr90d.dll
    Microsoft.VC90.DebugCRT.manifest
    这几个文件复制到应用程序安装后的根目录下(注:我装的是VS2008,如果是VS2005的话上面的90的地方全部换80),原因就是我的程序里依赖了VS里面的一些库,所以不装VS的机器上会找不到相应的dll。把这几个dll发布时一起发布就好了。
    但是这样之后,出现了另一个问题,提示“应用程序正常初始化失败”,无奈继续求助百度GOOGLE两位大神,一查发现自己中了大奖,号称VS发布程序的两大难题让我一次全遇到了。
    不断翻啊翻,翻到http://bbs.17173.com/topics/4550/200907/21/1852512,1.html?time=1248186834这个网页的时候,里面的第一种方法提醒了我,尝试了下,还不行,突然想起,我用的是VS2008,他提供的是2005的下载地址,于是按照那个名字复制的2008的,下载安装之,问题最终解决。

    下载的软件名字为Microsoft Visual C++ 2008 SP1 Redistributable Package (x86) 。

    快速描述
    Microsoft Visual C++ 2008 SP1 Redistributable Package (x86) 会为 Visual C++ 库安装必要的运行时组件,使用户能够在未安装 Visual C++ 2008 SP1 的计算机上运行使用 Visual C++ SP1 开发的应用程序。
    提供一个下载地址,微软的官方下载,速度还可以:
    http://www.microsoft.com/downloads/details.aspx?displaylang=zh-cn&FamilyID=a5c84275-3b97-4ab7-a40d-3802b2af5fc2

    同时提供另一个对此问题讲解比较透彻的网址:http://hi.baidu.com/kidcdf/blog/item/aad99901207fe1d2267fb5da.html
    OK,这样就可以把使用VS2008编写的程序运行在未装VS的机器上了。


    最后再转一篇

    转载于:http://hi.baidu.com/kidcdf/blog/item/aad99901207fe1d2267fb5da.html


    再谈VC2005 发布程序的两大问题:"应用程序正常初始化失败","应用程序配置不正确",攻略全
    2008年01月31日 星期四 23:29

    自己电脑上能用,到了其他电脑上就不能用了,是不是很头痛,除了必要的DLL文件,还有些什么是必须一起打包发行的呢?

    1."应用程序配置不正确"

    参考:http://blog.csdn.net/Blue_Dream_/archive/2007/10/05/1811975.aspx

    1.如果你的项目属性是 MD 或 MDd,那就要把以下文件放入你的EXE目录一起发布

    开始-运行- X:\Program Files\Microsoft Visual Studio 8\VC\redist\Debug_NonRedist\x86\Microsoft.VC80.DebugCRT

    2.如果你想静态编译进EXE,也就是 MT/MTd,那就参看这里:建议动态链接,这种不同开关的LIB也能一起工作了.

    参考:http://blog.csdn.net/primer_programer/archive/2008/01/09/2031412.aspx

    C Runtime Library:

    开关
    对应的库
    版本
    /MD
    MSVCRT.LIB
    多线程DLL的Release版本
    /MDd
    MSVCRTD.LIB
    多线程DLL的Debug版本
    /MT
    LIBCMT.LIB
    多线程静态链接的Release版本
    /MTd
    LIBCMTD.LIB
    多线程静态链接的Debug版本
    /clr
    MSVCMRT.LIB
    托管代码和非托管代码混合
    /clr:pure
    MSVCURT.LIB
    纯托管代码
    C++ Standard Library:

    开关
    对应的库
    版本
    /MD
    MSVCPRT.LIB
    多线程DLL的Release版本
    /MDd
    MSVCPRTD.LIB
    多线程DLL的Debug版本
    /MT
    LIBCPMT.LIB
    多线程静态链接的Release版本
    /MTd
    LIBCPMTD.LIB
    多线程静态链接的Debug版本

    在项目属性-链接-输入 中,输入对应的库,记住程序里还要还引用其他LIB,其他LIB也必须是相同的开关,比如都是 /MTD

    2.应用程序正常初始化失败:

    1.今天这两种情况都被我碰到了,这个比较好解决,在Microsoft Visual Studio 8文件夹内搜索

    vcredist_x86.exe VC可再发行包,到目标机器上安装一下,不用重启,即可使用.

    2.项目的文件被放在了fat/fat32分区上导致的, 解决方法是把它们都移动到ntfs分区上, 或者把“项目属性|Manifest Tool|General|Use FAT32 Work-around”设为yes。

    3.如果把相应的MFCDLL全COPY过去了,还不行怎么办呢?

    (1)用ultraedit,editplus打开你的EXE文件,搜索manifest,找到使用的DLL版本号,如version="8.0.50.XXX"

    (2)DEBUG模式下报此错的话, 把你电脑上的 c:\windows\winsxs\policies\x86_policy.8.0.Microsoft.VC80.DEBUGCRT.XXXXXXXXXXX

    找到对应版本号的cat,和policy这两个文件,再找到

    c:\windows\winsxs\manifest\x86_Microsoft.VC80.DebugCRT_XXXX_8.0.50727.762_XXXXX.cat和x86_Microsoft.VC80.DebugCRT_XXXXXX_8.0.50727.762_XXXXX.manifest

    复制到出问题的机子上的对应目录就OK了

    3.缺少SP1补丁,

    GHOST了C盘后,发觉再运行OGRE的程序就不行了,:"应用程序正常初始化失败",调试器输出:
    LDR: LdrpWalkImportDescriptor() failed to probe d:\program\project\BumperCar\BumperCar\Debug\exe\OgreMain_d.dll for its manifest, ntstatus 0xc0150002 ,想起来了,VC2005要装SP1才兼容OGRE1.4X,这里放出补丁.

    英文补丁 431M 

    http://download.microsoft.com/download/6/3/c/63c69e5d-74c9-48ea-b905-30ac3831f288/VS80sp1-KB926601-X86-ENU.exe 

    中文补丁 
    http://download.microsoft.com/download/8/0/7/8071514d-9370-45c3-8af1-4ff09a70e59d/VS80sp1-KB926604-X86-CHS.exe

  • 相关阅读:
    Java设计模式——单例模式
    关于 "static" 关键字的那点事
    安卓 修改系统时间
    android sdk 5.0下载步骤
    Android开发中调用系统窗口的方法
    Eclipse 导入已有工程时.classpath和.project文件拒绝访 ...
    Android开发错误总结
    CursorIndexOutOfBoundsException
    html移动端适配方案rem
    pc端和移动端的viewport 以及 像素的含义
  • 原文地址:https://www.cnblogs.com/lidabo/p/2869780.html
Copyright © 2020-2023  润新知