I need to start updater application by passing URL of the patch file. Basic Process.Run works fine, however when I pass argument nothing happens. (This is Linux Mint and Mono)
I have already checked SO, net, etc. and tried solutions such as setting UseShellExecute to false or using ProcessStartInfo.
What am I doing wrong ?
Updater is located in the same folder where the main exe is.
Mono console shows no errors.
Works : (works for everyone so no surprise there)
Process.Start (Application.StartupPath + #"/Updater.exe");
Doesn't work (Nothing happens, also expected ?) :
Process.Start(Application.StartupPath + #"/Updater.exe", "URLToFile");
From other solutions I have tried :
Process.Start(new ProcessStartInfo(Application.StartupPath + #"/Updater.exe", #"URLToFile.zip") { UseShellExecute = false });
I also tried many solutions proposed here :
How to use Process.Start() or equivalent with Mono on a Mac and pass in arguments
And I checked some other blogs and google results. No solution ever worked for me sadly.
More info that might not be as important but could help :
Code works in Windows
I run Mono code separated from Windows code by checking platform
Application checks for updates then starts updater and closes itself
Updater is located in the same folder in which the main exe is
Updater is separated project
This is an portable application
What am I doing wrong? Thanks.
Try to prefix "mono " since you want in fact to run mono with your .exe as an argument. Also I determine the application path in another way:
string sAppPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
Process.Start("mono " + sAppPath + #"/Updater.exe");
Sorry, I did not test my code. Now I did a small project and tested it - just a form with a label and a button. Working fine. I'm getting the right path and the HelloWorld App gets started and processes the CmdLineArg. Here the core content comes:
private void DoIt()
{
string sAppPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo();
psi.FileName = "mono";
psi.Arguments = sAppPath + #"/HelloWorld.exe CmdLineArg";
System.Diagnostics.Process.Start(psi);
}
Related
I created a WPF Desktop Application as well as a Worker Service (all .NET 6.0 Preview 3), packed them in a .MSI Setup File using Microsoft Visual Studio Installer Projects extension, which installs the WPF Application on the machine.
While the application installs and functions correctly, I had to somehow implement the service installation which should run after the WPF Application would be installed. I created a function for that, which runs sc.exe as administrator and installs the service using Process.Start(), which looks like this:
private static void InstallService()
{
const string ServiceName = "SomeService";
var path = Path.GetFullPath(#".\SomeService.exe");
var psi = new ProcessStartInfo
{
FileName = #"C:\Windows\system32\sc.exe",
Arguments = $"create { ServiceName } binPath= { path } start= auto",
Verb = "runas",
UseShellExecute = true,
};
try
{
Process.Start(psi);
}
catch (Exception ex)
{
MessageBox.Show($"Installation has failed: { ex.Message + ex.StackTrace }");
}
}
The problem with this function is that it executes properly when the application is ran in Visual Studio and when it is ran from the 'bin\Release' folder created by Visual Studio. The service is then installed and can be started. When the program, however, is installed using the .MSI package, the service does not install and no MessageBox is displayed, which shows that no exceptions are thrown.
What I have tried:
When the function is executed, a UAC prompt is shown and then the
process starts. I tried running the entire application as
administrator, but that didn't solve the issue.
I also tried copying all the files from the 'bin\Release' directory into the one in which the application is installed and replacing every file with the one from 'bin\Release', so that both directories should be the same, but that also didn't solve the issue.
After the installation function is executed, the service should start with another function for starting it:
private static void RunService()
{
const string ServiceName = "SomeService";
var psi = new ProcessStartInfo
{
FileName = #"C:\Windows\system32\sc.exe",
Arguments = $"start { ServiceName }",
Verb = "runas",
UseShellExecute = true,
};
try
{
Process.Start(psi);
}
catch (Exception ex)
{
MessageBox.Show($"Running was not approved or failed: { ex.Message }");
}
}
This function, however, functions correctly in both cases, although obviously only when the service is previously installed, which cannot be done in the .MSI installed application. As for the use of Process.Start() instead of ServiceController class, the application should not run as administrator by default, and it is not possible with the ServiceController, so I used Process.Start() with Verb = "runas" which runs the process as administrator only showing the UAC prompt when it is needed (starts the service only when it is not already running).
Is there any way to solve this problem and install a Worker Service in a .MSI installed WPF Application?
As I further proceeded to analyze all the possible factors, I finally noticed what was causing the issue in this case.
Generally, the paths generated by Visual Studio don't have any spaces, and because of that they can be written as a command argument without double quotes. In my case, the paths which contained the Project files also didn't have any spaces, which caused the commands without double quotes to be executed normally. The installation path, however, did contain spaces, as it's designed to be more user-friendly, which caused this piece of code to not execute as intended:
// the path parameter in the command will end when there will be a space somewhere in the path
Arguments = $"create { ServiceName } binPath= { path } start= auto"
The path variable only contains the full path, which is not wrapped in double quotes.
To prevent the issue the use of double quotes is necessary, and including the \ symbol notifies the compiler that these double quotes are a part of the string:
// the path parameter is wrapped in double quotes and will be fully read
Arguments = $"create { ServiceName } binPath= \"{ path }\" start= auto"
When the path would be fully written in the code, the missing double quotes are easy to notice. When, however, using string interpolation, it may cause problems, as it did in my case.
I have the following issue:
I have a C# app that runs as a 32-bit Application on my 64-Bit Machine. This application opens a process and starts wbadmin to make a backup of the C drive.
Now: when I call enter "wbadmin" in the command line wbadmin works and shows lists all its commands.
In my c# app when i do
ProcessStartInfo info = new ProcessStartInfo("wbadmin", $"start backup -backupTarget:{destinationDrive} -include:C: -quiet -vssCopy")
{
UseShellExecute = false
};
Process p = new Process()
{
StartInfo = info,
EnableRaisingEvents = true
};
p.Start();
it tells me that the file specified cannot be found.
I did some research and I think my app is looking for the wbadmin in the WOW64 folder, where it cant find it because it is inside the System32 Folder.
How do I tell my program to use the correct wbadmin.exe in the correct location?
Do I HAVE to run the app as a 64-bit application for it to work?
If so how would i support 32-bit architecture?
Thanks
Thanks to #PavelAnikhouski for providing me with the correct answer.
I had to specify the path to sysnative.
Like the title says, i'm trying to install an .exe silently (say, for example, inkscape) through my application written in WPF C#. The problem is, the install process i use always return an exception and fails.
Here is the code that i use :
public static bool StartInstall(string pathtofile)
{
try
{
Process process = new Process();
process.StartInfo.FileName = "Temp.exe";
process.StartInfo.Arguments = string.Format(" /S", pathtofile);
process.Start();
process.WaitForExit();
Console.WriteLine("Silent Install was successful.");
return true;
}
catch
{
MessageBox.Show("Error!");
return false;
}
}
According to this website, the switch for a silent install for NSIS packaged exes is /S. I'm not sure whether or not i'm doing something wrong in the syntax, though.
The code i'm using come from this stackoverflow post. It does work for a .msi package. Maybe it does not work for NSIS exes?
I'm relatively clueless as to why it does not work. The code above will crash at the "process.Start()" line, most probably because of a unknown command or something.
I'd be thankful if anybody could shred a bit of light as to how to launch that process for a NSIS installer.
I have solved the problem with the help of csharpfolk.
My problem was a combination of two different cause :
First, Admin privileges were indeed required to run the application.
Second, the line "process.StartInfo.Filename" requires the full path to the file. As soon as i changed it to "C:\Downloads\Temp.exe", it worked.
public void runBatchfile(String batchfilename)
{
try
{
ProcessStartInfo processInfo = new ProcessStartInfo(batchfilename);
processInfo.UseShellExecute = false;
Process batchProcess = new Process();
batchProcess.StartInfo = processInfo;
batchProcess.StartInfo.CreateNoWindow = true;
batchProcess.Start();
batchProcess.WaitForExit();
}
catch (Exception r) { }
}
runBatchfile(#"c:\lol.bat");
lol.bat contains these 2 lines
dir c:\ /s /b > c:\filelist.txt
exit
and when I run my code all it does is creating a filelist.txt file, but doesn't actually perform the rest of the command, which does work if I manually insert it into CMD.
Btw I've tried making the extension .cmd and I also tried without the exit command, without any other results.
please help me :)
On my Windows 7 64-bit machine with Visual Studio 2010, running this code straight from the IDE doesn't do anything whatsoever.
On a hunch that it might have something to do with permission to write to the root directory of drive C:, I tried running the .exe directly from an Explorer window with admin rights (right-click, Run as Administrator) and that worked.
I'd say it's a permission problem.
Maybe you could redirect the output to a file located elsewhere?
update:
I changed the batch file so that the dir command gets redirected to my desktop and it runs just fine.
I've had issues with this as well when calling from C#. The workaround that I usually use is to physically allow it to show the window when running the command. Not sure why this makes a difference but it has worked for me in the past.
I'm launching the path C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools\IIS Manager.lnk via Process.Start, but it fails with The system cannot find the file specified.
The link shows up on a dir, so it exists.
Can it be permissions?
Notes:
The path is auto-discovered by iterating over the Start Menu directory.
I can launch it via explorer and command line.
Clarifications:
Code is as follows:
public void Execute() { Process.Start(_shortcut.FullName);}
_shortcut is of type FileInfo
_shortcut.Exists is true, so the file can be found
replacing _shortcut.FullName with the explicit path #"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools\IIS Manager.lnk" has the same effect.
This is a WPF app using Caliburn and MEF.
Running as Administrator has the same effect.
This here on the other hand seems to work:
[Fact]
public void TestIisManager()
{
var path = new FileInfo(#"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools\IIS Manager.lnk");
Process.Start(path.FullName);
}
It does seem to be a bit "environment" based.
Second clarification:
It seems to work in a Windows 7 x86 but not in a Windows 7 x64.
I ran into this recently. Windows Forms based solution, VS2013, x64 machine. Process.Start() could not launch applications via .lnk file. Using process explorer, it seemed that the target specified in the .lnk file was resolving incorrectly to c:\program files (x86)... instead of c:\program files... I followed Bruno's excellent advice, but then again my Target was already marked as "AnyCPU".
After some head scratching, it turned out there's a new compiler flag in VS11+ called "Prefer 32-bit" that was checked by default. This was forcing the EXE output to be 32-bit even though my OS was 64-bit and platform was set to AnyCPU. After I unchecked and recompiled, the problem was fixed.
More reading at: http://blogs.microsoft.co.il/sasha/2012/04/04/what-anycpu-really-means-as-of-net-45-and-visual-studio-11/
Found the issue.
The WPF application was compiled as x86 (all other dlls were compiled as AnyCPU), and when launching some executables or links in a 64 bit machine it failed.
Changing the "Platform Target" to AnyCPU fixes this.
This may not actually relate to your situation, but you can launch the IIS Manager by using
Process.Start("inetmgr.exe")
If you want to continue to use the shortcut, it will probably work if you start the process using a ProcessStartInfo and set ProcessStartInfo.UseShellExecute to true
Can you make sure that you are trying this from an STA thread? You can see whether the apartment state is a problem if the following sample succeeds:
using System;
using System.Diagnostics;
public class Program
{
// make sure to call Process.Start from an STA thread
[STAThread]
static void Main(string[] args)
{
Process.Start(#"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools\IIS Manager.lnk");
}
}
Process.Start calls ShellExecute under the hood to run the file passed. As described by Raymond Chen, shell functions require an STA thread:
One possible reason why ShellExecute returns SE_ERR_ACCESSDENIED and ShellExecuteEx returns ERROR_ACCESS_DENIED
As stated already, you will see the "The system cannot find the file specified" error because Windows is looking for inetmgr.exe in ...\SysWOW64\intsrv\ (caused by file system redirection), but it only exists in ...\System32\intsrv\.
This is caused by your 32-bit executable attempting to launch a 64-bit executable. As suggested, not using a 32-bit executable will solve this, but for anyone who must build for 32-bit (a WiX installer bundle in my case), try the following.
Using the start menu LNK/shortcut to inetmgr.exe instead of the executable is a good start, but an extra level of distance is required. This can be provided by using explorer.exe, which can be launched from a 32-bit executable:
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = "explorer.exe";
startInfo.Arguments = "/seperate /root,\"C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Administrative Tools\\IIS Manager.lnk\"";
System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo = startInfo;
process.Start();
It's a bit of a hack, but try launching it like this:
string path = #"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools\IIS Manager.lnk";
Process.Start("cmd.exe", String.Format("/k \"\"{0}\"\"",path));
Note the double quotes needed to save the spaces in the path.
That way, you might see a more precise error message and/or walk around in the command environment afterwards to see what is wrong with the path.