Solved

WMI, Printer c# 2005 express ?

Posted on 2006-07-12
31
1,095 Views
Last Modified: 2008-01-09
ok Found this article on codeproject.com and this is the first time I have used c# and I dont see any download to the source code to a working example and am having a hard time trying to use wmi within any language in 2005 so if someone could help me get this example on code project working that would be great.

Preferably with a cancel button and a cancel all button so that I can cancel individual print jobs or all the print jobs in the printer's que for a remote machine.

Here is the code project article :

http://www.codeproject.com/csharp/prntjobcontrollerusingwmi.asp
0
Comment
Question by:gecko_au2003
  • 16
  • 13
31 Comments
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
Step 1:  Here is a class that I use to enumerate Win32_PrintJobs:

using System;
using System.Management;

public class Win32_PrintJob
{

  public string DataType;
  public string Description;
  public string Document;
  public string DriverName;
  public DateTime ElapsedTime;
  public string HostPrintQueue;
  public DateTime InstallDate;
  public int JobId;
  public string JobStatus;
  public string Notify;
  public string Owner;
  public int PagesPrinted;
  public string Parameters;
  public string PrintProcessor;
  public int Priority;
  public int Size;
  public System.DateTime StartTime;
  public string Status;
  public int StatusMask;
  public DateTime TimeSubmitted;
  public int TotalPages;
  public DateTime UntilTime;

  public static Win32_PrintJob[] GetList()
  {
    string query = "Select * From Win32_PrintJob";

    ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);

    ManagementObjectCollection results = searcher.Get();

    Win32_PrintJob[] listPrintJobs = new Win32_PrintJob[results.Count - 1];

    int index = 0;
    foreach (ManagementObject entryCurrent in results)
    {
      Win32_PrintJob job = new Win32_PrintJob();

      job.DataType = (string)entryCurrent["DataType"];
      job.Description = (string)entryCurrent["Description"];
      job.Document = (string)entryCurrent["Document"];
      job.DriverName = (string)entryCurrent["DriverName"];
      job.ElapsedTime = ConvertFileTime((string)entryCurrent["ElapsedTime"]);
      job.HostPrintQueue = (string)entryCurrent["HostPrintQueue"];
      job.InstallDate = ConvertFileTime((string)entryCurrent["InstallDate"]);
      job.JobId = Convert.ToInt32(entryCurrent["JobId"]);
      job.JobStatus = (string)entryCurrent["JobStatus"];
      job.Notify = (string)entryCurrent["Notify"];
      job.Owner = (string)entryCurrent["Owner"];
      job.PagesPrinted = Convert.ToInt32(entryCurrent["PagesPrinted"]);
      job.Parameters = (string)entryCurrent["Parameters"];
      job.PrintProcessor = (string)entryCurrent["PrintProcessor"];
      job.Priority = Convert.ToInt32(entryCurrent["Priority"]);
      job.Size = Convert.ToInt32(entryCurrent["Size"]);
      job.StartTime = ConvertFileTime((string)entryCurrent["StartTime"]);
      job.Status = (string)entryCurrent["Status"];
      job.StatusMask = Convert.ToInt32(entryCurrent["StatusMask"]);
      job.TimeSubmitted = ConvertFileTime((string)entryCurrent["TimeSubmitted"]);
      job.TotalPages = Convert.ToInt32(entryCurrent["TotalPages"]);
      job.UntilTime = ConvertFileTime((string)entryCurrent["UntilTime"]);

      listPrintJobs[index] = job;

      index++;

    }
    return listPrintJobs;
  }

  private static DateTime ConvertFileTime(string time)
  {
    if (time != null)
    {
      const string FILE_TIME_MASK = "yyyyMMddHHmmss";
      time = time.Substring(0, time.IndexOf("."));
      return DateTime.ParseExact(time, FILE_TIME_MASK, null);
    }
    return DateTime.MinValue;
  }

}

Step 2:  Get a list of print jobs
 Call the static GetList and get back and array of Win32_PrintJob objects.

Step 3:  Get this from a remote machine
  To follow.

Bob
0
 
LVL 41

Expert Comment

by:graye
Comment Utility
WMI requires that you add a "Reference" to your project before it will work.

This is typically done from the Solution Explorer (usually in the upper right-hand corner of the Visual Studio's IDE.  Right click on the "References" item and select "Add Reference".  A dialog box will appear... scroll about 3/4 of the way down, and select "System.Management".
0
 
LVL 23

Author Comment

by:gecko_au2003
Comment Utility
TheLearnedOne :

I need this in rich dummy terms with regards to where to put all this code as well as how to cancel individual jobs and or cancel all the print jobs.

graye :

I have already added the system management reference and that didnt help any as I still got errors as I have no clue where to copy and paste that code to because whenever I copy and paste the code that is given in that example from code project it just flags up errors.

Any chance you could get the example in the code project working and uploaded to some webspace in a zip file ( Because if the reply regarding connecting to a remote machine on code project is correct here :

//Connect to the remote computer
ConnectionOptions co = new ConnectionOptions();

co.Username = textUserID.Text;
co.Password = textPassword.Text;

//Point to machine
System.Management.ManagementScope ms = new System.Management.
ManagementScope("\\\\" + stringHostName + "\\root\\cimv2", co);

Then connecting to a remote machine shouldn't be an issue ( As long as I know how to cancel invidual jobs as well as all the jobs ( obviously in 2 seperate buttons ) Then I will be fine.

Thanks for the help
0
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
Step 4:  Cancel individual jobs.
The Win32_Printer class has CancelAllJobs.  The Win32_PrintJob has a Pause and a Resume method.  Neither of these will do what you need.   To cancel the print job, you need to just delete the management object.

job.Document.Delete();

External reference:
A simple approach for controlling print jobs using WMI
http://www.codeproject.com/csharp/prntjobcontrollerusingwmi.asp

Bob

0
 
LVL 23

Author Comment

by:gecko_au2003
Comment Utility
so remind me, where does all the code go ? Do I need to create a new class to put your public class into or can I just copy and paste that into the same code window as the rest of the code or what steps do I need to take exactly ?
0
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
Step 5:  Implementation

1) Add a new class, called Win32_PrintJob, and paste the code from the class definition

2) The Win32_PrintJob.GetList returns an array of Win32_PrintJob elements, which contain the properties for each of the print job objects

3) Add a new property to the class:

   public ManagementObject PrintJob;

4) Add this line to GetList:

 job.PrintJob = entryCurrent;

5) Add a method to Win32_PrintJob:

   public static DeleteJob()
  {
      PrintJob.InvokeMethod("Delete", null);
  }

6) Add your code to set the management scope for the remote machine

7) Get all the print jobs:

  Win32_PrintJob[] list = Win32_PrintJob.GetList();

8) Cancel the job that you need

HTH
Bob
0
 
LVL 23

Author Comment

by:gecko_au2003
Comment Utility
ok here is my code so far :

'-------------------------

using System;
using System.Collections.Generic;
using System.Text;
using System;
using System.Management;

namespace PrintJob
{
    class Win32_PrintJob
    {
  public ManagementObject PrintJob;
  public string DataType;
  public string Description;
  public string Document;
  public string DriverName;
  public DateTime ElapsedTime;
  public string HostPrintQueue;
  public DateTime InstallDate;
  public int JobId;
  public string JobStatus;
  public string Notify;
  public string Owner;
  public int PagesPrinted;
  public string Parameters;
  public string PrintProcessor;
  public int Priority;
  public int Size;
  public System.DateTime StartTime;
  public string Status;
  public int StatusMask;
  public DateTime TimeSubmitted;
  public int TotalPages;
  public DateTime UntilTime;

  public static Win32_PrintJob[] GetList()
  {
    string query = "Select * From Win32_PrintJob";

    ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);

    ManagementObjectCollection results = searcher.Get();

    Win32_PrintJob[] listPrintJobs = new Win32_PrintJob[results.Count - 1];

    int index = 0;
    foreach (ManagementObject entryCurrent in results)
    {
      Win32_PrintJob job = new Win32_PrintJob();

      job.PrintJob = entryCurrent;
      job.DataType = (string)entryCurrent["DataType"];
      job.Description = (string)entryCurrent["Description"];
      job.Document = (string)entryCurrent["Document"];
      job.DriverName = (string)entryCurrent["DriverName"];
      job.ElapsedTime = ConvertFileTime((string)entryCurrent["ElapsedTime"]);
      job.HostPrintQueue = (string)entryCurrent["HostPrintQueue"];
      job.InstallDate = ConvertFileTime((string)entryCurrent["InstallDate"]);
      job.JobId = Convert.ToInt32(entryCurrent["JobId"]);
      job.JobStatus = (string)entryCurrent["JobStatus"];
      job.Notify = (string)entryCurrent["Notify"];
      job.Owner = (string)entryCurrent["Owner"];
      job.PagesPrinted = Convert.ToInt32(entryCurrent["PagesPrinted"]);
      job.Parameters = (string)entryCurrent["Parameters"];
      job.PrintProcessor = (string)entryCurrent["PrintProcessor"];
      job.Priority = Convert.ToInt32(entryCurrent["Priority"]);
      job.Size = Convert.ToInt32(entryCurrent["Size"]);
      job.StartTime = ConvertFileTime((string)entryCurrent["StartTime"]);
      job.Status = (string)entryCurrent["Status"];
      job.StatusMask = Convert.ToInt32(entryCurrent["StatusMask"]);
      job.TimeSubmitted = ConvertFileTime((string)entryCurrent["TimeSubmitted"]);
      job.TotalPages = Convert.ToInt32(entryCurrent["TotalPages"]);
      job.UntilTime = ConvertFileTime((string)entryCurrent["UntilTime"]);

      listPrintJobs[index] = job;

      index++;

    }
    return listPrintJobs;
  }

  private static DateTime ConvertFileTime(string time)
  {
    if (time != null)
    {
      const string FILE_TIME_MASK = "yyyyMMddHHmmss";
      time = time.Substring(0, time.IndexOf("."));
      return DateTime.ParseExact(time, FILE_TIME_MASK, null);
    }
    return DateTime.MinValue;
  }

}

}

'---------------------------

Im not sure where to put the code for step 5 or 7 and how do I link this class to the actual user form so that I can see this working ?
0
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
Do you have a main GUI form?

Bob
0
 
LVL 23

Author Comment

by:gecko_au2003
Comment Utility
Yes I clicked in the toolbar on insert and selected add windows form and it inserted a form.
0
 
LVL 23

Author Comment

by:gecko_au2003
Comment Utility
Just looking at the coding side with regards to connecting to the remote machine ( I dont understand where to put the following code )

//Connect to the remote computer
ConnectionOptions co = new ConnectionOptions();

co.Username = textUserID.Text;
co.Password = textPassword.Text;

//Point to machine
System.Management.ManagementScope ms = new System.Management.
ManagementScope("\\\\" + stringHostName + "\\root\\cimv2", co);


Does it go in place of this code :


    ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);

    ManagementObjectCollection results = searcher.Get();
0
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
1)  Add the scope to the searcher:

    ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
    searcher.Scope = ms;

2) Add a list box to display the print job descriptions

3) Add a button to delete the job

4) Get a reference to the right Win32_PrintJob object, and call the DeleteJob method.

Bob
0
 
LVL 23

Author Comment

by:gecko_au2003
Comment Utility
ok uploaded it to here :

http://www.badongo.com/file/1049914

Not sure how Im supposed to add a button to a delete job and the other steps just went over my head :-S
0
 
LVL 23

Author Comment

by:gecko_au2003
Comment Utility
1 --> I can leave for now and just do it for the local machine and can work on the remote machine part later on.

2 --> Done that already when I added the form as I added a button called cmdPrinter with the caption set to Printer ( which in c sharp is called text obviously )

3 --> Im assuming you mean just adding a button to the form ( Cos thats all Ive done ) and not sure what else to do or what to put in the button or w/e

4 --> How can I tell If I have the right reference to the Win32_PrintJob object and how can I call the DeleteJob Method as that is what I was stuck on ( remember steps 5 and 7 ) with regards to not knowing where to put the code for that.

When I know where to put the code for that then I am assuming its just a case of doing a

Call FunctionName()

Inside of the button ?
0
 
LVL 23

Author Comment

by:gecko_au2003
Comment Utility
you still there or did you give up ?
0
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
Man, do you think I live next to my computer, or am I allowed to have a life away from it?  

1) If you have an array of objects and a 1-to-1 correspondence with a ListBox, you can get the SelectedIndex, and get the right object from the array

2) Adding a button to a form is a fairly basic operation, and I hope that you are not asking me how to do that.

3) This isn't Visual Basic, so leave off the Call, and just use the function name:

   Win32_PrintJob job = jobList[this.ListBox1.SelectedIndex];
   job.DeleteJob();

Bob
0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
LVL 23

Author Comment

by:gecko_au2003
Comment Utility
I wasnt trying to say you live next to your computer or anything like that just before you were replying swiftly and then all of a sudden no reply. Sorry about that.

Just about to head off to work so I will give this a try this afternoon when I get back :)

I mis read what you said earlier but hopefully I can get this to work later on.
0
 
LVL 23

Author Comment

by:gecko_au2003
Comment Utility
Is there any chance yourself or someone else could put it all together for me because I have left out the job.deletejob() and just tried to do it for the local machine and now I am even getting errors on this chunk of code

private static DateTime ConvertFileTime(string time)
  {
    if (time != null)
    {
      const string FILE_TIME_MASK = "yyyyMMddHHmmss";
      time = time.Substring(0, time.IndexOf("."));
      return DateTime.ParseExact(time, FILE_TIME_MASK, null);
    }
    return DateTime.MinValue;
  }

It said something about it not being compatable with the gregorian calendar or something about a string or something along those lines.

As per my question this is the first time I have used c# and I am just getting frustrated trying to add in all these niggly little bits left right and centre when I have absolutly no clue where I am supposed to put them exactly.

Is it asking too much for an example that is something like :

put this code into a class called Win32_PrintJob

'whatever the code is

Call it like so from a command button in a form like so :

' code to add the print jobs into a list view and have either a button or a context menu which when the job or jobs are selected you either click cancel all or cancel job to cancel a print job or all of the print jobs.
0
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
You are making me work very hard for my money--oh, wait, I do this for free*BIG GRIN*

Bob
0
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
How would you do this in VB6?

Bob
0
 
LVL 23

Author Comment

by:gecko_au2003
Comment Utility
I wouldn't I was gonna do this in vb 2005 express. I just wanted to give it a go in c# as I have never used c# before.

Any chance you could get an example working for the local machine or at least add in the relevant parts of code into the class and then just give me the code I need to enumerate a listview which would be called from a button or in the form somewhere so that it just fills the list view with the print jobs.

Other then that I have another question open in the vb.net TA so if neither of the above is feasable then possibly help me with the cancelling the print jobs in vb.net 2005 express because I am further ahead with using vb.net with regards to at least having a listview that returns the print jobs in all the printers ( which I can alter to specific printers by using the where clause ie where name = 'printername'

I mean at the end of the day I just want a utility that will allow me to select a printer and either cancel a print job or purge all the print jobs for that printer.
0
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
I only asked about VB6, because I see where you are involved in that, and I wanted to give you a jumping off point, since C# is not significantly different.  I was kinda hopin' that I wouldn't have to do the whole thing for you as I am working on my own problems.  Teach someone to fish, and all that ;)

Bob
0
 
LVL 23

Author Comment

by:gecko_au2003
Comment Utility
I've used wmi in vbscript and vb 6 but I havent done classes so that is where I am struggling at least afaik.

To be honest I would be happy just to see this class working and enumerating the print jobs into a listbox at this point.

@ Teach someone to fish, and all that ;)

Are you sure you didn't trip over the fishing line cos I can feel a hook through my finger lol
0
 
LVL 96

Accepted Solution

by:
Bob Learned earned 500 total points
Comment Utility
Fair enough *LOL

Here is a fully functional prototype:
https://filedb.experts-exchange.com/incoming/ee-stuff/384-Prototype.PrintManager.zip

Bob
0
 
LVL 23

Author Comment

by:gecko_au2003
Comment Utility
Its not letting me logon to that ee stuff site, saying my logon credentials are wrong ( which I know isnt true ). email me it ( email is in profile - the yahoo one )
0
 
LVL 23

Author Comment

by:gecko_au2003
Comment Utility
that example partialy works but when I click on delete print job it duplicates the other print job and then i click on delete on the duplicated print job and I get an array out of bounds error ( As I have 2 printers installed ) and it is saying that the printer que is for \\nameofmachine ( which is fair enough ) but it doesnt display which printer it is going to ie \\machinename\\printername

anway im off out and if you cant help me with being too busy or w/e thats fine and I will award you points as you have been helpful
0
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
1) I don't have 2 printers to debug this one

2) The Owner property might be a link to the machine, but I am not sure

Bob
0
 
LVL 23

Author Comment

by:gecko_au2003
Comment Utility
I just installed some fake printers as I want to be able to do this for multiple printers ( If you would prefer I will ask about the bugs in a seperate question )
0
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
Nah, we can deal with here.  I will try to add some printers, and print to them.

Bob
0
 
LVL 23

Author Comment

by:gecko_au2003
Comment Utility
much appriecated :) thx !! :)
0
 
LVL 96

Expert Comment

by:Bob Learned
Comment Utility
You need to clear the ListView items collection.

Bob
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Extention Methods in C# 3.0 by Ivo Stoykov C# 3.0 offers extension methods. They allow extending existing classes without changing the class's source code or relying on inheritance. These are static methods invoked as instance method. This…
This article is for Object-Oriented Programming (OOP) beginners. An Interface contains declarations of events, indexers, methods and/or properties. Any class which implements the Interface should provide the concrete implementation for each Inter…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now