winforms 如何启动作为资源的进程?

6tdlim6h  于 2022-12-14  发布在  其他
关注(0)|答案(1)|浏览(117)

我通过resx将我的test.bat添加为资源。

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

但上面说

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

我该如何解决这个问题?
下面是我的完整代码:

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;
        }

次要问题:看起来资源管理器并不关心文件的扩展名。那么如果我有两个同名但扩展名不同的文件呢?

xiozqbni

xiozqbni1#

如果嵌入的test.bat包含此文本:

@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

目标是以编程方式运行它...

...从嵌入式资源:

然后,这里有一种方法将其复制到一个临时文件并运行它(请参阅注解中的说明)。

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);

相关问题