2

我正在从事一个旨在监控打印作业的项目。我正在将 spl 和 shd 文件从 spool 文件夹复制到一个临时文件夹并尝试解析以获取我想要的数据,例如打印页数、所有者、日期和时间......

我正在使用以下代码来解析 spooler spl 文件(获取 emf 文件结构)

#include "stdafx.h"
#include <windows.h>
#include <winspool.h>
#include <stdio.h>
#include <locale.h>   
#include <tchar.h>
#include <iostream>
using namespace std;

BOOL AnalyseFile(const char* pszFileName);

void UPFM(const wchar_t pszInfo[])
{
    wprintf(L"%s\n",pszInfo);
}

 static char* ID_Func[] =
{ 
    "EMF_HEADER", "EMF_POLYBEZIER", /*....*/
};

int main()
{
    setlocale(LC_ALL,"");   

    const char* pszFileName = "~MyTempFolder\\00031.SPL";

    if(!AnalyseFile(pszFileName))
        printf("Analyse File Failed!");
    else
        printf("Analyse File Successed Completed!");

    return 0;
}


BOOL AnalyseFile(const char* pszFileName)
{
    BOOL bRet = FALSE;

    DWORD dwStartPos = 0;
    FILE * f ;
    f = fopen("log.txt", "w");
    FILE* pFile = fopen(pszFileName,"rb");

    if(!pFile)
    {
        fprintf(f,"Open File Failed!");
        return bRet;
    }

    /* =======================Headers================================ */
    DWORD dwTmp = 0;

    fseek(pFile,0,0);

    fread(&dwTmp,sizeof(DWORD),1,pFile);

    fread(&dwTmp,sizeof(DWORD),1,pFile);

    dwStartPos = dwTmp;

    fread(&dwTmp,sizeof(DWORD),1,pFile);

    long pos = ftell(pFile);

    fseek(pFile,dwTmp,SEEK_SET);

    wchar_t pszInfo[256] = {0};
    pszInfo[0] = L'(';

    WORD wTmp;
    int i;
   for( i = 1;;i++)
    {
        fread(&wTmp,sizeof(wTmp),1,pFile);

        if(!wTmp)
            break;

        memcpy((char*)&pszInfo[i],&wTmp,sizeof(wTmp));
    }
    pszInfo[i] = L')';
    UPFM(pszInfo);

    fseek(pFile,pos,SEEK_SET);

    fread(&dwTmp,sizeof(DWORD),1,pFile);

    fseek(pFile,dwTmp,SEEK_SET);

    memset(pszInfo,0,sizeof(wchar_t)*256);
    pszInfo[0] = L'(';
    for(i = 1;;i++)
    {
        fread(&wTmp,sizeof(wTmp),1,pFile);

        if(!wTmp)
            break;

        memcpy((char*)&pszInfo[i],&wTmp,sizeof(wTmp));
    }
    pszInfo[i] = L')';
    UPFM(pszInfo);

    /* ======================== Unknown datas ================================= */
    fseek(pFile,dwStartPos,SEEK_SET);

    fread(&dwTmp,sizeof(DWORD),1,pFile);

    fread(&dwTmp,sizeof(DWORD),1,pFile);

    /* ======================== Record datas ================================= */
     DWORD dwTmp2 = 0;
    for(int i=0;;i++)
    {
        pos = ftell(pFile);

        fread(&dwTmp,sizeof(DWORD),1,pFile);

        fread(&dwTmp2,sizeof(DWORD),1,pFile);
        FILE *f;
        f = fopen("log.txt", "a");

        fprintf(f,"index: (%04d)  type: 0x%04X  size: %04d  0x%08X (%s)\n",i,dwTmp,dwTmp2,pos,ID_Func[dwTmp-1]);
        fclose (f);

        if(dwTmp == 0x0E)
        {
            break;
        }

        fseek(pFile,pos+dwTmp2,SEEK_SET);
    }
    fclose (f);
    if(pFile) fclose(pFile);
    bRet = TRUE;

    return bRet;
}

有没有办法用这种方法计算 spl 文件的页数?

4

2 回答 2

0

要计算页面,您必须计算 PAGE 标题。

这是执行此操作的代码的一部分

 SpoolFilename = Path.ChangeExtension(SpoolFilename, ".SPL")

    '\\ Open a binary reader for the spool file
    Dim SpoolFileStream As New System.IO.FileStream(SpoolFilename, FileMode.Open, FileAccess.Read)
    Dim SpoolBinaryReader As New BinaryReader(SpoolFileStream, System.Text.Encoding.UTF8)

    'Read the spooler records and count the total pages
    Dim recNext As EMFMetaRecordHeader = NextHeader(SpoolBinaryReader)
    While recNext.iType <> SpoolerRecordTypes.SRT_EOF
        If recNext.iType = SpoolerRecordTypes.SRT_PAGE Then
            _Pages += 1
        End If
        'SpoolfileReaderPerformaceCounter.Increment()
        Call SkipAHeader(recNext, SpoolBinaryReader)
        recNext = NextHeader(SpoolBinaryReader)
    End While

代码获取文件名,为其打开二进制流,并在标题之后读取标题。如果标题代码是 SRT_PAGE,则增加页数计数器。

更多细节和来源在这里

于 2015-01-28T07:26:05.150 回答
0

这是您在 C++ 中的操作方法

struct EMFMetaRecordHeader {
    long Seek;
    SpoolerRecordTypes iType;
    int Size;
};  

if (splfile)
{
    EMFMetaRecordHeader recNext = NextHeader(splfile);
    while (recNext.iType != SpoolerRecordTypes::SRT_EOF)
    {
        if (recNext.iType == SpoolerRecordTypes::SRT_PAGE)
        {
            nPages++;
        }
        recNext = NextHeader(splfile);

    }

    nEmf_record_code = 0;
}

EMFMetaRecordHeader EMFSpoolfileReader::NextHeader(FILE* splfile){
EMFMetaRecordHeader recRet;
recRet.Seek = ftell(splfile);

fread(&recRet.iType, sizeof(int), 1, splfile);
if (feof(splfile))
{
    recRet.iType = SpoolerRecordTypes::SRT_EOF;
    return recRet;
}
fread(&recRet.Size, sizeof(int), 1, splfile);

return recRet;
}

splfile 是一个假脱机文件指针

更多细节和来源在这里

于 2018-01-24T05:10:54.757 回答