当前位置:必发365电子游戏 > 操作系统 > 必发365电子游戏文件被别的进程占用,右键菜单接收
必发365电子游戏文件被别的进程占用,右键菜单接收
2019-12-19

本身集团眼下升高程序经常报出更新失败难点,究其原因,原本是翻新时,他们恐怕又开垦了正在被更新的文书,招致改正文件时,文件被其余进程占用,无法平常更新而报错,为了消释这几个主题素材,作者花了17日时间查询多方资料及钻探,终于找到了四个询问进度的利器:handle.exe,下载地址:,笔者是透过它来找到被占用的长河,然后KILL掉占用进度,最终再来更新,那样就到家的搞定了更新时文件被侵夺报错的难点了,实现情势非常轻松,小编上边都有列出首要的法子,一些注意事项作者也都有认证,咱们生机勃勃看就掌握了,当然即便大家有越来越好的方案,接待交换,多谢!

假若使.exe程序在系统运营后自动运维

IsFileUsing:判定文件是或不是被占用

 

        [DllImport("kernel32.dll")]
        public static extern IntPtr _lopen(string lpPathName, int iReadWrite);

        [DllImport("kernel32.dll")]
        public static extern bool CloseHandle(IntPtr hObject);

        public const int OF_READWRITE = 2;
        public const int OF_SHARE_DENY_NONE = 0x40;
        public readonly IntPtr HFILE_ERROR = new IntPtr(-1);
        private bool IsFileUsing(string filePath)
        {
            if (!File.Exists(filePath))
            {
                return false;
            }
            IntPtr vHandle = _lopen(filePath, OF_READWRITE | OF_SHARE_DENY_NONE);
            if (vHandle == HFILE_ERROR)
            {
                return true;
            }
            CloseHandle(vHandle);
            return false;
        }

Java代码  

GetRunProcessInfos:获取钦命文件或目录中存在的(关联的卡塔尔(قطر‎运转进度音讯,以便前面能够打消占用

方法一:  

        /// <summary>
        /// 获取指定文件或目录中存在的(关联的)运行进程信息,以便后面可以解除占用
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        private Dictionary<int, string> GetRunProcessInfos(string filePath)
        {

            Dictionary<int, string> runProcInfos = new Dictionary<int, string>();
            string fileName = Path.GetFileName(filePath);
            var fileRunProcs = Process.GetProcessesByName(fileName);
            if (fileRunProcs != null && fileRunProcs.Count() > 0)
            {
                runProcInfos = fileRunProcs.ToDictionary(p => p.Id, p => p.ProcessName);
                return runProcInfos;
            }

            string fileDirName = Path.GetDirectoryName(filePath); //查询指定路径下的运行的进程
            Process startProcess = new Process();
            startProcess.StartInfo.FileName = RelaseAndGetHandleExePath();
            startProcess.StartInfo.Arguments = string.Format(""{0}"", fileDirName);
            startProcess.StartInfo.UseShellExecute = false;
            startProcess.StartInfo.RedirectStandardInput = false;
            startProcess.StartInfo.RedirectStandardOutput = true;
            startProcess.StartInfo.CreateNoWindow = true;
            startProcess.StartInfo.StandardOutputEncoding = ASCIIEncoding.UTF8;
            startProcess.OutputDataReceived += (sender, e) =>
            {
                if (!string.IsNullOrEmpty(e.Data) && e.Data.IndexOf("pid:", StringComparison.OrdinalIgnoreCase) > 0)
                {
                    //var regex = new System.Text.RegularExpressions.Regex(@"(^[w.?u4E00-u9FA5]+)s+pid:s*(d+)", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                    var regex = new System.Text.RegularExpressions.Regex(@"(^.+(?=pid:))bpid:s+(d+)s+", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                    if (regex.IsMatch(e.Data))
                    {
                        var mathedResult = regex.Match(e.Data);

                        int procId = int.Parse(mathedResult.Groups[2].Value);
                        string procFileName = mathedResult.Groups[1].Value.Trim();

                        if ("explorer.exe".Equals(procFileName, StringComparison.OrdinalIgnoreCase))
                        {
                            return;
                        }

                        //var regex2 = new System.Text.RegularExpressions.Regex(string.Format(@"b{0}.*$", fileDirName.Replace(@"", @"\").Replace("?",@"?")), System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                        var regex2 = new System.Text.RegularExpressions.Regex(@"bw{1}:.+$", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                        string procFilePath = (regex2.Match(e.Data).Value ?? "").Trim();

                        if (filePath.Equals(procFilePath, StringComparison.OrdinalIgnoreCase) || filePath.Equals(PathJoin(procFilePath, procFileName), StringComparison.OrdinalIgnoreCase))
                        {
                            runProcInfos[procId] = procFileName;
                        }
                        else //如果乱码,则进行特殊的比对
                        {
                            if (procFilePath.Contains("?") || procFileName.Contains("?")) //?乱码比对逻辑
                            {
                                var regex3 = new System.Text.RegularExpressions.Regex(procFilePath.Replace(@"", @"\").Replace(".", @".").Replace("?", ".{1}"), System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                                if (regex3.IsMatch(filePath))
                                {
                                    runProcInfos[procId] = procFileName;
                                }
                                else
                                {
                                    string tempProcFilePath = PathJoin(procFilePath, procFileName);

                                    regex3 = new System.Text.RegularExpressions.Regex(tempProcFilePath.Replace(@"", @"\").Replace(".", @".").Replace("?", ".{1}"), System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                                    if (regex3.IsMatch(filePath))
                                    {
                                        runProcInfos[procId] = procFileName;
                                    }
                                }
                            }
                            else if (procFilePath.Length == filePath.Length || PathJoin(procFilePath, procFileName).Length == filePath.Length) //其它乱码比对逻辑,仅比对长度,如果相同交由用户判断
                            {
                                if (MessageBox.Show(string.Format("发现文件:{0}可能被一个进程({1})占用,n您是否需要强制终止该进程?", filePath, procFileName), "发现疑似被占用进程", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
                                {
                                    runProcInfos[procId] = procFileName;
                                }
                            }
                        }
                    }
                }
            };

            startProcess.Start();
            startProcess.BeginOutputReadLine();
            startProcess.WaitForExit();

            return runProcInfos;
        }

将.exe程序增加到“以前菜单”---“全数程序”--“运维”里面。  

上述代码逻辑简要表明:创立叁个建程来运维handle.exe(以资源情势内嵌到项目中),然后异步选取重临数据,并透过正则表达式来合作拿到进度数据,由于handle.exe对于华语路线或文件名宽容不好,再次来到的数据存在?或其余乱码字符,故作者作了意气风发部分异样的模糊相配逻辑;

 

RelaseAndGetHandleExePath:从类型中放出handle.exe并保留到系统的应用软件Data目录下,以便后续直接能够使用(注意:由于handle.exe必要授权同意后才干健康的利用该工具,故作者在第三遍生成handle.exe时,会一向运行进度,让客户接受Agree后再去进行末端的逻辑管理,那样虽能一蹴即至难点,但有些不太融洽,方今七个是中文乱码、三个是必要同意技巧运用handle.exe作者觉着蓬蓬勃勃旦微软解决了大概会更加好)

主意如下:  

        private string RelaseAndGetHandleExePath()
        {
            var handleInfo = new FileInfo(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\SysUpdate\handle.exe");
            if (!File.Exists(handleInfo.FullName))
            {
                if (!Directory.Exists(handleInfo.DirectoryName))
                {
                    Directory.CreateDirectory(handleInfo.DirectoryName);
                }

                byte[] handleExeData = Properties.Resources.handle;
                File.WriteAllBytes(handleInfo.FullName, handleExeData);

                var handleProc = Process.Start(handleInfo.FullName);//若第一次,则弹出提示框,需要点击agree同意才行
                handleProc.WaitForExit();
            }

            return handleInfo.FullName;
        }

  1、选中.exe程序,右键菜单选用“发送到”----“桌面飞快格局”。  

必发365电子游戏,PathJoin:拼接路线(可是滤特殊字符),由于handle.exe对于华语路线或文件名包容倒霉,再次来到的数量存在?或别的乱码字符,如查接收:Path.Combine方法规会报错,故这里自定义壹个主意,只是简单的拼接

  2、右键“运行”,接收菜单的“浏览全体顾客”。  

        /// <summary>
        /// 拼接路径(不过滤殊字符)
        /// </summary>
        /// <param name="paths"></param>
        /// <returns></returns>
        private string PathJoin(params string[] paths)
        {
            if (paths == null || paths.Length <= 0)
            {
                return string.Empty;
            }

            string newPath = paths[0];

            for (int i = 1; i < paths.Length; i++)
            {
                if (!newPath.EndsWith("\"))
                {
                    newPath += "\";
                }

                if (paths[i].StartsWith("\"))
                {
                    paths[i] = paths[i].Substring(1);
                }

                newPath += paths[i];
            }

            return newPath;
        }

  3、将桌面快捷格局拖动到“运行”窗口侧面“运转”下边就可以。  

CloseProcessWithFile:大旨措施,关闭钦点文件被吞噬的长河,上述全数的章程均是为了达成该办法的功用

  www.2cto.com  

        private void CloseProcessWithFile(string filePath)
        {
            if (!IsFileUsing(filePath)) return;

            ShowDownInfo(string.Format("正在尝试解除占用文件 {0}", _FilePaths[_FileIndex]));

            var runProcInfos = GetRunProcessInfos(filePath); //获取被占用的进程


            System.IO.File.WriteAllText(Path.Combine(Application.StartupPath, "runProcInfos.txt"), string.Join("rn", runProcInfos.Select(p => string.Format("ProdId:{0},ProcName:{1}", p.Key, p.Value)).ToArray()));//DEBUG用,正式发布时可以去掉

            var localProcesses = Process.GetProcesses();
            bool hasKilled = false;
            foreach (var item in runProcInfos)
            {
                if (item.Key != currentProcessId) //排除当前进程
                {
                    var runProcess = localProcesses.SingleOrDefault(p => p.Id == item.Key);
                    //var runProcess = Process.GetProcessById(item.Key);
                    if (runProcess != null)
                    {
                        try
                        {
                            runProcess.Kill(); //强制关闭被占用的进程
                            hasKilled = true;
                        }
                        catch
                        { }
                    }
                }
            }

            if (hasKilled)
            {
                Thread.Sleep(500);
            }
        }

方法二:  

上述代码逻辑简要表明:先决断是或不是被占用,若被攻克,则得到该文件被并吞的经过列表,然后拿走一下脚下操作系统的全数进度列表,最终通过进程ID查询获得消灭当前先后自身的进程ID(currentProcessId

Process.GetCurrentProcess(卡塔尔国.Id)列表,若能拿到获得,注脚进度仍在运营,则抑遏结束该进度,完成排除文件占用

只顾:KILL掉占用进度后,大概由于缓存原因,若一直开展文件的覆盖与替换或转变操作,只怕仍会报错,故这里作了叁个推断,若有成功KILL掉进度,则需等待500MS再去做立异文件之类的操作;

修正注册表,将.exe程序加多到msconfig程序的“运营”选项卡。  

措施如下:  

1、新建“GPS.reg”文件。  

2、输入如下内容:  

Windows Registry Editor Version 5.00  

  

[HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRun]  

"GPS"=""C:\Program Files\GPS\GPS.exe" 1"  

  www.2cto.com  

3、保存文件,双击该文件导入注册表文件就能够。  

必发365电子游戏文件被别的进程占用,右键菜单接收。也足以,通过regedit命令步入注册表,找到HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRun,新建字符串项,名为GPS,值为“C:\Program Files\GPS\GPS.exe” 1。  

  

msconfig的“运营”选项卡里面程序的注册表消息保存在HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRun下面。  

Java代码 方法生机勃勃: 将.exe程序加多到早先菜单---全数程序--运转内部。 方法如下: 1、选中.exe程序,右...