Newsgroup: it.comp.lang.delphi
Titolo: Set Printer On line

Salve, sto cercando (senza successo) di modificare lo stato della
stampante predefinita.
function TestPrinterOffLine:Boolean;
var
  HPrinter : THandle;
  InfoSize,
  BytesNeeded: Cardinal;
  PI2: PPrinterInfo2;
  PrinterDefaults: TPrinterDefaults;
  SelectedPrinter: string;
begin
  Result:=False;
  SelectedPrinter:=Printer.Printers[Printer.PrinterIndex];
  with PrinterDefaults do begin
    DesiredAccess := PRINTER_ACCESS_USE;
    pDatatype := nil;
    pDevMode := nil;
  end;
  if OpenPrinter(PChar(SelectedPrinter), HPrinter, @PrinterDefaults)
then
  try
    if not GetPrinter(HPrinter, 2, nil, 0, @BytesNeeded) then  begin
      PI2 := AllocMem(BytesNeeded);
      try
        InfoSize := SizeOf(TPrinterInfo2);
        if GetPrinter(HPrinter, 2, PI2, BytesNeeded, @BytesNeeded)
then
            Result:=PI2^.Attributes and PRINTER_ATTRIBUTE_WORK_OFFLINE
= PRINTER_ATTRIBUTE_WORK_OFFLINE
        else
            Result:=False;
      finally
        FreeMem(PI2, BytesNeeded);
      end;
    end;
  finally
    ClosePrinter(HPrinter);
  end;
end;
Questa mi serve per controllare lo stato, funziona.
Per settare la stampante online (se non lo è) ho cercato la via di
creare uno script vbs ma non và.
C'e una strada per farlo direttamente con il delphi?

 C'e una strada per farlo direttamente con il delphi?
Quando si fanno domande cosi' specifiche che riguardano anche le API di 
Windows, � sempre meglio specificare anche: 
- versione del SO su cui deve funzionare (tutti da win95 a Vista? Solo 
Vista? ecc...)
- Modello della stampante: non � detto che quello che offre il sistema 
operativo sia supportato dal driver della stampante.
- la versione di delphi che si usa.
- spiegare meglio cosa significa "non va": la stampante non cambia stato,
il 
codice non compila, se usato su un altro computer o configurazione � tutto
a 
posto, ecc...
Detto tutto questo, non � sicuro che qualcuno conosca la risposta, ma 
sicuramente hai qualche speranza in pi� che qualcuno ti risponda.
Per il tuo problema specifico, solitamente con GETPRINTER si leggono i 
valori con SETPRINTER si impostano: vedi qui 
http://support.microsoft.com/kb/140285/EN-US/
Quindi, in sostanza, devi impostare il flag PRINTER_ATTRIBUTE_WORK_OFFLINE 
nella struttura PRINTER_INFO_2 con l'API SetPrinter.
ACSH
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 - Mostra testo citato -
Delphi 2010 e stampante in windows xp (home).
Devo srivere del codice che:
1 Trova la stampante di default (è sempre una hp laser)
2 Verifica se la stampante si trova nello stato "usa stampante non in
linea"
3 Se si strova in questo stato la riporta nello stato normale
4 se c'è un acoda di stala la elimina.
il passo 1, 2 e 4 l'ho già completato e funziona bene.
il passo 3 non riesco a farlo funzionare.
Ho provato con questo codice ma la stampante rimane sempre nello
stesso stato
function TestPrinterOffLine:Boolean;
var
  HPrinter : THandle;
  InfoSize,
  BytesNeeded: Cardinal;
  PI2: PPrinterInfo2;
  PrinterDefaults: TPrinterDefaults;
  SelectedPrinter: string;
begin

Poi ho provato con il comando script vb:
cscript prncnfg.vbs -t -p "Samsung SCX-4x21 Series" -workoffline
che funziona chiamandolo da finestra dos
ma non riesco a lanciarlo con shellexecute
Spero di essere stato chiaro questa volta.

avevo dimenticato:
procedure TForm24.Button1Click(Sender: TObject);
var
  HPrinter : THandle;
  InfoSize,
  BytesNeeded: Cardinal;
  PI2: PPrinterInfo2;
  PrinterDefaults: TPrinterDefaults;
  SelectedPrinter: string;
begin
  SelectedPrinter:=Printer.Printers[Printer.PrinterIndex];
  with PrinterDefaults do begin
    DesiredAccess := PRINTER_ACCESS_USE;
    pDatatype := nil;
    pDevMode := nil;
  end;
  if OpenPrinter(PChar(SelectedPrinter), HPrinter, @PrinterDefaults)
then
  try
    if not GetPrinter(HPrinter, 2, nil, 0, @BytesNeeded) then  begin
      PI2 := AllocMem(BytesNeeded);
      try
        InfoSize := SizeOf(TPrinterInfo2);
        if GetPrinter(HPrinter, 2, PI2, BytesNeeded, @BytesNeeded)
then begin
           ShowMessage(IntToStr(PI2^.Attributes)); // Show 1601
           PI2^.Attributes:=PI2^.Attributes and not
(PRINTER_ATTRIBUTE_WORK_OFFLINE);
           SetPrinter(Hprinter, 2, PI2, 0);
           ShowMessage(IntToStr(PI2^.Attributes));//Show 577
        end;


 ma non riesco a lanciarlo con shellexecute
Mostra il codice che hai usato per farlo.
Secondo me, qualcosa del genere dovrebbe funzionare 
(sistemandolo con i giusti path):
ShellExecute(Handle, 'open', 'cscript.exe', 
'"prncnfg.vbs -t -p "Samsung SCX-4x21 Series" -workoffline
"', nil,  SW_MINIMIZE);
Ciao
ACSH 
--- news://
freenews.netfront.net/
 - complaints: 
ne...@netfront.net
 ---

 --- news://
freenews.netfront.net/
 - complaints: 
n...@netfront.net
 ---
Giusto non è una finestra dos ma un prompt dei comandi.
Grazie ma
 ShellExecute(0, 'open', 'c:\windows\system32\cscript.exe',
                 '"C:\Progetto Maxi\Maxi\prncnfg.vbs -t -p "Samsung
SCX-4x21 Series" -workoffline"', nil,  SW_NORMAL);
Non funziona
Ho provato anche con ShellExecuteex stesso risultato.
Ancora grazie

 Magari usa qualche utlity appostina.
Ho dato unocchiata al file prncnfg.vbs
ho pensato che la arte che mi interessa è contenuta in una funzione
cheiamata setprinter
ho isolato questa parte di codice  codice della funzione:
    strServer   = oParamDict.Item(kServerName)
    strPrinter  = oParamDict.Item(kPrinterName)
    strNewName  = oParamDict.Item(kNewPrinterName)
    strUser     = oParamDict.Item(kUserName)
    strPassword = oParamDict.Item(kPassword)
    if WmiConnect(strServer, kNameSpace, strUser, strPassword,
oService) then
        set oPrinter = oService.Get("Win32_Printer='" & strPrinter &
"'")
    else
        SetPrinter = kErrorFailure
    end if
    if Err.Number = kErrorSuccess then
        if oParamdict.Exists(kWorkOffline)     then
           oPrinter.WorkOffline         = oParamDict.Item
(kWorkOffline)
        end if
        oPrinter.Put_(kFlagUpdateOnly)
Ciao

Risolto:
procedure TForm7.Button1Click(Sender: TObject);
var
  HPrinter : THandle;
  InfoSize,
  BytesNeeded: Cardinal;
  PI2: PPrinterInfo2;
  PrinterDefaults: TPrinterDefaults;
  SelectedPrinter: string;
begin
  SelectedPrinter:='Samsung SCX-4x21 Series';
  with PrinterDefaults do begin
    DesiredAccess := PRINTER_ALL_ACCESS;
    pDatatype := nil;
    pDevMode := nil;
  end;
  if OpenPrinter(PChar(SelectedPrinter), HPrinter, @PrinterDefaults)
then
  try
    if not GetPrinter(HPrinter, 2, nil, 0, @BytesNeeded) then  begin
      PI2 := AllocMem(BytesNeeded);
      try
        InfoSize := SizeOf(TPrinterInfo2);
        if GetPrinter(HPrinter, 2, PI2, BytesNeeded, @BytesNeeded)
then begin
           PI2^.Attributes:=PI2^.Attributes and not
(PRINTER_ATTRIBUTE_WORK_OFFLINE);
           if SetPrinter(Hprinter, 2, PI2, 0) then
        end;
      finally
        FreeMem(PI2, BytesNeeded);
      end;
    end;
  finally
    ClosePrinter(HPrinter);
  end;
end;
Il problema era avere i giusti diritti per modificare lo stato :
PRINTER_ALL_ACCESS;
Grazie a tutti.