質問

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.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top