Remote shutdown command not working for Windows Embedded computer. It is working fine for normal windows computers. Is there something special that we need to do for windows embedded?
I am trying to send following command from my C# program. Also tried over commandline.
shutdown /s /f /m \\192.168.100.2 /t 5 /d u:0:0 /c "The Computer is shutting down"
Code looks like following
Process proc = new Process();
proc.EnableRaisingEvents = false;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.FileName = "shutdown.exe";
proc.StartInfo.UserName = adminName;
proc.StartInfo.Password = adminPassword;
proc.StartInfo.Domain = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName;
proc.StartInfo.Arguments = string.Format(#" /s /f /m \\{0} /t 5 /d u:0:0 /c ""The computer is shutting down"" ", ipAddress);
try
{
proc.Start();
}
catch( Exception ex )
{
// log
}
Command line tools didn't work and I ended up writing following code to shutdown computer remotely. However the code will work also for the local computer.
public void ShutdownRemotePC(string ipAddress, string adminName, string adminPassword)
{
try
{
var query = new SelectQuery("Win32_OperatingSystem");
// create always a new management scope
// create a default one and get immediate info if connection is be possible
ConnectionOptions connectionOptions = new ConnectionOptions
{
Impersonation = ImpersonationLevel.Impersonate,
EnablePrivileges = true,
//changed to packet privacy as some service requires it
Authentication = AuthenticationLevel.PacketPrivacy,
Username = ipAddress + #"\" + adminName,
Password = adminPassword,
Timeout = TimeSpan.FromMilliseconds(5000)
};
string name = #"\\" + ipAddress + #"\root\cimv2";
ManagementScope managementScope = new ManagementScope(name, connectionOptions);
// if already connected is checked inside connect
managementScope.Connect();
if( !managementScope.IsConnected )
{
//Shutdown Failed. Managment Scope could not be connected.
return;
}
using( var searcher = new ManagementObjectSearcher(managementScope, query) )
{
// impersonate the searcher if not allready done
searcher.Scope.Options.Impersonation = System.Management.ImpersonationLevel.Impersonate;
searcher.Scope.Options.EnablePrivileges = true;
using( ManagementObjectCollection found = searcher.Get() )
{
foreach( ManagementObject os in found )
{
// Obtain in-parameters for the method
using( ManagementBaseObject inParams = os.GetMethodParameters("Win32Shutdown") )
{
// Add the input parameters.
inParams["Flags"] = 12;
// Execute the method and obtain the return values.
using( ManagementBaseObject outParams = os.InvokeMethod("Win32Shutdown", inParams, null) )
{
if( outParams != null )
{
var result = Convert.ToInt32(outParams["returnValue"]);
if( result == 0 )
{
Logger.LogError("Shutdown successfully.");
}
}
}
}
}
}
}
}
catch( Exception ex )
{
// Shutdown PC=failed.
}
}
Related
I found this code on an old thread to shutdown the local machine:
using System.Management;
void Shutdown()
{
ManagementBaseObject mboShutdown = null;
ManagementClass mcWin32 = new ManagementClass("Win32_OperatingSystem");
mcWin32.Get();
// You can't shutdown without security privileges
mcWin32.Scope.Options.EnablePrivileges = true;
ManagementBaseObject mboShutdownParams =
mcWin32.GetMethodParameters("Win32Shutdown");
// Flag 1 means we want to shut down the system. Use "2" to reboot.
mboShutdownParams["Flags"] = "1";
mboShutdownParams["Reserved"] = "0";
foreach (ManagementObject manObj in mcWin32.GetInstances())
{
mboShutdown = manObj.InvokeMethod("Win32Shutdown",
mboShutdownParams, null);
}
}
Is it possible to use a similar WMI method to reboot flag "2" a remote machine, for which i only have machine name, not IPaddress.
EDIT: I currently have:
SearchResultCollection allMachinesCollected = machineSearch.FindAll();
Methods myMethods = new Methods();
string pcName;
ArrayList allComputers = new ArrayList();
foreach (SearchResult oneMachine in allMachinesCollected)
{
//pcName = oneMachine.Properties.PropertyNames.ToString();
pcName = oneMachine.Properties["name"][0].ToString();
allComputers.Add(pcName);
MessageBox.Show(pcName + "has been sent the restart command.");
Process.Start("shutdown.exe", "-r -f -t 0 -m \\" + pcName);
}
but this doesn't work, and I would prefer WMI going forward.
To address WMI queries to a remote computer, you simply specify that computer's name (or IP address) in the ManagementScope object.
I'm not well up in C#, but here's an example I came up with using MSDN and WMI Code Creator (which is, by the way, an excellent tool for generating WMI code, and supports C# among others). Hope this code will give you the idea.
(Disclaimer: This code is untested.)
using System;
using System.Management;
...
void Shutdown()
{
try
{
const string computerName = "COMPUTER"; // computer name or IP address
ConnectionOptions options = new ConnectionOptions();
options.EnablePrivileges = true;
// To connect to the remote computer using a different account, specify these values:
// options.Username = "USERNAME";
// options.Password = "PASSWORD";
// options.Authority = "ntlmdomain:DOMAIN";
ManagementScope scope = new ManagementScope(
"\\\\" + computerName + "\\root\\CIMV2", options);
scope.Connect();
SelectQuery query = new SelectQuery("Win32_OperatingSystem");
ManagementObjectSearcher searcher =
new ManagementObjectSearcher(scope, query);
foreach (ManagementObject os in searcher.Get())
{
// Obtain in-parameters for the method
ManagementBaseObject inParams =
os.GetMethodParameters("Win32Shutdown");
// Add the input parameters.
inParams["Flags"] = 2;
// Execute the method and obtain the return values.
ManagementBaseObject outParams =
os.InvokeMethod("Win32Shutdown", inParams, null);
}
}
catch(ManagementException err)
{
MessageBox.Show("An error occurred while trying to execute the WMI method: " + err.Message);
}
catch(System.UnauthorizedAccessException unauthorizedErr)
{
MessageBox.Show("Connection error (user name or password might be incorrect): " + unauthorizedErr.Message);
}
}
I had trouble with this also. WMI can be misleading with methods for classes and object. My solution is for rebooting a host on the network with C# and WMI, but is easily simplified for local machine:
private void rebootHost(string hostName)
{
string adsiPath = string.Format(#"\\{0}\root\cimv2", hostName);
ManagementScope scope = new ManagementScope(adsiPath);
// I've seen this, but I found not necessary:
// scope.Options.EnablePrivileges = true;
ManagementPath osPath = new ManagementPath("Win32_OperatingSystem");
ManagementClass os = new ManagementClass(scope, osPath, null);
ManagementObjectCollection instances;
try
{
instances = os.GetInstances();
}
catch (UnauthorizedAccessException exception)
{
throw new MyException("Not permitted to reboot the host: " + hostName, exception);
}
catch (COMException exception)
{
if (exception.ErrorCode == -2147023174)
{
throw new MyException("Could not reach the target host: " + hostName, exception);
}
throw; // Unhandled
}
foreach (ManagementObject instance in instances)
{
object result = instance.InvokeMethod("Reboot", new object[] { });
uint returnValue = (uint)result;
if (returnValue != 0)
{
throw new MyException("Failed to reboot host: " + hostName);
}
}
}
You can use shutdown command if you need an non-WMI solution.
shutdown [{-l|-s|-r|-a}] [-f] [-m [\\ComputerName]] [-t xx] [-c "message"] [-d[u][p]:xx:yy]
Use the -m for shutting the remote machine.
Refer this link for more info.
http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/shutdown.mspx
this will work like sharm
gwmi win32_operatingsystem -ComputerName xxxxxxxxxxxx | Invoke-WmiMethod -Name reboot
My code uses a C# Diagnostic Process to run a GDAL process.
This process ends with an exit code 1.
But running from a command prompt works.
Where's my mistake?
Already tested (see code below):
files to transform exists,
directory to write to exists and "My programme" has access rights,
the GDAL library exists.
This is my code:
private string AddSrs(string tempFile, string User)
{
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
string geoserverDatadir = ConfigurationManager.AppSettings["geoserverDatadir"];
string dirOut = Path.Combine(geoserverDatadir, User, Guid.NewGuid().ToString());
string fileOut = Path.Combine(dirOut, (Path.GetFileNameWithoutExtension(tempFile) + ".geoTiff"));
Directory.CreateDirectory(dirOut);
if (File.Exists(fileOut))
{
File.Delete(fileOut);
}
string binDirectory = ConfigurationManager.AppSettings["binDirectory"];
startInfo.FileName = Path.Combine(binDirectory, "gdal_translate.exe");
string args = String.Format(#"-a_srs EPSG:28992 {0}{1}{0} {0}{2}{0}", "\"", tempFile, fileOut);
startInfo.Arguments = args;
process.StartInfo = startInfo;
if(!File.Exists(startInfo.FileName))
{
_log.Error("file not exists: " + startInfo.FileName));
}
if (!File.Exists(tempFile))
{
_log.Error("file not exists: " + tempFile));
}
if (!Directory.Exists(dirOut))
{
_log.Error("directory not exists: " + dirOut));
}
try
{
// Attempt to get a list of security permissions from the folder.
// This will raise an exception if the path is read only or do not have access to view the permissions.
System.Security.AccessControl.DirectorySecurity ds = Directory.GetAccessControl(dirOut);
}
catch (UnauthorizedAccessException ex)
{
_log.Error("no access rights for directory: " + dirOut));
}
try
{
process.Start();
int processTimeOut = 1000;
if (!process.WaitForExit(processTimeOut))
{
process.Kill();
_log.Error("Process killed by timeOut: " + processTimeOut));
return string.Empty;
}
else
{
var exitCode = process.ExitCode;
_log.Error("Process ended. Exitcode: " + exitCode));
return fileOut;
}
}
catch (Exception ex)
{
_log.Error(ex.Message));
_log.Error(ex.StackTrace));
return string.Empty;
}
}
EDIT:
This is the full command as logged in my logfile:
D:\OSGeo4W64\bin\gdal_translate.exe -a_srs EPSG:28992 "D:\data\Temp\Merkator\Hengelo Veldwijk Zuid Revisie.temp" "D:\data\Geoserver\data\Merkator\aa84dc6d-aff2-4254-975a-3ede8eea5c6d\Hengelo Veldwijk Zuid Revisie.geoTiff"
And this is the same command pasted in commandline (works with and without admin rights):
C:\Users\Administrator>D:\OSGeo4W64\bin\gdal_translate.exe -a_srs EPSG:28992 "D:\data\Temp\Merkator\Hengelo Veldwijk Zuid Revisie.temp" "D:\data\Geoserver\data\Merkator\aa84dc6d-aff2-4254-975a-3ede8eea5c6d\Hengelo Veldwijk Zuid Revisie.geoTiff"
Input file size is 1273, 378
0...10...20...30...40...50...60...70...80...90...100 - done.
INFO:
The problem exists on a (virtual) server. On my computer (debug-mode) this code works fine.
I need to run a command into CMD window and want to get result into a variable.
I used below code to do the same but the out put is incorrect
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = " wmic.exe /node:(computername or ip address) computersystem get username ",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
proc.Start();
string line = "";
while (!proc.StandardOutput.EndOfStream)
{
line += (line.Length > 0 ? "-----" : "") + proc.StandardOutput.ReadLine();
}
proc.WaitForExit();
Out put
Microsoft Windows [Version 6.1.7601]-----Copyright (c) 2009 Microsoft Corporation. All rights reserved.----------C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\10.0>
But when i run this command into CMD window it shows the current logged in users name.
Can any one help me to solve the issue.
Note :- The given command is used to get the current logged in users
name on network system by using it's IP Address.
What you need is the /c option for cmd
C:\>cmd /?
Starts a new instance of the Windows command interpreter
CMD [/A | /U] [/Q] [/D] [/E:ON | /E:OFF] [/F:ON | /F:OFF] [/V:ON | /V:OFF]
[[/S] [/C | /K] string]
/C Carries out the command specified by string and then terminates
I would question the need for cmd.exe here. You can just invoke wmic directly as below
var proc = new Process {
StartInfo = new ProcessStartInfo {
FileName = "wmic.exe",
Arguments = "/node:localhost computersystem get username ",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
proc.Start();
string line = "";
while (!proc.StandardOutput.EndOfStream) {
line += (line.Length > 0 ? "-----" : "") + proc.StandardOutput.ReadLine();
}
proc.WaitForExit();
Why would you go to the trouble of invoking a commandline tool and parsing its results if System.Management has all the classes you need to obtain the information in-process and managed?
var ip = "127.0.0.1";
var scope = new ManagementScope(
String.Format("\\\\{0}\\root\\cimv2", ip),
new ConnectionOptions { Impersonation = ImpersonationLevel.Impersonate });
scope.Connect();
var users = new ManagementObjectSearcher(
scope,
new ObjectQuery("Select * from Win32_LoggedonUser"))
.Get()
.GetEnumerator();
while(users.MoveNext())
{
var user = users.Current["antecedent"];
var mo = new ManagementObject(new ManagementPath(user.ToString()));
try
{
var username = mo.Properties["name"];
Console.WriteLine("username {0}", username.Value);
}
catch
{
Console.WriteLine(mo);
}
}
All you have to do is create a ManagementScope and then use the ManagementObjectSearcher to run any WMI Query Language statement by using one of the available WMI Classes.
If you have a working wmic call you can always add /TRACE:ON so you can inspect the calls being made. Use wmic /? to see the aliasses.
I have this code that execute shell commands:
public void ExecuteShellCommand(string _FileToExecute, string _CommandLine, ref string _outputMessage, ref string _errorMessage)
{
//Set process variable.
//Provides access to local and remote processes and enables you to start and stop local system processes.
System.Diagnostics.Process _Process = null;
try
{
_Process = new System.Diagnostics.Process();
_Process.StartInfo.Verb = "runas";
//Invokes the cmd process specifying the command to be executed.
var culture = new System.Globalization.CultureInfo("pt-BR", true);
Thread.CurrentThread.CurrentUICulture = new CultureInfo("pt-BR", false);
string _CMDProcess = string.Format(culture, #"{0}\cmd.exe",
new object[] { Environment.SystemDirectory });
//Pass executing file to cmd (Windows command interpreter) as a arguments
// /C tells cmd we want it to execute the comand that follows, then exit.
string _Arguments = string.Format(culture, "/C {0}",
new object[] { _FileToExecute });
//Pass any command line parameters for execution
if (!string.IsNullOrEmpty(_CommandLine))
{
_Arguments += string.Format(culture, " {0}",
new object[] { _CommandLine, culture });
}
var _ProcessStartInfo =
new System.Diagnostics.ProcessStartInfo(_CMDProcess, _Arguments);
//Sets a value indicating not to start the process in a new window.
_ProcessStartInfo.CreateNoWindow = true;
//Sets a value indicating now to use the operating system shell to start the process.
_ProcessStartInfo.UseShellExecute = false;
//Sets the value that indicates the output/input/error of an aplication is written to the Process.
_ProcessStartInfo.RedirectStandardOutput = true;
_ProcessStartInfo.RedirectStandardInput = true;
_ProcessStartInfo.RedirectStandardError = true;
_Process.StartInfo = _ProcessStartInfo;
//Starts a process resource and associates it with a Process component.
_Process.Start();
//Instructs the Process component t wait indefitely for the associated process to exit.
_errorMessage = _Process.StandardError.ReadToEnd();
_Process.WaitForExit();
//Instructs the Process component to wait indefinitely for the associated process to exit.
_outputMessage = _Process.StandardOutput.ReadToEnd();
_Process.WaitForExit();
}
catch (Win32Exception _Win32Exception)
{
//Error
MessageBox.Show("Win32 Exception caught in process: " + _Win32Exception.ToString());
}
catch (Exception _Exception)
{
//Error
MessageBox.Show("Exception caught in process: " + _Exception.ToString());
}
finally
{
_Process.Close();
_Process.Dispose();
_Process = null;
}
}
The problem is that my system language is pt-BR, the output:
_outputMessage = _Process.StandardOutput.ReadToEnd();
returns broken strings:
Returned string: "Autentica‡Æo"
Expected string: "Autenticação"
But if I use the same command inside CMD, everything returns okay, no erros or broken strings...
What is wrong with my code?
EDIT:
I'm trying execute shell commands via code. Using cmd.exe + arguments.
Working:
_ProcessStartInfo.StandardOutputEncoding = Encoding.GetEncoding(850);
Now, the encoding matches.
It is code page 850, the MS-Dos code page for Portuguese. ç = 0x87, ã = 0xc6.
Your program is currently incorrectly using code page 1252, 0x87 = ‡, 0xc6 = Æ.
I am writing a module which will be executing any kind of shell commands related to Active Directory and other shell commands on a particular domain controller.
Some of command are working but some of commands are not working properly.
Here is the code
public static void ExecuteShellCommand(string _FileToExecute, string _CommandLine, ref string _outputMessage, ref string _errorMessage)
{
System.Diagnostics.Process _Process = null;
try
{
_Process = new System.Diagnostics.Process();
string _CMDProcess = string.Format(System.Globalization.CultureInfo.InvariantCulture, #"{0}\cmd.exe", new object[] { Environment.SystemDirectory });
string _Arguments = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}", new object[] { _FileToExecute });
_Arguments = string.Format(" /C \"{0}\"", _Arguments);
Console.WriteLine("---aruguments quering : cmd.exe" + _Arguments);
System.Diagnostics.ProcessStartInfo _ProcessStartInfo = new System.Diagnostics.ProcessStartInfo(_CMDProcess, _Arguments);
_ProcessStartInfo.CreateNoWindow = true;
_ProcessStartInfo.UseShellExecute = false;
_ProcessStartInfo.RedirectStandardOutput = true;
_ProcessStartInfo.RedirectStandardInput = true;
_ProcessStartInfo.RedirectStandardError = true;
_Process.StartInfo = _ProcessStartInfo;
//_ProcessStartInfo.Domain = System.DirectoryServices.ActiveDirectory.Domain.GetCurrentDomain().Name;
_Process.Start();
_errorMessage = _Process.StandardError.ReadToEnd();
_Process.WaitForExit();
_outputMessage = _Process.StandardOutput.ReadToEnd();
_Process.WaitForExit();
}
catch (Exception _Exception)
{
Console.WriteLine("Exception caught in process: {0}", _Exception.ToString());
}
finally
{
_Process.Close();
_Process.Dispose();
_Process = null;
}
}
CommandExecutionEngine.ExecuteShellCommand("nltest", "/logon_query /server:india.cobra.net", ref output, ref error);
Console.WriteLine("output for dir : " + output + " error : " + error);
Commands:
repadmin /showrepl
dcdiag
dcdiag /s:<dcname
command nltest executing but not returning any result. Where the other mentioned commands giving error is not recognized as internal or external command. Where if I execute command directly from console its working fine.
Here I am invoking a process under the context of domain administrator account so that I will not be have any permission issues.
Please suggest.
Possibly since UseShellExecute = false, the application location is not being found. Use the full path.