I have this code:
Process myProcess = new Process();
myProcess.StartInfo.UseShellExecute = true;
myProcess.StartInfo.FileName = "rdpclip.exe";
myProcess.Start();
to start an exe file which is located in system32
I always get an error that, the system file cannot be found. In windows 2008 server.
Even if I set the StartupInfo.FileName="c:\\windows\\system32\\rdpclip.exe" it still does not find the file !?
It works if I place the file in other folder, but in System32 it does not start. I just need to kill this process and start again, but I never thought that in C# is such a pain to do such a simple thing ?!
This error is misleading because it usually means you to do not have permission to that folder. Try building your program, then right click the resulting .exe and click 'run as administrator'.
Try this (you'll need to import System.Runtime.InteropServices):
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);
IntPtr ptr = IntPtr.Zero;
if(Wow64DisableWow64FsRedirection(ref ptr))
{
Process myProcess = new Process();
myProcess.StartInfo.UseShellExecute = true;
myProcess.StartInfo.FileName = "rdpclip.exe";
myProcess.Start();
Process.Start(myProcess);
Wow64RevertWow64FsRedirection(ptr);
}
Related
I'm trying to start .lnk shortcuts from my application. However, I'm struggling with the infamous automatic filesystem redirection for 32/64-bit processes.
I'm searching for a way to simply start an application from the shortcut and I don't care, what happens to that process later. Effectively I'd like to start the shortcut the same way as if user doubleclicked it in the Explorer.
Currently I'm using the following method, but it still doesn't work (ie. I'm unable to start Word this way):
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);
private static void Start(string shortcut)
{
IntPtr temp = IntPtr.Zero;
try
{
Wow64DisableWow64FsRedirection(ref temp);
var error = Marshal.GetLastWin32Error();
ProcessStartInfo info = new ProcessStartInfo(shortcut);
info.UseShellExecute = true;
Process.Start(info);
}
finally
{
Wow64RevertWow64FsRedirection(temp);
}
}
How can I reliably start an application, knowing its direct location on the drive in C#?
Edit:
I used SysInternals' ProcMon to check, what is done behind scenes. It looks like the proper path is searched, but then system for some reason still falls back to the forced 32-bit one.
I am not able to launch narrator program from Visual Studio using C#. I have tried using complete path and other similar hacks but no outcome ?
The code is :
System.Diagnostics.Process.Start(#"C:\windows\system32\narrator.exe");
Similar code is able to execute notepad.exe present in the same folder. Can anyone help me in this regard ?
The execption which i got was ::
"An unhandled exception of type 'System.ComponentModel.Win32Exception' occurred in System.dll
Additional information: The system cannot find the file specified "
however the file exists in the specified path.
Then i copied the entire system32 folder to my desktop and gave the new location .then the code passes through without any exception but no narrator application is launched .
You can disable the filesystem redirection using some system calls. Note that even with the redirection fixed, you still cannot launch Narrator without elevated privileges.
const int ERROR_CANCELLED = 1223; //The operation was canceled by the user.
var oldValue = IntPtr.Zero;
Process p = null;
try
{
if (SafeNativeMethods.Wow64DisableWow64FsRedirection(ref oldValue))
{
var pinfo = new ProcessStartInfo(#"C:\Windows\System32\Narrator.exe")
{
CreateNoWindow = true,
UseShellExecute = true,
Verb = "runas"
};
p = Process.Start(pinfo);
}
// Do stuff.
p.Close();
}
catch (Win32Exception ex)
{
// User canceled the UAC dialog.
if (ex.NativeErrorCode != ERROR_CANCELLED)
throw;
}
finally
{
SafeNativeMethods.Wow64RevertWow64FsRedirection(oldValue);
}
[System.Security.SuppressUnmanagedCodeSecurity]
internal static class SafeNativeMethods
{
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);
}
I'm using a small C# executable to launch a java jar. I want to recover the exit code returned by the jar so i can restart the jar if i need to.
However the c# application keeps showing a black console window and i can't get rid of it, does anyone know how to fix this?
I'm using t he following C# code to start the process
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = "jre/bin/java.exe";
p.StartInfo.Arguments = "-Djava.library.path=bin -jar readermanager.jar";
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
p.waitForExit();
return p.ExitCode;
The console window only keeps visible when using the waitForExit(); method. Without it (and withoud p.ExitCode) the console windows closes. I also tried setting the StartInfo.WindowStyle to Hidden and Minimized but both don't have any effect on the window.
Just change the output type of your C# program to be a "Windows Application" instead of a "Console Application". A C# Windows application doesn't really care if you actually display any windows.
From How to run a C# console application with the console hidden
System.Diagnostics.ProcessStartInfo start =
new System.Diagnostics.ProcessStartInfo();
start.FileName = dir + #"\Myprocesstostart.exe";
start.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
But if that does not work, how about this: http://social.msdn.microsoft.com/Forums/eu/csharpgeneral/thread/ea8b0fd5-a660-46f9-9dcb-d525cc22dcbd
using System.Runtime.InteropServices;
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName,string lpWindowName);
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
IntPtr hWnd = FindWindow(null, "Window caption here");
if(hWnd != IntPtr.Zero)
{
//Hide the window
ShowWindow(hWnd, 0); // 0 = SW_HIDE
}
if(hWnd != IntPtr.Zero)
{
//Show window again
ShowWindow(hWnd, 1); //1 = SW_SHOWNORMA
}
I have written a service which starts a java.exe or ruby.exe (I know there are some solutions but I need my own service for some reasons).
The service works find so far, I gather my configs from the registry, then start the services. When the service get stopped I get my processes and send a .Kill().
So far so good.
But I found out, that the .Kill() is a problem due the fact that the ruby.exe (I use thin to start a service) or the java.exe (I start a SOLR with it) listen on a tcp socket port. If this port get in use and I kill the process windows will block the ports for 72 seconds (by design).
If I do a solr:start and a thin -start from a shell command shell and stop it using the Ctrl+C the processes terminate and the port is available to use instantly.
So my guess is: If I manage to send a ctrl-c to the process it terminate correctly.
So I found this thread How to Run an exe from windows service and stop service when the exe process quits? where a proof of concept is posted.
But by starting a process from a window service I don't have a windowHandle.
I start my service like this:
m_process.StartInfo = new ProcessStartInfo
{
FileName = "java"
, Arguments = arguments
, UseShellExecute = true
, WorkingDirectory = workDirectory
, CreateNoWindow = false
};
m_process.Start();
Where arguments contais the jetty data to start the SOLR or in the ruby case I use "ruby.exe thin start ...".
Now on stopping the service I tried:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32")]
public static extern int SetForegroundWindow(IntPtr hwnd);
[DllImport("user32.dll", SetLastError = true)]
public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
foreach (int i in m_processList)
{
MyLogEvent(Process.GetProcessById(i).MainModule.ModuleName);
MyLogEvent(Process.GetProcessById(i).MainWindowTitle);
try
{
IntPtr ptr = FindWindow(null, Process.GetProcessById(i).MainWindowTitle);
{
SetForegroundWindow(ptr);
Thread.Sleep(1000);
InputSimulator.SimulateModifiedKeyStroke(VirtualKeyCode.CONTROL, VirtualKeyCode.CANCEL);
// SendKeys.Send("^{BREAK}");
Thread.Sleep(1000);
}
//Process.GetProcessById(i).Kill();
}
catch(Exception ex)
{
MyLogEvent(ex.ToString());
Process.GetProcessById(i).Kill();
}
}
But as I don't have a WindowTitle, I guess I don't even have a window I can't allocate the process like this.
So does anyone have a idea how I can allocate process and send the stop signal to it?
I can live with just killing the process, but this just a service restart impossible without waiting a long time.
Thanks for any hints, tips and solutions.
GenerateConsoleCtrlEvent might work
m_process.StartInfo = new ProcessStartInfo
{
FileName = "java"
, Arguments = arguments
, UseShellExecute = true
, WorkingDirectory = workDirectory
, CreateNoWindow = false
};
var process = m_process.Start();
When time to kill child app...
GenerateConsoleCtrlEvent(CTRL_C_EVENT, process.Id);
member declarations
public const UInt32 CTRL_C_EVENT = 0;
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GenerateConsoleCtrlEvent(uint dwCtrlEvent,
uint dwProcessGroupId);
In my application comes with an uninstaller.
Everything is working fine, except that I can't find no way to delete the uninstaller.exe file when it's all done.
I tried to copy the current assembly exe into a temp directory, but the file-handle of the original file is still locked.
Any ideas?
You will need to PInvoke to do this. MoveFileEx has the ability to schedule deleting the file on next reboot.
If dwFlags specifies MOVEFILE_DELAY_UNTIL_REBOOT and lpNewFileName is NULL, MoveFileEx registers the lpExistingFileName file to be deleted when the system restarts.
Something like:
[return: MarshalAs (UnmanagedType.Bool)]
[DllImport ("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool MoveFileEx (string lpExistingFileName, string lpNewFileName, int dwFlags);
public static bool ScheduleDelete (string fileFullName) {
if (!File.Exists (fileFullName))
throw new InvalidOperationException ("File does not exist.");
return MoveFileEx (fileFullName, null, 0x04); //MOVEFILE_DELAY_UNTIL_REBOOT = 0x04
}
It would be interesting if you posted some code of how you exactly copy the uninstaller.exe and change execution to that specific executable.
I think unloading the application domain will free the file-handle.
You might be able to achieve what you want by using shadow copying of assemblies, but I haven't tried that for this scenario.
You can use "cmd" with delay:
internal static void ExitAndDelete()
{
var f = Application.ExecutablePath;
Process.Start(new ProcessStartInfo("CMD.exe", "/C timeout 2&del \"" + f + "\"") { WindowStyle = ProcessWindowStyle.Hidden });
}