I'm making an installer using IExpress to unpack the files, create a folder and move the files to the folder.
However, when choosing which program to run upon installation I can only get it to work using a batch-file:
#ECHO OFF
MD C:\PlugInFolder
MOVE /Y "%USERPROFILE%\AppData\Local\Temp\IXP000.TMP\*.png" C:\PlugInFolder
MOVE /Y "%USERPROFILE%\AppData\Local\Temp\IXP000.TMP\PlugIn.dll" C:\PlugInFolder
MOVE /Y "%USERPROFILE%\AppData\Local\Temp\IXP000.TMP\PlugIn2021.addin" C:\ProgramData\Autodesk\Revit\Addins\2021
MOVE /Y "%USERPROFILE%\AppData\Local\Temp\IXP000.TMP\PlugIn2022.addin" C:\ProgramData\Autodesk\Revit\Addins\2022
Is it possible to run an exe file instead? I've tried the following C#-code (for one of the files only) but it only creates the folder and doesn't move the files:
// Creating paths
string path = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
string folderName = "PlugInFolder";
string pathString = Path.Combine(path, folderName) + "\\PlugIn.dll";
string tempName = Path.GetTempPath() + "IXP000.TMP\\";
string fileName = "PlugIn.dll";
string filePath = tempName + fileName;
// Creating new directory
Directory.CreateDirectory(pathString);
// Moving files from temp folder
File.Move(filePath, pathString);
There are a few typos in your code. Here's what could work, correctly using Path.Combine which is a powerful command:
// Creating paths
string source = Path.Combine(Path.GetTempPath(), "IXP000.TMP");
string dest1 = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
string dest2 = "PlugInFolder";
string dest = Path.Combine(dest1, dest2);
// Creating new directory
// Directory.CreateDirectory(dest);
// Don't create the directory, because we will use Directory.Move
// and it would raise an exception "Directory already exists"
// Moving files from temp folder to destination
// File.Move is meant to move one file at a time.
// For an entire directory, use Directory.Move which can also be used for renaming the directory.
Directory.Move(source, dest);
And, by the way, is it a choice to put an application in the user profile dir? Otherwise, you may use:
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
which would be C:\Users\yourName\AppData\Roaming for example in Windows 11.
I have a C# program that is running and I want to launch another executable in different directory.
I have this code on event:
string path = "Y:\Program\test.exe";
Process.Start(path);
Problem is that in order for program to work right it need to take information from settings.ini where the exe file is located but it takes settings.ini from program folder with which I am trying to launch second program. test.exe is working fine when I am opening it from its folder by double click. What could be the problem?
You need to tell the process what the working directory is via ProcessStartInfo.WorkingDirectory:
var processStartInfo = new ProcessStartInfo
{
WorkingDirectory = #"Y:\Program",
FileName = #"Y:\Program\test.exe",
};
Process.Start(processStartInfo);
Edit:
In order to get the directory from the user, you can use DirectoryInfo.FullName:
var userFileInfo = new FileInfo(userInsertedVariableHere);
var parentDirectory = userFileInfo.Directory.FullName;
So I have a small setup file that needs to install a few run-time files. The files are located within sub directories of the root of the drive. The drive letter will be different on every customers machine, so I was trying this and several other methods to no avail.
// File is being ran from D:\ "eg: D:\setup.exe"
// All my runtimes are in the Tools\Runtime direcorties
string path = Directory.GetCurrentDirectory();
string ext = "/q /norestart";
string location = "\\Tools\\Runtimes\\Net\\";
string step1 = "dotnetfx35.exe";
var process = Process.Start(path + location + step1 + ext);
process.WaitForExit();
As you pros and more experienced programmers know, for some reason... It doesn't work
I keep getting file not found.
I have a C# application which assume it runs from bin directory
string current_directory = Directory.GetCurrentDirectory(); //get current directory, this is the bin dir
string parent_dir = Directory.GetParent(current_directory).ToString();// this is parent of bin dir
string _Config1 = parent_dir + "\\config\\x.cfg";
string _Config2 = parent_dir + "\\config\\y.cfg";
string _Log = parent_dir + "\\log\\z.log";
The problem is for some reasons the user can not go to the bin directory and run the app (just type "application_name"). He has to run it using path (ie d:\blah\1\blah\2\blah\3\bin\application_name)
when he does this he gets
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location)
so either I have to capture the path he uses to run the program and use it in my program or somehow make my application to be able to run using path.
You can use AppDomain.CurrentDomain.BaseDirectory.
Use the Application.StartupPath for WinForms.
You can use reflection:
var path = System.IO.Path.GetDirectoryName( System.Reflection.Assembly.GetExecutingAssembly().GetName().GetCodebase );
I've been searching and experimenting for a while with this, but I have had no luck.
I am trying to make a console program to automate some tasks that I couldn't quite do with a BAT file. I want to call "signcode.exe" from the Windows SDK, the bin folder with all the tools in my system PATH, and I can call "signcode" from anywhere, but Process.Start is ignoring the path.
Current code:
System.Diagnostics.Process sign = new System.Diagnostics.Process();
sign.StartInfo.FileName = signCommand.Substring(0, signCommand.IndexOf(' ')); // signtool.exe
sign.StartInfo.Arguments = signCommand.Substring(signCommand.IndexOf(' ') + 1); // /sign /a file1 file2
// sign.StartInfo.EnvironmentVariables["Path"] = Environment.GetEnvironmentVariable("PATH"); // This doesn't work either
sign.StartInfo.UseShellExecute = false;
sign.StartInfo.RedirectStandardOutput = true;
sign.StartInfo.RedirectStandardError = true;
sign.Start(); // Throws Win32Exception - The system cannot find the file specified
I've confirmed that StartInfo.EnvironmentVariables["Path"] matches my system path, and contains the Windows SDK folder. Setting it manually doesn't work either.
I've even tried setting TempPath as shown on the MSDN page for EnvironmentVariables Property, but that didn't work either. I wonder why you would be able to set this if it has no effect.
If System.Diagnostics.Process cannot use the path, are there any other functions I could use? I'd like to see the output of the command in my console application as well.
Here is some additional debug values:
Console.WriteLine("Sign Filename = '{0}'", sign.StartInfo.FileName);
Sign Filename = 'signtool.exe'
Console.WriteLine("Sign Arguments = '{0}'", sign.StartInfo.Arguments);
Sign Arguments = '/sign /f C:\Visual Studio\Projects\MGInsight\MGInsight\APPARENTINC.pfx /t http://timestamp.comodoca.com/authenticode "C:\Visual Studio\Projects\MGInsight\MGInsight\Publish\Application Files\\MGInsight_0_9_1_85\MGInsight.exe" "C:\Visual Studio\Projects\MGInsight\MGInsight\Publish\Application Files\\MGInsight_0_9_1_85\XPXScanner.dll" "C:\Visual Studio\Projects\MGInsight\MGInsight\Publish\Application Files\\MGInsight_0_9_1_85\NetworkCalculations.dll"'
Console.WriteLine("Sign Path = '{0}'", sign.StartInfo.EnvironmentVariables["Path"]);
Sign Path = 'C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;"C:\Program Files\Intel\WiFi\bin\";"C:\Program Files\Common Files\Intel\WirelessCommon\";"C:\Program Files (x86)\cwRsync\bin";"C:\Program Files (x86)\Git\cmd";"C:\Program Files (x86)\Git\bin";"C:\Program Files (x86)\Zend\ZendServer\bin";"C:\Program Files (x86)\Zend\ZendServer\share\ZendFramework\bin";"C:\Program Files\Java\jre6\bin";"C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\";"C:\Program Files\Microsoft Windows Performance Toolkit\";C:\MinGW\bin;"C:\Program Files (x86)\Microsoft\ILMerge";"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin";C:\Program Files (x86)\Nmap'
The path "C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin" is where signtool.exe is, and I can run it from a command prompt by simply typing signtool, but if I run this application from the same prompt, it doesn't register that path.
Adding to mhutch's answer: It does indeed take PATH into consideration, but I have noticed you actually need to restart Visual Studio to pick up any path changes. It is kind of sneaky.
I'm pretty sure Process.Start does respect PATH.
Are you sure your signCommand value is correct?
Is the directory value in PATH specified using quotes? The docs mention that such values will not be respected.
Note that FileName can also be a full path to the executable.
If you updated PATH recently, be sure to restart Visual Studio. Environment variables are loaded at the launch of Visual Studio. Note that this applies to DEBUG mode execution.
Well, I guess the problem was related to what mhutch said, from the MSDN docs:
If you have a path variable declared in your system using quotes,
you must fully qualify that path when starting any process found
in that location. Otherwise, the system will not find the path. For
example, if c:\mypath is not in your path, and you add it using
quotation marks: path = %path%;"c:\mypath", you must fully qualify
any process in c:\mypath when starting it.
I saw that initially, but it seemed strange so I disregard it. Not sure why that's the case but it seems to be.
I tried copying signtool.exe to C:\sign\tool\bin and added that to my path, and then my code worked, so I guess because I have quotes in that path due to the spaces, I am SOL and will have to manually search the path for the windows SDK path unless there is some way to add something with spaces to the path without using quotes.
I believe you're looking for the ProcessStartInfo.WorkingDirectory property.
The StartInfo filename is actually the full path to the executable
For example, on a wrapper I have for x264, it looks like this:
x264Start.FileName = Directory.GetCurrentDirectory() + #"\Tools\x264\x264x86-r1995.exe";
I'd sense-check the code by adding a try {}, catch {} in there and writing the actual filename you are trying to call into the debug if you have an error.
Otherwise add something like the below:
if (File.exists(sign.FileName))
{
sign.Start();
}
else
{
Console.WriteLine("Can't find {0}", sign.FileName);
throw new Exception("File doesn't exist");
}
EDIT: Added a full example - this searches for CCleaner and then runs it with the "/AUTO" switch. Just tested and works fine.
// detect if 64-bit system
string programFiles = "";
if (Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE").Contains("64"))
{
Console.WriteLine("#info# x64 detected");
programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
}
else
{
Console.WriteLine("#info# x86 detected");
programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
}
// search
string[] dirs = Directory.GetDirectories(programFiles, "CCleaner", SearchOption.AllDirectories);
string[] exes = Directory.GetFiles(programFiles, "CCleaner64.exe", SearchOption.AllDirectories);
//debug only
foreach (string s in dirs)
{
Console.WriteLine(s);
}
foreach (string s in exes)
{
Console.WriteLine(s);
}
// access directly
ProcessStartInfo CCleaner = new ProcessStartInfo(exes[0], "/AUTO");
Process.Start(CCleaner);
Your code does seem to take the path into account for me.
It's hard to say what might be wrong in your case, but you might try running your command through cmd.exe:
sign.StartInfo.FileName = "cmd";
sign.StartInfo.Arguments = "/c signtool.exe ...";