Q&A

  • Spooler 왼도우를 실행하는 방법
안녕하십니까?



먼저 3000번 프린터 Spooler제어에 대하여 김용대님의

답변 감사드립니다.



한가지 질문 더 드리겠습니다.



프린터 Spooler 왼도우를 직접 실행하는 방법은 없는지요?

답변을 부탁드리겠습니다.





감사합니다.

2  COMMENTS
  • Profile
    김영대 1999.11.16 22:42
    류한규 wrote:

    > 안녕하십니까?

    >

    > 먼저 3000번 프린터 Spooler제어에 대하여 김용대님의

    > 답변 감사드립니다.

    >

    > 한가지 질문 더 드리겠습니다.

    >

    > 프린터 Spooler 왼도우를 직접 실행하는 방법은 없는지요?

    > 답변을 부탁드리겠습니다.

    >

    > 감사합니다.



    제 이름은 김영대입니다

    아래 소스에서 OpenThisPrinter() 를 보세요



    unit Unit1;



    interface



    uses

    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

    StdCtrls, Printers, SHPrinters;



    type

    TForm1 = class(TForm)

    B_Queue: TButton;

    B_Properties: TButton;

    B_Add: TButton;

    ListBox1: TListBox;

    procedure B_QueueClick(Sender: TObject);

    procedure B_PropertiesClick(Sender: TObject);

    procedure B_AddClick(Sender: TObject);

    private

    { Private declarations }

    public

    { Public declarations }

    end;



    var

    Form1: TForm1;



    implementation

    {$R *.DFM}



    procedure TForm1.B_QueueClick(Sender: TObject);

    var

    PrinterName: String;

    begin

    // 프린터 리스트를 구한다

    ListBox1.Items := Printer.Printers;



    // default printe의 이름을 구한다

    PrinterName := Printer.Printers[Printer.PrinterIndex];

    PrinterName := Copy(PrinterName,1,Pos(' on ', PrinterName)-1);



    // 기본 프린터의 대기문서(Queue)를 보여준다

    if not OpenThisPrinter(PrinterName) then

    ShowMessage('Queue for Printer '+ PrinterName+ ' is not available');

    end;



    procedure TForm1.B_PropertiesClick(Sender: TObject);

    var

    PrinterName: String;

    begin

    // 프린터 리스트를 구한다

    ListBox1.Items := Printer.Printers;



    // default printe의 이름을 구한다

    PrinterName := Printer.Printers[Printer.PrinterIndex];

    PrinterName := COPY(PrinterName,1,POS(' on ', PrinterName)-1);



    // 기본 프린터의 등록정보(Properties)를 보여준다

    if not OpenPrinterProperties(PrinterName) then

    ShowMessage('"Printer Properties" for ' +PrinterName+ ' are not available');

    end;



    procedure TForm1.B_AddClick(Sender: TObject);

    begin

    // 프린터 추가 마법사를 실행한다

    ExecuteAddPrinter;

    end;



    end.





  • Profile
    김영대 1999.11.16 23:00
    // Adapted from Microsoft's Q153751:

    // "Sample: PRINTERS.EXE: Using Printers with Windows 95 Shell"

    // http://premium.microsoft.com/support/kb/articles/q153/7/51.asp

    // Microsoft's "pidl" is a pItemIDlist here.



    // Earl F. Glynn

    // November 1997



    UNIT SHprinters;



    INTERFACE



    USES

    Windows, // hResult, Failed, Succeeded, ZeroMemory, CopyMemory

    ActiveX, // IMalloc

    ShlObj; // Shell Objects: pItemIDList, IShellFolder





    FUNCTION ExecuteAddPrinter: BOOLEAN;

    FUNCTION GetAddPrinterItem(CONST Allocator: IMalloc): pItemIDList;



    FUNCTION GetItemIDName(CONST Folder: IShellFolder;

    CONST ItemIDList: pItemIDList;

    CONST Flags: INTEGER;

    CONST Name: pCHAR;

    CONST MaxNameLength: INTEGER): BOOLEAN;

    FUNCTION GetPrinterItemIDList(CONST DeskTopFolder: IShellFolder): pItemIDList;

    FUNCTION GetThisPrinter(CONST PrinterName: STRING; CONST Allocator: IMalloc): pItemIDlist;



    FUNCTION ItemIDListCreate(CONST Allocator: IMalloc; CONST size: INTEGER): pItemIDList;

    FUNCTION ItemIDListGetNextItem(CONST ItemIDList: pItemIDList): pItemIDList;

    FUNCTION ItemIDListGetSize(CONST ItemIDList: pItemIDList): INTEGER; {size in bytes}



    FUNCTION ItemIDListsConcatenate(CONST Allocator: IMalloc;

    CONST List1, List2: pItemIDList): pItemIDlist;



    FUNCTION OpenPrinterProperties(CONST PrinterName: STRING): BOOLEAN;

    FUNCTION OpenThisPrinter(CONST PrinterName: STRING): BOOLEAN;



    IMPLEMENTATION



    USES

    ShellAPI, // TShellExecuteInfo, ShellExecuteEx

    SysUtils; // Exception



    TYPE

    ESHprintersError = CLASS(Exception);





    // See ExecuteAddPrinter in Printers.CPP (line 359)

    FUNCTION ExecuteAddPrinter: BOOLEAN;

    VAR

    AddPrinterItemIDList: pItemIDList;

    Allocator : IMalloc;

    ShellExecuteInfo : TShellExecuteInfo;

    BEGIN

    RESULT := FALSE;



    IF CoGetMalloc(MEMCTX_TASK, Allocator) = S_OK

    THEN BEGIN

    AddPrinterItemIDList := GetAddPrinterItem(Allocator);

    TRY

    IF AddPrinterItemIDList = NIL

    THEN RESULT := FALSE

    ELSE BEGIN

    ZeroMemory(@ShellExecuteInfo, SizeOf(TShellExecuteInfo));



    WITH ShellExecuteInfo DO

    BEGIN

    cbSize := SizeOf(TShellExecuteInfo);

    fMask := SEE_MASK_INVOKEIDLIST OR SEE_MASK_FLAG_NO_UI;

    lpIDList := AddPrinterItemIDlist;

    nShow := SW_SHOWDEFAULT

    END;



    ShellExecuteEx(@ShellExecuteInfo);

    RESULT := TRUE

    END

    FINALLY

    Allocator.Free(AddPrinterItemIDList)

    END

    END

    END {ExecuteAddPrinter};





    // See GetAddPrinterItem in Printers.CPP (line 428)

    FUNCTION GetAddPrinterItem(CONST Allocator: IMalloc): pItemIDList;

    VAR

    DeskTopFolder : IShellFolder;

    EnumIDList : IEnumIDList;

    hOK : hResult;

    PrinterItemIDList: pItemIDList;

    PrintersFolder : IShellFolder;

    Retrieved : INTEGER;

    TargetItemIDList : pItemIDList;

    TempItemIDList : pItemIDList;

    BEGIN

    TargetItemIDList := NIL;



    IF Allocator <> NIL

    THEN BEGIN



    IF Succeeded(SHGetDesktopFolder(DeskTopFolder))

    THEN BEGIN



    PrinterItemIDList := GetPrinterItemIDList(DeskTopFolder);

    IF PrinterItemIDList <> NIL

    THEN BEGIN

    // Get the IShellFolder for Printers

    hOK := DeskTopFolder.BindToObject(PrinterItemIDList,

    NIL,

    IID_IShellFolder,

    Pointer(PrintersFolder));

    IF Succeeded(hOK)

    THEN BEGIN

    IF Succeeded(PrintersFolder.EnumObjects(0, SHCONTF_FOLDERS OR SHCONTF_NONFOLDERS,

    EnumIDList))

    THEN BEGIN

    // Get the first item's ItemIDList. This will be the item for adding a printer.

    hOK := EnumIDList.Next(1, TempItemIDList, Retrieved);



    IF (Retrieved > 0) AND Succeeded(hOK)

    THEN TargetItemIDList := ItemIDListsConcatenate(Allocator,

    PrinterItemIDList,

    TempItemIDList);



    END



    END

    END



    END;

    END;



    RESULT := TargetItemIDList

    END {GetAddPrinterItem};





    // See GetItemIDName in Printers.CPP (line 551)

    FUNCTION GetItemIDName(CONST Folder: IShellFolder;

    CONST ItemIDList: pItemIDList;

    CONST Flags: INTEGER;

    CONST Name: pCHAR;

    CONST MaxNameLength: INTEGER): BOOLEAN;

    VAR

    p : PCHAR;

    StrRet: TStrRet;

    BEGIN

    RESULT := TRUE; // Be optimistic

    IF Succeeded(Folder.GetDisplayNameOf(ItemIDList, Flags, StrRet))

    THEN BEGIN

    CASE StrRet.uType OF

    STRRET_WSTR: WideCharToMultiByte(CP_ACP, 0, StrRet.pOleStr,

    -1, Name, MaxNameLength,

    NIL, NIL);



    STRRET_OFFSET:

    BEGIN

    p := pCHAR(ItemIDlist);

    INC(p, StrRet.uOffset);

    StrLCopy(Name, p, MaxNameLength)

    END;



    STRRET_CSTR: StrLCopy(Name, StrRet.cStr, MaxNameLength)



    ELSE

    RESULT := FALSE

    END

    END

    ELSE RESULT := FALSE

    END {GetItemIDName};





    // See GetPrintersPidl in Printers.CPP (line 406)

    FUNCTION GetPrinterItemIDList(CONST DeskTopFolder: IShellFolder): pItemIDlist;

    VAR

    hOK : hResult;

    PrinterItemIDList: pItemIDList;

    BEGIN

    IF DeskTopFolder = NIL

    THEN RESULT := NIL

    ELSE BEGIN

    hOK := SHGetSpecialFolderLocation(0,

    CSIDL_PRINTERS, // Virtual folder of installed printers

    PrinterItemIDList);

    IF Failed(hOK)

    THEN RESULT := NIL

    ELSE RESULT := PrinterItemIDList

    END

    END {GetPrinterItemIDList};





    // See GetThisPrinter in Printers.CPP (line 485)

    FUNCTION GetThisPrinter(CONST PrinterName: STRING;

    CONST Allocator: IMalloc): pItemIDlist;

    VAR

    Continue : BOOLEAN;

    DeskTopFolder : IShellFolder;

    EnumIDList : IEnumIDList;

    hOK : hResult;

    PrinterItemIDList: pItemIDList;

    PrintersFolder : IShellFolder;

    Retrieved : INTEGER;

    TargetItemIDList : pItemIDList;

    TempItemIDList : pItemIDList;

    TempString : ARRAY[0..255] OF CHAR;

    BEGIN

    TargetItemIDList := NIL;



    IF Allocator <> NIL

    THEN BEGIN



    IF Succeeded(SHGetDesktopFolder(DeskTopFolder))

    THEN BEGIN



    PrinterItemIDList := GetPrinterItemIDList(DeskTopFolder);

    IF PrinterItemIDList <> NIL

    THEN BEGIN



    // Get the IShellFolder for Printers

    hOK := DeskTopFolder.BindToObject(PrinterItemIDList,

    NIL,

    IID_IShellFolder,

    Pointer(PrintersFolder));

    IF Succeeded(hOK)

    THEN BEGIN

    IF Succeeded(PrintersFolder.EnumObjects(0, SHCONTF_FOLDERS OR SHCONTF_NONFOLDERS,

    EnumIDList))

    THEN BEGIN

    continue := TRUE;

    WHILE continue

    DO BEGIN

    hOK := EnumIDList.Next(1, TempItemIDList, Retrieved);



    // Check its name

    GetItemIDName(PrintersFolder, TempItemIDList, SHGDN_NORMAL,

    @TempString, SizeOf(TempString));

    continue := Succeeded(hOK) AND (Retrieved > 0) AND

    (StrIComp(TempString, pChar(PrinterName)) <> 0);

    END;



    IF (Retrieved > 0) AND Succeeded(hOK)

    THEN TargetItemIDList := ItemIDListsConcatenate(Allocator,

    PrinterItemIDList,

    TempItemIDList);



    END



    END

    END

    END

    END;



    RESULT := TargetItemIDList;

    END {GetThisPrinter};





    // See Pidl_Create in Printers.CPP (line 689)

    // Returns a pointer to the new ItemIDList, or NIL if a problem occurred.

    FUNCTION ItemIDListCreate(CONST Allocator: IMalloc; CONST size: INTEGER): pItemIDList;

    VAR

    NewItemIDList: pItemIDList;

    BEGIN

    NewItemIDList := Allocator.Alloc(size);



    IF NewItemIDList <> NIL

    THEN ZeroMemory(NewItemIDList, size);



    RESULT := NewItemIDList

    END {ItemIDListCreate};



    // See Pidl_GetNextItem in Printers.CPP (line 710)

    // Returns a pointer to the next item in the ItemIDList (Microsoft's Pidl_GetNextItem)

    FUNCTION ItemIDListGetNextItem(CONST ItemIDList: pItemIDList): pItemIDList;

    BEGIN

    IF ItemIDlist = NIL

    THEN RESULT := NIL

    ELSE RESULT := Pointer(INTEGER(ItemIDList) + ItemIDList.mkid.cb)

    END {ItemIDListGetNextItem};





    // See Pidl_GetSize in Printers.CPP (line 655)

    // Returns total number of bytes in an ItemIDList (Microsoft's Pidl_GetSize)

    FUNCTION ItemIDListGetSize(CONST ItemIDList: pItemIDList): INTEGER; {size in bytes}

    VAR

    TempItemIDList: pItemIDList;

    BEGIN

    RESULT := 0;

    TempItemIDList := ItemIDList;



    IF TempItemIDList <> NIL

    THEN BEGIN

    WHILE (TempItemIDList.mkid.cb > 0) DO

    BEGIN

    INC(RESULT, TempItemIDList.mkid.cb);

    TempItemIDList := ItemIDListGetNextItem(TempItemIDList)

    END;



    // Requires a 16 bit zero value for the null terminator

    INC(RESULT, 2*SizeOf(BYTE))

    END

    END {ItemIDListGetSize};





    // See Pidl_Concatenate in Printers.CPP (line 612)

    // Creates a new ItemIDList with List1 appended to List2

    FUNCTION ItemIDListsConcatenate(CONST Allocator: IMalloc;

    CONST List1, List2: pItemIDList): pItemIDlist;

    VAR

    List1Length : INTEGER;

    List2Length : INTEGER;

    NewItemIDList: pItemIDList;

    BEGIN

    List1Length := 0;

    // List1 can possibly be NIL if it points to the desktop. Since we only

    // need a sngle NIL terminator, we remove the extra 2 bytes from the size

    // of the first ItemIDList

    IF List1 <> NIL

    THEN List1Length := ItemIDListGetSize(List1) - 2*SizeOf(BYTE);



    List2Length := ItemIDListGetSize(List2);



    // Create a new ItemIDList that is the size of List1 and List2, then

    // copy List1 and List2 to the new list.



    NewItemIDList := ItemIDListCreate(Allocator, List1Length + List2Length);



    IF NewItemIDList <> NIL

    THEN BEGIN

    IF List1 <> NIL

    THEN CopyMemory(NewItemIDList, List1, List1Length);



    CopyMemory(Pointer(INTEGER(NewItemIDList) + List1Length),

    List2, List2Length)

    END;



    RESULT := NewItemIDList

    END {ItemIDListsConcatenate};





    // See OpenThisPrinter in Printers.CPP (line 233)

    FUNCTION OpenThisPrinter(CONST PrinterName: STRING): BOOLEAN;

    VAR

    Allocator : IMalloc;

    PrinterItemIDList: pItemIDList;

    ShellExecuteInfo : TShellExecuteInfo;

    BEGIN

    RESULT := FALSE;



    IF CoGetMalloc(MEMCTX_TASK, Allocator) = S_OK

    THEN BEGIN



    PrinterItemIDList := GetThisPrinter(PrinterName, Allocator);

    TRY

    IF PrinterItemIDList = NIL

    THEN RESULT := FALSE

    ELSE BEGIN

    ZeroMemory(@ShellExecuteInfo, SizeOf(TShellExecuteInfo));



    WITH ShellExecuteInfo DO

    BEGIN

    cbSize := SizeOf(TShellExecuteInfo);

    fMask := SEE_MASK_INVOKEIDLIST OR SEE_MASK_FLAG_NO_UI;

    lpIDList := PrinterItemIDlist;

    nShow := SW_SHOWDEFAULT

    END;



    ShellExecuteEx(@ShellExecuteInfo);

    RESULT := TRUE

    END

    FINALLY

    Allocator.Free(PrinterItemIDList)

    END

    END

    END {OpenThisPrinter};





    // See OpenPrinterProperties in Printers.CPP (line 41)

    FUNCTION OpenPrinterProperties(CONST PrinterName: STRING): BOOLEAN;

    VAR

    Allocator : IMalloc;

    PrinterItemIDList: pItemIDList;

    ShellExecuteInfo : TShellExecuteInfo;

    BEGIN

    RESULT := FALSE;

    IF CoGetMalloc(MEMCTX_TASK, Allocator) = S_OK

    THEN BEGIN

    PrinterItemIDList := GetThisPrinter(PrinterName, Allocator);

    TRY

    IF PrinterItemIDList = NIL

    THEN RESULT := FALSE

    ELSE BEGIN

    ZeroMemory(@ShellExecuteInfo, SizeOf(TShellExecuteInfo));



    WITH ShellExecuteInfo DO

    BEGIN

    cbSize := SizeOf(TShellExecuteInfo);

    fMask := SEE_MASK_INVOKEIDLIST OR SEE_MASK_FLAG_NO_UI;

    lpIDList := PrinterItemIDlist;

    lpVerb := 'Properties';

    nShow := SW_SHOWDEFAULT

    END;



    ShellExecuteEx(@ShellExecuteInfo);

    RESULT := TRUE

    END

    FINALLY

    Allocator.Free(PrinterItemIDList)

    END

    END

    END {OpenPrinterProperties};

    END.