C# 代码,SendKeys.Send 偶尔会出现“访问被拒绝...”错误

问题描述 投票:0回答:1

我有一个 C# 代码,其中我需要运行一个非常旧的供应商二进制到 ASCII 转换程序,这是我的代码的相关部分:

C# code with SendKeys.Send

这些代码在 30 分钟计时器内连续运行。每天大约有 50 到 150 个文件需要转换,但是每天一次,输入文件名的行会收到“访问被拒绝...”错误,仅一次,重新启动我的 C# 代码后,转换就会恢复很好。

当我在办公室时,它永远不会损坏,只有当我不在办公室时,它才会损坏。我调整了这条线之前的等待时间,但没有效果。

我有点不知道如何解决这个问题。感谢您的建议和帮助。

c# process sendkeys access-denied standardinput
1个回答
0
投票

您可以尝试使用不同的方式将数据发送到StandardInput。下面我将展示一些不同的方法来写入StandardInput和从StandardOutput读取。该代码已使用 .NET Framework v4.8 进行了测试。文章末尾是我用于测试的控制台应用程序的代码。

注意:在下面的代码中,确保将响应更改为所需的值。

添加以下 using 指令

  • using System.Diagnostics;
  • using System.IO;

选项1

private void RunProcess(string exeFilename)
{
    ProcessStartInfo startInfo = new ProcessStartInfo()
    {
        CreateNoWindow = true,
        FileName = exeFilename,
        RedirectStandardError = true,
        RedirectStandardInput = true,
        RedirectStandardOutput = true,
        UseShellExecute = false,
        WindowStyle = ProcessWindowStyle.Hidden
    };

    using (Process p = new Process() { StartInfo = startInfo, EnableRaisingEvents = true })
    {
        //subscribe to event and add event handler code
        p.ErrorDataReceived += (sender, e) =>
        {
            if (!String.IsNullOrEmpty(e.Data))
            {
                //ToDo: add desired code 
                Debug.WriteLine("Error: " + e.Data);
            }
        };

        //subscribe to event and add event handler code
        p.OutputDataReceived += (sender, e) =>
        {
            if (!String.IsNullOrEmpty(e.Data))
            {
                //ToDo: add desired code
                Debug.WriteLine("Output: " + e.Data);
            }
        };

        //start
        p.Start();

        p.BeginErrorReadLine(); //begin async reading for standard error
        p.BeginOutputReadLine(); //begin async reading for standard output

        using (StreamWriter sw = p.StandardInput)
        {
            //response for 1st prompt
            sw.WriteLine(@"C:\Temp\Test.txt");

            //response for 2nd prompt
            sw.WriteLine("n");

            //response for 3rd prompt
            sw.WriteLine("y");

            //response for 4th prompt
            //sw.WriteLine("y");
            sw.WriteLine("");
        }

        //waits until the process is finished before continuing
        p.WaitForExit();
    }
}

选项2

注意:响应被放入List中,然后使用foreach循环写入StandardInput

private void RunProcess(string exeFilename)
{
    ProcessStartInfo startInfo = new ProcessStartInfo()
    {
        CreateNoWindow = true,
        FileName = exeFilename,
        RedirectStandardError = true,
        RedirectStandardInput = true,
        RedirectStandardOutput = true,
        UseShellExecute = false,
        WindowStyle = ProcessWindowStyle.Hidden
    };

    using (Process p = new Process() { StartInfo = startInfo, EnableRaisingEvents = true })
    {
        //subscribe to event and add event handler code
        p.ErrorDataReceived += (sender, e) =>
        {
            if (!String.IsNullOrEmpty(e.Data))
            {
                //ToDo: add desired code 
                Debug.WriteLine("Error: " + e.Data);
            }
        };

        //subscribe to event and add event handler code
        p.OutputDataReceived += (sender, e) =>
        {
            if (!String.IsNullOrEmpty(e.Data))
            {
                //ToDo: add desired code
                Debug.WriteLine("Output: " + e.Data);
            }
        };

        //start
        p.Start();

        p.BeginErrorReadLine(); //begin async reading for standard error
        p.BeginOutputReadLine(); //begin async reading for standard output
        
        using (StreamWriter sw = p.StandardInput)
        {
            //provide values for each input prompt
            //ToDo: add values for each input prompt 
            List<string> responses = new List<string>() { @"c:\Temp\Test.txt", "n", "y", string.Empty };

            foreach (string resp in responses)
            {
                sw.WriteLine(resp);
            }
        }

        //waits until the process is finished before continuing
        p.WaitForExit();
    }
}

选项3

注意:此选项使用Task(或Thread)从StandardOutput读取。这允许人们读取不以换行符结尾的StandardOutput,以及包含换行符的输出。如果 .exe 文件的输出不以换行符结尾,请尝试此选项以查看它是否提供所需的输出。

private CancellationTokenSource _tokenSource;
private CancellationToken _token;

              ...

private async void ReadStandardOutput(Stream s, CancellationToken token)
{
    int bufferSize = 1024;

    int totalBytesRead = 0;

    while(true)
    {
        if (token.IsCancellationRequested)
            return;

        byte[] buffer = new byte[bufferSize];

        int bytesRead = await s.ReadAsync(buffer, 0, bufferSize, token);

        //add
        totalBytesRead += bytesRead;

        if (bytesRead > 0)
        {
            //convert to string
            string output = Encoding.ASCII.GetString(buffer, 0, bytesRead).Trim();
            //Debug.WriteLine($"StandardOutput: '{output}'");
            Debug.WriteLine($"{output}");
        }
    }    
}

private void RunProcess(string exeFilename)
{
    //create new instance
    _tokenSource = new CancellationTokenSource();

    //create reference
    _token = _tokenSource.Token; 

    ProcessStartInfo startInfo = new ProcessStartInfo()
    {
        CreateNoWindow = true,
        FileName = exeFilename,
        RedirectStandardError = true,
        RedirectStandardInput = true,
        RedirectStandardOutput = true,
        UseShellExecute = false,
        WindowStyle = ProcessWindowStyle.Hidden
    };

    using (Process p = new Process() { StartInfo = startInfo, EnableRaisingEvents = true })
    {
        //subscribe to event and add event handler code
        p.ErrorDataReceived += (sender, e) =>
        {
            if (!String.IsNullOrEmpty(e.Data))
            {
                //ToDo: add desired code 
                Debug.WriteLine("Error: " + e.Data);
            }
        };

        p.Exited += (sender, e) =>
        {
            //cancel reading from StandardOutput
            _tokenSource.Cancel();

            Debug.WriteLine("Process has exited.");
        };
       

        //start
        p.Start();

        p.BeginErrorReadLine(); //begin async reading for standard error

        Task.Factory.StartNew(() => ReadStandardOutput(p.StandardOutput.BaseStream, _token));

        //Thread t = new Thread(() => ReadStandardOutput(p.StandardOutput.BaseStream, _token)) { IsBackground = true };
        //t.Start();

        //sleep to allow time for task/thread to start
        System.Threading.Thread.Sleep(200);

        using (StreamWriter sw = p.StandardInput)
        {
            //provide values for each input prompt
            //ToDo: add values for each input prompt 
            List<string> responses = new List<string>() { @"c:\Temp\Test.txt", "n", "y", string.Empty };

            foreach (string resp in responses)
            {
                sw.WriteLine(resp);
                //System.Threading.Thread.Sleep(200);
            }
        }

        //waits until the process is finished before continuing
        p.WaitForExit();

        Debug.WriteLine("After p.WaitForExit");
    }
}


用法

RunProcess(@"C:\Temp\ConsoleInputTest.exe");

为了测试,我创建了一个 控制台应用程序(.NET Framework)(名称:ConsoleInputTest)

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace ConsoleInputTest
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Dictionary<string, string> flagsDict = null;

            if (args.Length != 0)
            {
                //get command-line args and put them in a Dictionary
                 flagsDict = GetCommandLineArgs(args);
            }
            else
            {
                //create new instance
                flagsDict = new Dictionary<string, string>();

                string filename = string.Empty;

                do
                {
                    //prompt user
                    Console.Write("Please enter filename: ");

                    //read input
                    filename = Console.ReadLine();

                    if (!File.Exists(filename))
                        Console.Error.WriteLine($"File doesn't exist ('{filename}'). ");

                } while (!File.Exists(filename));

                flagsDict.Add("filename", filename);

                string prompt2 = GetYesNoAnswer("Prompt2 - For testing, please enter 'n' for this prompt (default: y)");
                flagsDict.Add("prompt2", prompt2);

                string prompt3 = GetYesNoAnswer("Prompt3 - For testing, please press enter or enter 'y' for this prompt (default: y)");
                flagsDict.Add("prompt3", prompt3);

                string prompt4 = GetYesNoAnswer("Prompt4 - For testing, please press enter or enter 'y' for this prompt (default: y)");
                flagsDict.Add("prompt4", prompt4);
            }

            if (flagsDict != null)
            {
                //for testing, output arguments/input and values
                foreach (KeyValuePair<string, string> kvp in flagsDict)
                {
                    Console.WriteLine($"{kvp.Key}: {kvp.Value}");
                }
            }
            
        }

        private static string GetYesNoAnswer(string message)
        {
            string result = string.Empty;

            do
            {
                Console.Write($"{message}: ");
                result = Console.ReadLine();

                if (String.IsNullOrWhiteSpace(result))
                    result = "y";

                if (result.ToLower() != "y" && result.ToLower() != "yes" && result.ToLower() != "n" && result.ToLower() != "no")
                    Console.Error.WriteLine("Invalid response. ");

            } while (result.ToLower() != "y" && result.ToLower() != "yes" && result.ToLower() != "n" && result.ToLower() != "no");

            return result;
        }

        private static void DisplayUsage()
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat($"{Environment.NewLine}");

            sb.AppendFormat($"  Usage 1:{Environment.NewLine}");
            sb.AppendFormat($"  {System.Reflection.Assembly.GetExecutingAssembly().GetName().Name}.exe{Environment.NewLine}");

            sb.AppendFormat($"{Environment.NewLine}");

            sb.AppendFormat($"  Usage 2:{Environment.NewLine}");
            sb.AppendFormat($"  {System.Reflection.Assembly.GetExecutingAssembly().GetName().Name}.exe <flag> <value>{Environment.NewLine}");

            sb.AppendFormat($"{Environment.NewLine}");

            sb.AppendFormat($"  Flags: {Environment.NewLine}");

            sb.AppendFormat($"{Environment.NewLine}");

            sb.AppendFormat($@"  -filename: <filename> (ex: -filename: ""C:\My Folder\filename1.txt"") {Environment.NewLine}");

            sb.AppendFormat($@"  -prompt2: [y|n] (ex: -prompt2: n) {Environment.NewLine}");
            sb.AppendFormat($@"  -prompt3: [y|n] (ex: -prompt3: y) {Environment.NewLine}");
            sb.AppendFormat($@"  -prompt4: [y|n] (ex: -prompt4: y) {Environment.NewLine}");

            Console.WriteLine(sb.ToString());
        }

        private static Dictionary<string, string> GetCommandLineArgs(string[] args)
        {
            Dictionary<string, string> flagsDict = new Dictionary<string, string>();
            string currentFlag = string.Empty;

            //the following retrieves the command-line arguments
            //it handles values that contain spaces
            //such as 'C:\My Folder\filename1.exe'
            for (int i = 0; i < args.Length; i++)
            {
                //get flag
                //ex: '-f:'
                if (args[i].StartsWith("-"))
                {
                    //this keeps track of the current flag which
                    //is necessary in order to handle values that contain spaces

                    if (!args[i].EndsWith(":"))
                    {
                        //set value; if flag doesn't end with ':', add it
                        currentFlag = $"{args[i]}:";
                    }
                    else
                    {
                        //set value
                        currentFlag = args[i];
                    }

                    if (!flagsDict.ContainsKey(currentFlag))
                    {
                        //add to Dictionary
                        flagsDict.Add(currentFlag, string.Empty);
                    }
                    else
                    {
                        Console.Error.WriteLine($"Error: '{currentFlag}' already specified. A flag is only permitted to be specified once.");
                        Environment.Exit(-1);
                    }
                }
                else if (args[i] == "/?")
                {
                    DisplayUsage();
                }
                else
                {
                    //if no flag is specified, assume it's a filename
                    if (String.IsNullOrEmpty(currentFlag))
                    {
                        currentFlag = "-f:"; //filename 
                        flagsDict.Add(currentFlag, args[i]); //add to Dictionary
                    }
                    else if (flagsDict.ContainsKey(currentFlag))
                    {
                        if (!String.IsNullOrEmpty(flagsDict[currentFlag]))
                            flagsDict[currentFlag] += " "; //add space

                        flagsDict[currentFlag] += args[i]; //set or update value in Dictionary
                    }
                }
            }


            return flagsDict;
        }
    }
}

资源

© www.soinside.com 2019 - 2024. All rights reserved.