Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding jobs to a specific user's PrintQueue

I have an application that does some central file generation based on user requests. What I want to be able to do with it once the files are created is to place them in that user's print queue ( in this organisation there is a central print queue so users are responsible for printing their own documents ) so that they can then be printed off when the user is ready.

By using the System.Printing assemblies in .net I am able to add a job to my own print queue, so I am sound on that part. My print code looks like this:

private void RunPrintJob( string myFileName )
    {
        PrintServer ps = new PrintServer(@"\\printatron");
        PrintQueue queue = new PrintQueue(ps, "psandqueues");
        try
        {
            PrintSystemJobInfo pj = queue.AddJob(myFileName);
            Stream myStream = pj.JobStream;
            Byte[] myByteBuffer = GenerateBufferFromFile(myFileName);                myStream.Write(myByteBuffer, 0, myByteBuffer.Length);
            myStream.Close();
        }
        catch (Exception ed)
        {
            Debug.WriteLine(ed.Message);
            if (ed.InnerException != null)
            {
                Debug.WriteLine(" -> " + ed.InnerException);
            }
            result = false;
        }
        queue.Commit();
    }

So I have my centrally created documents, I know which user was responsible for their creation and I can send them to the printer.

What I need now is a way to send them to the printer with the user who created them set as their user. Is there a way to do this through the print queue? I know it is readable from the PrintSystemJobInfo.Submitter property, but that is read-only. If not, do I have to do it through impersonation and if so in the latter case is there anything I can do to avoid having to store a bunch of user passwords and have the software fail every time the user changes their password? That seems like it would be a really clumsy way of operating, but as this activity isn't currently performed interactively what other options do I have?

like image 628
glenatron Avatar asked May 21 '12 14:05

glenatron


1 Answers

I'm doing something similar. Impersonation is not too bad, if the process has sufficient permissions to get the level of impersonation you need (e.g. impersonation or delegation vs identification).

Here is what I do to impersonate:

    public static bool GetImpersonationToken(string UPN, out IntPtr dupToken)
    {
        dupToken = IntPtr.Zero;
        WindowsImpersonationContext impersonationContext = null;

        bool result = false;
        try
        {
            WindowsIdentity wid = new WindowsIdentity(UPN);
            impersonationContext = wid.Impersonate();
            result = DuplicateToken(wid.Token, 2, ref dupToken) != 0;
        }
        finally
        {
            if (impersonationContext != null)
                impersonationContext.Undo();
        }

        return result;
    }

Note: it is the calling method's responsibility to clean up that token handle.

I resolve the UPN from an LDAP query based on a users email (usually they are the same, but often enough they're not).

But I'm having some issues with the byte array that I'm passing in. I tried File.ReadAllBytes, but that causes the printer to spit out gibberish. Is there some special encoding that needs to happen in GenerateBufferFromFile?

** Update **

Looks like there are a bunch of issues around working with the JobStream directly:

Is PrintSystemJobInfo.JobStream broken?

So i'm just going to write to file, although I was hoping to avoid that.

like image 73
doveryai Avatar answered Sep 20 '22 07:09

doveryai