【发布时间】:2012-01-19 11:39:55
【问题描述】:
我在 Windows 7 上使用 Winforms,在 Visual Studio 2010 中使用 C#。 目前在 Windows 7 中,安装和调试器都可以使用以下代码。但是,当程序安装在 Windows XP 中时,永远不会到达最后一行。
此代码从 MenuStrip 调用,然后传递给后续方法以根据在菜单中单击的项目执行操作。但是,这不是 SaveFileDialog 失败的唯一地方,它总是在 ShowDialog() 方法上失败。
MenuItem 的代码:
private void saveOnlyPlaylistToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
MainMenuClick(sender, e);
}
catch (Exception ex)
{
StackTrace st = new StackTrace();
string methodName = st.GetFrame(1).GetMethod().Name;
Logger.LogToFile("Failure in " + methodName + ": " + ex.Message);
}
}
失败的代码:
Logger.LogToFile("Entered Save Only Playlist.");
SaveFileDialog sfd = new SaveFileDialog();
string playlistSaveLocation = config["PlaylistLocation"];
if (!Directory.Exists(playlistSaveLocation))
Directory.CreateDirectory(playlistSaveLocation);
sfd.InitialDirectory = playlistSaveLocation;
sfd.Filter = "L Playlist (*.lpl)|*.lpl";
DialogResult result = sfd.ShowDialog();
Logger.LogToFile("Result of Dialog: " + result.ToString());
我不知道为什么最后一行没有被调用,感觉 SaveFileDialog 的 ShowDialog() 方法没有完成。之后程序继续正常运行,但不再与文件目录交互,无法创建新进程。
调试器中没有错误,事件日志也没有。我已经使用 Visual Studio 2010 在 Windows XP 上对其进行了重建,并且运行良好,该错误似乎仅在该程序在 Windows 7 中创建然后安装在 Windows XP 上时出现。 Windows 7 是 64 位。
我应该注意,我从 Debug -> Exceptions 抛出了所有异常。
我已经四处搜索,似乎没有很多像 SaveFileDialog 这样的基本方法失败的案例,关于可能导致此问题的任何想法?
基于以下答案的进一步分析使我相信这可能与调用 SaveFileDialog 的方式有关。由于这是从 MenuStrip 调用的,我相信它会作为一个单独的线程出现。这可能是 ShowDialog() 方法永远不会返回的原因,但我无法确定为什么会这样。为了找到问题,我创建了一个单独的窗口窗体,它什么都不做,只是有一个按钮来打开一个保存文件对话框。此按钮有效,并正确返回,但在将控制权返回给原始线程后,它似乎再次失败。这一切都基于我为调试目的而放置的日志记录。
记录代码:
public static void LogToFile(string message, FileInfo fInfo)
{
try
{
if (!fInfo.Exists)
using (FileStream fs = fInfo.Create()) ;
message = DateTime.Now.ToString("yyyy-MM-dd hh-mm-ss") + ": " + message;
File.AppendAllText(fInfo.FullName, message + "\n");
}
catch (Exception ex)
{
StackTrace st = new StackTrace();
string methodName = st.GetFrame(1).GetMethod().Name;
MessageBox.Show("Failure in " + methodName + ": " + ex.Message);
}
}
附加窗口的代码:
public partial class Buffer : Form
{
public Buffer()
{
InitializeComponent();
}
private void Buffer_Load(object sender, EventArgs e)
{
Logger.LogToFile("Entered Save Only Playlist.");
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "Playlist (*.lpl)|*.lpl";
DialogResult result = System.Windows.Forms.DialogResult.Cancel;
try
{
result = sfd.ShowDialog();
}
catch (Exception ex)
{
MessageBox.Show("Dialog problem: " + ex.Message);
}
Logger.LogToFile("Result of Dialog: " + result.ToString());
MessageBox.Show("Result of Dialog: " + result.ToString());
DialogResult = result;
}
}
上面的代码有效,MessageBox.Show() 实际显示了对话框结果。
【问题讨论】:
-
普通对话框使用 COM,如果您不在单线程单元中,它们会以各种奇怪的方式运行。您的
Main方法中有[STAThread]属性吗? -
嘿乔,是的,我的主线程上有 [STAThread]:[STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(新 frmLTSBC()); }
-
如果注释掉“string playlistSaveLocation...”行和接下来的两行会发生什么? Win7电脑上playlistSaveLocation的值是多少?可能是 UAC 安全性受到干扰。
-
我实际上已经尝试注释掉 DialogResult result = sfd.ShowDialog() 之前的所有代码,以查看这是否是问题所在。注释掉这些行没有效果,在 Windows 7 和 Windows XP 中 playlistSaveLocation 的值都是 C:\bin\Playlist\
-
shell 对话框,如 SaveFileDialog,允许将 shell 扩展加载到您的进程中。当您打开非托管调试时,您可以在“输出”窗口中看到它们正在加载。那台 XP 机器可能有一个与您的程序或对话框混淆的机器。使用 SysInternals 的 AutoRuns 实用程序将其关闭。
标签: c# visual-studio-2010 windows-7 windows-xp savefiledialog