OpenFileDialog默认路径

时间:2012-04-02 16:37:35

标签: c#

using (var openFileDialog1 = new OpenFileDialog())
        {
            openFileDialog1.Reset();
            if (!string.IsNullOrEmpty(ExcelFilePath))
            {
                string fileName = Path.GetFileName(ExcelFilePath);
                string fileExt = Path.GetExtension(ExcelFilePath);
                //Avoid "you can't open this location using this program file" dialog 
                //if there is a file name in the path strip it )
                if (!string.IsNullOrEmpty(fileName))
                    initialDirectory = Path.GetDirectoryName(ExcelFilePath);  
      //if not let it be   
                else
                    initialDirectory = ExcelFilePath;

            openFileDialog1.InitialDirectory = initialDirectory;
            }
            else
                openFileDialog1.InitialDirectory = "c:\\";
            openFileDialog1.Filter = "Excel files (*.xls or *.xlsx)|*.xls;*.xlsx";
            //openFileDialog1.Filter = "xls files (*.xls)|*.xls|xlsx files(*.xlsx)|.xlsx";
            openFileDialog1.FilterIndex = 2;
            openFileDialog1.RestoreDirectory = false;
            openFileDialog1.CheckFileExists = true;
            openFileDialog1.CheckPathExists = true;
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                var browseSelectionMade = BrowseSelectionMade;
                if (browseSelectionMade!=null)
                    browseSelectionMade(this, new DataEventArgs<string>(openFileDialog1.FileName));
            }
        }

无论我是否将RestoreDirectory设置为true,如果我的初始目录设置为不存在的路径,我将始终浏览到LAST used目录。 OpenFileDialog保存的最后一个使用目录在哪里?有没有办法来覆盖这种行为? (例如,我总是想将它设置为C:\,如果初始目录不存在?)

8 个答案:

答案 0 :(得分:34)

您似乎需要做的就是:

string path; // this is the path that you are checking.
if(Directory.Exists(path)) {
    openFileDialog1.InitialDirectory = path;
} else {
    openFileDialog1.InitialDirectory = @"C:\";
} 

除非我遗漏了一些东西。

答案 1 :(得分:16)

  

上次使用的目录保存在哪里?

它存储在注册表中。具体位置取决于Windows版本,对于Win7,它是HKEY_CURRENT_USER \ Software \ Microsoft \ Windows \ CurrentVersion \ Explorer \ ComDlg32。快速查看注册表应该说服您想要搞砸它。

简单的解决方法是提供有效的路径。如果您计算的那个无效,则Directory.Exists返回false,然后提供有效的。与Environment.GetFolderPath()返回的Documents文件夹一样。再说一次,上次使用的也没有任何问题,用户很容易认出它,恰好接近所需的几率。

答案 2 :(得分:4)

我认为没有内置任何内容。在打开对话框之前检查一下:

if (!Directory.Exists(initialDirectory))
{
    openFileDialog1.InitialDirectory = @"C:\";
}

答案 3 :(得分:2)

检查ExcelFilePath是否存在,检查它是否为null或空,但是如果在块之前检查目录是否存在,如果它没有将值重置为空字符串,则应该检查是金色的。

(是的,你需要先应用你的文件名逻辑等)但是一旦你解析了所有这些,那么确定目录是否退出是微不足道的

if (!Directory.Exists(excelPath))
{
    ExcelFilePath = String.Empty;
}

答案 4 :(得分:2)

另外,要设置默认扩展名,您应该设置FilterIndex属性而不是DefaultExt。见:https://stackoverflow.com/a/6104319/381082

这是一篇关于C#中OpenFileDialog的好文章:http://www.c-sharpcorner.com/uploadfile/mahesh/openfiledialog-in-C-Sharp/

答案 5 :(得分:1)

编辑:在与一个知识渊博的朋友协商之后,事后看来,更好的解决方案是显而易见的。只需将您自己的注册表项存储在HKEY_CURRENT_USER \ SOFTWARE \ YourCompanyOrAppName \ Whatevs或类似的文件中(不确定最佳实践,或者您具有读/写访问权限的文件夹,请自行进行研究),然后完全避免该问题。只需让用户导航到他们想要的位置一次,然后将路径存储在注册表中(作为普通字符串,而不是PIDL),然后下次检索该路径。作为参考,请参见Registry和RegistryKey类上的MSDN文章,以及RegistryKey / Methods / SetValue文章中的示例。尽管如此,出于好奇心还是如果某人有一个非常具体的问题并且需要此解决方案,我将保留此职位。一如既往,祝你好运!

对于将来在这里徘徊的任何可怜的灵魂,看来我已经弄清楚了如何找到上次使用的目录。如前所述,它存储在注册表中,更具体地说,存储在HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSavePidlMRU\中 这是每个文件扩展名的一组文件夹,其中包括用于未知文件扩展名的“ *”。我将对txt文件执行此操作,并根据需要更改路径。要访问此路径,我们创建一个RegistryKey并调用OpenSubKey(BTW,下面的完整代码)

string RegistryPath = @"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\OpenSavePidlMRU\\txt";
RegistryKey rk = Registry.CurrentUser.OpenSubKey(RegistryPath);

这是一组条目,所有条目都包含最后打开或保存的项目的PIDL(我们将转到该内容)。 请注意:文件夹名称OpenSavePidlMRU,我已经看到它叫OpenSaveMRU,而且似乎适用于Win 10之前的版本。 同样在这里还有一个名为“ MRUListEx”的条目,MRU代表“最近使用过的”。在此项中,是最近使用过的项目的索引。因此,如果我有10个条目(名为0到9),而最后一个使用9,则MRUListEx中的第一个字节将为0x09。因此:

byte[] mrulistex = (byte[])rk.GetValue("MRUListEx");
byte Last = mrulistex[0];

最后将等于0x09(在我的系统上) 然后,我们再次调用GetValue,但需要输入该条目

byte[] LastPathByteArray = (byte[])rk.GetValue(Last.ToString());

这就是问题所在,因为它不会返回一个字节数组,每个字节都是我们文件路径中的一个字符,它将返回称为PIDL的字节数组。虽然字节数组似乎包含char和wide char中的路径,但它还包含一堆乱码,这些不容易被转换。 我不会假装理解它,但是https://stackoverflow.com/a/4318663提供了一种将其转换为字符串的方法。 (请参见下面的代码)

string LastPath = GetPathFromPIDL(LastPathByteArray);

我们完成了。请注意,这不一定代表一个好的解决方案,但是在半小时的挖掘过程中,我找不到很多官方文档。显然,此代码不会检查注册表路径是否正确,注册表项是否存在,或者根本不执行任何错误检查,但这至少可以正常工作。

using Microsoft.Win32; //for the registry class
using System.Runtime.InteropServices; //for converting the PIDL

//GetPathFromPIDL from matt.schechtman at https://stackoverflow.com/a/4318663
[DllImport("shell32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SHGetPathFromIDListW(IntPtr pidl, MarshalAs(UnmanagedType.LPTStr)] StringBuilder pszPath);
private string GetPathFromPIDL(byte[] byteCode)
{
    //MAX_PATH = 260
    StringBuilder builder = new StringBuilder(260);

    IntPtr ptr = IntPtr.Zero;
    GCHandle h0 = GCHandle.Alloc(byteCode, GCHandleType.Pinned);
    try
    {
        ptr = h0.AddrOfPinnedObject();
    }
    finally
    {
        h0.Free();
    }

    SHGetPathFromIDListW(ptr, builder);

    return builder.ToString();
}

public void OnClick_Button_OpenFile(object sender, RoutedEventArgs e)
{
    string RegistryPath = @"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\OpenSavePidlMRU\\txt";
    RegistryKey rk = Registry.CurrentUser.OpenSubKey(RegistryPath);
    byte[] mrulistex = (byte[])rk.GetValue("MRUListEx");
    byte Last = mrulistex[0];
    byte[] LastPathByteArray = (byte[])rk.GetValue(Last.ToString());
    string LastPath = GetPathFromPIDL(LastPathByteArray);

    // Configure open file dialog box
    Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();`
    dlg.InitialDirectory = LastPath;
    result = dlg.ShowDialog();
    if (result == true)
    {
        string filename = dlg.FileName;
    }
    //etc etc, rest of your code
}

祝你好运。

答案 6 :(得分:0)

如果您使用存储在某个字符串中的文件名,最好使用Path来剪切文件名(在我的W10上,打开的对话框不会在初始目录中打开,如果我只提供文件名):

    if (!System.IO.Directory.Exists(filename))
    {
        openDlg.InitialDirectory =
            System.IO.Path.GetDirectoryName(filename);
    }

答案 7 :(得分:0)

为了将来我

记得这样做:

            try        
            {
                result = dialog.ShowDialog(Window);
            }
            catch
            {
                dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
                result = dialog.ShowDialog(Window);
            }

这有助于用户从位置打开文件时不再存在的情况(例如USB记忆棒,映射网络驱动器) - 如果InitialDirectory无效,ShowDialog会抛出异常。