Run Active Directory shell commands using C# - c#

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.

Related

Process.Start cannot run batch file properly

I am trying to run a batch file using C#
The batch file for the test purposes contains
msg * Test
It works if I run it manually.
Then I use the following code to run this .bat file
filePath = full path to batch file
var startInfo = new ProcessStartInfo
{
Arguments = "/C \"" + filePath + "\"",
FileName = "cmd.exe",
UseShellExecute = true
};
Process p = Process.Start(startInfo);
and it does not work ->
cannot find msg
What I am doing wrong?
P.S. the batch file should not be changed.
Try this way:
batchfile:
set "msg=%SystemRoot%\System32\msg.exe"
if not exist "%msg%" set "msg=%SystemRoot%\Sysnative\msg.exe"
"%msg%" * Hello
code:
string sFile = <full path to batch file>;
Process.Start("cmd.exe", "/c " + sFile);
Probably need some authorization, you may try the following code:
static void ExecuteCommand(string command)
{
int exitCode;
ProcessStartInfo processInfo;
Process process;
processInfo = new ProcessStartInfo("cmd.exe", "/c " + command);
processInfo.CreateNoWindow = true;
processInfo.Domain = "domain"; // Your own domain
processInfo.UserName = "userName"; // Your own user name
System.Security.SecureString s = new System.Security.SecureString();
s.AppendChar('p'); // Your own password
s.AppendChar('a');
s.AppendChar('s');
s.AppendChar('s');
s.AppendChar('w');
s.AppendChar('o');
s.AppendChar('r');
s.AppendChar('d');
processInfo.Password = s;
processInfo.UseShellExecute = false;
// *** Redirect the output ***
processInfo.RedirectStandardError = true;
processInfo.RedirectStandardOutput = true;
process = Process.Start(processInfo);
process.WaitForExit();
// *** Read the streams ***
// Warning: This approach can lead to deadlocks, see Edit #2
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
exitCode = process.ExitCode;
Console.WriteLine("output>>" + (String.IsNullOrEmpty(output) ? "(none)" :
output));
Console.WriteLine("error>>" + (String.IsNullOrEmpty(error) ? "(none)" :
error));
Console.WriteLine("ExitCode: " + exitCode.ToString(), "ExecuteCommand");
process.Close();
}
static void Main()
{
ExecuteCommand(#"C:\displayMsg.bat");
}
You may check your domain in Control Panel >> User Account >> Manage User Accounts
Source of reference: source
The problem is the location of the file (msg.exe) in the different OS versions (32bit/64bit)
I suppose it helps How can I execute msg.exe by C# in windows?
Edited:
It works fine -
class Program
{
static void Main(string[] args)
{
int ExitCode;
try
{
var returnedMsgPath = string.Empty;
if (LocateMsgExe(out returnedMsgPath))
{
var startInfo = new ProcessStartInfo()
{
FileName = returnedMsgPath,
Arguments = #"* /v Hello",
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardError = true,
RedirectStandardOutput = true
};
var p = Process.Start(startInfo);
p.WaitForExit();
// *** Read the streams ***
string output = p.StandardOutput.ReadToEnd();
string error = p.StandardError.ReadToEnd();
ExitCode = p.ExitCode;
MessageBox.Show("output >>" + (String.IsNullOrEmpty(output) ? "(none)" : output));
MessageBox.Show("error>>" + (String.IsNullOrEmpty(error) ? "(none)" : error));
MessageBox.Show("ExitCode: " + ExitCode.ToString(), "ExecuteCommand");
p.Close();
}
else
{
MessageBox.Show("Not found");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
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;
}
}

Can't export HKLM registry key in C#/.NET

I need to export a registry key from the HKLM hive to a file. This is a key which I've successfully created just a few lines back in the same program. I am using a Process object to have my C# program execute the shell command:
cmd.exe /c regedit.exe /e C:\temp\CDPRegExport.txt HKEY_LOCAL_MACHINE\SOFTWARE\NPTMigration
If I execute my program, the file C:\temp\CDPRegExport.txt is not created. However, if I run the command above directly (in this same administrative console window) it works fine!
I tried adding an application manifest to ensure that my .NET program is running as an administrator.
I tried invoking reg.exe export instead of regedit.exe /e but the result is the same (I'm guessing the same DLL is ultimately being used by these 2 programs).
Here's the main Registry Export method:
static bool RegistryExport(string regKey, string destFile)
{
Cmd cmd = new Cmd()
{
CreateNoWindow = true
};
cmd.Exec(#"regedit.exe", #"/e", destFile, regKey);
Console.WriteLine("Standard Out:\r\n" + cmd.StandardOut);
Console.WriteLine("Standard Error:\r\n" + cmd.StandardErr);
if (!File.Exists(destFile))
{
AppContext.log.Critical(#"Registry export file ({0}) not found!", destFile);
return false;
}
return true;
}
...And here's Cmd.Exe():
public void Exec(string command, params string[] Parameters)
{
string fullyQualifiedCommand = #"/c " + command + GetParameters(Parameters);
Console.WriteLine(fullyQualifiedCommand);
try
{
psi = new ProcessStartInfo(#"cmd", fullyQualifiedCommand)
{
RedirectStandardOutput = true,
RedirectStandardError = true,
};
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
using (Process process = new Process())
{
process.StartInfo = psi;
process.Start();
if (RedirectIOStreams)
{
StandardOut = process.StandardOutput.ReadToEnd();
StandardErr = process.StandardError.ReadToEnd();
}
process.WaitForExit();
}
NormalExit = true;
}
catch (Exception ex)
{
StandardOut = string.Empty;
StandardErr = ex.ToString();
}
}
private static string GetParameters(string[] Parameters)
{
string expression = string.Empty;
if (Parameters.Length == 0)
return string.Empty;
for (int index=0; index<Parameters.Length; index++)
{
if (Parameters[index].Contains(" "))
expression += " \"" + Parameters[index] + "\"";
else
expression += " " + Parameters[index];
}
return expression;
}
When the program uses regedit.exe both standard out and standard error are simply blank.
When it uses reg.exe export however, standard error shows:
"ERROR: The system was unable to find the specified registry key or value."
Again, this is odd because if I invoke the exact same reg.exe or regedit.exe syntax directly via the command window, it works fine!
If 32-bit process on 64-bit OS, you must disable the WOW64 file system redirection
This test works for me (Windows 10, VS 2015 ) =>
bool bWow64 = false;
IsWow64Process(Process.GetCurrentProcess().Handle, out bWow64);
if (bWow64)
{
IntPtr OldValue = IntPtr.Zero;
bool bRet = Wow64DisableWow64FsRedirection(out OldValue);
}
string sKey = #"HKEY_LOCAL_MACHINE\SOFTWARE\NPTMigration";
string sFile = #"C:\temp\CDPRegExport.txt";
using (Process process = new Process())
{
ProcessStartInfo psi = new ProcessStartInfo();
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.FileName = "reg";
psi.Arguments = "export " + "" + sKey + "" + " " + "" + sFile + "";
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
process.StartInfo = psi;
process.Start();
using (StreamReader reader = process.StandardOutput)
{
string sResult = reader.ReadToEnd();
Console.Write(sResult);
}
}
with declarations :
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool IsWow64Process(IntPtr hProcess, out bool Wow64Process);
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool Wow64DisableWow64FsRedirection(out IntPtr OldValue);

Diagnostic Process ends with exit code 1 but same action on command prompt works

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.

How I can execute a exe file with parameter in C# with my User ?

net application that use the process class for execute a exe with parameter. My Problem is that it works a few day good but now I dont can execute this exe with the parameter -.-
If I try it manuell with a terminal than it works but if I do it with C# Code than I get a message that I dont can create the file.
*** ERROR *** Cannot create qrun.inf file
Here is my c# code:
string cmd = Server.MapPath(#"~/exe/lstc_qrun.exe -s server01 -R");
string output = ExecuteCommand(cmd);
//Output = "*** ERROR *** Cannot create qrun.inf file"
here is the ExecuteCommand Method:
public static string ExecuteCommand(string command)
{
int exitCode;
ProcessStartInfo processInfo;
Process process;
try
{
processInfo = new ProcessStartInfo("cmd.exe", "/c " + command);
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
processInfo.RedirectStandardError = true;
processInfo.RedirectStandardOutput = true;
using (process = Process.Start(processInfo))
{
string output = process.StandardOutput.ReadToEnd();
exitCode = process.ExitCode;
return output;
}
}
catch (Exception ex)
{
return "error: " + ex.Message;
}
}
What can I do ..I work on my local machine :(
Check this reference of Process.Start() :
public static Process Start(
string fileName,
string arguments,
string userName,
SecureString password,
string domain
)
or you can just fill the ProcessStartInfo members :
processInfo.Username = 'Username' ;
processInfo.Password = 'Password' ;
processInfo.Domain = 'MyDomain' ;

System.Diagnostics.Process.StandardOutput returning bad string that have accentuation

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 = Æ.

Categories

Resources