I've made a C++ code editor in C# and now am trying to invoke g++ to compile the source files. So I've copied the TDM-GCC installation besides my program and wrote a small batch script to call that.
#echo off
#set PATH="%~dp0TDM-GCC-32\bin\";%PATH%
call "%~dp0TDM-GCC-32\mingwvars.bat"
cd %1
"%~dp0TDM-GCC-32\bin\g++.exe" %2 -o %3
And from C# code, I'm trying to call this script by using CMD like in this script of code.
string fileName = Path.GetFileName(CurrentFile);
string exeName = Path.GetFileNameWithoutExtension(CurrentFile) + ".exe";
string workingDir = Directory.GetParent(CurrentFile) + "";
string compile = Directory.GetParent(Application.ExecutablePath) + "\\compile.cmd";
File.Delete(Path.Combine(workingDir, exeName));
StartProcess(true, "cmd", "/c", "\"" + compile + "\"", workingDir, fileName, exeName);
And here is the StartProcess method:
void StartProcess(bool hidden, string command, params string[] args)
{
ProcessStartInfo pStartInfo = new ProcessStartInfo();
pStartInfo.FileName = command;
pStartInfo.Arguments = string.Join(" ", args);
pStartInfo.UseShellExecute = false;
if (hidden)
{
pStartInfo.RedirectStandardError = true;
pStartInfo.RedirectStandardOutput = true;
pStartInfo.CreateNoWindow = true;
}
Process proc = new Process();
proc.StartInfo = pStartInfo;
proc.Start();
logBox.Clear();
if (hidden)
{
while (!proc.StandardError.EndOfStream)
{
logBox.AppendText(GetTimestamp() + " Error: " + proc.StandardError.ReadLine() + Environment.NewLine);
}
}
}
Update: 26-9-14
I doubted whether the batch file is ever called, because if I call it from cmd, it simply works. So I tried to echo to the standard error from the batch file like this:
echo %PATH% 1>&2
And I can see that the GCC's bin folder is in the path too, but for some reason, the exe is not getting created. But sometimes, the script works, and the exe gets created.
But whenever I execute this, there will be nothing in the LOG and also, no executable is being created. I know that the TDM-GCC's bin folder must be in the PATH, but that is what the second line of the batch script needs to do. Dunno what this is and why this error.
End of update
Any suggestions on how can I get it working?
Thanks.
I don't know if anything written below really helps on this issue. But at least those hints should be useful in any case.
I suggest for the batch file
#echo off
call "%~dp0TDM-GCC-32\mingwvars.bat"
set "PATH=%~dp0TDM-GCC-32\bin;%PATH%"
cd /D %1
"%~dp0TDM-GCC-32\bin\g++.exe" %2 -o %3
PATH is modified after execution of mingwvars.bat. It could be that this batch file also modifies PATH. Or it runs commands like find.exe with the executables expected in %SystemRoot%\System32, but perhaps also existing in directory bin. I have seen already several times not working logon batch scripts because PATH on client computer contained as first folder path the bin directory of a compiler ported from Unix to Windows with executables also found in %SystemRoot%\System32, but working completely different as ported from Unix.
Folder paths should be added to environment variable PATH always without double quotes even if the folder path contains 1 or more spaces. The double quotes used in third line just make sure that a trailing space is not added additionally to PATH and that command set works even with not typical folder paths like an ampersand in path.
And folder paths should be added to environment variable PATH without a trailing backslash.
On command cd the parameter /D is additionally used in case of a change to a different drive must be performed, too. The command cd would not change the current directory if the specified path is on a different drive without parameter /D.
In C# code you have to make sure that workingDir, fileName and exeName are finally on execution of cmd.exe enclosed in double quotes in the arguments string as Erti-Chris Eelmaa already wrote.
And it would be perhaps better to read in your C# application the value of environment variable ComSpec and use this value instead of just cmd for executing the batch file.
This might, or might not be part of the problem, but you don't take care of spaces.
pStartInfo.Arguments = string.Join(" ", args);
you probably would want something like this:
pStartInfo.Arguments = string.Join(" ", args.Select(x => "\"" + x + "\""));
Related
I wanted to create a text file with all names of the files in a folder.
So I went like this:
Process getNamesProcess = new Process();
getNamesProcess.StartInfo.FileName = #"c:\**my folder path**";
getNamesProcess.StartInfo.Arguments = "dir /b >> names.txt";
getNamesProcess.Start();
However this doesn't work for me. The process opens me a folder, nothing more. What should I change?
I do not know what you were hoping to accomplish by placing a folder path in StartInfo.FileName, but what you need to put in there is the full path to cmd.exe.
Then, in StartInfo.Arguments you need to put "/C dir /b " + my_folder_path + " >> names.txt".
For an explanation of what the /C does, open up a command prompt and type help cmd.
A better way would be:
File.WriteAllLines("names.txt", Directory.GetFiles("c:\\path").Select(Path.GetFileName));
The File, Directory and Path classes are in the System.IO namespace.
when i run copy command in my c# code it produce no error or exception because it is not finding the parts path i do not know how to give full directory path or path of every part which i am joining.actually i am merging file parts to a single file using coy/b by using this code...
string strCmdText;
strCmdText = "/C copy/b test.txt.10485760.0000.part" +
"test.txt.10485760.0001.part" +
"test.txt.10485760.0002.part" +
"test.txt.10485760.0003.part" +
"test.txt.10485760.0004.part" +
"test.txt.10485760.0005.part test.txt";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
You can specify the path of your files as the working path of the process. For example:
var startInfo = new System.Diagnostics.ProcessStartInfo
{
WorkingDirectory = #"THE\PATH\OF\FILES",
WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal,
FileName = "cmd.exe",
Arguments = "YOUR COMAND HERE";
};
Process process = Process.Start(startInfo);
For your command, note that you can copy all files into one using a wildcard for the parts:
copy *.part test.txt
/b is for binary data, so i think is not needed in your case.
You can also set other properties for a process, for more info check the doc: ProcessStartInfo.
For such a complex task, I would use the process as a bash rather then just an execution tool.
Create a Process
Redirect it's streams (Input, Output)
With a StreamReader and StreamWriter u can now access the cmd
Now just control it the way u need it, like setting the working directory to the path and do ur command.
If this is not what u want, u can allways set the working directory on the ProcessStartInfor -> Link
I am writing a C# program that needs to run a script. I want to include the script with the application so that it is available when the user installs the program after I publish it.
I tried adding the script as a resource. In the Solution Explorer, under the Resources directory, I can see the script file.
In the program, I call a function that starts a process and runs the desired command:
runNewProcess("tclsh \\Resources\\make.tcl " + activeProducts);
I get the command prompt with the message "couldn't read file "\Resources\make.tcl": no such file or directory". So I guess it cannot find the file? Am I not referencing the file correctly? Is this the correct way of doing something like this?
Thank you all for your suggestions. Using them and with a bit more research, I was able to come up with a perfect solution for me.
1) Add the TCL script file as a resource to the project and set the Build Action to 'Content' in it's Properties.
2) Get the path to the TCL script (even after installation from a published version):
string makeScriptPath = System.Windows.Forms.Application.StartupPath + "\\Resources\\make.tcl";
3) Construct the run command using all the required variables and pass it to a routine that can execute it.
localCommand = String.Format("tclsh \"{0}\" --librarytype {1} --makeclean {2} --buildcode {3} --copybinary {4} --targetpath \"{5}\" --buildjobs {6} --products {7}",
makeScriptPath, library, makeClean, buildCode, copyBinary, targetPath, buildJobs, activeProducts);
runNewProcess(localCommand);
where:
private void runNewProcess(string command)
{
System.Diagnostics.ProcessStartInfo procStartInfo =
new System.Diagnostics.ProcessStartInfo("cmd", "/k " + command);
procStartInfo.RedirectStandardOutput = false;
procStartInfo.UseShellExecute = true;
procStartInfo.CreateNoWindow = true;
// Now we create a process, assign its ProcessStartInfo and start it
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
}
This gives some added perks. Since the file is included with the application, but remains a separate entity, this allows it to be tweaked and modified without needing to re-build, re-publish and re-install the application.
The script runner is unable to dig into you executable to find the commands, as it most likely only know what to do with files on disk. Shipping as a resource is a good idea, but for make anything useful with it you should extract it into a real file on disk so that other programs can use it.
A good pattern for such things would be to create a temporary file on %TEMP%, make the script runner execute that file, and delete it afterwards.
To expand on Alejandro's answer, The easiest way to handle this is to use the temporary folder and copy your script there first.
var scriptPath = Path.Combine(Path.GetTempPath(), "make.tcl");
// Copy the text of the script to the temp folder. There should be a property
//you can reference associated with the script file if you added the file using
//the resources tab in the project settings. This will have the entire script in
//string form.
File.WrteAllText(scriptPath, Resources.make);
runNewProcess("tclsh \"" + scriptPath + "\"" + activeProducts); //added quotes in case there are spaces in the path to temp.
File.Delete(scriptPath); //Clean up after yourself when you are done.
You need to ensure that the Build Action of the script file is set to Content to keep it as an independent file. By default it will be set to Resource which means you will have to programmatically extract it and then save it to a temporary location before attempting to run it.
I have a batch file with following content:
echo %~dp0
CD Arvind
echo %~dp0
Even after changing directory value of %~dp0 is the same.
However, if I run this batch file from CSharp program, the value of %~dp0 changes after CD. It now points to new directory. Following is the code that I use:
Directory.SetCurrentDirectory(//Dir where batch file resides);
ProcessStartInfo ProcessInfo;
Process process = new Process();
ProcessInfo = new ProcessStartInfo("mybatfile.bat");
ProcessInfo.UseShellExecute = false;
ProcessInfo.RedirectStandardOutput = true;
process = Process.Start(ProcessInfo);
process.WaitForExit();
ExitCode = process.ExitCode;
process.Close();
Why is there a difference in output on executing same script by different ways?
Do I miss something here?
This question started the discussion on this point, and some testing was done to determine why. So, after some debugging inside cmd.exe ... (this is for a 32 bit Windows XP cmd.exe but as the behaviour is consistent on newer system versions, probably the same or similar code is used)
Inside Jeb's answer is stated
It's a problem with the quotes and %~0.
cmd.exe handles %~0 in a special way
and here Jeb is correct.
Inside the current context of the running batch file there is a reference to the current batch file, a "variable" containing the full path and file name of the running batch file.
When a variable is accessed, its value is retrieved from a list of available variables but if the variable requested is %0, and some modifier has been requested (~ is used) then the data in the running batch reference "variable" is used.
But the usage of ~ has another effect in the variables. If the value is quoted, quotes are removed. And here there is a bug in the code. It is coded something like (here simplified assembler to pseudocode)
value = varList[varName]
if (value && value[0] == quote ){
value = unquote(value)
} else if (varName == '0') {
value = batchFullName
}
And yes, this means that when the batch file is quoted, the first part of the if is executed and the full reference to the batch file is not used, instead the value retrieved is the string used to reference the batch file when calling it.
What happens then? If when the batch file was called the full path was used, then there will be no problem. But if the full path is not used in the call, any element in the path not present in the batch call needs to be retrieved. This retrieval assumes relative paths.
A simple batch file (test.cmd)
#echo off
echo %~f0
When called using test (no extension, no quotes), we obtain c:\somewhere\test.cmd
When called using "test" (no extension, quotes), we obtain c:\somewhere\test
In the first case, without quotes, the correct internal value is used. In the second case, as the call is quoted, the string used to call the batch file ("test") is unquoted and used. As we are requesting a full path, it is considered a relative reference to something called test.
This is the why. How to solve?
From the C# code
Don't use quotes : cmd /c batchfile.cmd
If quotes are needed, use the full path in the call to the batch file. That way %0 contains all the needed information.
From the batch file
Batch file can be invoked in any way from any place. The only reliable way to retrieve the information of the current batch file is to use a subroutine. If any modifier (~) is used, the %0 will use the internal "variable" to obtain the data.
#echo off
setlocal enableextensions disabledelayedexpansion
call :getCurrentBatch batch
echo %batch%
exit /b
:getCurrentBatch variableName
set "%~1=%~f0"
goto :eof
This will echo to console the full path to the current batch file independtly of how you call the file, with or without quotes.
note: Why does it work? Why the %~f0 reference inside a subroutine return a different value? The data accessed from inside the subroutine is not the same. When the call is executed, a new batch file context is created in memory, and the internal "variable" is used to initialize this context.
I'll try to explain why this behaves so oddly. A rather technical and long-winded story, I'll try to keep it condense. Starting point for this problem is:
ProcessInfo.UseShellExecute = false;
You'll see that if you omit this statement or assign true that it works as you expected.
Windows provides two basic ways to start programs, ShellExecuteEx() and CreateProcess(). The UseShellExecute property selects between those two. The former is the "smart and friendly" version, it knows a lot about the way the shell works for example. Which is why you can, say, pass the path to an arbitrary file like "foo.doc". It knows how to look up the file association for .doc files and find the .exe file that knows how to open foo.doc.
CreateProcess() is the low-level winapi function, there's very little glue between it and the native kernel function (NtCreateProcess). Note the first two arguments of the function, lpApplicationName and lpCommandLine, you can easily match them to the two ProcessStartInfo properties.
What is not so visible that CreateProcess() provides two distinct ways to start a program. The first one is where you leave lpApplicationName set to an empty string and use lpCommandLine to provide the entire command line. That makes CreateProcess friendly, it automatically expands the application name to the full path after it has located the executable. So, for example, "cmd.exe" gets expanded to "c:\windows\system32\cmd.exe". But it does not do this when you use the lpApplicationName argument, it passes the string as-is.
This quirk has an effect on programs that depend on the exact way the command line is specified. Particularly so for C programs, they assume that argv[0] contains the path to their executable file. And it has an effect on %~dp0, it too uses that argument. And flounders in your case since the path it works with is just "mybatfile.bat" instead of, say, "c:\temp\mybatfile.bat". Which makes it return the current directory instead of "c:\temp".
So what your are supposed to do, and this is totally under-documented in the .NET Framework documentation, is that it is now up to you to pass the full path name to the file. So the proper code should look like:
string path = #"c:\temp"; // Dir where batch file resides
Directory.SetCurrentDirectory(path);
string batfile = System.IO.Path.Combine(path, "mybatfile.bat");
ProcessStartInfo = new ProcessStartInfo(batfile);
And you'll see that %~dp0 now expands as you expected. It is using path instead of the current directory.
Joey's suggestion helped.
Just by replacing
ProcessInfo = new ProcessStartInfo("mybatfile.bat");
with
ProcessInfo = new ProcessStartInfo("cmd", "/c " + "mybatfile.bat");
did the trick.
It's a problem with the quotes and %~0.
cmd.exe handles %~0 in a special way (other than %~1).
It checks if %0 is a relative filename, then it prepend it with the start directory.
If there a file can be found it will use this combination, else it prepends it with the actual directory.
But when the name begins with a quote it seems to fail to remove the quotes, before prepending the directory.
That's the cause why cmd /c myBatch.bat works, as then myBatch.bat is called without quotes.
You could also start the batch with a full qualified path, then it also works.
Or you save the full path in your batch, before changing the directory.
A small test.bat can demonstrate the problems of cmd.exe
#echo off
setlocal
echo %~fx0 %~fx1
cd ..
echo %~fx0 %~fx1
Call it via (in C:\temp)
test test
The output should be
C:\temp\test.bat C:\temp\test
C:\temp\test.bat C:\test
So, cmd.exe was able to find test.bat, but only for %~fx0 it will prepend the start directory.
In the case of calling it via
"test" "test"
It fails with
C:\temp\test C:\temp\test
C:\test C:\test
cmd.exe isn't able to find the batch file even before the directory was changed, it can't expand the name to the full name of c:\temp\test.bat
EDIT: FixIt, retrieve the fullname even when %~0 has quotes
There exists a workaround with a function call.
#echo off
echo This can be wrong %~f0
call :getCorrectName
exit /b
:getCorrectName
echo Here the value is correct %~f0
exit /b
Command line interpreter cmd.exe has a bug in code on getting path of batch file if the batch file was called with double quotes and with a path relative to current working directory.
Create a directory C:\Temp\TestDir. Create inside this directory a file with name PathTest.bat and copy & paste into this batch file the following code:
#echo off
set "StartIn=%CD%"
set "BatchPath=%~dp0"
echo Batch path before changing working directory is: %~dp0
cd ..
echo Batch path after changing working directory is: %~dp0
echo Saved path after changing working directory is: %BatchPath%
cd "%StartIn%"
echo Batch path after restoring working directory is: %~dp0
Next open a command prompt window and set working directory to C:\Temp\TestDir using the command:
cd /D C:\Temp\TestDir
Now call Test.bat in following ways:
PathTest
PathTest.bat
.\PathTest
.\PathTest.bat
..\TestDir\PathTest
..\TestDir\PathTest.bat
\Temp\TestDir\PathTest
\Temp\TestDir\PathTest.bat
C:\Temp\TestDir\PathTest
C:\Temp\TestDir\PathTest.bat
Output is four times C:\Temp\TestDir\ as expected for all 10 test cases.
The test cases 7 and 8 start the batch file with a path relative to root directory of current drive.
Now let us look on results on doing the same as before, but with using double quotes around batch file name.
"PathTest"
"PathTest.bat"
".\PathTest"
".\PathTest.bat"
"..\TestDir\PathTest"
"..\TestDir\PathTest.bat"
"\Temp\TestDir\PathTest"
"\Temp\TestDir\PathTest.bat"
"C:\Temp\TestDir\PathTest"
"C:\Temp\TestDir\PathTest.bat"
Output is four times C:\Temp\TestDir\ as expected for the test cases 5 to 10.
But for the test cases 1 to 4 the second output line is just C:\Temp\ instead of C:\Temp\TestDir\.
Now use cd .. to change working directory to C:\Temp and run PathTest.bat as follows:
"TestDir\PathTest.bat"
".\TestDir\PathTest.bat"
"\Temp\TestDir\PathTest.bat"
"C:\Temp\TestDir\PathTest.bat"
The result for second output for the test cases 1 and 2 is C:\TestDir\ which does not exist at all.
Starting the batch file without the double quotes produces for all 4 test cases the right output.
This makes it very clear that the behavior is caused by a bug.
Whenever a batch file is started with double quotes and with a path relative to current working directory on start, %~dp0 is not reliable on getting the path of batch file when current working directory is changed during batch execution.
This bug is also reported to Microsoft according to Windows shell bug with how %~dp0 is resolved.
It is possible to workaround this bug by assigning the path of the batch file immediately to an environment variable as demonstrated with the code above before changing the working directory.
And then reference the value of this variable wherever path of batch file is needed with using double quotes where required. Something like %BatchPath% is always better readable as %~dp0.
Another workaround is starting the batch file always with full path (and with file extension) on using double quotes as class Process does.
Each new line in your batch called by your ProcessStart is independently considered as a new cmd command.
For example, if you give it a try like this:
echo %~dp0 && CD Arvind && echo %~dp0
It works.
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 ...";