Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c#wpf SaveFileDialog即使在内部也会崩溃Try..Catch_C#_Wpf - Fatal编程技术网

c#wpf SaveFileDialog即使在内部也会崩溃Try..Catch

c#wpf SaveFileDialog即使在内部也会崩溃Try..Catch,c#,wpf,C#,Wpf,我有一个WPF应用程序,其中我使用了一个SaveFileDialog。 流程如下: 1-用户使用SaveFileDialog选择文件名并关闭对话框 2-应用程序尝试写入文件 3-尝试写入文件时,如果文件被锁定,将引发IOException 4-如果我再次尝试打开SaveFileDialog,应用程序将崩溃,并在ntdll.dll上显示“堆已损坏” 我想不出一个解决办法。即使在一次尝试中,也会发现应用程序崩溃 SaveFileDialog的代码 try{ Dispatcher.BeginI

我有一个WPF应用程序,其中我使用了一个SaveFileDialog。 流程如下:

1-用户使用SaveFileDialog选择文件名并关闭对话框

2-应用程序尝试写入文件

3-尝试写入文件时,如果文件被锁定,将引发IOException

4-如果我再次尝试打开SaveFileDialog,应用程序将崩溃,并在ntdll.dll上显示“堆已损坏”

我想不出一个解决办法。即使在一次尝试中,也会发现应用程序崩溃

SaveFileDialog的代码

try{
    Dispatcher.BeginInvoke(new Action(() =>
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Reset();

            sfd.AddExtension = true;
            sfd.CheckFileExists = false;
            sfd.CheckPathExists = true;
            sfd.CreatePrompt = false;
            sfd.OverwritePrompt = true;
            sfd.DefaultExt = defaultExt;
            sfd.Filter = filter;
            sfd.Title = "Save As " + fileTypeDisplay;
            sfd.InitialDirectory = specialFolder;
            sfd.FileName = newFileNameNoExt;
            sfd.FilterIndex = 1;


            if (!string.IsNullOrEmpty(specialFolder))
            {
                FileDialogCustomPlace cp = new FileDialogCustomPlace(specialFolder);  // does not throw exceptions
                sfd.CustomPlaces.Add(cp);
            }
            try
            {
                if (sfd.ShowDialog(MyMainWindow) == true) //<-- ERROR HERE
                {
                    fileToSave = sfd.FileName;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                sfd = null;
            }
        })).Wait();
}
catch(exception ex)
{
...log exception...
}
试试看{
Dispatcher.BeginInvoke(新操作(()=>
{
SaveFileDialog sfd=新建SaveFileDialog();
sfd.Reset();
sfd.AddExtension=真;
sfd.CheckFileExists=false;
sfd.CheckPathExists=true;
sfd.CreatePrompt=false;
sfd.OverwritePrompt=true;
sfd.DefaultExt=DefaultExt;
sfd.过滤器=过滤器;
sfd.Title=“另存为”+文件类型显示;
sfd.InitialDirectory=specialFolder;
sfd.FileName=新文件名noext;
sfd.FilterIndex=1;
如果(!string.IsNullOrEmpty(specialFolder))
{
FileDialogCustomPlace cp=新建FileDialogCustomPlace(specialFolder);//不引发异常
sfd.CustomPlaces.Add(cp);
}
尝试
{

如果(sfd.ShowDialog(MyMainWindow)==true)/这不是答案,而是我如何解决崩溃的。这是很久以前的遗留代码,线索是崩溃总是在异常之后发生。但是为什么异常会导致SaveFileDialog出现问题并导致应用程序崩溃

深入了解我学到的代码,下面的代码是在用户在SaveFileDialog上选择文件后执行的

注意对catch块中的方法另一个用户islockingpkg的调用

当我注释掉对该方法的调用时,对该问题的SaveFileDialog.ShowDialog()的调用停止,以使应用程序崩溃。我将尝试按照其他建议查看其行为

如果有人知道为什么会发生这种情况,欢迎发表评论

FileStream strm = null;
try
{
    strm = fi.Open(FileMode.Open, forFileAccessMode, fileShare);
}
catch (IOException) // the file is already open
{
    ...

    fiuEx.IsByOtherUser = AnotherUserIsLockingPkg(filePath);

    ...
}
catch (Exception ex) 
{
    ...
}
finally
{
    ....
}
下面的代码用于检查文件是否被其他应用程序锁定。它使用了一些API调用。看起来此代码是从

下面列出了AnotherUserIsLockingPkg的方法

#region Check if another user's process is locking a pkg

[StructLayout(LayoutKind.Sequential)]
private struct RM_UNIQUE_PROCESS
{
    public int dwProcessId;
    public System.Runtime.InteropServices.ComTypes.FILETIME ProcessStartTime;
}

private const int RmRebootReasonNone = 0;
private const int CCH_RM_MAX_APP_NAME = 255;
private const int CCH_RM_MAX_SVC_NAME = 63;

//private enum RM_APP_TYPE
//{
//    RmUnknownApp = 0,
//    RmMainWindow = 1,
//    RmOtherWindow = 2,
//    RmService = 3,
//    RmExplorer = 4,
//    RmConsole = 5,
//    RmCritical = 1000
//}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct RM_PROCESS_INFO
{
    public RM_UNIQUE_PROCESS Process;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_APP_NAME + 1)]
    public string strAppName;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_SVC_NAME + 1)]
    public string strServiceShortName;

    //public RM_APP_TYPE ApplicationType;
    public uint AppStatus;
    public uint TSSessionId;
    [MarshalAs(UnmanagedType.Bool)]
    public bool bRestartable;
}

[DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)]
private static extern int RmRegisterResources(uint pSessionHandle,
                                      UInt32 nFiles,
                                      string[] rgsFilenames,
                                      UInt32 nApplications,
                                      [In] RM_UNIQUE_PROCESS[] rgApplications,
                                      UInt32 nServices,
                                      string[] rgsServiceNames);

[DllImport("rstrtmgr.dll", CharSet = CharSet.Auto)]
private static extern int RmStartSession(out uint pSessionHandle, int dwSessionFlags, string strSessionKey);

[DllImport("rstrtmgr.dll")]
private static extern int RmEndSession(uint pSessionHandle);

[DllImport("rstrtmgr.dll")]
private static extern int RmGetList(uint dwSessionHandle,
                            out uint pnProcInfoNeeded,
                            ref uint pnProcInfo,
                            [In, Out] RM_PROCESS_INFO[] rgAffectedApps,
                            ref uint lpdwRebootReasons);


/// <summary>
/// Checks if a pkg has been locked by another user
/// </summary>
/// <param name="path">The pkg file path.</param>
/// <param name="includeCurrentUserProcesses">Check also for current user's processes</param>
/// <returns></returns>
public static bool AnotherUserIsLockingPkg(string path, bool includeCurrentUserProcesses = false)
{
    uint handle;
    string key = Guid.NewGuid().ToString();
    Process currentProcess = Process.GetCurrentProcess();

    int res = RmStartSession(out handle, 0, key);
    if (res != 0)
        throw new Exception("Could not begin restart session. Unable to determine file locker.");

    try
    {
        const int ERROR_MORE_DATA = 234;

        uint pnProcInfoNeeded = 0,
             pnProcInfo = 0,
             lpdwRebootReasons = RmRebootReasonNone;

        string[] resources = new string[] { path }; // Just checking on one resource.

        res = RmRegisterResources(handle, (uint)resources.Length, resources, 0, null, 0, null);

        if (res != 0)
            throw new Exception("Could not register resource.");

        //Note: there's a race condition here -- the first call to RmGetList() returns
        //      the total number of process. However, when we call RmGetList() again to get
        //      the actual processes this number may have increased.
        res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, null, ref lpdwRebootReasons);

        if (res == ERROR_MORE_DATA)
        {
            // Create an array to store the process results
            RM_PROCESS_INFO[] processInfo = new RM_PROCESS_INFO[pnProcInfoNeeded];
            pnProcInfo = pnProcInfoNeeded;

            // Get the list
            res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, processInfo, ref lpdwRebootReasons);
            //pnProcInfo contains all the processes that are using the pkg

            if (res == 0)
            {
                // Enumerate all of the results and check for waf3 process and not same session
                for (int i = 0; i < pnProcInfo; i++)
                {
                    try
                    {
                        if (includeCurrentUserProcesses)
                        {
                            if (processInfo[i].strAppName == currentProcess.ProcessName)
                                return true;
                        }
                        else
                        {
                            if (processInfo[i].strAppName == currentProcess.MainModule.ModuleName && processInfo[i].TSSessionId != currentProcess.SessionId)
                                return true;
                        }
                    }
                    // catch the error -- in case the process is no longer running
                    catch (ArgumentException)
                    { }
                }
            }
            else
                throw new Exception("Could not list processes locking resource.");
        }
        else if (res != 0)
            throw new Exception("Could not list processes locking resource. Failed to get size of result.");
    }
    finally
    {
        RmEndSession(handle);
    }

    return false;
}
#endregion
#区域检查其他用户的进程是否正在锁定pkg
[StructLayout(LayoutKind.Sequential)]
私有结构RM\u唯一\u进程
{
公共int-dwProcessId;
public System.Runtime.InteropServices.ComTypes.FILETIME ProcessStartTime;
}
private const int rmrebootorreasonone=0;
私有常数int CCH\U RM\U MAX\U APP\U NAME=255;
私有const int CCH_RM_MAX_SVC_NAME=63;
//私有枚举RM_应用程序_类型
//{
//RmUnknownApp=0,
//RmMainWindow=1,
//RmOtherWindow=2,
//RmService=3,
//RmExplorer=4,
//RmConsole=5,
//RmCritical=1000
//}
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)]
私有结构RM\u进程\u信息
{
公共RM_唯一的流程;
[Marshallas(UnmanagedType.ByValTStr,SizeConst=CCH\u RM\u MAX\u APP\u NAME+1)]
公共字符串名称;
[Marshallas(UnmanagedType.ByValTStr,SizeConst=CCH\u RM\u MAX\u SVC\u NAME+1)]
公共字符串strServiceShortName;
//公共RM_应用程序类型应用程序类型;
公共应用状态;
公共uint TSSessionId;
[Marshallas(UnmanagedType.Bool)]
公共布尔布尔表;
}
[DllImport(“rstrtmgr.dll”,CharSet=CharSet.Unicode)]
专用静态外部RmRegisterResources(uint pSessionHandle,
UInt32文件,
字符串[]rgsFilenames,
UInt32应用程序,
[在]RM_唯一_流程[]RGA应用程序中,
UInt32 N服务,
字符串[]rgsServiceNames);
[DllImport(“rstrtmgr.dll”,CharSet=CharSet.Auto)]
私有静态外部int-RmStartSession(out-uint-pSessionHandle、int-dwSessionFlags、字符串stressionkey);
[DllImport(“rstrtmgr.dll”)]
私有静态外部内部RmEndSession(uint pSessionHandle);
[DllImport(“rstrtmgr.dll”)]
私有静态外部内部RmGetList(uint dwSessionHandle,
需要的输出单元pnprocinfo,
参考uint pnProcInfo,
[In,Out]RM_流程_信息[]rgAffectedApps,
参考单元LPDWREBOTREASOS);
/// 
///检查pkg是否已被其他用户锁定
/// 
///pkg文件路径。
///还要检查当前用户的进程
/// 
公共静态bool AnotherUserIsLockingPkg(字符串路径,bool includecurrentuserprocesss=false)
{
uint手柄;
字符串键=Guid.NewGuid().ToString();
Process currentProcess=Process.GetCurrentProcess();
int res=RmStartSession(输出句柄,0,键);
如果(res!=0)
抛出新异常(“无法开始重新启动会话。无法确定文件锁定程序。”);
尝试
{
const int ERROR\u MORE\u DATA=234;
uint pnProcInfoNeeded=0,
pnProcInfo=0,
lpdwRebootReasons=RmRebootReasonNone;
string[]resources=newstring[]{path};//只检查一个资源。
res=RmRegisterResources(handle,(uint)resources.Length,resources,0,null,0,null);
如果(res!=0)
抛出新异常(“无法注册资源”);
//注意:这里有一个竞争条件——对RmGetList()的第一个调用返回
//进程总数。但是,当我们再次调用RmGetList()以获取
//这一数字的实际进程可能有所增加。
res=RmGetList(handle,out pnProcInfoNeeded,ref pnProcInfo,null,ref lpdwrebootoreasons);
如果(res==错误\u更多\u数据)