我正在尝试为旧主机名,新主机名,用户名和密码提供文本字段,并远程更改计算机名称。那部分工作太棒了。这一切都很棒,直到我的经理看到它在行动,因为我们有一个反对下载和使用免费软件的政策。
如果我做的话,它不是免费软件。不幸的是,他把它发给了我的导演,并且知道我的导演知道我对Visual Basic有一点了解,所以他想从CSV文件循环名称,更改名称,并向最终用户发送消息,指示他们保存文件并重新启动。
不幸的是,自Vista发布以来,net send已经成为了XP的方式。但是,从Vista-Win8.1开始,在C:\ Windows \ System32中有一个名为msg.exe的实用程序。要使用它,目标计算机必须将HKLM \ SYSTEM \ CurrentControlSet \ Control \ Terminal Services中的注册表值AllowRemoteRPC设置为1.
所以这就是应用程序的作用:
读取DWORD键AllowRemoteRPC并将其存储到变量(MyVal),将键更改为1,尝试发送消息,提醒用户需要重新启动,将密钥更改回MyVal,然后执行netdom renamecomputer和重命名PC。一切都很完美除了发送消息。我可以打开命令提示符并输入:
msg /server:hostname * /v /time:3600 "my message here
它完美地工作(在手动编辑注册表项以获得所需的值之后)。
但是,从VB运行它不起作用。这是我尝试过的:
"msg /server:" & hostname & " * /v /time:3600 ""my message here"""
"cmd.exe /D /c msg /server:" & hostname & " * /v /time:3600 ""my message here"""
两者似乎都不起作用。我知道注册表值正在改变。我在每一步之后都放了消息框并刷新了regedit以实际看到DWORD键的值,它正在改变。一切顺利,消息就是没有被发送。
我确实将这些命令作为我创建的函数的参数运行,以便创建一个进程,以便将streamreader输出到列表框。
这是我的代码。请记住,我在学习视觉基础方面只有两个多月,所以它可能不是那里最漂亮的代码:
Imports System
Imports System.IO
Imports System.Diagnostics
Imports System.Security.Permissions
Imports Microsoft.Win32
Public Class applicationMain
Private Sub btnExecute_Click(sender As Object, e As EventArgs) Handles btnExecute.Click
Dim oldPC As String = txtOldPC.Text
Dim newPC As String = txtNewPC.Text
Dim username As String = txtUsername.Text
Dim password As String = txtPassword.Text
If oldPC <> "" And newPC <> "" And username <> "" And password <> "" Then
Dim MyReg As Microsoft.Win32.RegistryKey = Microsoft.Win32.RegistryKey.OpenRemoteBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, oldPC)
Dim MyRegKey As Microsoft.Win32.RegistryKey
Dim MyVal As String
lbOutput.Items.Clear()
MyRegKey = MyReg.OpenSubKey("System\CurrentControlSet\Control\Terminal Server")
MyVal = MyRegKey.GetValue("AllowRemoteRPC", RegistryValueKind.DWord)
MyRegKey.Close()
lbOutput.Items.Add("Processing registry changes...")
Try
MyRegKey = MyReg.OpenSubKey("System\CurrentControlSet\Control\Terminal Server", True)
MyRegKey.SetValue("AllowRemoteRPC", &H1, RegistryValueKind.DWord)
Catch ex As Exception
MessageBox.Show("An Error Has Occured:" & vbCrLf & vbCrLf & ex.ToString())
lbOutput.Items.Add("")
lbOutput.Items.Add("ABORTED!")
Exit Sub
End Try
lbOutput.Items.Add("Success!")
lbOutput.Items.Add("Sending message to user:")
Try
ExecuteCommand("cmd.exe", "/D /c msg /SERVER:" & oldPC & ".na.int.grp * /v /TIME:3600 ""Changes have been made by IS to your computer that require a restart. Please save your files and restart your computer to avoid service interruption.""")
Catch ex As Exception
MessageBox.Show("An Error Has Occured:" & vbCrLf & vbCrLf & ex.ToString())
lbOutput.Items.Add("")
lbOutput.Items.Add("ABORTED!")
MyRegKey = MyReg.OpenSubKey("System\CurrentControlSet\Control\Terminal Server", True)
MyRegKey.SetValue("AllowRemoteRPC", MyVal, RegistryValueKind.DWord)
Exit Sub
End Try
lbOutput.Items.Add(" Message: ""Changes have been made by IS to your computer that require a restart. Please save your files and restart your computer to avoid service interruption."" ")
lbOutput.Items.Add("Reverting registry changes...")
Try
MyRegKey = MyReg.OpenSubKey("System\CurrentControlSet\Control\Terminal Server", True)
MyRegKey.SetValue("AllowRemoteRPC", MyVal, RegistryValueKind.DWord)
Catch ex As Exception
MessageBox.Show("An Error Has Occured:" & vbCrLf & vbCrLf & ex.ToString())
lbOutput.Items.Add("")
lbOutput.Items.Add("ABORTED!")
Exit Sub
End Try
Try
ExecuteCommand("netdom", "renamecomputer " & oldPC & " /newname:" & newPC & " /userD:na\" & username & " /passwordd:" & password & " /usero:na\" & username & " /passwordo:" & password & " /Force")
Catch ex As Exception
MessageBox.Show("An Error Has Occured:" & vbCrLf & vbCrLf & ex.ToString())
lbOutput.Items.Add("")
lbOutput.Items.Add("ABORTED!")
Exit Sub
End Try
lbOutput.Items.Add("Success!")
lbOutput.Items.Add("")
lbOutput.Items.Add("Rename successful for " & oldPC & "!")
lbOutput.Items.Add("******************************************************************")
lbOutput.Items.Add("")
End If
End Sub
Private Function ExecuteCommand(ByVal cmd As String, ByVal arguments As String)
Dim cmdProcess As New Process()
Dim cmdProcessStartInfo As New ProcessStartInfo()
Dim cmdStreamReader As IO.StreamReader
Dim output As String
cmdProcessStartInfo.UseShellExecute = False
cmdProcessStartInfo.CreateNoWindow = True
cmdProcessStartInfo.RedirectStandardOutput = True
cmdProcessStartInfo.FileName = cmd
cmdProcessStartInfo.Arguments = arguments
cmdProcess.StartInfo = cmdProcessStartInfo
cmdProcess.Start()
cmdStreamReader = cmdProcess.StandardOutput
Do While cmdStreamReader.EndOfStream = False
output = cmdStreamReader.ReadLine()
lbOutput.SelectedIndex = lbOutput.Items.Count - 1
lbOutput.Items.Add(output)
Loop
cmdProcess.WaitForExit()
cmdProcess.Close()
Return vbNull
End Function
End Class
答案 0 :(得分:0)
你知道些什么。我的代码根本没有任何问题。在尝试使用paths变量时,我决定&#34; Fuhgeddaboudit,我只是将可执行文件添加到项目中!&#34;。右键单击该项目,添加 - &gt;现有项目。选择Executable作为类型,然后转到C:\ Windows \ System32,并立即获取此信息, msg.exe没有。完全没有。打开资源管理器并转到System32,msg.exe就在那里。无论出于何种原因,Visual Studio根本无法看到该程序。这本身就很奇怪。
所以我将msg.exe复制到我的桌面,将其添加到源代码,该程序现在就像魅力一样。