I'm trying to find out a way to run a CMD process in my WPF application without the need to write the CMD application to the user's temp directory.
The application I have created is essentially a wrapper to execute another CMD application and the intent is as follows:
Install the application to the user's Program Files directory.
The directory that the app installs would also have a folder labeled something like "resources" that would hold the CMD application (upgrade.exe) and a file that the CMD application requires (image.bin).
Run the application either from a shortcut on the desktop or from the Start menu.
When the application needs to, call the upgrade.exe CMD application from the Program Files location it resides ("C:\Program Files\appname\resources\upgrade.exe").
What I have right now is code that writes the file to the user's temp directory and then runs it from there (code below). Both of the files are added to my solution as Resources to the project but if I need to do something different with them to use them, that's no problem. I don't know if there is a way to know exactly the location as I described it above but, if there is, how would I go about changing my code to work that way?
path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "upgrade.exe");
File.WriteAllBytes(path, Properties.Resources.upgrade);
imagepath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "image.bin");
File.WriteAllBytes(imagepath, Properties.Resources.image);
ProcessStartInfo processSetup = new ProcessStartInfo(path)
{
WorkingDirectory = System.IO.Path.GetTempPath(),
Arguments = String.Format("-F -p {0} -f image.bin, UserComPort),
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardError = true,
RedirectStandardOutput = true
};
update = Process.Start(processSetup);
I don't love this method because it puts my files into a different location than where I would like them to reside permanently on the user's PC, even though I know I can delete them after I'm done using them.
Any help would be greatly appreciated.
EDIT: As indicated below, the correct solution was to use the AppDomain.CurrentDomain.BaseDirectory location and then append the known directory location to that path. You have to know where your resource is going to go in your program's directory structure to use this method (I used Inno Setup and defined the "Dir" that I wanted those resources to reside). The final solution is below:
path = AppDomain.CurrentDomain.BaseDirectory + "resources\\upgrade.exe";
imagepath = AppDomain.CurrentDomain.BaseDirectory + "resources\\image.bin";
This results in a much cleaner solution that does not require writing the file to a new location on the user's PC. Thank you to Phil N DeBlanc for this solution!
If I understand what you're asking, I think you can find a solution here. You can get the current executing directory then append the necessary remaining path information to your CMD directory.
Related
I have some strange problem (for me).
There is an application which is a windows form application "firstapp.exe".
There is another application which is windows form application too "launcher.exe".
And there is a console application with name "server.exe".
Both firstapp and launcher are in the same directory. In that directory there is also a "Config" folder with some other files in it.
The code which I use to read one file from config folder in firstapp:
StreamReader reader = new StreamReader("Config\\launcher.txt");
string readed_config = reader.ReadToEnd();
reader.Close();
If I run the firstapp application with launcher (using process.start) all goes fine.
When I run it with console application, which is not in the same directory as firstapp I get the "directory not found exception" from that part of code (posted above).
How can I solve the problem?
Why is console application adding its own path to another application which should run independently?
Sounds like you need to set the WorkingDirectory property of your Process before calling Process.Start.
string launcherPath = #"C:\SomePathToLauncher\Launcher.exe";
myProcess.StartInfo.FileName = launcherPath;
myProcess.StartInfo.WorkingDirectory = Path.GetDirectoryName(launcherPath);
myProcess.Start();
StreamReader reader = new StreamReader("Config\\launcher.txt");
Never use hard-coded relative file paths in your code. It critically depends on Environment.CurrentDirectory and that's way too unpredictable. External code can kill you as you found out. Internal code as well, use OpenFileDialog and your code will crash. You can always get a full path with Assembly.GetEntryAssembly().Location and the Path class:
var exedir = Path.GetDirectory(Assembly.GetEntryAssembly().Location);
var path = Path.Combine(exedir, #"Config\launcher.txt");
using (var reader = new StreamReader(path)) {
//...
}
Now it always works.
It's because your path is relative and the Current Working Directory is different when the console app kicks off your winform. Also, you should wrap the stream reader in a using statement. As it stands, unless you explicitly call Dispose() elsewhere in your code you're holding on to resources that should be freed.
To fix your problem either change the WorkingDirectory when you start the process using Process.StartInfo.WorkingDirectory or change the path in your code so it is not relative. Or another option would be to pass the path to the application or read it from a resource file so that it can be given the appropriate path when it executes.
the answer is in the question. you are saying that "When I run it with console application, which is not in the same directory". if it's not in the same directory how will it find a directory "Config" if it diesn't exist there. make sure that the directory exist there
I have created a .msi by using VS2008 setup project. My application frequently writes some value in a .txt file in the application directory (C:\Program Files\MyApp\MyFile.txt). After insalling it in Win7, it raises an exception "Access to the path .... is denied."
But whenever I run it as administrator, no such exception occurs. Here is my sscce
string FilePath=Application.StartupPath + #"\AppSettings\CurrentUserName.inf";
using (StreamWriter writer=new StreamWriter(FilePath,false))
{
writer.Write(txtLoginName.Text.Trim());
}
MainForm.ProcessLogIn();
this.DialogResult = DialogResult.OK;
I don't know how to solve this problem. Any suggestion?
Move your file out of Program Files directory. In Win7 is readonly for normal users.
You could move the file in the ProgramData directory.
Your installer should create a directory for your application there.
Then inside your code you could retrieve the correct full pathname using these lines of code
string dataPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData));
string appFile = Path.Combine(dataPath, "MyAppDir", "MyFile.txt");
usually (on Win7) this result in a path like this
c:\programdata\MyAppDir\MyFile.txt
but using the SpecialFolder enum you are guaranteed to use a folder available in readwrite to your application not depending on the current operating system.
The only way to solve this problem is to not write to that folder. You are not allowed to write to that folder by convention, unfortunately, older versions of Windows did not hold you to this.
Instead, you can use Environment.SpecialFolder to help you find where you need to go:
// your application data for just that User running the app
var perUserAppData = Environment.GetFolderPath(
Environment.SpecialFolder.ApplicationData);
// your application data for ALL users running the app
var allUsersAppData = Environment.GetFolderPath(
Environment.SpecialFolder.CommonApplicationData);
// better!
var path = Path.Combine(perUserAppData, #"MyApp\MyFile.txt");
Basically, Windows 7 is telling you that you're going to have to stop driving on the sidewalks and use the street as was intended.
As a short-term fix, you can use ICACLS to grant write access to the file. Note: NOT the whole directory.
As a longer term fix, you should NOT write to the program directory if you are running as unprivileged users, but instead somewhere like %LOCALAPPDATA% or %APPDATA%.
I'm trying to delete a folder off the desktop when I get the error that the path is denied. I've even made my app.manifest start the program as administrator. Now with the code below I can delete the folder successfully, but it seems so unnecessary.
string folder = "c:\\users\\jim\\desktop\\Proto";
ProcessStartInfo process = new ProcessStartInfo("cmd.exe", #"/C " + #"rmdir " + folder + " /s /q");
process.Verb = "runas";
Process p = Process.Start(process);
p.WaitForExit();
Im trying to use ...
string folder = "c:\\users\\jim\\desktop\\Proto";
Directory.Delete(folder, true);
Is it possible to to make that method "runas"?
As far as I know it's impossible to elevate just a single call/command. You'll have to launch a new process that might get blocked by UAC. Some programs seem to do so otherwise (e.g. different Windows dialogs), but they just call another process (or their own executable) with different parameters in background.
Besides that: By default, you should have full access to everything on your own desktop. Or are you trying to modify some other user's desktop?
Well for a start, the user running the application should be able to create a folder on their own desktop.
If the above is the case get rid of the stuff you put in the manifest but don't use a hard coded path
String desktopFolder = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
Directory.Delete(Path.Combine(desktopFolder,"proto");
If this folder is being deleted for another other user (and admin is another user, elevated or not), then you have to run with elevated all the time, (not a good idea) , or as you are kick off another process with elevated rights to do the elevated stuff.
Take a look at this, it shows you how to run a single method as Admin user
I have an exe which I call from the command line. Is it possible to execute that file on the server? On the computer if the file is located in the folder abc, I go to folder abc and than I execute the batch. Hw do I do this in C#
Code example below, make sure you have your permissions setup correctly:
System.Diagnostics.Process yourProcess = new System.Diagnostics.Process();
// Set the directory
yourProcess.StartInfo.WorkingDirectory = Request.MapPath("~/"); //or wherever your file is
// Set the filename
yourProcess.StartInfo.FileName = Request.MapPath("bla.exe");
// Start the process
yourProcess.Start();
ASP Net - Run Application (EXE) from ASP.Net C#
In server side code certainly, Process.Start(MyExeFile) will do that but, as long as the user account you are running your stuff on can execute it.
I Added textfile on my Application Folder where the application is also located.
I having a problem where to locate and read the content of the texfile regarding what location the users specify the application to be installed.
Example:
CASE 1: If Application Installed on C
Get the path of: C:\Textfile.txt
CASE 2:If Application Installed on Program files
Get the path of C:\Program Files\Default Company Name\Textfile.Text
Thanks in Regards.
i am not sure if this is what you wanted
string StartPath = Application.StartupPath; //or what SilverbackNet suggested
string FileName = "YourFileName.txt"
Textreader tr = new StreamReader(StartPath+ "\\" + FileName);
Console.WriteLine(tr.ReadLine());
tr.Close();
System.Windows.Forms.Application.ExecutablePath is pretty much the go-to for this particular situation, especially for loading libraries. Please look at System.Environment.GetFolderPath(SpecialFolder.*) for storing data, however, or you'll probably run afowl of stricter permission problems at some point.