简体   繁体   中英

How to start a process that is a resource?

I add my test.bat as a resource via resx. I then try

proc.StartInfo.FileName = myNamespace.Properties.Resources.test;

but it says

System.ComponentModel.Win32Exception: The system cannot find the file specified.'

How can I fix this?

Here is my full code:

public async void button_A_Click(object sender, EventArgs e)
        {
            button_A.Enabled = false;
            await Task.Run(() => {
                var proc = new Process();
                proc.StartInfo.FileName = LOS_Installer.Properties.Resources.test;
                proc.StartInfo.RedirectStandardOutput = true;
                proc.StartInfo.RedirectStandardError = true;
                proc.StartInfo.CreateNoWindow = true;
                proc.StartInfo.Arguments = path;
                if (proc.Start())
                {
                    void outputCallback(string data)
                    {
                        textBoxLog.AppendText(data);
                        textBoxLog.AppendText(Environment.NewLine);
                    }
                    proc.OutputDataReceived += (_, e) => Invoke(outputCallback, e.Data);
                    proc.ErrorDataReceived += (_, e) => Invoke(outputCallback, e.Data);
                    proc.BeginOutputReadLine();
                    proc.BeginErrorReadLine();

                }
                proc.WaitForExit();
            });
            button_A.Enabled = true;
        }

Minor question: it seems that the resource manager doesn't care about file's extension. So what if I have 2 files with the same name yet different extensions?

If embedded test.bat contains this text:

@echo off
title Testing...
echo Lorem ipsum is placeholder text commonly used in
echo the graphic, print, and publishing industries for
echo previewing layouts and visual mockups.
pause

and the objective is to run it programmatically...

脚本

... from an embedded resource:

嵌入式

Then here's one way to copy it to a tmp file and run it (see explanation in the comments).

public MainForm()
{
    InitializeComponent();
    buttonRunBatch.Click += runFromEmbedded;
}

private void runFromEmbedded(object sender, EventArgs e)
{
    var asm = GetType().Assembly;

    // Obtain the full resource path (different from a file path).
    var res =
        asm
        .GetManifestResourceNames()
        .Where(_ => _.Contains("Scripts.test.bat"))
        .FirstOrDefault();
    // Make path for a temporary file
    var tmp = Path.Combine(Path.GetTempPath(), "tmp.bat");
    // Get the byte stream for the embedded resource...
    byte[] bytes;
    using (var stream = asm.GetManifestResourceStream(res))
    {
        bytes = new byte[stream.Length];
        stream.Read(bytes, 0, (int)stream.Length);
    }
    // ... and write it to the tmp file
    using (FileStream fileStream = new FileStream(tmp, FileMode.Create))
    {
        try
        {
            fileStream.Lock(0, bytes.Length);
            fileStream.Write(bytes, 0, bytes.Length);
        }
        catch (Exception ex)
        {
            Debug.Assert(false, ex.Message);
        }
        finally
        {
            fileStream.Unlock(0, bytes.Length);
        }
    }
    // RUN the bat file.
    var process = Process.Start(fileName: tmp);

    SetForegroundWindow(process.MainWindowHandle);
    process.WaitForExit();
    // Clean up.
    File.Delete(tmp);
}

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM