Loading

WPF-mvvm学习4 cmd运行与多线程通信

mvvm多线程通信 绑定 执行cmd 相关问题

情景

我想使用cmd调用yara 并实时获取执行结果 由于想要扫描的目录比较大 如果使用阻塞函数可能会被卡死

解决方案1 官方文档

https://docs.microsoft.com/en-us/windows/communitytoolkit/mvvm/observableobject

image-20220527131742873

很好 但是不适合我 似乎cmd在运行时等待输入会自动阻塞)

但是执行别的异步函数没问题

关于该解决方案的一个demo

private TaskNotifier<int> _count;
/// <summary>
/// 任务属性绑定
/// </summary>
public Task<int> Count
{
    get => _count;
    set => SetPropertyAndNotifyOnCompletion(ref _count, value);
}
public ICommand RequestValueCmd { get; set; }

private async void RequestValue()
{
    await Task.Delay(5000);
    Count = Task.Run(() =>
                     {
                         return 50;
                     });
}
<TextBlock Text="{Binding Count.Result, UpdateSourceTrigger=PropertyChanged}" />
<Button
        Command="{Binding RequestValueCmd}"
        Content="延时绑定" />

解决方案2

https://blog.csdn.net/fangyu723/article/details/118783975

使用他封装好的类


namespace CmdNameSpace
{
    
    public class Command
    {
        private const int _ReadSize = 1024;
        private Process _CMD;//cmd进程
        private Encoding _OutEncoding;//输出字符编码
        private Stream _OutStream;//基础输出流
        private Stream _ErrorStream;//错误输出流
        public event Action<string> Output;//输出事件
        public event Action<string> Error;//错误事件
        public event Action Exited;//退出事件
        private bool _Run;//循环控制
        private byte[] _TempBuffer;//临时缓冲
        private byte[] _ReadBuffer;//读取缓存区
        private byte[] _ETempBuffer;//临时缓冲
        private byte[] _ErrorBuffer;//错误读取缓存区
        public Command()
        {
            _CMD = new Process();
            _CMD.StartInfo.FileName = "cmd.exe";
            _CMD.StartInfo.UseShellExecute = false;//是否使用操作系统shell启动
            _CMD.StartInfo.RedirectStandardInput = true;//接受来自调用程序的输入信息
            _CMD.StartInfo.RedirectStandardOutput = true;//由调用程序获取输出信息
            _CMD.StartInfo.RedirectStandardError = true;//重定向标准错误输出
            _CMD.StartInfo.CreateNoWindow = true;//不显示程序窗口
            _CMD.Exited += _CMD_Exited;
            _ReadBuffer = new byte[_ReadSize];
            _ErrorBuffer = new byte[_ReadSize];
            ReStart();
        }

        /// <summary>
        /// 停止使用,关闭进程和循环线程
        /// </summary>
        public void Stop()
        {
            _Run = false;
            _CMD.Close();
        }
        /// <summary>
        /// 重新启用
        /// </summary>
        public void ReStart()
        {
            Stop();
            _CMD.Start();
            _OutEncoding = _CMD.StandardOutput.CurrentEncoding;
            _OutStream = _CMD.StandardOutput.BaseStream;
            _ErrorStream = _CMD.StandardError.BaseStream;
            _Run = true;
            _CMD.StandardInput.AutoFlush = true;
            ReadResult();
            ErrorResult();
        }
        //退出事件
        private void _CMD_Exited(object sender , EventArgs e)
        {
            Exited?.Invoke();
        }

        /// <summary>
        /// 执行cmd命令
        /// </summary>
        /// <param name="cmd">需要执行的命令</param>
        public void RunCMD(string cmd)
        {

            if (!_Run)
            {
                if (cmd.Trim().Equals("/restart" , StringComparison.CurrentCultureIgnoreCase))
                {
                    ReStart();
                }
                return;
            }
            if (_CMD.HasExited)
            {
                Stop();
                return;
            }
            _CMD.StandardInput.WriteLine(cmd);
        }



        //异步读取输出结果
        private void ReadResult()
        {
            if (!_Run)
            {
                return;
            }
            _OutStream.BeginRead(_ReadBuffer , 0 , _ReadSize , ReadEnd , null);
        }

        //一次异步读取结束
        private void ReadEnd(IAsyncResult ar)
        {
            int count = _OutStream.EndRead(ar);

            if (count < 1)
            {
                if (_CMD.HasExited)
                {
                    Stop();
                }
                return;
            }

            if (_TempBuffer == null)
            {
                _TempBuffer = new byte[count];
                Buffer.BlockCopy(_ReadBuffer , 0 , _TempBuffer , 0 , count);
            }
            else
            {
                byte[] buff = _TempBuffer;
                _TempBuffer = new byte[buff.Length + count];
                Buffer.BlockCopy(buff , 0 , _TempBuffer , 0 , buff.Length);
                Buffer.BlockCopy(_ReadBuffer , 0 , _TempBuffer , buff.Length , count);
            }

            if (count < _ReadSize)
            {
                string str = _OutEncoding.GetString(_TempBuffer);
                Output?.Invoke(str);
                _TempBuffer = null;
            }

            ReadResult();
        }


        //异步读取错误输出
        private void ErrorResult()
        {
            if (!_Run)
            {
                return;
            }
            _ErrorStream.BeginRead(_ErrorBuffer , 0 , _ReadSize , ErrorCallback , null);
        }

        private void ErrorCallback(IAsyncResult ar)
        {
            int count = _ErrorStream.EndRead(ar);

            if (count < 1)
            {
                if (_CMD.HasExited)
                {
                    Stop();
                }
                return;
            }

            if (_ETempBuffer == null)
            {
                _ETempBuffer = new byte[count];
                Buffer.BlockCopy(_ErrorBuffer , 0 , _ETempBuffer , 0 , count);
            }
            else
            {
                byte[] buff = _ETempBuffer;
                _ETempBuffer = new byte[buff.Length + count];
                Buffer.BlockCopy(buff , 0 , _ETempBuffer , 0 , buff.Length);
                Buffer.BlockCopy(_ErrorBuffer , 0 , _ETempBuffer , buff.Length , count);
            }

            if (count < _ReadSize)
            {
                string str = _OutEncoding.GetString(_ETempBuffer);
                Error?.Invoke(str);
                _ETempBuffer = null;
            }

            ErrorResult();
        }

        ~Command()
        {
            _Run = false;
            _CMD?.Close();
            _CMD?.Dispose();
        }

    }
}

调用

private async void ScanSingleFileExecute()
{
    fppath.Info = "";
    Command command = new Command();
    command.Output += Command_Output;
    //用Task避免发送命令太多堵塞
    
    _ = Task.Run(() =>
                 {
                     for (int i = 0 ; i < fppath.RuleList.Count ; i++)
                     {
                         string cmdString = currentpath + "\\yara\\yara64.exe " + fppath.RuleList[i] + " " + fppath.FilePath + " -r";
                         // string cmdString = "ipconfig";
                         command.RunCMD(cmdString);
                     }
                 });
}

private void Command_Output(string msg)
{	//或者对msg做些处理啥的再加
    fppath.test += msg;
}
<TextBox
         Grid.Row="2"
         Grid.Column="0"
         Margin="0,0,0,0"
         Text="{Binding fppath.test, Mode=OneWay, 				   UpdateSourceTrigger=PropertyChanged}" />

这样就实现了绑定到xaml 并实时更新返回值

image-20220527184118310

MVVM 跨线程更改数据源

 ThreadPool.QueueUserWorkItem(delegate
                {
                    System.Threading.SynchronizationContext.SetSynchronizationContext(new
                        System.Windows.Threading.DispatcherSynchronizationContext(System.Windows.Application.Current.Dispatcher));
                    System.Threading.SynchronizationContext.Current.Post(p1 =>
                    {
                       //代码
                    } , null);
                });

yara

yara是病毒匹配工具

先上help

YARA 4.2.0, the pattern matching swiss army knife.
Usage: yara [OPTION]... [NAMESPACE:]RULES_FILE... FILE | DIR | PID
Mandatory arguments to long options are mandatory for short options too.

       --atom-quality-table=FILE           path to a file with the atom quality table
  -C,  --compiled-rules                    load compiled rules
  -c,  --count                             print only number of matches
  -d,  --define=VAR=VALUE                  define external variable
       --fail-on-warnings                  fail on warnings
  -f,  --fast-scan                         fast matching mode
  -h,  --help                              show this help and exit
  -i,  --identifier=IDENTIFIER             print only rules named IDENTIFIER
       --max-process-memory-chunk=NUMBER   set maximum chunk size while reading process memory (default=1073741824)
  -l,  --max-rules=NUMBER                  abort scanning after matching a NUMBER of rules
       --max-strings-per-rule=NUMBER       set maximum number of strings per rule (default=10000)
  -x,  --module-data=MODULE=FILE           pass FILE's content as extra data to MODULE
  -n,  --negate                            print only not satisfied rules (negate)
  -N,  --no-follow-symlinks                do not follow symlinks when scanning
  -w,  --no-warnings                       disable warnings
  -m,  --print-meta                        print metadata
  -D,  --print-module-data                 print module data
  -e,  --print-namespace                   print rules' namespace
  -S,  --print-stats                       print rules' statistics
  -s,  --print-strings                     print matching strings
  -L,  --print-string-length               print length of matched strings
  -g,  --print-tags                        print tags
  -r,  --recursive                         recursively search directories
       --scan-list                         scan files listed in FILE, one per line
  -z,  --skip-larger=NUMBER                skip files larger than the given size when scanning a directory
  -k,  --stack-size=SLOTS                  set maximum stack size (default=16384)
  -t,  --tag=TAG                           print only rules tagged as TAG
  -p,  --threads=NUMBER                    use the specified NUMBER of threads to scan a directory
  -a,  --timeout=SECONDS                   abort scanning after the given number of SECONDS
  -v,  --version                           show version information

Send bug reports and suggestions to: vmalvarez@virustotal.com.

img

img

简单使用yara yourrules.yar testfile来检测

使用yarac yourrule compilerule来编译规则以加快检测速度

posted @ 2022-07-12 23:09  FW_ltlly  阅读(285)  评论(0编辑  收藏  举报