shuai's profile娱乐精神PhotosBlog Tools Help

Blog


    8/30/2006

    难以理解的错误

    今天我的程序出现了这个问题,比较绕:
    A程序:建立了一个AppDomain, 在这个AppDomain中调用一个MarshalByRefObject的子类---B类
    然后,我将A程序写入字节流保存
    C程序将A程序从字节流中还原,并动态调用A程序中的方法,这时将报A程序中的B类无法加载的错误
     
    一句话就是,反射调用的程序集中的其它应用程序域中的类无法调用
    (为什么是其它应用程序域?因为A程序中的默认应用程序域中的其它类我都可以调用。)
    看来序列化(MarshalByRefObject)有很多限制

    这只是初步的想法,还需要证实一下
     
    -----------------------------------------------------
    解决了:
    我把
    AppDomain.CreateInstanceAndUnwrap(Assembly.GetCallingAssembly().FullName, typeof(TargetType).FullName);中的
    Assembly.GetEntryAssembly()
    换成了
    Assembly.GetCallingAssembly()
     
    不过又出现了无法将透明代理转换为目标类的错误,不过这下总算放心了
     
    8/27/2006

    得到PE文件信息 (下)


    三、使用函数:
    首先使用imagehlp.dll中的函数MapAndLoad
    函数MapAndLoad将一个映像文件映射到虚拟地址空间中,并填充结构LOADED_IMAGE
    定义如
    下BOOL MapAndLoad(
       IN LPSTR ImageName,
       IN LPSTR DllPath,
       OUT LOADED_IMAGE LoadedImage,
       IN BOOL DotDll,
       IN BOOL ReadOnly
    );
    另外还有相对应的函数UnMapAndLoad

    为了由相对虚拟地址得到虚拟地址,使用ImageRvaToVa:
    LPVOID ImageRvaToVa(
       IN IMAGE_PE_FILEHEADER NtHeaders,
       IN LPVOID Base,
       IN DWORD Rva,
       IN OUT IMAGE_SECTION_HEADER *LastRvaSection
    );
    这个函数返回的是虚拟内存地址
    四、得到导出名(VB代码仅供示例,无法运行):
    'LOADED_IMAGE结构定义如下:
    Public Type LOADED_IMAGE      '48个字节
       ModuleName As Long
       hFile As Long
       MappedAddress As Long      '映射文件基址
       pFileHeader As Long         'IMAGE_PE_FILE_HEADER的指针
       pLastRvaSection As Long      '第一个COFF段文件头的指针   ??
       NumberOfSections As Long
       pSections As Long         '第一个COFF段文件头的指针
       Characteristics As Long      '映像特征值
       fSystemImage As Byte
       fDosImage As Byte
       Links As LIST_ENTRY         '2个长整型
       SizeOfImage As Long
    End Type
    '检查&H3C偏移处是否为&H4550(PE文件标记)
    Get #fr, &H3C+1, bSigOffset
    Get #fr, bSigOffset+1, iSignature
    If Not iSignature = &H4550 Then
       '非PE文件
       Close fr
       Exit Function
    End if
    '将文件映射到内存,并填充LOADED_IMAGE
    Dim loadimage As LOADED_IMAGE
    lret = MapAndLoad(sFile, "", loadimage, True, True)
    '得到映像的基址
    baseaddr = loadimage.MappedAddress
    '将PE头复制到我们自已的变量peheader中
    Dim peheader As IMAGE_PE_FILE_HEADER
    CopyMemory ByVal VarPtr(peheader), ByVal loadimage.pFileHeader, 256
    '由第一个数据目录的相对虚拟地址得到虚拟地址
    rvaExportDirTable = peheader.OptionalHeader, DataDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT).RVA
    vaExportDirTable = ImageRvaToVa(loadimage.pFileHeader, loadimage.MappedAddress, rvaExportDirTable, 0&)
    '将导出表复制出来
    Dim exportdir As IMAGE_EXPORT_DIRECTORY_TABLE
    CopyMemory ByVal VarPtr(exportdir), ByVal vaExportDirTable, LenB(exportdir)
    '现在exportdir.ExportNamePointerTableRVA是这个导出名指针表的相对虚拟地址,我们转成虚拟地址
    ExportNamePointerTableVa = ImageRvaToVa(loadimage.pFileHeader, loadimage.MappedAddress, exportdir.ExportNamePointerTableVa, 0&)
    '输出导出表
    pNextAddress = ExportnamePointerTableVa      '从起点开始
    VBGetTaget lNextAddress, pNextAddress, 4   '得到下一个地址
    For i=0 To exportdir.NumberOfNames
       '将该名称地址由相对虚拟地址转为虚拟地址
       lNextAddress =  ImageRvaToVa(loadimage.pFileHeader, loadimage.MappedAddress, lNextAddress, 0&)  
       sName = LPSTRtoBSTR(lNextAddress)   '将ANSI转为BSTR,得到名称
       pNextAddress = pNextAddress + 4      '指向表的下一个地址
       VBGetTarget lNextAddress, pNextAddress, 4   '得到地址
    Next
    '最后调用UnMapAndLoad

    得到PE文件信息 (上)

    一、PE文件格式:
    1)PE文件头:
       MS-DOS占位符
       PE标记
       COFF文件头
       可选文件头(它并不是可选的,提供加栽器的信息):
          标准字段
          Windows专有字段
          数据索引表:它用来得到导出和导入表的相对虚拟地址
    2)段表:是段的头,注意所有这些段头是相连的,段表的项目数目是通过COFF的NumberOfSections字段给出
    3)段:
          正文段(.text 包括执行代码)
          数据段(.bss、.rdata、.data 包括文字串和常量)
          资源段(.rsrc)
          重定位段(.reloc 回填项目,即记录实际加载时基地址的调整)
          导出段(.edata 包括所有的导出函数和全局变量信息,由一个导出目录表开始)
          导入段(.idata 包括了文件导入的函数信息)


    二、结构

    '没有MS-DOS占位程序的PE文件头
    Public Type IMAGE_PE_FILE_HEADER   '256个字节
       Signature As Long            'PE文件标记,4个字节
       FileHeader As IMAGE_COFF_HEADER   'COFF文件头,20个字节
       OptionalHeader As IMAGE_OPTIONAL_HEADER   '可选头,232个字节
    End Type


    'COFF文件头
    Public Type IMAGE_COFF_HEADER      '20个字节
       Machine As Integer            '处理器类型
       NumberOfSections As Integer      '段的数目
       TimeDateStamp As Long         '文件建立时间
       PointerToSymbolTable As Long   'COFF文件符号表的偏移
       NumberOfSymbols As Long         '符号表中项目个数,可以用来定位字符串表它紧跟着符号表
       SizeOfOptionalHeader As Integer   'PE文件可选头的大小
       Characteristics As Integer
    End Type

    Public Type IMAGE_OPTIONAL_HEADER   '232个字节
       '标准字段
       Magic As Integer
       MajorLinkerVersion As Byte
       MinorLinkerVersion As Byte
       SizeOfCode As Long
       SizeOfInitializedData As Long
       AddressOfEntryPoint As Long
       BaseOfCode As Long
       BaseOfData As Long

       'Windows字段
       ImageBase As Long
       SectionAlignment As Long
       FileAlignment As Long
       MajorOperatingSystemVersion As Integer
       MinorOperatingSystemVersion As Integer
       MajorImageVersion As Integer
       MinorImageVersion As Integer
       MajorSubsystemVersion As Integer
       MinorSubsystemVersion As Integer
       Win32VersionValue As Long
       SizeOfImage As Long
       SizeOfHeaders As Long
       CheckSum As Long
       Subsystem As Integer
       DllCharacteristics As Integer
       SizeOfStackReserve As Long
       SizeOfStackCommit As Long
       SizeOfHeapReserve As Long
       SizeOfHeapCommit As Long
       LoaderFlags As Long
       NumberOfRvaAndSizes As Long      '96

       '数据目录(数据索引表)
       DataDirectory(0 To IMAGE_NUMBEROF_DIRECTORY_ENTRIES) As IMAGE_DATA_DIRECTORY      '17*8+96=232
    End Type

    '数据目录
    Public Type IMAGE_DATA_DIRECTORY   '8字节
       RVA As Long
       Size As Long
    End Type


    '导出表
    Public Type IMAGE_EXPORT_DIRECTORY_TABLE   '40字节
       Characteristics As Long            '导出标志(保留)
       TimeDateStamp As Long            '导出数据的时间
       MajorVersion As Integer
       MinorVersion As Integer
       Name As Long                  '包含这个DLL名称字符串的相对虚拟地址
       Base As Long                  '导出地址表的导出开始的序号
       NumberOfFunctions As Long        
       NumberOfNames As Long            '导出地址表中项目个数
       pAddressOfFunctions As Long         '导出地址表的相对虚拟地址
       ExportNamePointerTableRva As Long   '导出名称指针表的相对虚拟地址(保存了导出名称表位置)
       pAddressOfNameOrdinals As Long      '序号表的相对虚拟地址
    End Type

     

    8/14/2006

    C#泛型-小心使用静态成员变量

    旧贴转过来:
     
    对于泛型类的声明
    其中使用类型参数的构造类型,比如List<T>被称为开放构造类型(open constructed type)
    而不使用类型参数的构造类型,例如List<int>被称为封闭构造类型(closed constructed type)。
    特别要强调的是不同类型参数的封闭构造类型之间是不共享静态成员变量的。

    举个例子

    using System;

    public class List<T>
    {  
        public List(T t)
        {
            _value = t;
            _closedCount++;
        }

        public T Value
        {
            get { return _value; }
        }

        public int ClosedCount
        {
            get { return _closedCount; }
        }

        public static int StaticCount
        {
            get { return _closedCount; }
        }


        private T _value;
        private static int _closedCount = 0;
    }

    public class Test
    {
        static void Main()
        {
            List<double> list1 = new List<double>(3.14);
            Console.WriteLine("List1 Value: {0} \t Closed Count: {1}", list1.Value, list1.ClosedCount);

            List<double> list2 = new List<double>(0.618);
            Console.WriteLine("List2 Value: {0} \t Closed Count: {1}", list2.Value, list2.ClosedCount);

            List<string> list3 = new List<string>("divino");
            Console.WriteLine("List3 Value: {0} \t Closed Count: {1}", list3.Value, list3.ClosedCount);

            Console.WriteLine();

            Console.WriteLine("List<double> Count: {0}", List<double>.StaticCount);
            Console.WriteLine("List<string> Count: {0}", List<string>.StaticCount);
        }
    }

    输出结果:
    List1 Value: 3.14         Closed Count: 1
    List2 Value: 0.618        Closed Count: 2
    List3 Value: divino       Closed Count: 1

    List<double> Count: 2
    List<string> Count: 1

    其中:
    list1与list2同为List<double>,它们之间共用静态成员_closedCount
    而类型为List<string>的list3不能使用_closedCount
    我们从最后两行的输出也可看出结果
    即:不同类型参数的封闭构造类型之间是不共享静态成员变量的。