精华内容
下载资源
问答
  • (Excel如何实现跨文件引用数据)excel引用其他表格数据路径
    千次阅读
    2021-07-26 06:16:16

    Excel如何实现跨文件表引用数据

    这个与使用本簿中的数据没有任何不同(其他工作簿未打开的时据不会更新),只跨工作更没有什么顾忌了。

    跨工作簿引用数据格式为:

    '[工作簿名称.xls]工作表名称'!$K$30

    以上中文都要被实际内容替换掉,且部分工作簿的后缀可能不是 xls而是 xlsx。

    工作表引用只需要去掉 【】 及里面的内容即可。

    EXCEL如何引用其它文件名下表格中单元格数据?

    将被引用件打开,然后将目件点为活动窗口,在单元格中输入“=”光标开的情,用鼠标直接在WINDOWS任务栏点击被引用文件,使之成为活动窗口,然后点击你想引用的单元格,也可以将被引用文件中多个单元格运算结果直接引用到目标文件某一单元格。选择好后,回到目标文件,回车即可。但要注意,目标文件和被引用文件必须保持同在一台计算机里,如果目标文件要移动到另一台计算机,也要同时将被引用文件移到原来计算机得相同位置。也可采用如下方法:一、引用完后,将目标文件中引用的数据复制——选择性粘贴——数值。二、将被引用文件与目标文件放在一个文件夹中,要移动,二者一起移动。

    excel表格中引用了外部数据表格,怎么能找到是哪个表格引用了外部数据?

    先解除工作表的保护,Ctrl F》查找:*.xls》查找全部》Ctrl A

    Ctrl F

    查找  =   号

    点选项,查找范围,改成“工作簿”

    全部查找

    在excel的地址引用中,如果要引用其他工作薄表中的内容将如何操作

    打开相关的文件 输入 = 鼠标单击另一工作簿相应工作表的单元格

    结果类似于 =[示例文件.xls]Sheet1!$D$4

    EXCEL如何引用其它文件名下表格中单元格数据

    引用的打开,然后将目标文件点为活动窗口,元格中输入“=”光离开的情况下,用鼠标直接在WINDOWS任务栏点击被引用文件,使之成为活动窗口,然后点击你想引用的单元格,也可以将被引用文件中多个单元格运算结果直接引用到目标文件某一单元格。选择好后,回到目标文件,回车即可。但要注意,目标文件和被引用文件必须保持同在一台计算机里,如果目标文件要移动到另一台计算机,也要同时将被引用文件移到原来计算机得相同位置。也可采用如下方法:一、引用完后,将目标文件中引用的数据复制——选择性粘贴——数值。二、将被引用文件与目标文件放在一个文件夹中,要移动,二者一起移动。

    在Excel中,一个表格引用另一个表格的数据,用哪些公式进行操作?

    怎样用excel引用其他表格数据

    在实际工作过程中,我们经要编制各种模板供其他人填写。所以,利用数据有效性制供选择的下拉菜单就是一个很常用的方法。一般来说,我们会制作一个包含全部基本信息的表,表单列示所有的备选项目,比如说姓名、型号、部门等等,而实际的填写表格是另外一张表。那么在excel中如何跨工作表自动引用数据或计算?下面小编就为大家介绍一下,一起来看看吧!

    方法/步骤

    暗渠简单的一种是直接等于其它工作表的单元格,比如:sheet2工作表中A1单元格引用sheet1表中A1单元格,则直接=Sheet1!A1就引用过来了。

    excel表中数据跨工作表引用的方法

    第二种,给定条件引用。比如我要根据sheet2中B3单元格数据来引用sheet1中所对应相同数据的C列数据,如图,则可以用VLOOKUP公式。当然,首先得确定这数据是否有唯一性,因为VLOOKUP函数只能引用唯一性数据

    excel表中数据跨工作表引用的方法

    excel表中数据跨工作表引用的方法

    第三种,跨工作表统计数据,分类汇总求和,可以用sumif条件公式。如图,要注意的是,如果不是整列查找,则记得查找区域范围要加上绝对引用哟。

    excel表中数据跨工作表引用的方法

    excel表中数据跨工作表引用的方法

    第四种,根据日期范围返回sheet1中的数据到sheet2中,如图所示,这里就得用到数组了,根据条件判断返回满足条件的值,然后按同时按下ctrl shift enter组合键。

    excel表中数据跨工作表引用的方法

    第五种,利用数据透视表简单操作,也可以跨表分类统计,如图所示:当然,这种统计数据方法比较快,但有时候不太方便,看个人情况使用。

    excel表中数据跨工作表引用的方法

    excel表中数据跨工作表引用的方法

    excel表中数据跨工作表引用的方法

    excel表中数据跨工作表引用的方法

    当然,因为跨工作表引用,因为数据都是引用其它表的链接,所以选项中的自动重算功能必须打开,要不数据容易出错哟。

    excel表中数据跨工作表引用的方法

    以上就是在excel中如何跨工作表自动引用数据或计算介绍,希望能对大家有所帮助!

    更多相关内容
  • Latex是论文写作格式化的很好的工具,但是有时候论文是用word写的,这个时候就要用Mendeley来设置参考文献的引用格式。不同期刊有不同的参考文献引用格式,有时已有的参考文献引用格式并不适用当前的期刊,所以需要...

    Latex是论文写作格式化的很好的工具,但是有时候论文是用word写的,这个时候就要用Mendeley来设置参考文献的引用格式。不同期刊有不同的参考文献引用格式,有时已有的参考文献引用格式并不适用当前的期刊,所以需要自适应的去设计与修改这个引用格式。

    自定义参考文献的引用格式的过程还是稍微有些复杂的,我大概花了一个晚上加一个上午的时间才搞的比较熟悉,所以这里记录一下,备忘并与大家共享。

    第一步:打开mendeley

    第二步:“View”-->“Citation Style”-->“More Styles...”-->"About"-->"CSL Editor"

    得到以下界面:

     在搜索框中搜索相关的citation style 模板,如输入IEEE,得到以下搜索列表:

     这里选择IEEE/ACM为模板进行编辑,点击“Edit”,弹出以下对话框,点击“确定”

    进入以下界面:

     选择“info”-->"Title"命名自己的模板,我这里命名为“IEEE-wzg”.

    界面功能介绍:

    1. 选择示例参考文献,点击右上角选择示例参考文献,包括书籍的示例,期刊的示例等,只能选择三个。

    2. 当前的参考文献模板引用文献时在正文中的表现。

    3. 当前参考文献模板在正文参考文献章节中的表现效果。

     4. 是主要的编辑区域,与3具有对应关系,通过在3中点击相关区域,在4中会弹出对应的编辑区域

     

     编辑作者的名字:先姓后名还是先名后姓,在如下区域进行编辑。有三个选项

    • 空白:所有作者的名称是先名后姓。常用这个设置。
    • first:只有第一个作者的名称是先姓后名,其余作者的名称是先名后姓
    • all:所有作者的名称都是先姓后名

     5. 我们主要修改的是左侧的BIBLIOGRAPHY部分。

    说明:一下画红线的部分是不同的参考文献类型,如期刊,会议,书籍等等。不同的参考文献类型的引用模板需要单独编辑。其中常用的参考文献类型就是期刊,会议,书籍,在下图中已经使用黄色荧光笔标出。

    具体修改的内容是“Group”下面的内容:

    • title: 文章标题
    • container-title:期刊名称
    • locators:应该是volume。可以置换
    • page:文章在期刊中的页数
    • issue:

    选中“Group”,点击右上角的“+”号,可以得到下图所示对话框,添加更多条目,如日期等等。拖动条目,可以调整不同条目之间的顺序。

    6. 点击左侧的条目在右侧进行格式设置,此处略过。

    7. 保存citation style:

    左上角:style-->Save Style 或者 Save Style as...

    此时会打开:

     

     点击标红区域即可。后续操作不再赘述。

    8. 把citation style保存为csl文件,用于以后加载

    Step1:点击“code editor”

     Step2:ctrl +A选中所有代码,复制代码

     step3:新建一个脚本文件(比如我是用notepad++新建的脚本文件),粘贴以上代码,然后保存,并把后缀改成“.csl”即可。

    step4:加载“.csl”参考文献模板

    “Visual Editor”-->左上角"style"--》“load style”加载该csl文件即可。

    注:我没有找到其他的保存参考文件模板为“csl”文件的方式,在界面上没有找到对应的按钮,所以只能使用这个笨办法。

    PPPS:为什么要保存为csl文件到本地,因为,在mendeley中右键编辑引用模板时,

     会出现以下错误:

    修改作者个数:

    设置:

    (1)'et-al-min' (set to 6), et-al-use-first (set to 1), 

    (2)et-al-subsequent-min (set to 3) and et-al-subsequent-use-first (set to 1).

    意思分别是:

    (1)如果少于5个作者,全显示;如果六个或以上作者,显示第一个加et al。

    (1)如果少于3个作者,全显示;如果4个或以上作者,显示姓氏加et al。


    以下转自:【Mendeley】参考文献中et al 的格式修改_小白兔de窝-CSDN博客 

     

    --------------------------------------------------------

    04. Example - modifying 'et al' usage

    The use of 'et al' in citations and bibliographies is a practice which varies from style to style, and there are a number of conditional arguments which can be applied to its use.

    An example of this type of logic would be to say 'if a reference has three or fewer authors, display all of the author names in full. If a reference has four or more authors, display the first author and add 'et al' to reflect the additional authors'.

    The threshold that triggers this behaviour can be modified by editing the style using the CSL Editor - and you can find step-by-step instructions on how to modify this behaviour below.

    For this example, we'll be using the American Psychological Association (APA) (6th edition) style and we'll be modifying how 'et al' is used in in-line citations.

    Back to top

    1. Firstly, we need to open the APA style for editing using the CSL Editor. You can find the steps for this in the first section of this guide - an overview of the CSL Editor.

    2. Once the style has been opened for editing, we need to identify the element that we want to update. In this instance, we know we want to modify the in-line citations, so we can find those in the Example Panel.

    CSL_APA_Citations

    3. From the example citations that are provided, we can see that 'et al' is already being used for in-line citations. Assuming we want to modify this behaviour, we need to modify the settings associated with In-line citations. Click on the 'In-line Citations' heading in the Style Overview panel to display the settings for this item.

    4. With In-line citations selected, we can see a number of settings that control the use of 'et al'. In this instance, the relevant fields are 'et-al-min' (set to 6), et-al-use-first (set to 1), et-al-subsequent-min (set to 3) and et-al-subsequent-use-first (set to 1).

    In lay terms, this can be read as follows:

    If a reference has five or fewer authors, display all the author names in the citation. If a reference has six or more authors, display the first name followed by 'et al' in the citation.

    If a reference has three or more authors, display all three authors in the first citation, but for any subsequent citations use the first name, followed by 'et al'.

    CSL_APA_et_al

    4. If we want to modify this behaviour, we just need to alter the values set here. As an example, let's look at how to cause the style to display the first three names before displaying 'et al'. To achieve this, we just need to modify the setting for 'et-al-use-first' to be '3' instead of '1'.

    5. As soon as this value is changed, you should see the change take place in the example panel, with three names being displayed (followed by et al) instead of one.

    6. However, note that the rules which apply to subsequent citations will still apply, so any citations of a reference with three or more authors - other than the very first - will use the first name followed by 'et al'. We can either modify 'et-al-subsequent-use-first' to be '3' to bring it into line with 'et-al-use-first' (modified in step 4), or we can remove the instructions for 'subsequent citations entirely by settings both the relevant values to be blank. This will mean that all citations are subject to the same rules, without considering if they're the first or a subsequent instance.

    CSL_APA_et_al_updated

    The style has now been modified as intended. To start using it in your working documents, see the section on saving and installing your modified style.

     更多参考:

    【Mendeley】解决mendeley无法自动安装cite style的问题_小白兔de窝-CSDN博客

    【Mendeley】参考文献中et al 的格式修改_小白兔de窝-CSDN博客

    Mendeley下载安装,导出参考文献以及自定义参考文献_Eonekne的博客-CSDN博客

    mendeley参考文献格式设置大全(参考GB T 7714 - 2015)(步骤超级详细,CSL编辑器无法使用、格式设置等多类问题汇总)_EstrangedZ的博客-CSDN博客

    展开全文
  • PE文件格式分析

    千次阅读 2017-09-28 10:11:31
    最近需要对文件加壳,看到这篇文章挺好的转载一下... PE(Portable Execute)文件是Windows下可执行文件的总称,常见的有DLL,EXE,OCX,SYS等,事实上,一个文件是否是PE文件与其扩展名无关,PE文件可以是任何扩展名

    最近需要对文件加壳,看到这篇文章挺好的转载一下,原文地址http://blog.csdn.net/shitdbg/article/details/49734495

    一、PE的基本概念

        PE(Portable Execute)文件是Windows下可执行文件的总称,常见的有DLL,EXE,OCX,SYS等,事实上,一个文件是否是PE文件与其扩展名无关,PE文件可以是任何扩展名。

        认识PE文件不是作为单一内存映射文件被装入内存是很重要的。Windows加载器(又称PE加载器)遍历PE文件并决定文件的哪一部分被映射,这种映射方式是将文件较高的偏移位置映射到较高的内存地址中。PE文件的结构在磁盘和内存中是基本一样的,但在装入内存中时又不是完全复制。Windows加载器会决定加载哪些部分,哪些部分不需要加载。而且由于磁盘对齐与内存对齐的不一致,加载到内存的PE文件与磁盘上的PE文件各个部分的分布都会有差异。



    二、PE结构分析


    图1:PE文件的框架结构

    PE文件至少包含两个段,即数据段和代码段。Windows NT 的应用程序有9个预定义的段,分别为 .text 、.bss 、.rdata 、.data 、.pdata 和.debug 段,这些段并不是都是必须的,当然,也可以根据需要定义更多的段(比如一些加壳程序)。
    在应用程序中最常出现的段有以下6种:
    .执行代码段,通常  .text (Microsoft)或 CODE(Borland)命名;
    .数据段,通常以 .data 、.rdata 或 .bss(Microsoft)、DATA(Borland)命名;
    .资源段,通常以 .rsrc命名;
    .导出表,通常以 .edata命名;
    .导入表,通常以 .idata命名;
    .调试信息段,通常以 .debug命名;

    1、DOS头结构

    所有的PE文件都是以一个64字节的DOS头开始。这个DOS头只是为了兼容早期的DOS操作系统。DOS头的结构如下:

    [cpp]  view plain  copy
    1. typedef struct IMAGE_DOS_HEADER{  
    2.       WORD e_magic;         //DOS头的标识,为4Dh和5Ah。分别为字母MZ  
    3.       WORD e_cblp;  
    4.       WORD e_cp;  
    5.       WORD e_crlc;  
    6.       WORD e_cparhdr;  
    7.       WORD e_minalloc;  
    8.       WORD e_maxalloc;  
    9.       WORD e_ss;  
    10.       WORD e_sp;  
    11.       WORD e_csum;  
    12.       WORD e_ip;  
    13.       WORD e_cs;  
    14.       WORD e_lfarlc;  
    15.       WORD e_ovno;  
    16.       WORD e_res[4];  
    17.       WORD e_oemid;  
    18.       WORD e_oeminfo;  
    19.       WORD e_res2[10];  
    20.       DWORD e_lfanew;             //指向IMAGE_NT_HEADERS的所在  
    21. }IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;  

    DOS头后跟一个DOS Stub数据,是链接器链接执行文件的时候加入的部分数据,一般是“This program must be run under Microsoft Windows”。这个可以通过修改链接器的设置来修改成自己定义的数据。

    2、PE头文件

        紧跟着DOS stub的时PE头文件(PE Header)。PE Header是PE相关结构NT映像头(IMAGE_NT_HEADER)的简称,其中包含许多PE装载器用到的重要字段。执行体在支持PE文件结构的操作系统中执行时,PE装载器将从IMAGE_DOS_HEADER结构中的e_lfanew字段里找到PE Header的起始偏移量,加上基址得到PE文件头的指针。

    PNTHeader = ImageBase + dosHeader->e_lfanew

    PE头的数据结构被定义为IMAGE_NT_HEADERS。包含三部分,其结构如下:

    [cpp]  view plain  copy
    1. typedef struct IMAGE_NT_HEADERS{  
    2.       DWORD Signature;  
    3.       IMAGE_FILE_HEADER FileHeader;  
    4.       IMAGE_OPTIONAL_HEADER32 OptionalHeader;  
    5. }IMAGE_NT_HEADERS,*PIMAGE_NT_HEADERS;   

    Signature字段: PE头的标识。双字结构。为50h, 45h, 00h, 00h. 即“PE\0\0”。

    FileHeader字段:IMAGE_FILE_HEADER(映像头文件)结构包含了文件的物理层信息及文件属性。共20字节的数据,其结构如下:

    [cpp]  view plain  copy
    1. typedef struct _IMAGE_FILE_HEADER {  
    2.     WORD    Machine;                    //运行平台  
    3.     WORD    NumberOfSections;           //文件的区块数目  
    4.     DWORD   TimeDateStamp;              //文件创建日期和时间  
    5.     DWORD   PointerToSymbolTable;       //指向符号表(用于调试)  
    6.     DWORD   NumberOfSymbols;            //符号表中符号个数(用于调试)  
    7.     WORD    SizeOfOptionalHeader;       //IMAGE_OPTIONAL_HEADER32结构大小  
    8.     WORD    Characteristics;            //文件属性  
    9. } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;  
    OptionalHeader字段: IMAGE_OPTIONAL_HEADER(可选映像头)是一个可选的机构,实际上 IMAGE_FILE_HEADER结构不足以定义PE文件属性,因此可选映像头中定义了更多的数据。 总共224个字节,最后128个字节为数据目录(Data Directory) ,其结构如下:
    [cpp]  view plain  copy
    1. typedef struct _IMAGE_OPTIONAL_HEADER {  
    2.     WORD    Magic;                          //标志字  
    3.     BYTE    MajorLinkerVersion;             //链接器主版本号  
    4.     BYTE    MinorLinkerVersion;             //链接器次版本号  
    5.     DWORD   SizeOfCode;                     //所有含有代码表的总大小  
    6.     DWORD   SizeOfInitializedData;          //所有初始化数据表总大小  
    7.     DWORD   SizeOfUninitializedData;        //所有未初始化数据表总大小  
    8.     DWORD   AddressOfEntryPoint;            //程序执行入口RVA  
    9.     DWORD   BaseOfCode;                     //代码表其实RVA  
    10.     DWORD   BaseOfData;                     //数据表其实RVA  
    11.     DWORD   ImageBase;                      //程序默认装入基地址  
    12.     DWORD   SectionAlignment;               //内存中表的对齐值  
    13.     DWORD   FileAlignment;                  //文件中表的对齐值  
    14.     WORD    MajorOperatingSystemVersion;    //操作系统主版本号  
    15.     WORD    MinorOperatingSystemVersion;    //操作系统次版本号  
    16.     WORD    MajorImageVersion;              //用户自定义主版本号  
    17.     WORD    MinorImageVersion;              //用户自定义次版本号  
    18.     WORD    MajorSubsystemVersion;          //所需要子系统主版本号  
    19.     WORD    MinorSubsystemVersion;          //所需要子系统次版本号  
    20.     DWORD   Win32VersionValue;              //保留,通常设置为0  
    21.     DWORD   SizeOfImage;                    //映像装入内存后的总大小  
    22.     DWORD   SizeOfHeaders;                  //DOS头、PE头、区块表总大小  
    23.     DWORD   CheckSum;                       //映像校验和  
    24.     WORD    Subsystem;                      //文件子系统  
    25.     WORD    DllCharacteristics;             //显示DLL特性的旗标  
    26.     DWORD   SizeOfStackReserve;             //初始化堆栈大小  
    27.     DWORD   SizeOfStackCommit;              //初始化实际提交堆栈大小  
    28.     DWORD   SizeOfHeapReserve;              //初始化保留堆栈大小  
    29.     DWORD   SizeOfHeapCommit;               //初始化实际保留堆栈大小  
    30.     DWORD   LoaderFlags;                    //与调试相关,默认值为0  
    31.     DWORD   NumberOfRvaAndSizes;            //数据目录表的项数  
    32.     IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];  
    33. } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;  
    DataDirectory是OptionalHeader的最后128个字节,也是IMAGE_NT_HEADERS的最后一部分数据。它由16个IMAGE_DATA_DIRECTORY结构组成的数组构成,指向输出表、输入表、资源块等数据。IMAGE_DATA_DIRECTORY的结构如下:
    [cpp]  view plain  copy
    1. typedef struct _IMAGE_DATA_DIRECTORY {  
    2.     DWORD   VirtualAddress;         //数据块的起始RVA  
    3.     DWORD   Size;                   //数据块的长度  
    4. } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;  

    数据表成员结构如下:

    [cpp]  view plain  copy
    1. #define IMAGE_DIRECTORY_ENTRY_EXPORT          0   // Export Directory  
    2. #define IMAGE_DIRECTORY_ENTRY_IMPORT          1   // Import Directory  
    3. #define IMAGE_DIRECTORY_ENTRY_RESOURCE        2   // Resource Directory  
    4. #define IMAGE_DIRECTORY_ENTRY_EXCEPTION       3   // Exception Directory  
    5. #define IMAGE_DIRECTORY_ENTRY_SECURITY        4   // Security Directory  
    6. #define IMAGE_DIRECTORY_ENTRY_BASERELOC       5   // Base Relocation Table  
    7. #define IMAGE_DIRECTORY_ENTRY_DEBUG           6   // Debug Directory  
    8. #define IMAGE_DIRECTORY_ENTRY_COPYRIGHT       7   // (X86 usage)  
    9. #define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE    7   // Architecture Specific Data  
    10. #define IMAGE_DIRECTORY_ENTRY_GLOBALPTR       8   // RVA of GP  
    11. #define IMAGE_DIRECTORY_ENTRY_TLS             9   // TLS Directory  
    12. #define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG    10   // Load Configuration Directory  
    13. #define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT   11   // Bound Import Directory in headers  
    14. #define IMAGE_DIRECTORY_ENTRY_IAT            12   // Import Address Table  
    15. #define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT   13   // Delay Load Import Descriptors  
    16. #define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14   // COM Runtime descriptor  

    用LordPE查看EXE文件的数据目录表:



    3、区块表

    3.1 区块结构

    在PE文件头与原始数据之间存在一个区块表(Section Table),它是一个IMAGE_SECTION_HEADER结构数组,区块表包含每个块在映像中的信息(如位置、长度、属性),分别指向不同的区块实体。全部有效结构的最后以一个空的IMAGE_SECTION_HEADER结构作为结束,所以节表中总的IMAGE_SECTION_HEADER结构数量等于节的数量加一。另外,节表中 IMAGE_SECTION_HEADER 结构的总数总是由PE文件头 IMAGE_NT_HEADERS->FileHeader.NumberOfSections 字段来指定的。


    IMAGE_SECTION_HEADER结构定义如下:

    [cpp]  view plain  copy
    1. typedef struct _IMAGE_SECTION_HEADER {  
    2.     Name                        //8个字节的块名  
    3.     union                         
    4.     {  
    5.         DWORD PhysicalAddress;  
    6.         DWORD VirtualSize;  
    7.     } Misc;                     //区块尺寸</span>  
    8.     DWORD VirtualAddress;       //区块的RVA地址  
    9.     DWORD SizeOfRawData;        //在文件中对齐后的尺寸  
    10.     DWORD PointerToRawData;     //在文件中偏移  
    11.     DWORD PointerToRelocations; //在OBJ文件中使用,重定位的偏移  
    12.     DWORD PointerToLinenumbers; //行号表的偏移(供调试使用地)  
    13.     WORD NumberOfRelocations;   //在OBJ文件中使用,重定位项数目  
    14.     WORD NumberOfLinenumbers;   //行号表中行号的数目  
    15.     DWORD Characteristics;      //区块属性如可读,可写,可执行等  
    16. } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;  

    (1)Name:这是一个8位的ASCII(不是Unicode内码),用来定义块名,多数块名以,开始(如.Text),这个实际上不是必需的,注意如果块名超过了8个字节,则没有最后面的终止标志NULL字节,带有$的区块的名字会从编译器里将带有$的相同名字的区块被按字母顺序合并。
    (2) VirtualSize:指出实际的,被使用的区块大小,是区块在没有对齐处理前的实际大小.如果VirtualSize > SizeOfRawData,那么SizeOfRawData是可执行文件初始化数据的大小(SizeOfRawData – VirtualSize)的字节用0来填充。这个字段在OBJ文件中被设为0。
    (3)VirtualAddress:该块时装载到内存中的RVA,注意这个地址是按内存页对齐的,她总是SectionAlignment的整数倍,在工具中第一个块默认RVA为1000,在OBJ中为0。
    (4)SizeofRawData:该块在磁盘中所占的大小,在可执行文件中,该字段包括经过FileAlignment调整后块的长度。例如FileAlignment的大小为200h,如果VirtualSize中的块长度为19Ah个字节,这一块保存的长度为200h个字节。
    (5) PointerToRawData:该块是在磁盘文件中的偏移,程序编译或汇编后生成原始数据,这个字段用于给出原始数据块在文件的偏移,如果程序自装载PE或COFF文件(而不是由OS装载),这种情况,必须完全使用线性映像方法装入文件,需要在该块处找到块的数据。
    (6) PointerToRelocations 在PE中无意义
    (7) PointerToLinenumbers 行号表在文件中的偏移值,文件调试的信息
    (8) NumberOfRelocations 在PE中无意义
    (9) NumberOfLinenumbers 该块在行号表中的行号数目
    (10) Characteristics 块属性,(如代码/数据/可读/可写)的标志,这个值可通过链接器的/SECTION选项设置.下面是比较重要的标志:


    通常,区块中的数据在逻辑上是关联的。PE 文件一般至少都会有两个区块:一个是代码块,另一个是数据块。每一个区块都需要有一个截然不同的名字,这个名字主要是用来表达区块的用途。例如有一个区块叫.rdata,表明他是一个只读区块。注意:区块在映像中是按起始地址(RVA)来排列的,而不是按字母表顺序。
    另外,使用区块名字只是人们为了认识和编程的方便,而对操作系统来说这些是无关紧要的。微软给这些区块取了个有特色的名字,但这不是必须的。当编程从PE 文件中读取需要的内容时,如输入表、输出表,不能以区块名字作为参考,正确的方法是按照数据目录表中的字段来进行定位。

    区块名称以及意义:


    每个区块的名称都是唯一的,不能有同名的两个区块。但事实上节的名称不代表任何含义,他的存在仅仅是为了正规统一编程的时候方便程序员查看方便而设置的一个标记而已。所以将包含代码的区块命名为“.Data” 或者说将包含数据的区块命名为“.Code” 都是合法的。当我们要从PE 文件中读取需要的区块时候,不能以区块的名称作为定位的标准和依据,正确的方法是按照 IMAGE_OPTIONAL_HEADER32 结构中的数据目录字段结合进行定位。

    在Visual C++中,用#pragma来声明,告诉编译器插入数据到一个区块内:

    #pragma data_seg("MY_DATA")

    链接器的一个有趣特征就是能够合并区块。如果两个区块有相似、一致性的属性,那么它们在链接的时候能被合并成一个单一的区块。这取决于是否开启编译器的 /merge 开关。下面的链接器选项将.rdata与.text区块合并为一个.text区块:

    /MERGE : .rdata = .text

    注意:当合并区块时,因为这没有什么硬性规定。例如,把.rdata合并到.text里不会有什么问题,但是不应该将.rsrc、.reloc或者.pdata合并到其它的区块里。

    3.2 区块的对齐

        区块大小是要对齐的,有两种对齐值,一种用于磁盘文件内,另一种用于内存中。PE文件头指出了这两个值,他们可以不同。PE 文件头里边的FileAligment 定义了磁盘区块的对齐值。每一个区块从对齐值的倍数的偏移位置开始存放。而区块的实际代码或数据的大小不一定刚好是这么多,所以在多余的地方一般以00h 来填充,这就是区块间的间隙。例如,在PE文件中,一个典型的对齐值是200h ,这样,每个区块都将从200h 的倍数的文件偏移位置开始,假设第一个区块在400h 处,长度为90h,那么从文件400h 到490h 为这一区块的内容,而由于文件的对齐值是200h,所以为了使这一区块的长度为FileAlignment 的整数倍,490h 到 600h 这一个区间都会被00h 填充,这段空间称为区块间隙,下一个区块的开始地址为600h 。
        PE 文件头里边的SectionAligment 定义了内存中区块的对齐值。PE 文件被映射到内存中时,区块总是至少从一个页边界开始。一般在X86 系列的CPU 中,页是按4KB(1000h)来排列的;在IA-64 上,是按8KB(2000h)来排列的。所以在X86 系统中,PE文件区块的内存对齐值一般等于 1000h,每个区块按1000h 的倍数在内存中存放。

    3.3 文件偏移与RVA

    由于一些PE文件为减少体积,磁盘对齐值不是一个内存页 1000h,而是 200h,当这类文件被映射到内存后,同一数据相对于文件头的偏移量在内存中和磁盘文件中是不同的,这样就存在着文件偏移地址与虚拟地址的转换问题。


    由上图可以看出,文件被映射到内存,DOS文件头,PE文件头,区块表的偏移位置和大小都没有发生改变。而各区块映射到内存后,起偏移位置发生了改变。
    转换需要前面提到的一个公式:设:
    ΔK为相对虚拟地址RVA与文件偏移地址File Offset的差值
    VA = ImageBase + RVA
    File Offset = RVA - ΔK
    File Offset = VA - ImageBase - ΔK

    3.3 输入表

    3.3.1 输入表地址定位

        PE文件头可选映像头中数据目录表的第二成员指向输入表,输入表以一个 IAMGE_IMPORT_DESCRITPTOR 数组开始,每个被PE文件隐式地链接进来的DLL都有一个IID,在这个数组中没有字段指出该结构数组的项数,但他最后一个单元是NULL。

        数据目录表的第二成员 IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] 就对应输入表。回忆文章上面内容可知,数据目录表 IMAGE_DATA_DIRECTORY 中结构成员 VirtualAddress 就是输入表的RVA了,而区块表 IMAGE_SECTION_HEADER 中结构成员 VirtualAddress 对应区块的RVA。通过输入表的RVA与区块的RVA比较,我们就能知道输入表在哪个区块里面。

    3.3.2 输入表结构

    IID的结构如下:

    [cpp]  view plain  copy
    1. STRUCT IAMGE_IMPORT_DESCRIPTOR  
    2. {  
    3.     union  
    4.     {  
    5.         DWORD Characteristics;  
    6.         DWORD OriginalFirstThunk;    //指向输入名称表(INT)的RVA  
    7.     }  
    8.     DWORD TimeDateStamp;             //一个32位的时间标志  
    9.     DWORD ForwarderChain;            //这是一个被转向API的索引,一般为0  
    10.     DWORD Name;                      //DLL名字,是个以00结尾的ASCII字符的RVA地址  
    11.     DWORD FirstThunk;                //指向输入地址表(IAT)的RVA  
    12. } ;  

        通过上图 OriginalFisrtThunk 和 FirstThunk 非常相似,两个数组都有一个IMAGE_THUNK_DATA结构类型的元素,他是一个指针大小的联合,每一个IAMGE_THUNK_DATA元素对应于一个从可执行文件输入的函数,两个数组的结束通过一个值为零的IAMGE_THUNK_DATA元素表示的,IMAGE_THUNK_DATA结构实际上是一个双字,该结构不同时刻有不同的含义,定义如下:

    [cpp]  view plain  copy
    1. STRUCT IMAGE_THUNK_DATA  
    2. {  
    3.     union u1  
    4.       DWORD ForwarderString;    //指向一个转向者字符串的RVA  
    5.       DWORD Function;           //被输入的函数的内存地址  
    6.       DWORD Ordinal;            //被输入的API的序数值  
    7.       DWORD AddressOfData;      //指向IAMGE_IMPORT_BY_NAME  
    8.     ends  
    9. };  

    (1)OriginalFirstThunk:它指向输入名称表(简称INT),INT是一个 IMAGE_THUNK_DATA 结构的数组,数组中的每个 IMAGE_THUNK_DATA 结构的成员 AddressOfData都指向IMAGE_IMPORT_BY_NAME结构。
    (2)TimeDateStamp:一个32位时间标志,该字段可以忽略。
    (3)ForwarderChain:当程序引用一个DLL中的API,而这个API又引用别的DLL的API时使用,这种情况很少出现。
    (4)Name:它表示DLL 名称的相对虚地址(译注:相对一个用null作为结束符的ASCII字符串的一个RVA,该字符串是该导入DLL文件的名称,如:KERNEL32.DLL)。
    (5)FirstThunk:它指向输入地址表(简称IAT),IAT是一个 IMAGE_THUNK_DATA 结构的数组。

        IAMGE_THUNK_DATA 值的最高位为1时,表示函数以序列号方式输入,这时低31位(或者一个64位可执行文件的低63位)被看做是一个函数序号,当双字的最高位为0时,表示函数以字符串类型的函数名方式输入,这时双字的值是一个RVA,指向一个IAMGE_IMPORT_BY_NAME结构,该结构定义如下:

    [cpp]  view plain  copy
    1. STRUCT  IAMGE_IMPORT_BY_NAME  
    2. {  
    3.     DWORD Hint;    //本函数在其所驻留DLL的输出表中的序号   
    4.     BYTE  name     //输入函数的函数名,函数名是一个ASCII码字符串,以NULL结尾  
    5. };  

        为什么由两个并行的指针数组指向IAMGE_IMPORT_BY_NAME结构呢?
        第一个数组(由OriginalFirstThunk所指向)是但单独的一项,而且不可改变,成为INT,第二个数组(由FirstThunk所指向)是由PE装载器重写的,PE装载器首先搜索OriginalFirstThunk,如果找到了,加载程序迭代搜索数组中的每个指针,找到每个 IMAGE_IMPORT_BY_NAME 结构所指向的输入函数的地址,然后加载器用函数真实入口地址来代替由FirstThunk指向的 IAMGE_IMPORT_BY_NAME 数组所指向数组里的元素值,JMP dword ptr[xxxxxxxx]中的[xxxxxxxx]指向FirstThunk 数组中的一个入口,所以当PE文件装载内存后准备执行时,所有函数入口地址被排列在一起,此时输入表中其他就不重要的,依靠IAT提供地址就可以正常运行。


        有些情况,一些函数仅由序号引出,也就是说不能用函数名来调用它,只能通过位置调用它,此时 IMAGE_THUNK_DATA 的值低位字指示函数序数,而高二进位(MSB)设为1,Microsoft提供了一个方便的常量测量DWORD值的MSB位,就是 IMAGE_ORDINAL_FLAG32,其值是80000000h。第二是程序的 OriginalFirstThunk 的值为0,初始化时,系统根据FirstThunk 的值指向函数名的地址串,由地址串找到函数名,再根据函数名入口地址,然后用入口地址取代 FirstThunk 指向的地址串的原值。

    3.3 输出表
        输出表(Export Table)包含函数名称,输出序数等,序数是指定DLL中某个函数的16位数字,在所指向的DLL里是独一无二的。数据目录表中的第一个成员 IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] 指向输出表。输出表 IAMGE_EXPORT_DIRECTORY 结构如下:

    [cpp]  view plain  copy
    1. STRUCT  IAMGE_EXPORT_DIRECTORY  
    2. {  
    3.     DWORD Characteristics;          //未使用,总为0  
    4.     DWORD TimeDateStamp;            //创建输出表创建时间(GMT时间)  
    5.     WORD MajorVersion;              //主版本号,一般为0  
    6.     WORD MinorVersion;              //次版本号,一般为0  
    7.     DWORD Name;                     //模块的真实名称  
    8.     DWORD Base;                     //基数,加上序数就是函数数组的索引值  
    9.     DWORD NumberOfFunctions;        //AddressOfFunctions阵列中的元素个数  
    10.     DWORD NumberOfNames;            //AddressOfNameS阵列中的元素个数  
    11.     DWORD AddressOfFunctions;       //指向函数地址数组  
    12.     DWORD AddressOfNames;           //函数名字的指针地址  
    13.     DWORD AddressOfNameOrdinals;    //指向输出序号数组  
    14. };  
    Name: 指向一个ASCII字符串的RVA,既模块的名字。
    Base: 序号的基数,按序号导出函数的序号值从Base开始递增。当通过序数来查询一个输出函数时,这个值从序数里被减去,结果被用作进入输出地址表(EAT)的索引。
    NumberOfFunctions: 输出地址表(EAT)中的条目数量,即所有导出函数的数量。
    NumberOfNames: 输出名称表(ENT)中的条目数量,即 按名称导出函数的数量,这个值总是小于或者等于NumberOfFunctions的值。
    AddressOfFunctions: EAT的RVA,指向一个DWORD数组,数组中的每一项是一个导出函数的RVA,顺序与导出序号相同。
    AddressOfNames: ENT的RVA,指向一个DWORD数组,数组中的每一项仍然是一个RVA,指向一个表示函数名字。

    AddressOfNameOrdinals:输出序数表的RVA,指向一个WORD数组。数组中的每一项与AddressOfNames中的每一项对应,表示该名字的函数在AddressOfFunctions中的序号。

    下图是一个经典的输出表结构:


    3.4 基址重定位

        重定位就是你本来这个程序理论上要占据这个地址,但是由于某种原因,这个地址现在不能让你霸占,你必须转移到别的地址,这就需要基址重定位。如果可执行文件不在首选的地址装入,那么文件中每一个定位都需要被修正。对加载器来说,它不需要知道关于地址如何使用的任何细节,它只需要知道有一系列的数据需要以某种一致的方式来修正就可以了。

        对于EXE文件来说,每个文件总是使用独立的虚拟地址空间,所以EXE总能够按照这个地址装入,不需要重定位信息。而对于DLL来说,由于多个DLL文件全部使用宿主EXE文件的地址空间,不能保证装入地址没有被其它的DLL使用,所以DLL文件中必须包含重定位信息。

        下面以实例 DllDemo.DLL为例讲述其定位过程。

    [cpp]  view plain  copy
    1. ......  
    2. :0040100E  6800204000               push  00402000  
    3. ......  
        在这个例子中汇编语句将一个指针压栈,402000h是某一字符串的指针。指令是来自一个基置为 00400000h 的DLL文件,因此这个字符串的RVA是2000h。如果DLL确实在 00400000h 处装入,那么指令能够按照现在的样子正确执行。假设当DLL执行时,Windows加载器决定将其映射到 870000h 处,此时就需要进行基址重定位,计算方式如下:

    402000h + (870000h - 400000h)= 872000h

        基址重定位表(Base Relocation Table)位于一个叫.reloc 的区块内,但是找到它们正确方式是通过数据目录表的 IMAGE_DIRECTORY_ENTRY_BASERELOC 条目。基址重定位数据组织方法采用类似按页分割的方法,其许多重定位块串接在成的,每个块存放4KB(1000h)大小的重定位信息,每个重定位数据块的大小必须以DWORD(4字节)对齐,他们以IMAGE_BASE_RELOCATION 结构开始,格式如下:

    [cpp]  view plain  copy
    1. STRUCT IMAGE_BASE_RELOCATION  
    2. {  
    3.     DWORD VirtualAddress;     //重定位数据开始RVA地址  
    4.     DWORD SizeOfSlock;       //重定位块的长度  
    5.     WORD TypeOffset;          //重定项位数组  
    6. };  

    VirtualAddress:这是一组重定位数据的开始RVA地址,各重定位项的地址加上这个值才是重定位项完整的RVA地址。
    SizeOfBlock:是当前重定位结构的大小,因为VirtualAddress 和 SizeOfBlock 大小都是固定的4个字节,因此这个项减去8,则是TypeOffset 大小。
    TypeOffset:是一个数组。数组每项大小为两个字节,共16位,它又分为高4位与低12位,高四位代表重定位类型,低12位是重定位的地址,与VirtualAddress 相加即是指向PE映像中需要修改地址数据的指针。
        对于X86 可执行文件,所有的基址重定位类型都是IMAGE_REL_BASED_HIGHLOW,在一组重定位结束的地方会出现一个类型是IAMGE_REL_BASED_ABSOLUTE的重定位,这些重定位什么都不做,在哪里只是填充,以便下一个IAMGE_BASE_RELOCATION 是以4个字节分界线来对齐,所有重定位最终以一个 VirtualAddress 字段为0的 IAMGE_BASE_RELOCATION 结构对齐。


        重定位表的结构如下图,由数个 IMAGE_BASE_RELOCATION 结构组成,每个结构VirtualAddress,SizeOfSlock 和 TypeOffset 三部分组成。


    展开全文
  • Windows 系统中的文件路径格式

    千次阅读 2019-05-17 23:10:00
    title: Windows 系统中的文件路径格式 ms.date: 06/28/2018 ms.technology: dotnet-standard dev_langs: csharp vb helpviewer_keywords: I/O, long paths long paths path formats, Windows author: ...

    System.IO命名空间中很多类型的成员都包括 path 参数,让你可以指定指向某个文件系统资源的绝对路径或相对路径。 此路径随后会传递至 Windows 文件系统 API。 本主题讨论可在 Windows 系统上使用的文件路径格式。

    传统 DOS 路径

    标准的 DOS 路径可由以下三部分组成:

    • 卷号或驱动器号,后跟卷分隔符 (:)。
    • 目录名称。 目录分隔符用来分隔嵌套目录层次结构中的子目录。
    • 可选的文件名。 目录分隔符用来分隔文件路径和文件名。

    如果以上三项都存在,则为绝对路径。 如未指定卷号或驱动器号,且目录名称的开头是目录分隔符,则路径属于当前驱动器根路径上的相对路径。 否则路径相对于当前目录。 下表显示了一些可能出现的目录和文件路径。

    路径说明
    C:\Documents\Newsletters\Summer2018.pdfC: 盘根路径上的绝对文件路径。
    \Program Files\Custom Utilities\StringFinder.exe当前驱动器根路径上的绝对路径。
    2018\January.xlsx指向当前目录的子目录中的文件的相对路径。
    ..\Publications\TravelBrochure.pdf指向当前目录的同级目录中的文件的相对路径。
    C:\Projects\apilibrary\apilibrary.sln指向 C: 盘根路径中的文件的绝对路径。
    C:Projects\apilibrary\apilibrary.slnC: 盘当前目录上的相对路径。

    请注意最后两个路径之间的差异。 两者都指定了可选的卷说明符(均为“C:”),但前者以所指定卷的根开头,而后者不是。 结果,前者表示 C: 盘根目录上的绝对路径,而后者表示 C: 盘当前目录上的相对路径。 应使用前者时使用了后者是涉及 Windows 文件路径的 bug 的常见原因。

    可以通过调用 System.IO.Path.IsPathFullyQualified方法来确定文件路径是否完全限定(即是说,该路径独立于当前目录,且在当前目录更改时不发生变化)。 请注意,如果解析的路径始终指向同样的位置,那么此类路径可以包括相对目录段(...),而同时依然是完全限定的。

    以下示例演示绝对路径和相对路径之间的差异。 假定存在目录 D:\FY2018\,且在运行该示例之前还没有通过命令提示符为 D:\ 设置任何当前目录。

    using System;
    using System.Diagnostics;
    using System.IO;
    using System.Reflection;
    
    public class Example
    {
       public static void Main(string[] args)
       {
          Console.WriteLine($"Current directory is '{Environment.CurrentDirectory}'");
          Console.WriteLine("Setting current directory to 'C:\\'");
          
          Directory.SetCurrentDirectory(@"C:\");
          string path = Path.GetFullPath(@"D:\FY2018");
          Console.WriteLine($"'D:\\FY2018' resolves to {path}");
          path = Path.GetFullPath(@"D:FY2018");
          Console.WriteLine($"'D:FY2018' resolves to {path}");
    
          Console.WriteLine("Setting current directory to 'D:\\Docs'");
          Directory.SetCurrentDirectory(@"D:\Docs");
    
          path = Path.GetFullPath(@"D:\FY2018");
          Console.WriteLine($"'D:\\FY2018' resolves to {path}");
          path = Path.GetFullPath(@"D:FY2018");
    
          // This will be "D:\Docs\FY2018" as it happens to match the drive of the current directory
          Console.WriteLine($"'D:FY2018' resolves to {path}");
    
          Console.WriteLine("Setting current directory to 'C:\\'");
          Directory.SetCurrentDirectory(@"C:\");
    
          path = Path.GetFullPath(@"D:\FY2018");
          Console.WriteLine($"'D:\\FY2018' resolves to {path}");
    
          // This will be either "D:\FY2018" or "D:\FY2018\FY2018" in the subprocess. In the sub process,
          // the command prompt set the current directory before launch of our application, which
          // sets a hidden environment variable that is considered.
          path = Path.GetFullPath(@"D:FY2018");
          Console.WriteLine($"'D:FY2018' resolves to {path}");
    
          if (args.Length < 1)
          {
             Console.WriteLine(@"Launching again, after setting current directory to D:\FY2018");
             Uri currentExe = new Uri(Assembly.GetExecutingAssembly().GetName().CodeBase, UriKind.Absolute);
             string commandLine = $"/C cd D:\\FY2018 & \"{currentExe.LocalPath}\" stop";
             ProcessStartInfo psi = new ProcessStartInfo("cmd", commandLine); ;
             Process.Start(psi).WaitForExit();
    
             Console.WriteLine("Sub process returned:");
             path = Path.GetFullPath(@"D:\FY2018");
             Console.WriteLine($"'D:\\FY2018' resolves to {path}");
             path = Path.GetFullPath(@"D:FY2018");
             Console.WriteLine($"'D:FY2018' resolves to {path}");
          }
          Console.WriteLine("Press any key to continue... ");
          Console.ReadKey();
       }
    }
    // The example displays the following output:
    //      Current directory is 'C:\Programs\file-paths'
    //      Setting current directory to 'C:\'
    //      'D:\FY2018' resolves to D:\FY2018
    //      'D:FY2018' resolves to d:\FY2018
    //      Setting current directory to 'D:\Docs'
    //      'D:\FY2018' resolves to D:\FY2018
    //      'D:FY2018' resolves to D:\Docs\FY2018
    //      Setting current directory to 'C:\'
    //      'D:\FY2018' resolves to D:\FY2018
    //      'D:FY2018' resolves to d:\FY2018
    //      Launching again, after setting current directory to D:\FY2018
    //      Sub process returned:
    //      'D:\FY2018' resolves to D:\FY2018
    //      'D:FY2018' resolves to d:\FY2018
    // The subprocess displays the following output:
    //      Current directory is 'C:\'
    //      Setting current directory to 'C:\'
    //      'D:\FY2018' resolves to D:\FY2018
    //      'D:FY2018' resolves to D:\FY2018\FY2018
    //      Setting current directory to 'D:\Docs'
    //      'D:\FY2018' resolves to D:\FY2018
    //      'D:FY2018' resolves to D:\Docs\FY2018
    //      Setting current directory to 'C:\'
    //      'D:\FY2018' resolves to D:\FY2018
    //      'D:FY2018' resolves to D:\FY2018\FY2018
    

    UNC 路径

    通用命名约定 (UNC) 路径,用于访问网络资源,具有以下格式:

    • 一个以 \\ 开头的服务器名或主机名。 服务器名称可以为 NetBIOS 计算机名称或者 IP/FQDN 地址(支持 IPv4 和 IPv6)。
    • 共享名,使用 \ 将其与主机名分隔开。 服务器名和共享名共同组成了卷。
    • 目录名称。目录分隔符(System.IO.Path.DirectorySeparatorChar)用来分隔嵌套目录层次结构中的子目录。
    • 可选的文件名。 目录分隔符用来分隔文件路径和文件名。

    以下是一些 UNC 路径的示例:

    路径说明
    \\system07\C$\system07 上 C: 盘的根目录。
    \\Server2\Share\Test\Foo.txt\\Server2\Share 卷的测试目录中的 Foo.txt 文件。

    UNC 路径必须始终是完全限定的。 它们可以包括相对目录段(...),但是这些目录段必须是完全限定的路径的一部分。 只能通过将 UNC 路径映射至驱动器号来使用相对路径。

    DOS 设备路径

    Windows 操作系统有一个指向所有资源(包括文件)的统一对象模型。 可从控制台窗口访问这些对象路径;并通过旧版 DOSUNC 路径映射到的符号链接的特殊文件,将这些对象路径公开至 Win32 层。 此特殊文件夹可通过 DOS 设备路径语法(以下任一)进行访问:

    \\.\C:\Test\Foo.txt
    \\?\C:\Test\Foo.txt

    从 NET Core 1.1 和 .NET Framework 4.6.2 开始,运行在 Windows 上的 .NET 实现支持 DOS 设备路径语法。

    DOS 设备路径由以下部分组成:

    • 设备路径说明符(\\.\\\?\),它将路径标识为 DOS 设备路径。

      .NET Core 的所有版本以及从 4.6.2 开始的 .NET Framework 版本都支持 \\?\

    • 指向“真正”设备对象(这里是 C:)的符号链接。

      设备路径说明符后的第一个 DOS 设备路径段标识了卷或驱动器。 (例如,\\?\C:\\\.\BootPartition\。)

      UNC 有个特定的链接,很自然地名为 UNC。 例如:

      \\.\UNC\Server\Share\Test\Foo.txt
      \\?\UNC\Server\Share\Test\Foo.txt

      对于设备 UNC,服务器/共享部分构成了卷。 例如,在 \\?\server1\e:\utilities\\filecomparer\ 中,服务器/共享部分是 server1\utilities。 使用相对目录段调用Path.GetFullPath(System.String,System.String)等方法时,这一点非常重要;决不可能越过卷。

    DOS 设备路径通过定义进行完全限定。 不允许使用相对目录段(...)。 也不会包含当前目录。

    示例:引用同一个文件的方法

    以下示例演示了一些方法,以此可在使用System.IO命名空间中的 API 时引用文件。 该示例实例化 System.IO.FileInfo 对象,并使用它的 System.IO.FileInfo.NameFileInfo.Length属性来显示文件名以及文件长度。

    using System;
    using System.IO;
    
    class Program
    {
        static void Main()
        {
            string[] filenames = {
                @"c:\temp\test-file.txt",
                @"\\127.0.0.1\c$\temp\test-file.txt",
                @"\\LOCALHOST\c$\temp\test-file.txt",
                @"\\.\c:\temp\test-file.txt",
                @"\\?\c:\temp\test-file.txt",
                @"\\.\UNC\LOCALHOST\c$\temp\test-file.txt",
                @"\\127.0.0.1\c$\temp\test-file.txt" };
    
            foreach (var filename in filenames)
            {
                FileInfo fi = new FileInfo(filename);
                Console.WriteLine($"file {fi.Name}: {fi.Length:N0} bytes");
            }
        }
    }
    // The example displays output like the following:
    //      file test-file.txt: 22 bytes
    //      file test-file.txt: 22 bytes
    //      file test-file.txt: 22 bytes
    //      file test-file.txt: 22 bytes
    //      file test-file.txt: 22 bytes
    //      file test-file.txt: 22 bytes
    //      file test-file.txt: 22 bytes
    

    路径规范化

    几乎所有传递至 Windows API 的路径都经过规范化。 规范化过程中,Windows 执行了以下步骤:

    • 识别路径。
    • 将当前目录应用于部分限定(相对)路径。
    • 规范化组件和目录分隔符。
    • 评估相对目录组件(当前目录是 .,父目录是 ..)。
    • 剪裁特定字符。

    这种规范化隐式进行,若想显式进行规范化,可以调用 Path.GetFullPath方法,这会包装对 GetFullPathName() 函数的调用。 还可以使用 P/Invoke 直接调用 Windows GetFullPathName() 函数

    识别路径

    路径规范化的第一步就是识别路径类型。 路径归为以下几个类别之一:

    • 它们是设备路径;就是说,它们的开头是两个分隔符和一个问号或句点(\\?\\.)。
    • 它们是 UNC 路径;就是说,它们的开头是两个分隔符,没有问号或句点。
    • 它们是完全限定的 DOS 路径;就是说,它们的开头是驱动器号、卷分隔符和组件分隔符 (C:\)。
    • 它们指定旧设备(CONLPT1)。
    • 它们相对于当前驱动器的根路径;就是说,它们的开头是单个组件分隔符 (\)。
    • 它们相对于指定驱动器的当前目录;就是说,它们的开头是驱动器号和卷分隔符,而没有组件分隔符 (C:)。
    • 它们相对于当前目录;就是说,它们的开头是上述情况以外的任何内容 (temp\testfile.txt)。

    路径的类型决定是否以某种方式应用当前目录。 还决定该路径的“根”是什么。

    处理旧设备

    如果路径是旧版 DOS 设备(例如 CON``COM1LPT1),则会转换为设备路径(方法是在其前面追加 \\.\)并返回。

    开头为旧设备名的路径始终被 Path.GetFullPath(System.String)方法解释为旧设备。 例如,CON.TXT 的 DOS 设备路径为 \\.\CON,而 COM1.TXT\file1.txt 的 DOS 设备路径为 \\.\COM1

    应用当前目录

    如果路径非完全限定,Windows 会向其应用当前目录。 不会向 UNC 和设备路径应用当前目录。 带有分隔符 C:\\ 的完整驱动器也不会。

    如果路径的开头是单个组件分隔符,则会应用当前目录中的驱动器。 例如,如果文件路径是 \utilities 且当前目录为 C:\temp\,规范化后路径则为 C:\utilities

    如果路径开头是驱动器号和卷分隔符,而没有组件分隔符,则应用从命令行界面为指定驱动器设置的最新当前目录。 如未设置最新当前目录,则只应用驱动器。 例如,如果文件路径为 D:sources,当前目录为 C:\Documents\,且 D: 盘上的最新当前目录为 D:\sources\,则结果为 D:\sources\sources。 这些“驱动器相对”路径是导致程序和脚本逻辑错误的常见原因。 假设以字母和冒号开头的路径不是相对路径,显然是不正确的。

    如果路径不是以分隔符开头的,则应用当前驱动器和当前目录。 例如,如果路径是 filecompare 且当前目录是 C:\utilities\,则结果为 C:\utilities\filecompare\

    相对路径在多线程应用程序(也就是大多数应用程序)中很危险,因为当前目录是分进程的设置。 任何线程都能在任何时候更改当前目录。 从 .NET Core 2.1 开始,可以调用 Path.GetFullPath(System.String,System.String)方法,从想要据此解析绝对路径的相对路径和基础路径(当前目录)获取绝对路径。

    规范化分隔符

    将所有正斜杠 (/) 转换为标准的 Windows 分隔符,也就是反斜杠 (\)。 如果存在斜杠,前两个斜杠后面的一系列斜杠都将折叠为一个斜杠。

    评估相对组件

    处理路径时,会评估所有由一个或两个句点(...)组成的组件或分段:

    • 如果是单句点,则删除当前分段,因为它表示当前目录。

    • 如果是双句点,则删除当前分段和父级分段,因为双句点表示父级目录。

      仅当父级目录未越过路径的根时,才删除父级目录。 路径的根取决于路径的类型。 对于 DOS 路径,根是驱动器 (C:\);对于UNC,根是服务器/共享 (\\Server\Share);对于设备路径,则为设备路径前缀(\\?\\\.\)。

    剪裁字符

    随着分隔符的运行和相对段先遭删除,一些其他字符在规范化过程中也删除了:

    • 如果某段以单个句点结尾,则删除此句点。 (单个或两个句点的段在之前的步骤中已规范化。 三个或更多句点的段未规范化,并且实际上是有效的文件/目录名。)

    • 如果路径的结尾不是分隔符,则删除所有尾随句点和空格 (U+0020)。 如果最后的段只是单个或两个句点,则按上述相对组件规则处理。

      此规则意味着可以创建以空格结尾的目录名称,方法是在空格后添加结尾分隔符。

      请勿创建以空格结尾的目录名或文件名。 如果以空格结尾,则可能难以或者无法访问目录,并且应用程序在尝试处理这样的目录或文件时通常会操作失败。

    跳过规范化

    一般来说,任何传递到 Windows API 的路径都会(有效地)传递到 GetFullPathName 函数并进行规范化。 但是有一种很重要的例外情况:以问号(而不是句点)开头的设备路径。 除非路径确切地以 \\?\ 开头(注意使用的是规范的反斜杠),否则会对它进行规范化。

    为什么要跳过规范化过程? 主要有三方面的原因:

    1. 为了访问那些通常无法访问但合法的路径。 例如名为 hidden. 的文件或目录,这是能访问它的唯一方式。

    2. 为了在已规范化的情况下通过跳过规范化过程来提升性能。

    3. 为了跳过路径长度的 MAX_PATH 检查以允许多于 259 个字符的路径(仅在 .NET Framework 上)。 大多数 API 都允许这一点,也有一些例外情况。

    .NET Core 显式处理长路径,且不执行 MAX_PATH 检查。 MAX_PATH 检查只适用于 .NET Framework。

    跳过规范化和路径上限检查是两种设备路径语法之间唯一的区别;除此以外它们是完全相同的。 请谨慎地选择跳过规范化,因为很容易就会创建出“一般”应用程序难以处理的路径。

    如果将开头为 \\?\ 的路径显式地传递至 GetFullPathName 函数,则依然会对它们进行规范化。

    请注意,可将超过 MAX_PATH 字符数的路径传递至 GetFullPathName,前提是该路径不含 \\?\。 支持任意长度的路径,只要其字符串大小在 Windows 能处理的范围内。

    大小写和 Windows 文件系统

    Windows 文件系统有一个让非 Window 用户和开发人员感到困惑的特性,就是路径和目录名称不区分大小写。 也就是说,目录名和文件名反映的是创建它们时所使用的字符串的大小写。 例如,名为

    Directory.Create("TeStDiReCtOrY");
    

    的方法创建名为 TeStDiReCtOrY 的目录。 如果重命名目录或文件以改变大小写,则目录名或文件名反映的是重命名它们时所使用的字符串的大小写。 例如,以下代码将文件 test.txt 重命名为 Test.txt

    using System.IO;
    
    class Example
    {
       static void Main()
       {
          var fi = new FileInfo(@".\test.txt");
          fi.MoveTo(@".\Test.txt");
       }
    }
    

    但是比较目录名和文件名时不区分大小写。 如果搜索名为“test.txt”的文件,.NET 文件系统 API 会在比较时忽略大小写问题。Test.txt、TEST.TXT、test.TXT 和其他任何大写和小写的字母组合都会成为“test.txt”的匹配项。

    展开全文
  • 论文文献引用格式总结整理

    万次阅读 多人点赞 2018-06-26 15:32:54
    毕业论文参考文献规范格式  一、参考文献的类型  参考文献(即引文出处)的类型以单字母方式标识,具体如下:  M——专著 C——论文集 N——报纸文章  J——期刊文章 D——学位论文 R——报告  对于不属于...
  • obj文件格式详解及示例

    千次阅读 2021-07-30 14:46:47
    OBJ文件是Alias|Wavefront公司为它的一套基于工作站的3D建模和动画软件"Advanced Visualizer"开发的一种标准3D模型文件格式,很适合用于3D软件模型之间的互导,也可以通过Maya读写。比如你在3dsMax或LightWave中建了...
  • XML文件格式说明

    千次阅读 2020-07-22 17:22:25
    文章目录XML简介XML文件内容示例XML组成XML声明XML 元素XML命名规则XML基本语法形式良好的XML文档 XML简介  XML全称是Extensible Markup Language,中文译为可扩展的标记语言,它是SGML(标准通用标记语言)的一个...
  • endnote引用格式自定义

    万次阅读 2019-02-22 20:05:44
    有时候endnote默认的期刊格式不见得正确,这时候就需要进行手动改进了。下面进行一些常用自定义进行介绍。 可以参考教程:https://kemh.libguides.com/library/endnote/getting_started,写的非常全面 output ...
  • elf文件格式解析

    千次阅读 2019-05-20 09:38:11
    文件(目标文件格式主要三种: 1) 可重定向文件文件保存着代码和适当的数据,用来和其他的目标文件一起来创建一个可执行文件或者是一个共享目标文件。(目标文件或者静态库文件,即linux通常后缀为.a和.o的...
  • arXiv上引用文章在bibtex下的引用格式

    万次阅读 多人点赞 2020-01-29 22:00:43
    1. 推荐一个网站,输入arXiv上被引用文章的编号,即可自动生成bibtex的引文格式。 https://arxiv2bibtex.org/?q=2001.09678&format=bibtex 注意:这个网站需要翻墙。效果如下图 2.自己手写的话,就按照...
  • 深入理解Java Class文件格式(一)

    万次阅读 多人点赞 2014-03-18 23:31:37
    本篇博客主要讲解能够被JVM识别, 加载并执行的class文件格式。 对于理解JVM和深入理解Java语言, 学习并了解class文件格式都是必须要掌握的功课。 原因很简单, JVM不会理解我们写的Java源文件, 我们必须把...
  • PDF文件格式:基本结构

    千次阅读 2019-12-28 22:42:30
    引言2.PDF文件结构3.增量更新4.例子5.PDF数据类型5.1.布尔值(Booleans)5.2.数字(Numbers)5.3.名称(Names)5.5.数组(Arrays)5.6.字典5.7.流(Streams)6.文件结构 1.引言 众所周知,大量的攻击事件都是由黑客通过在PDF...
  • .obj文件格式与.mtl文件格式

    万次阅读 多人点赞 2015-07-07 17:55:23
    最近在学习obj文件格式,上网查了些资料,很难找到比较全面的文章,尤其是对.mtl文件的说明甚少。今天把最近搜索的资料整合了一下。这里的obj文件格式指的是Wavefront公司为它的一套基于工作站的3D建模和动画软件...
  • 近日遇到有客户反应,页面打开显示不正常,不能完全的显示出页面。细问之下才得知,原来是有一个js文件修改了一个方法,但是上线后由于浏览器缓存的原因,还是加载的旧js...先是考虑在页面引用的js文件后面加随机数来
  • Sat格式文件详解翻译

    万次阅读 2018-04-14 11:02:00
    SAT Save File Format 7.0(Sat文件存储格式7.0) 译者:Mrzhu007 日期:2018年04月13日 博客地址:金色世界 ACIS can store modeling information in external files,called save files. These files have...
  • 感叹在excel中是什么意思如果主机引用excel文件图标上的感叹,则表示excel包含vba宏代码。因为如果恶意宏代码不小的话,可能会损坏系统或用户数据,因此在文件图标中添加一个感叹来警告用户。普通excel2007年...
  • pcap文件格式及写pcap文件

    千次阅读 2019-05-13 10:10:09
    一、pcap文件格式(该部分引用网络资料) pcap文件格式文件解析 第一部分:PCAP包文件格式 (一)、基本格式文件头 数据包头 数据报 数据包头 数据报… (二)、文件头: 文件头结构体,libpcap源码中定义如下 ...
  • 参考文献引用格式实例

    万次阅读 2018-01-10 15:39:22
    推荐引用方式: Zhang YL,Liang W,Tan JD,et al. PCA & HMM Based Arm Gesture Recognition Using Inertial Measurement Unit[C]. 8th International Conference on Body Area Networks. Boston, MA, USA. ...
  • 写了这么多个 C# 项目,是否对...本文将直接从 csproj 文件格式的本质来看以上这些问题。 阅读本文,你将: 可以通读 csproj 文件,并说出其中每一行的含义 可以手工修改 csproj 文件,以实现你希望达到的高...
  • ELF文件格式详解

    万次阅读 2016-07-21 00:36:58
    ARM的可执行文件格式是ELF格式文件,下文对ELF格式做个详细的介绍。 序言 1. OBJECT文件  导言  ELF头(ELF Header)  Sections  String表(String Table)  Symbol表(Symbol Table)  重定位(Relocation) 2. ...
  • BMP文件格式详解(BMP file format)

    万次阅读 多人点赞 2018-09-11 14:23:11
    BMP格式详解 BMP文件格式详解(BMP file format) ...BMP文件格式,又称为Bitmap(位图)或是DIB(Device-Independent Device,设备无关位图),是Windows系统中广泛使用的图像文件格式。由于它可以...
  • article/TeX/283102 发信人: bleach (nevermind...标 题: Re: 请问:在bibtex下引用arXiv的文献格式是什么?  发信站: 水木社区 (Thu Mar 12 00:22:12 2009), 站内    问题自己解决了,呵呵  参考 http://arx...
  • md文件的相关使用

    千次阅读 2021-01-10 15:48:13
    天已雪,一杯否? —— 南风落尽 ...该类型文件可使用普通编辑器打开或者编辑,例如:记事本,EditPlus,sublime等等,当然了,也有更专业的编辑器,例如我现在正在使用的——Typora。 md文件的书写格
  • 对于php和js,json文件格式中的变量的引用总结。 对于php文件,在双引号里面引入变量需要加{变量名}; .变量名或者.变量名.;   $a ="gegweg{$demo}; $a ="gegweg".$demo; $a ="gegweg".$demo."fweffwef";   对于...
  • linux文件系统及磁盘格式

    万次阅读 2017-02-13 10:10:38
    不用了解文件系统的原理。此处将对两种分区机制磁盘进行分区格式化(MBR类型磁盘——用fdisk###GPT类型磁盘——用parted)。fdisk不支持大于2T的分区寻址(后边再详细介绍原理,这里为保持简单不涉及)。 1> fdisk ...
  • 证书体系: PFX 文件格式解析

    千次阅读 2018-11-24 19:22:26
    章节目录 PFX 简介 PFX 格式解析 2.1 最外层结构 ...在密码学中,PKCS #12 定义了一种存档文件格式,用于实现存储许多加密对象在一个单独的文件中。通常用它来打包一个私钥及有关的 X.509 证书,或者打包信任...
  • 程序集版本:在.net框架中和CLR运行时钟引用,如使用程序集的强命名时就会使用. 按照我的理解,你所使用的库如log4net,常见的有2.0和4.0的,那么你下载的库是否是你工程中用的库,就要看这个程序集版本. 比如我自己...
  • RTF文件格式分析

    千次阅读 2016-07-15 15:28:06
    如将WPS文件另存为RTF格式,用Word进行编辑处理,原WPS下设置的字形、字号保持不变 RTF文件格式分析 摘 要 RTF是一种在不同操作系统下不同应用软件之间进行文本和图象信息交换的文件格式。以RTF格式作为...
  • 假如现在需要用author-year格式引用一篇文献,首先在LaTeX文件开头加入这一句: \documentclass[preprint,12pt,authoryear]{elsarticle} 然后把这篇文献写成author-year格式格式:\bibitem[Author(year)]{label}...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 265,687
精华内容 106,274
关键字:

引用文件号的格式