Home All Groups Group Topic Archive Search About

Process that copies a prn file to a network printer under username

Author
17 Jan 2006 1:59 AM
Philip Wagenaar
I need to send printjobs to a printqueue under diffrent usernames. The
printsoftware on the queue is not very 'secure' so I can create a user on 1
system and send a printjob under it's name to the printqueue.

This is why I created a program that picks the username out for the .PRN
file, creates a local user, copies the PRN file the network printer and
deletes the user.

I cannot get it to work. I tried first copying a normal text file from one
folder to another but that also does not work. I am having a difficult time
getting a new process to run cmd.exe with /c copy aaaa.txt c:\ as arguments,
let alone copy a .prn file to a network printer (which is also copy aaa.prn
//server/printqueue).

What am I doing wroing?

My code:

Imports System.IO
Imports System.Diagnostics

Public Class Form1

    Public watchfolder As FileSystemWatcher
    Public ComputerName As String
    Public PrintQueue As String
    Public Password As String
    Public ini As New iniFile(Environment.CurrentDirectory + "\settings.ini")

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
        Password = "P@ssw0rd"

        watchfolder = New System.IO.FileSystemWatcher()

        'this is the path we want to monitor
        watchfolder.Path = ini.GetString("main", "folder", "")

        'Add a list of Filter we want to specify
        'make sure you use OR for each Filter as we need to
        'all of those

        watchfolder.NotifyFilter = IO.NotifyFilters.DirectoryName
        watchfolder.NotifyFilter = watchfolder.NotifyFilter Or _
                                   IO.NotifyFilters.FileName
        watchfolder.NotifyFilter = watchfolder.NotifyFilter Or _
                                   IO.NotifyFilters.Attributes

        ' add the handler to each event
        AddHandler watchfolder.Created, AddressOf CopyJob
        MsgBox(ini.FileName)
        MsgBox(watchfolder.Path)
        'Set this property to true to start watching
        watchfolder.EnableRaisingEvents = True


    End Sub

    Private Sub StartCommand(ByVal Command As String, ByVal Args As String,
ByVal User As String, ByVal Password As String, ByVal WorkDir As String)
        Dim ProcessInfo As New ProcessStartInfo
        Dim sstr As New System.Security.SecureString
        Dim pwd As String = Password

        Dim chars() As Char = pwd.ToCharArray()

        Dim i As Integer

        For i = 0 To chars.Length - 1
            sstr.AppendChar(chars(i))
        Next
        ProcessInfo.UseShellExecute = False
        ProcessInfo.UserName = User
        ProcessInfo.Password = sstr
        ProcessInfo.FileName = Command
        ProcessInfo.Arguments = Args
        ProcessInfo.WorkingDirectory = WorkDir
        ProcessInfo.WindowStyle = ProcessWindowStyle.Hidden
        ProcessInfo.CreateNoWindow = True

        Dim myProcess As New Process()
        myProcess.StartInfo = ProcessInfo
        myProcess.Start()

    End Sub

    Private Sub CreateUser(ByVal User As String)
        'Create Account
        Dim strUser As String = User
        Dim oDomain As Object = GetObject("WinNT://" + ComputerName)
        Dim oUser As Object = oDomain.Create("user", strUser)
        If (Err.Number = 0) Then
            oUser.SetInfo()
            oUser.SetPassword(Password)
            oUser.SetInfo()
        End If
    End Sub

    Private Sub DeleteUser(ByVal User As String)
        Dim strUser As String = User
        Dim oDomain As Object = GetObject("WinNT://" + ComputerName)
        Try
            Dim oUser As Object = oDomain.Delete("user", strUser)
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try

    End Sub

    Private Sub CopyJob(ByVal source As Object, ByVal e As
System.IO.FileSystemEventArgs)
        Dim filename As String = e.FullPath
        MsgBox(filename)
        ComputerName = System.Environment.MachineName
        PrintQueue = ini.GetString("main", "printqueue", "")
        Dim Username As String = ""

        If Not e.Name.IndexOf("_") = -1 Then
            Dim NewOwner() As String = e.Name.ToString.Split("_")
            Username = NewOwner(0)
        End If

        If Not Username = "" Then
            DeleteUser(Username)
            CreateUser(Username)
            StartCommand("c:\windows\system32\cmd.exe", "/c copy " &
filename & " " & PrintQueue, Username, Password, Environment.CurrentDirectory)
            DeleteUser(Username)
            MsgBox("Done")
        End If


    End Sub

End Class

Author
17 Jan 2006 9:01 AM
Peter Huang" [MSFT]
Hi,

Based on my understanding, copy a file onto a file share folder under
certain username.
I think we can call the impersonate code to run the File.Copy code under
certain user credentials to achive the job.

Here is an KB about how to call logon user to impersonate a user credential.
841699    How to validate Windows user rights in a Visual Basic .NET
application
http://support.microsoft.com/default.aspx?scid=kb;EN-US;841699

If I have misunderstood, please feel free to post here.

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
Author
17 Jan 2006 10:17 AM
Philip Wagenaar
Can this be used to copy a file to a network printer?

PCL files can be copied to a network printer with copy myprintjob.prn
//server/printername

This works from the shell command.

Show quoteHide quote
""Peter Huang" [MSFT]" wrote:

> Hi,
>
> Based on my understanding, copy a file onto a file share folder under
> certain username.
> I think we can call the impersonate code to run the File.Copy code under
> certain user credentials to achive the job.
>
> Here is an KB about how to call logon user to impersonate a user credential.
> 841699    How to validate Windows user rights in a Visual Basic .NET
> application
> http://support.microsoft.com/default.aspx?scid=kb;EN-US;841699
>
> If I have misunderstood, please feel free to post here.
>
> Best regards,
>
> Peter Huang
> Microsoft Online Partner Support
>
> Get Secure! - www.microsoft.com/security
> This posting is provided "AS IS" with no warranties, and confers no rights.
>
>
Author
17 Jan 2006 10:56 AM
Philip Wagenaar
And the kb is for framework 1.1, in 2.0 you can start a process under a
diffrent username.

Show quoteHide quote
"Philip Wagenaar" wrote:

> Can this be used to copy a file to a network printer?
>
> PCL files can be copied to a network printer with copy myprintjob.prn
> //server/printername
>
> This works from the shell command.
>
> ""Peter Huang" [MSFT]" wrote:
>
> > Hi,
> >
> > Based on my understanding, copy a file onto a file share folder under
> > certain username.
> > I think we can call the impersonate code to run the File.Copy code under
> > certain user credentials to achive the job.
> >
> > Here is an KB about how to call logon user to impersonate a user credential.
> > 841699    How to validate Windows user rights in a Visual Basic .NET
> > application
> > http://support.microsoft.com/default.aspx?scid=kb;EN-US;841699
> >
> > If I have misunderstood, please feel free to post here.
> >
> > Best regards,
> >
> > Peter Huang
> > Microsoft Online Partner Support
> >
> > Get Secure! - www.microsoft.com/security
> > This posting is provided "AS IS" with no warranties, and confers no rights.
> >
> >
Author
18 Jan 2006 7:39 AM
Peter Huang" [MSFT]
Hi Philip,

From your description, I understand that you want to know how to use the
Process class to run a shell command using another user account in .NET 2.0.

Based on my research, we can use the Start method of the Process class to
achieve your job.

Here is the code snippet for your reference.

============================================================================
============
'TextBox1: username
'TextBox2: password
'TextBox3: domain
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
        Dim pass As New SecureString
        Dim s As String = TextBox2.Text
        For Each c As Char In s.ToCharArray()
            pass.AppendChar(c)
        Next
        Process.Start("cmd", "/c copy c:\test.bmp \\servername\myshare",
Me.TextBox1.Text, pass, TextBox3.Text)
    End Sub
============================================================================
============

If you still have any concern, please feel free to let me know.
I look forward to hearing from you.

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
Author
18 Jan 2006 10:17 AM
Philip Wagenaar
This works for copying a file to another folder or drive. But this does not
work for copying a .prn file to a network printer. But when you try to copy a
..prn file to a network printer using the same commands using a dosbox it does
work.

So why does copying prn file work from a dosbox and not from process.start
(can you confirm this?)

Show quoteHide quote
""Peter Huang" [MSFT]" wrote:

> Hi Philip,
>
> From your description, I understand that you want to know how to use the
> Process class to run a shell command using another user account in .NET 2.0.
>
> Based on my research, we can use the Start method of the Process class to
> achieve your job.
>
> Here is the code snippet for your reference.
>
> ============================================================================
> ============
> 'TextBox1: username
> 'TextBox2: password
> 'TextBox3: domain
>     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
> System.EventArgs) Handles Button1.Click
>         Dim pass As New SecureString
>         Dim s As String = TextBox2.Text
>         For Each c As Char In s.ToCharArray()
>             pass.AppendChar(c)
>         Next
>         Process.Start("cmd", "/c copy c:\test.bmp \\servername\myshare",
> Me.TextBox1.Text, pass, TextBox3.Text)
>     End Sub
> ============================================================================
> ============
>
> If you still have any concern, please feel free to let me know.
> I look forward to hearing from you.
>
> Best regards,
>
> Peter Huang
> Microsoft Online Partner Support
>
> Get Secure! - www.microsoft.com/security
> This posting is provided "AS IS" with no warranties, and confers no rights.
>
>
Author
19 Jan 2006 6:59 AM
Peter Huang" [MSFT]
Hi Philip,

Based on  my test, I can not reproduce the problem.
Here is my test code.
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
        'Dim p As New Process
        Dim pass As New SecureString
        Dim s As String = TextBox2.Text
        For Each c As Char In s.ToCharArray()
            pass.AppendChar(c)
        Next
        Dim par As String
        par = "/c copy c:\test.prn \\servername\printername"
        'par = "/c copy c:\test.bmp \\servername\myshare"
        Process.Start("cmd", par, Me.TextBox1.Text, pass, TextBox3.Text)
    End Sub

BTW: Did you run the code in a Window Service? Because the Window Service
will run under another desktop which is different from the logoned
interactive desktop, in that desktop, the network share printer did not
work as  \\servername\printername, this is commonly user percific.

To isolate the problem, I suggest you run the code in a winform application
directly.

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
Author
20 Jan 2006 9:25 AM
Philip Wagenaar
For some reason today it works, I think it has to do with space in the
printername and quotation marks.

I changed my approach from a windows service to a forms application. When
the forms app works I will try to convert it to a window service.

I am doing this because I need to start a print job under a specific
username. I have solved the problem of the shared printername for when I
convert to service.

- I installed services for unix on both machines.
- Installed a localprinter that uses a LPR printer poort to the networked
printer
- Now I can print to a local printer (machine specific) from any account on
the machine

I will try

Show quoteHide quote
""Peter Huang" [MSFT]" wrote:

> Hi Philip,
>
> Based on  my test, I can not reproduce the problem.
> Here is my test code.
>     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
> System.EventArgs) Handles Button1.Click
>         'Dim p As New Process
>         Dim pass As New SecureString
>         Dim s As String = TextBox2.Text
>         For Each c As Char In s.ToCharArray()
>             pass.AppendChar(c)
>         Next
>         Dim par As String
>         par = "/c copy c:\test.prn \\servername\printername"
>         'par = "/c copy c:\test.bmp \\servername\myshare"
>         Process.Start("cmd", par, Me.TextBox1.Text, pass, TextBox3.Text)
>     End Sub
>
> BTW: Did you run the code in a Window Service? Because the Window Service
> will run under another desktop which is different from the logoned
> interactive desktop, in that desktop, the network share printer did not
> work as  \\servername\printername, this is commonly user percific.
>
> To isolate the problem, I suggest you run the code in a winform application
> directly.
>
> Best regards,
>
> Peter Huang
> Microsoft Online Partner Support
>
> Get Secure! - www.microsoft.com/security
> This posting is provided "AS IS" with no warranties, and confers no rights.
>
>
Author
23 Jan 2006 6:30 AM
Peter Huang" [MSFT]
Hi

Thanks for your quickly reply!

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.