How can i execute msg.exe by C# in windows? - c#

Is there a way to display the windows popup msg by using C#?
I mean by using the windows msg.exe program that can be used in cmd, for example:" msg * Hello "
PD: I know that i can use MessageBox.Show() instead. But i want to know if this is possible :(
I wrote 2 ways to do it but none worked:
Process.Start("cmd.exe","/C msg * Hello");
and...
Process cmd = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = "/C msg * Hello",
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
}
};
cmd.Start();

Did you try adding msg.exe directly?
Process cmd = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = #"msg.exe",
Arguments = #"* /v Hello",
WorkingDirectory = Environment.SystemDirectory;
WindowStyle = ProcessWindowStyle.Normal
}
};
cmd.Start();

I encountered the same problem.
This was because the project was configured as "AnyCPU" but the "Prefer 32-bit" option was checked in the "Build" tab of the project configuration. Uncheck that option and the problem will disappear.
Edit: personnaly, I use the following function to locate the binary according to the executable and OS platform (32/64 bits):
public static bool LocateMsgExe(out string returnedMsgPath)
{
returnedMsgPath = null;
string[] msgPaths = new string[] { Environment.ExpandEnvironmentVariables(#"%windir%\system32\msg.exe"),
Environment.ExpandEnvironmentVariables(#"%windir%\sysnative\msg.exe") };
foreach (string msgPath in msgPaths)
{
if (File.Exists(msgPath))
{
returnedMsgPath = msgPath;
return true;
}
}
return false;
}
And for invoking it :
if (LocateMsgExe(out string strMsgPath))
{
Process.Start(strMsgPath, "* \"Hello world!\"");
}
Regards,
damien.

This is my solution. It consists of a webpage (.aspx) with a listbox (lstComputers), a textbox (txtMessageToSend), a dropdownlist to select the OU that contains the computers that will receive the message and a button (btnSendMessage).
This is the code for btnSendMessage on the aspx.cs
protected void btnSendMessage_Click(object sender, EventArgs e)
{
string searchbase = ddlZaal.SelectedItem.Text; //This is a dropdownlist to select an OU
DirectoryEntry entry = new DirectoryEntry("LDAP://OU=" + searchbase + ",OU=YourOU,OU=YourSubOU," + Variables.Domain + ""); //Variables.Domain is specified in the Web.config
DirectorySearcher mySearcher = new DirectorySearcher(entry);
mySearcher.Filter = ("(objectClass=computer)");
foreach (SearchResult result in mySearcher.FindAll())
{
DirectoryEntry directoryObject = result.GetDirectoryEntry();
string computernaam = directoryObject.Properties["Name"].Value.ToString();
lstComputers.Items.Add(computernaam); //This is a listbox that shows the computernames. To each computer a message is sent.
string pingnaam = computernaam + "dns.suffix"; //Might be necessary for connecting to the computes in the domain
string MessageToSend = txtMessageToSend.Text; //The text in this textbox will be the messagetext
Process process = new Process();
ProcessStartInfo psi = new ProcessStartInfo(#"C:\inetpub\wwwroot\PsExec.exe"); //Location of PsExec.exe on the webserver that hosts the web-application.
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
psi.RedirectStandardInput = true;
psi.WindowStyle = ProcessWindowStyle.Minimized;
psi.CreateNoWindow = true;
psi.Arguments = "/accepteula -s -i \\\\" + pingnaam + " cmd /c msg.exe * " + MessageToSend;
process.StartInfo = psi;
process.Start();
}
}

Related

c# Programm using Process.Start(ProcessStartInfo info) does not work

I tried to open a OpenVPN connection using a small c# program.
Below is the code I used.
static void Main(string[] args)
{
Process rs = new Process();
var netCredential = new System.Net.NetworkCredential("User", "PWD", "Domain");
System.Environment.CurrentDirectory = ".\\";
ProcessStartInfo info = new ProcessStartInfo
{
FileName = "c:\\programme\\openvpn\\bin\\openvpn.exe",
Arguments = "--config c:\\programme\\openvpn\\config\\NAS-Name.ovpn",
UserName = netCredential.UserName,
Domain = netCredential.Domain,
Password = netCredential.SecurePassword,
UseShellExecute = false,
//RedirectStandardError = true,
//RedirectStandardOutput = true,
//CreateNoWindow = true,
WorkingDirectory = Path.GetDirectoryName("c:\\programme\\openvpn\\bin\\openvpn.exe")
};
var p = Process.Start(info);
}
This code does work, but only on the computer were I compiled it.
On our server (Win server 2019) I get the error:
Unhandled Exception: System.ComponentModel.Win32Exception:System cant find file
at System.Diagnostics.ProcessWithCreateProcess(ProcessStartInfo startInfo)
at System.Diagnostics.Process.Start()
at System.Diagnostics.Process.Start(ProcessStartInfo startInfo)
at ConnectOpenVPN.Program.Main(String[] args) in
C:\User\path\to\Program.cs:Zeile 43
I donĀ“t understand where the last line of the error message comes from.
I assume you are using a german windows or similar.
Beware that the display value of file pathes in windows explorer does not reflect the real path, see picture.
C:\Programme -> C:\Program Files
You can reveal the real path by clicking in the address bar.
try:
static void Main(string[] args)
{
Process rs = new Process();
var netCredential = new System.Net.NetworkCredential("User", "PWD", "Domain");
Environment.CurrentDirectory = ".\\";
var vpnConfigPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles),
"openvpn", "config", "NAS-Name.ovpn");
var vpnPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles),
#"openvpn","bin","openvpn.exe");
ProcessStartInfo info = new ProcessStartInfo
{
FileName = vpnPath,
Arguments = $"--config \"{vpnConfigPath}\"",
UserName = netCredential.UserName,
Domain = netCredential.Domain,
Password = netCredential.SecurePassword,
UseShellExecute = false,
//RedirectStandardError = true,
//RedirectStandardOutput = true,
//CreateNoWindow = true,
WorkingDirectory = Path.GetDirectoryName(vpnPath)
};
var p = Process.Start(info);
}

Executing Process on a remote Machine c#

i connected over WMI on a remote Machine.
username and password is correctly set.
var options = new ConnectionOptions();
servicePath = "\\\\Testserver\\root\\cimv2";
options.EnablePrivileges = true;
options.Username = username;
options.Password = pwd;
serviceScope = new ManagementScope(servicePath, options);
serviceScope.Connect();
this is the code sequence i want to run on the remote machine
Process process = new Process();
process.StartInfo.FileName = "diskpart.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
process.StandardInput.WriteLine("list volume");
process.StandardInput.WriteLine("exit");
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
// extract information from output
string table = output.Split(new string[] { "DISKPART>" }, StringSplitOptions.None)[1];
var rows = table.Split(new string[] { "\n" }, StringSplitOptions.None);
for (int i = 3; i < rows.Length; i++)
{
if (rows[i].Contains("Volume"))
{
int index = Int32.Parse(rows[i].Split(new string[] { " " }, StringSplitOptions.None)[3]);
string label = rows[i].Split(new string[] { " " }, StringSplitOptions.None)[8];
Console.WriteLine($#"Volume {index} {label}:\");
}
}
if i am going to call the process over wmi like this...
object[] theProcessToRun = { "diskpart" };
using (var managementClass = new ManagementClass(serviceScope, new ManagementPath("Win32_Process"), new ObjectGetOptions()))
{
managementClass.InvokeMethod("Create", theProcessToRun);
}
i can call the process, but havent the possibilites to hand over the commands i would like to execute in this process...
How to solve this ?
You can use a script to be passed in as part of the command line arguments that will contain your command.
Reference: https://www.computerhope.com/diskpart.htm
Also you should redirect your output to a file using cmd as you should get your output directly either.
For script, make sure you use a unc that other machine/user has access to. For output file, make sure you use a unc that other machine/user can write to and you can read from via the program.

Application.exe to open as runas administrator

Hey i am trying to launch my Application.exe as a runas administrator but still not able to launch i have tried both verb="runas" as well as created app.manifest file but my exe not opening in administrator mode.
I am using this code :
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = GetASDeploymentExe(),
Arguments = GetASDeploymentCmdArgs(),
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
Domain = "***",
UserName = username,
Password = secstr,
Verb = "runas"
}
};
proc.Start();
config.ASDeploymentToolPID = proc.Id;
string line = string.Empty;
do
{
line = proc.StandardOutput.ReadLine();
Console.WriteLine(line);
} while (!proc.HasExited);
string error = string.Empty;
while (!proc.StandardError.EndOfStream)
{
error = proc.StandardError.ReadLine();
Logger.WriteError(error);
}
}
Try this:
//Vista or higher check
if (System.Environment.OSVersion.Version.Major >= 6)
{
p.StartInfo.Verb = "runas";
}
Alternatively, go the manifest route for your application.

Running exe with parameters doesn't work

var p = Process.Start(#"c:\PsTools\PsExec.exe", #"C:\Windows\System32\notepad.exe");
var err = p.StandardError.ReadToEnd();
var msg = p.StandardOutput.ReadToEnd();
lblStatusResponse.Text = "Err: " + err + "Msg: " + msg;
Why is my code not working?
I getting error:
System.InvalidOperationException: StandardError has not been redirected.
But when I add following:
p.StartInfo.RedirectStandardError = true;
var p = Process.Start(#"c:\PsTools\PsExec.exe", #"C:\Windows\System32\notepad.exe");)
it still gets the same error.
The main problem is that I wanna execute a exe with arguments, but I can't get it to work.
The following code generates a new p, this ignoring the settings you change in the previous instance:
var p = Process.Start(#"c:\PsTools\PsExec.exe", #"C:\Windows\System32\notepad.exe");)
So it doesn't really matter whether you initialize p like this
p.StartInfo.RedirectStandardError = true;
or not.
What you need to do
You need to create a ProcessStartInfo object, configure it and then pass it to Process.Start.
ProcessStartInfo p = new ProcessStartInfo(#"c:\PsTools\PsExec.exe", #"C:\Windows\System32\notepad.exe");
p.UseShellExecute = false;
p.RedirectStandardError = true;
p.RedirectStandardOutput = true;
Process proc = Process.Start(p);
var err = proc.StandardError.ReadToEnd();
var msg = proc.StandardOutput.ReadToEnd();
Taken from MSDN: https://msdn.microsoft.com/en-us/library/system.diagnostics.process.standardoutput(v=vs.110).aspx
The StandardOutput stream has not been defined for redirection; ensure ProcessStartInfo.RedirectStandardOutput is set to true and ProcessStartInfo.UseShellExecute is set to false.
So remember to set those flags as instructed by MS.
Process proc = new Process();
proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.Arguments = "/C " + command; //Enter your own command
proc.Start();
string output =proc.StandardOutput.ReadToEnd();
I know this is not the same code you have but this is was the only working code I have , that will run external command/process in C# , and return all of it output/errors to the application main window
public void Processing()
{
//Create and start the ffmpeg process
System.Diagnostics.ProcessStartInfo psi = new ProcessStartInfo("ffmpeg")
{ // this is fully command argument you can make it according to user input
Arguments = "-y -i '/mnt/Disk2/Video/Antina03.jpg' pp.mp4 ",
RedirectStandardOutput = true,
WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden,
UseShellExecute = false,
RedirectStandardError=true,
RedirectStandardInput=true
};
System.Diagnostics.Process ischk;
ischk = System.Diagnostics.Process.Start(psi);
ischk.WaitForExit();
////Create a streamreader to capture the output of ischk
System.IO.StreamReader ischkout = ischk.StandardOutput;
ischk.WaitForExit();
if (ischk.HasExited) // this condition very important to make asynchronous output
{
string output = ischkout.ReadToEnd();
out0 = output;
}
/// in case you got error message
System.IO.StreamReader iserror = ischk.StandardError;
ischk.WaitForExit();
if (ischk.HasExited)
{
string output = iserror.ReadToEnd();
out0 = output;
}
}
if you want to run this process just call the function Processing() BTW out0 are global variable so it can use out the function .
credit
I'm using MonoDevlop "C# devloping tool on Linux " and I get the output this way :-
public MainWindow() : base(Gtk.WindowType.Toplevel)
{
Build();
Processing();
textview2.Buffer.Text = out0;
}

Running / spawning commands vs files in c#

I can in C# do the following:
var pSpawn = new Process
{
StartInfo = { WorkingDirectory = #"C:\temp", FileName = fileToRun, CreateNoWindow = true }
};
pSpawn.Start();
and this works fine.... however I am wondering if there is a way to run a command (ie: "dir /b") without having to encapsulate it in a batch file?
Just start the cmd.exe and pass the arguments required
var pSpawn = new Process
{
StartInfo =
{
WorkingDirectory = #"C:\temp",
FileName = "cmd.exe",
Arguments ="/K dir /b" }
};
pSpawn.Start();
I have added the parameter /K to leave the command window open so, it is possible to see the output of the command dir.
Of course I think that you are really interested to catch the output of the command.
In this case you could work with something like this:
StringBuilder sb = new StringBuilder();
var pSpawn = new Process
{
StartInfo =
{
WorkingDirectory = #"C:\temp",
FileName = "cmd.exe",
Arguments ="/c dir /b",
CreateNoWindow = true,
RedirectStandardOutput = true,
RedirectStandardInput = true,
UseShellExecute = false
}
};
pSpawn.OutputDataReceived += (sender, args) => sb.AppendLine(args.Data);
pSpawn.Start();
pSpawn.BeginOutputReadLine();
pSpawn.WaitForExit();
Console.WriteLine(sb.ToString());
You can call something like this:
ProcessStartInfo info = new ProcessStartInfo("cmd.exe");
info.Arguments = "/c dir /b";
Process.Start(info);

Categories