derek7467
asked on
vb.net and adding user to local group using PSEXEC
I am attempting to add a domain user to the local admin group using psexec, when i use the below string in a cmd prompt, it works flawlessly:
When i use the below vb.net code, the cmd window flashes and the local group doesnt get updated:
psexec \\10.1.10.10 net localgroup administrators tbuser.text /add
When i use the below vb.net code, the cmd window flashes and the local group doesnt get updated:
Dim targetpc As String = TextBox1.Text
Dim pstools As String = "C:\SWDEPOT\SD Remote Tool\PSTools"
Try
Dim p As New Process()
p.StartInfo.FileName = "C:\SWDEPOT\SD Remote Tool\PSTools\PsExec.exe"
p.StartInfo.Arguments = "-s" & " " & "-i" & " " & "-d" & " " & "\\" & targetpc & " " & Chr(34) & "localgroup" & " " & "administrators" & " " & tbUser.Text & " " & "/add" & Chr(34)
p.Start()
p.StartInfo.CreateNoWindow = True
p.WaitForExit()
Catch ex As Exception
MsgBox("Remote Workstation Unavailable", , "Information")
End Try
ASKER
I tried that already but i tried it again and the below still didnt work:
p.StartInfo.Arguments = "\\" & targetpc & " " & Chr(34) & "localgroup administrators test\username /add" & Chr(34)
ASKER
Also, the quotation marks are needed if using psexec in vb, versus not needing them doing in a cmd prompt
Usually this is indicative of an error with running the command (as Kimputer pointed out, your command between the explicit command line running and the program process creation are different. This is most likely producing a syntax error.). Couple of options I can see.
1. Capture the redirected output from the console window. Here is a very crude example:
Form1.vb -
Form1.Designer.vb -
Produces the following output when ran:
2. Redesign your application as a console application and use command line parameters. But then, you might as well just use a batch file or vb script if that is the case.
-saige-
1. Capture the redirected output from the console window. Here is a very crude example:
Form1.vb -
Imports System.Net
Imports System.ComponentModel
Public Class Form1
Private address As IPAddress
Private Function ValidateText(ByVal text As String) As Boolean
If String.IsNullOrEmpty(text) Then Return False
Return IPAddress.TryParse(text, address)
End Function
Private Sub OnClick(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
RichTextBox1.Clear()
Button1.Enabled = False
BackgroundWorker1.RunWorkerAsync()
End Sub
Public Sub OnDataReceived(ByVal sender As Object, ByVal e As DataReceivedEventArgs)
If e.Data IsNot Nothing Then BackgroundWorker1.ReportProgress(0, String.Format("{0}{1}", e.Data, Environment.NewLine))
End Sub
Private Sub OnTextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
ValidateText(TextBox1.Text)
End Sub
Private Sub OnValidating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles TextBox1.Validating
If ValidateText(TextBox1.Text) Then
Button1.Enabled = True
Else
Button1.Enabled = False
MessageBox.Show("Please enter a valid IP Address", "Invalid IP Address", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
TextBox1.Focus()
e.Cancel = True
End If
End Sub
Private Sub OnLoad(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
Button1.Enabled = False
End Sub
Private Sub OnDoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim [process] As Process = New Process()
Dim startInfo As ProcessStartInfo = New ProcessStartInfo() With _
{ _
.Arguments = address.ToString(), _
.CreateNoWindow = True, _
.FileName = "ping", _
.RedirectStandardError = True, _
.RedirectStandardOutput = True, _
.UseShellExecute = False _
}
[process].EnableRaisingEvents = True
AddHandler [process].ErrorDataReceived, AddressOf OnDataReceived
AddHandler [process].OutputDataReceived, AddressOf OnDataReceived
[process].StartInfo = startInfo
[process].Start()
[process].BeginErrorReadLine()
[process].BeginOutputReadLine()
[process].WaitForExit()
End Sub
Private Sub OnProgessChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
RichTextBox1.AppendText(e.UserState)
End Sub
Private Sub OnWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
Button1.Enabled = ValidateText(TextBox1.Text)
End Sub
End Class
Form1.Designer.vb -
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.RichTextBox1 = New System.Windows.Forms.RichTextBox()
Me.Button1 = New System.Windows.Forms.Button()
Me.TextBox1 = New System.Windows.Forms.TextBox()
Me.Label1 = New System.Windows.Forms.Label()
Me.BackgroundWorker1 = New System.ComponentModel.BackgroundWorker()
Me.SuspendLayout()
'
'RichTextBox1
'
Me.RichTextBox1.Location = New System.Drawing.Point(13, 13)
Me.RichTextBox1.Name = "RichTextBox1"
Me.RichTextBox1.ReadOnly = True
Me.RichTextBox1.Size = New System.Drawing.Size(368, 239)
Me.RichTextBox1.TabIndex = 0
Me.RichTextBox1.Text = ""
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(305, 258)
Me.Button1.Name = "Button1"
Me.Button1.Size = New System.Drawing.Size(75, 23)
Me.Button1.TabIndex = 1
Me.Button1.Text = "Ping Me!"
Me.Button1.UseVisualStyleBackColor = True
'
'TextBox1
'
Me.TextBox1.Location = New System.Drawing.Point(79, 259)
Me.TextBox1.Name = "TextBox1"
Me.TextBox1.Size = New System.Drawing.Size(220, 20)
Me.TextBox1.TabIndex = 2
'
'Label1
'
Me.Label1.AutoSize = True
Me.Label1.Location = New System.Drawing.Point(12, 262)
Me.Label1.Name = "Label1"
Me.Label1.Size = New System.Drawing.Size(61, 13)
Me.Label1.TabIndex = 3
Me.Label1.Text = "IP Address:"
'
'BackgroundWorker1
'
Me.BackgroundWorker1.WorkerReportsProgress = True
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(393, 293)
Me.Controls.Add(Me.Label1)
Me.Controls.Add(Me.TextBox1)
Me.Controls.Add(Me.Button1)
Me.Controls.Add(Me.RichTextBox1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Friend WithEvents RichTextBox1 As System.Windows.Forms.RichTextBox
Friend WithEvents Button1 As System.Windows.Forms.Button
Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
Friend WithEvents Label1 As System.Windows.Forms.Label
Friend WithEvents BackgroundWorker1 As System.ComponentModel.BackgroundWorker
End Class
Produces the following output when ran:
2. Redesign your application as a console application and use command line parameters. But then, you might as well just use a batch file or vb script if that is the case.
-saige-
ASKER
But the below psexec process actually works. IM just having trouble making the new one. The below code i use on a different button to open regedit on a remote computer, and it works fine.
Dim pstools As String = "C:\SWDEPOT\SD Remote Tool\PSTools"
Try
Dim p As New Process()
p.StartInfo.FileName = "C:\SWDEPOT\SD Remote Tool\PSTools\PsExec.exe"
p.StartInfo.Arguments = "-s" & " " & "-i" & " " & "-d" & " " & "\\" & targetpc & " " & Chr(34) & "regedit" & Chr(34)
p.Start()
p.StartInfo.CreateNoWindow = True
p.WaitForExit()
Catch ex As Exception
MsgBox("Remote Workstation Unavailable", , "Information")
End Try
ASKER
going to use the below method to do this instead of psexec:
Private Sub adduserasadmin()
Dim localusrname As String = "jdoe"
Dim PCNAME As String = TextBox1.Text
'Dim localusrname As String = UserNameTxtBx.Text
Dim LCL As New DirectoryEntry("WinNT://" & PCNAME & ",computer")
Dim DOM As New DirectoryEntry("WinNT://test.net")
Dim DOMUSR As DirectoryEntry = DOM.Children.Find(localusrname, "user")
Dim LCLGRP As DirectoryEntry = LCL.Children.Find("Administrators", "group")
LCLGRP.Invoke("Add", New Object() {DOMUSR.Path.ToString})
End Sub
I don't doubt that your command runs (in either case). But if you are not getting the expected results then you need to determine why. The way that you determine why is by redirecting the console output, whether to a rich textbox or textbox as I have shown above, to a log file or some other means.
-saige-
-saige-
ASKER
I've requested that this question be closed as follows:
Accepted answer: 0 points for derek7467's comment #a40483130
for the following reason:
better solution
Accepted answer: 0 points for derek7467's comment #a40483130
for the following reason:
better solution
Both solutions would have worked. In my case, I clearly said
You would know you're missing the "net" command.
The second solution would grant you insight on the error.
It would probably say "localgroup is not a valid command", thereby also directing you to put the "net" command in front of your code.
That you found a better solution is totally besides the point in question (even though it looks better, or even works better, the solution was provided by experts)
If the first command really works, mimic it in your code.
You would know you're missing the "net" command.
The second solution would grant you insight on the error.
It would probably say "localgroup is not a valid command", thereby also directing you to put the "net" command in front of your code.
That you found a better solution is totally besides the point in question (even though it looks better, or even works better, the solution was provided by experts)
ASKER
experts did not provide the solution. Even when using net it still didnt work
ASKER
I've requested that this question be deleted for the following reason:
identifying business info
identifying business info
Simply modifying my solution to use psexec with your initial command line parameters produces the following output:
This give's you the reason that your command was not working as "PsExec could not start localgroup administrators paul /add on localhost". This simply means that localgroup is not a valid command.
I believe that you were trying to do this:
Which does execute and produces intended results. (which is what Kimputer also recommended).
-saige-
This give's you the reason that your command was not working as "PsExec could not start localgroup administrators paul /add on localhost". This simply means that localgroup is not a valid command.
I believe that you were trying to do this:
Dim [process] As Process = New Process()
Dim startInfo As ProcessStartInfo = New ProcessStartInfo() With _
{ _
.Arguments = String.Format("-s -i -d \\{0} net localgroup administrators {1} /add", targetpc, tbUser.Text), _
.CreateNoWindow = True, _
.FileName = "C:\_admin\PsTools\psexec.exe", _
.RedirectStandardError = True, _
.RedirectStandardOutput = True, _
.UseShellExecute = False _
}
Which does execute and produces intended results. (which is what Kimputer also recommended).
-saige-
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
-s -i -d \\10.0.0.0 "localgroup administrators user /add"
Not only did you not mention the -s -i -d in the first command, you added two quotation marks as well.
If the first command really works, mimic it in your code.