首页 > 编程语言 >C++实现删除打印机副本功能

C++实现删除打印机副本功能

时间:2024-05-28 18:59:00浏览次数:16  
标签:打印机 副本 return Format C++ CString PrintSum jsonData

 我们要实现此功能,首先需要获取到打印机的名称,其次是将获取到的打印机名称依次删除。

一、获取打印机副本名称

1.我们获取打印机副本名称,可以使用windows API中的EnumPrinters函数,该函数可以枚举出我们电脑中的打印机设备信息,该函数使用方法如下:

DWORD Flags = PRINTER_ENUM_FAVORITE | PRINTER_ENUM_LOCAL;
        DWORD cbBuf;
        DWORD pcReturned;
        DWORD Level = 2;
        TCHAR Name[4096] = { 0 };
        HANDLE hPrinter = NULL;
        PRINTER_DEFAULTS defaults = { NULL, NULL, PRINTER_ALL_ACCESS };
        ::EnumPrinters(Flags, Name, Level, NULL, 0, &cbBuf, //需要多少内存
            &pcReturned);
        const LPPRINTER_INFO_2 pPrinterEnum = (LPPRINTER_INFO_2)LocalAlloc(LPTR, cbBuf + 4);
        if (!pPrinterEnum)
        {
            setSearchResult("false", "打印机信息获取内存失败,请重试");
            return -1;
        }
        if (!EnumPrinters(Flags, Name, Level, (LPBYTE)pPrinterEnum, cbBuf, &cbBuf, &pcReturned))
        {
            setSearchResult("false", "打印机信息获取内存失败,请重试");
            return -1;
        } 

2.我们获取到打印机信息以后,需要对获取到的打印机信息进行处理,然后就可进行删除功能实现

二、删除获取到的打印机副本

1.删除打印机功能,我们可以使用windows API中的DeletePrinter函数,但是使用DeletePrinter函数之前,我们需要使用OpenPrinter函数来打开打印机,OpenPrinter函数使用如下:

 if (!OpenPrinter(pPrinterEnum[i].pPrinterName, &hPrinter, &defaults))
                {
                    printf("Error opening printer : %d\n",  GetLastError());
                    return -1;
                }

2.DeletePrinter函数使用如下:

    dataChangeToJson(printName, PrintSum);
                if (!OpenPrinter(pPrinterEnum[i].pPrinterName, &hPrinter, &defaults))
                {
                    printf("Error opening printer : %d\n",  GetLastError());
                    return -1;
                }
                BOOL result = DeletePrinter(hPrinter);
                ClosePrinter(hPrinter); 

三、重启打印服务

我们删除打印机后,需要重启打印机服务后,打印机枚举函数才能枚举出更新的打印机设备,否则我们再次使用EnumPrinters函数时,效果与我们的预期不符。重启打印机服务如下:

完整代码如下:

CopyFunction.h文件

#include <atlstr.h>
#include <iostream>
#include <windows.h>
#include <tchar.h>
#include <string>
#include <io.h>
#include <fstream>
#include <filesystem>
#include<vector>
#include <Winspool.h>

#include <stdio.h>
#include <locale.h>
#pragma comment(lib, "Winspool.lib")
#include <setupapi.h>
#pragma comment(lib, "setupapi.lib")

using namespace std;

extern "C"{
    __declspec(dllexport) int GetPrintName(CString *PrintName , int &PrintSum);
    //__declspec(dllexport) BOOL DeletePrint(const wchar_t* printerName);
    __declspec(dllexport) BOOL RestartSpoolerService();
    __declspec(dllexport) int DeleteLocalPrinter(char *PrinterName);
}

CopyFunction.c文件

#include "CopyFunction.h"

CString jsonData;
void setSearchResult(CString sFlag , CString sState);
bool dataChangeToJson(CString printerName , int PrintSum);


int DeleteLocalPrinter(char *PrinterName)
{
    try
    {
        int res = 0;
        int PrintSum = 0;
        CString *PrintName = new CString[4096];
        jsonData.Format(_T("{\n\t\"PrintName\":["));
        res = GetPrintName(PrintName, PrintSum);
        if (res == -1)
        {
            //jsonData.Format(jsonData + _T("\n\t]\,\n\t\"DeleteCount\":") + _T("%d\,"), PrintSum);
            //jsonData.Format(jsonData + _T("\n\t\"message\":") + _T("\"删除USB打印副本失败,接口未成功执行\"\n}"));
            jsonData.Format(jsonData + _T("\n\t\t\t\"删除USB打印副本失败,接口未成功执行\"\n\t]\n}"));
            memcpy(&PrinterName[0], jsonData, jsonData.GetLength());
            return -1;
        }
        if (PrintSum == 0)
        {
            setSearchResult("false", "打印机副本删除失败");
            //jsonData.Format(jsonData + _T("\n\t]\,\n\t\"DeleteCount\":") + _T("%d\,"), PrintSum);
            //jsonData.Format(jsonData + _T("\n\t\"message\":") + _T("\"接口未搜索到打印机副本\"\n}"),PrintSum);
            jsonData.Format(jsonData +  _T("\n\t\t\t\"接口未搜索到打印机副本\"\n\t]\n}"), PrintSum);
            memcpy(&PrinterName[0], jsonData, jsonData.GetLength());
            return -1;
        }
        int flag = jsonData.ReverseFind(',');  //移除最后一个多余“,”
        if (flag > 0)
        {
            jsonData = jsonData.Mid(0, flag);
        }
        setSearchResult("true", "打印机副本删除成功");
        /*if (PrintSum>10)
            jsonData.Format(jsonData + _T("\n\t..............."));*/
        jsonData.Format(jsonData + _T("\n\t\t\t......"));
        jsonData.Format(jsonData + _T("\n\t\t\t\"删除USB打印副本成功, 总共删除了%d个\"\n\t]\n}"),PrintSum);
        /*jsonData.Format(jsonData + _T("\n\t\t\t\"DeleteCount\":") + _T("%d"),PrintSum);
        jsonData.Format(jsonData + _T("\n\t\t\t\"message\":") + _T("\"删除USB打印副本成功, 总共删除了%d个\"\n\t]\n}"),
            PrintSum);*/
        memcpy(&PrinterName[0], jsonData, jsonData.GetLength());
        if (!RestartSpoolerService())
        {
            printf("StartService failed with spooler.\n");
        }
        //cout << jsonData << endl;
    }
    catch (exception &e)
    {
        cout << "ERROR:" << e.what() << endl;
    }
    return 0;
}

void setSearchResult(CString sFlag, CString sState)
{
    CString jdata; //转存jsonData数据
    CString searchFlag;
    CString searchState;
    jdata = jsonData.Mid(1);
    searchFlag.Format(_T("\n\t\"searchFlag\":\"") + sFlag + _T("\","));
    searchState.Format(_T("\n\t\"searchState\":\"") + sState + _T("\","));
    jsonData.Format(_T("{") + searchFlag + searchState + jdata);
}

bool dataChangeToJson(CString printerName, int PrintSum)
{
    CString jdata;//用于存储打印机名称及twain名的键值对数据
    if (PrintSum !=0)
    { 
        jdata.Format(_T("\t\t\n\t\t\t\"%d、")+ printerName + _T("\","), PrintSum);
        jsonData += jdata;
    }
    else
    {
        jdata.Format(_T("\t\t\n\t\t\t\"") + printerName + _T("\","), PrintSum);
    }
    return true;
}

int GetPrintName(CString *PrintName,int &PrintSum)
{
    try
    {
        CString strDescription;
        CString printName;
        CString PLocation;
        CString NETName;
        DWORD Flags = PRINTER_ENUM_FAVORITE | PRINTER_ENUM_LOCAL;
        DWORD cbBuf;
        DWORD pcReturned;
        DWORD Level = 2;
        TCHAR Name[4096] = { 0 };
        HANDLE hPrinter = NULL;
        PRINTER_DEFAULTS defaults = { NULL, NULL, PRINTER_ALL_ACCESS };
        ::EnumPrinters(Flags, Name, Level, NULL, 0, &cbBuf, //需要多少内存
            &pcReturned);
        const LPPRINTER_INFO_2 pPrinterEnum = (LPPRINTER_INFO_2)LocalAlloc(LPTR, cbBuf + 4);
        if (!pPrinterEnum)
        {
            setSearchResult("false", "打印机信息获取内存失败,请重试");
            return -1;
        }
        if (!EnumPrinters(Flags, Name, Level, (LPBYTE)pPrinterEnum, cbBuf, &cbBuf, &pcReturned))
        {
            setSearchResult("false", "打印机信息获取内存失败,请重试");
            return -1;
        }
        for (unsigned int i = 0, j = 0; i < pcReturned; i++)
        {
            LPPRINTER_INFO_2 pInfo = &pPrinterEnum[i];
            strDescription.Format(_T("pPrinterName: %s,pDriverName: %s ,pLocation: %s, Status: %ld"),
                (LPCTSTR)pInfo->pPrinterName,
                (LPCTSTR)pInfo->pDriverName, (LPCTSTR)pInfo->pLocation,
                pInfo->Attributes);
            printName.Format(_T("%s"), (LPCTSTR)pInfo->pPrinterName);
            int PrintSign = printName.Find("(");
            if (PrintSign != -1)
            {
                PrintName[j] = printName;
                //dataChangeToJson(printName);
                PrintSum++;
                if (PrintSum <= 10)
                    dataChangeToJson(printName, PrintSum);
                if (!OpenPrinter(pPrinterEnum[i].pPrinterName, &hPrinter, &defaults))
                {
                    printf("Error opening printer : %d\n",  GetLastError());
                    return -1;
                }
                BOOL result = DeletePrinter(hPrinter);
                ClosePrinter(hPrinter);
                j++;
                //PrintSum++;
            }
        }
    }
    catch (exception &e)
    {
        cout << "ERROR:" << e.what() << endl;
    }
    return 0;
}

/*函数功能:重启Spooler服务
函数参数:无
函数返回:打印服务重启与否*/
BOOL RestartSpoolerService()
{
    try
    {
        // 打开服务控制管理器
        SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, GENERIC_EXECUTE);
        if (hSCManager == NULL) {
            cerr << "OpenSCManager failed with error: " << GetLastError() << endl;
            return false;
        }
        // 打开Spooler服务
        SC_HANDLE hService = OpenService(hSCManager, _T("Spooler"), SERVICE_START | SERVICE_QUERY_STATUS | SERVICE_STOP);
        if (hService == NULL) {
            cerr << "OpenService failed with error: " << GetLastError() << endl;
            CloseServiceHandle(hSCManager);
            return false;
        }
        //查询spooler服务的状态
        SERVICE_STATUS status;
        if (QueryServiceStatus(hService, &status) == FALSE)
        {
            CloseServiceHandle(hService);
            CloseServiceHandle(hSCManager);
            return false;
        }
        // 停止服务
        if (ControlService(hService, SERVICE_CONTROL_STOP, &status) == FALSE)
        {
            CloseServiceHandle(hService);
            CloseServiceHandle(hSCManager);
            cerr << "ControlService STOP failed with error: " << GetLastError() << endl;
        }
        else
        {
            // 等待服务停止
            while (QueryServiceStatus(hService, &status) && status.dwCurrentState != SERVICE_STOPPED)
            {
                Sleep(1000); // 暂停1秒再检查
            }
        }

        // 启动服务
        if (status.dwCurrentState == SERVICE_STOPPED)
        {
            if (StartService(hService, NULL, NULL) == FALSE)
            {
                CloseServiceHandle(hService); // 关闭服务句柄
                CloseServiceHandle(hSCManager); // 关闭服务控制管理器句柄
                cerr << "StartService failed with error: " << GetLastError() << endl;
            }
        }
        CloseServiceHandle(hService); // 关闭服务句柄
        CloseServiceHandle(hSCManager); // 关闭服务控制管理器句柄
    }
    catch (exception &e)
    {
        cout << "ERROR:" << e.what() << endl;
    }
    return true;
}

标签:打印机,副本,return,Format,C++,CString,PrintSum,jsonData
From: https://blog.csdn.net/qq_57661075/article/details/139201608

相关文章

  • C++实现dll文件的显示调用
    我们实现dll文件的显示调用,主要分为三个步骤:创建DLL、导出函数、使用DLL。其中离不开WindowsAPI函数,使用到了LoadLibrary、GetProcAddress、 FreeLibrary等,以下是一个简单的示例程展示整个过程。:1.创建DLLMyLibrary.h//MyLibrary.h#ifndefMY_LIBRARY_H#defineMY_LI......
  • C++跨平台库boost和Poco的编译
    PrerequisitesCMake3.5ornewerAC++17compiler(VisualC++2022,GCC8.0,Clang5,ornewer)在window下编译依赖的三方库编译POCO$gitclone-bmasterhttps://github.com/pocoproject/poco.git$cdpoco$mkdircmake-build$cdcmake-build$cmake..$cma......
  • C++17 链接 C++11 lib 出现重复定义
    C++11实现staticconstexpr是按照conststatic实现的,需要在.cpp中定义://tmp.hclassStatisTest{public:staticconstexprconstcharliteral[]="xxxliteral";};//tmp.cc#include"tmp.h"constcharStatisTest::literal[];//compile......
  • 阿赵UE引擎C++编程学习笔记——文件夹操作和文件读写
      大家好,我是阿赵。  这次学习一下在UE里面使用C++的API操作文件读写和文件夹操作。一、UE引擎获取相关路径  获取到路径一般是相对路径,使用FPaths::ConvertRelativePathToFull转换后,可以获得完整的绝对路径。FStringcontentDir=FPaths::ProjectContentDir();......
  • 《C++primer》第八章课后习题
    练习8.1istream&abc(istream&is){ strings; is>>s; cout<<s; s.clear(); returnis;}练习8.2abc(cin);练习8.3答:输入类型与i不符,或者输入结束标识练习8.4vector<string>s;voidabc(strings1){ strings2; ifstreamin(s1); while(getline(......
  • 《C++primer》读书笔记---第八章:IO库
    8.1IO类下表列出的是一些IO类型:  为了支持使用宽字符的语言,标准库定义了一组类型和对象来操纵wchar_t类型的数据。宽字符版本的类型和函数的名字以一个w开始,例如,wcin、wcout、wcerr是分别对应cin、cout、cerr的宽字符类型。注:IO对象无拷贝或赋值ofstreamout1,out2;......
  • C++二进制文件的读写
    二进制文件的读取:voidTransformSession::generateData(conststd::string&filePath,std::vector<uint8_t>&data){std::ifstreamifs(filePath,std::ios::binary);if(!ifs){SPDLOG_ERROR("failedtoopenreadfile:{}",filePath);......
  • c#调用TSC打印机进行打印
    需求背景业务打印需求需要使用TSC打印机进行条码二维码打印(由旧项目改造触发的需求)前期准备vs2022+WORK Service+TSCLIB.DLL使用方式及部分代码示例创建一个类PrinterHelper.cs。类中来使用TSCLIB进行模版的编辑及调用打印机进行打印。在需要使用打印功能的地方调用打印......
  • C++Primer Plus对象和类的练习,练习10.10类和对象 练习2默认参数和重载
    2.下面是一个非常简单的类定义:classPerson{private:staticconstLIMIT=25;stringlname;//Person’slastnamecharfname[LIMIT];//Person’sfirstnamepublic:Person()(lname=“”;fname[0]=0’;}//#1Person(conststring&ln,constchar*fn=“Heyyou”);//......
  • c++ rand
     在C++中,可以使用<cstdlib>头文件中的rand()函数生成随机数。这个函数会生成一个介于0和RAND_MAX(通常是32767)之间的伪随机整数。通常情况下,你可能还需要使用srand()函数来设置随机数生成器的种子。下面是一个简单的示例,展示了如何在C++中使用rand()函数生成随......