如何从取消的登录表单中干净地将我的应用程序短路,并在登录成功时调用我的主表单?

时间:2015-01-20 19:27:30

标签: c# forms compact-framework windows-ce application-shutdown

我有一个登录表单显示在主表单之前,使用Program.cs中的代码:

static void Main()
{
    AppDomain.CurrentDomain.UnhandledException += Unhandled;
    frmLogin loginForm;
    using (loginForm = new frmLogin())
    {
        if (loginForm.ShowDialog() == DialogResult.OK)
        {
            NRBQConsts.userName = loginForm.UserName;
            NRBQConsts.pwd = loginForm.Password;
            NRBQConsts.currentSiteNum = loginForm.SiteNumber;
        }
        else
        {
            Application.Exit(); // klang!
        }
    }
    Application.Run(new frmMain());
}

static void Unhandled(object sender, UnhandledExceptionEventArgs exArgs)
{
    ExceptionLoggingService.Instance.WriteLog(String.Format("From 
application-wide exception handler: {0}", exArgs.ExceptionObject));
}

如果用户选择"关闭"按钮(而不是尝试登录),登录表单应该关闭,主窗体不应该显示,应用程序应该关闭。如果用户选择" OK"按钮,登录表单应该关闭,然后应该显示主表单。

选择"关闭"会发生什么?按钮导致应用程序与clangy,Gong Show-esque"崩溃"崩溃声音。我的日志文件中有这个异常消息:

日期:2009/9/9 8:57:51 PM 消息:已到达frmLogin.buttonOK_Click 日期:2009年4月9日8:57:51 PM 消息:来自应用程序范围的异常处理程序:System.NullReferenceException:NullReferenceException    在NRBQ.frmLogin.GetSiteNum()    在NRBQ.frmLogin.buttonOK_Click(对象发件人,EventArgs e)    在System.Windows.Forms.Control.OnClick(EventArgs e)    在System.Windows.Forms.Button.OnClick(EventArgs e)    在System.Windows.Forms.ButtonBase.WnProc(WM wm,Int32 wParam,Int32 lParam)    在System.Windows.Forms.Control._InternalWnProc(WM wm,Int32 wParam,Int32 lParam)    在Microsoft.AGL.Forms.EVL.EnterModalDialog(IntPtr hwnModal)    在System.Windows.Forms.Form.ShowDialog()    在NRBQ.Program.Main()

以下是登录表单中的相关代码:

public partial class frmLogin : Form
{
    public string UserName { get { return textBoxUsername.Text; } }
    public string Password { get { return textBoxPwd.Text; } }
    public string SiteNumber { get { return GetSiteNum(); } }

    private string GetSiteNum()
    {
        String candidateSiteNum = 
    listBoxSitesWithFetchedData.SelectedItem.ToString();
        if (String.IsNullOrEmpty(candidateSiteNum))
        {
            candidateSiteNum = "42"; // TODO: Remove before deploying
        }
        return candidateSiteNum;
    }

    public frmLogin()
    {
        InitializeComponent();
    }

    private void buttonClose_Click(object sender, EventArgs e)
    {
        ExceptionLoggingService.Instance.WriteLog("Reached 
    frmLogin.buttonClose_Click");
    }

    private void buttonOK_Click(object sender, EventArgs e)
    {
        ExceptionLoggingService.Instance.WriteLog("Reached 
    frmLogin.buttonOK_Click");
        if (SanityCheck())
        {
            this.Close(); // closing this login form should make the main 
    form active/visible
        }
        else
        {
            MessageBox.Show("You have not yet provided some key data; be 
    sure to enter a username and a password");
        }
    }

    private bool SanityCheck()
    {
        // For now, anyway, no site has to be selected; if none, use "42" by 
    default
        return ((!(String.IsNullOrEmpty(textBoxUsername.Text.Trim())))
            && (!(String.IsNullOrEmpty(textBoxPwd.Text.Trim()))));
    }

注意:" OK"按钮的DialogResult设置为" OK&#34 ;; "关闭"按钮的DialogResult设置为"取消"

为什么Application.Exit()会导致应用崩溃?什么是更友善,更温和的终止应用程序的方式?

为什么选择Okay按钮不允许主窗体随后显示?登录表单 关闭,即使选择了确定按钮(如果通过健全性检查),但是全部......主窗体不显示。

更新

我根据下面的答案修改了我的代码,现在取消工作正常(关闭应用程序没有klang /崩溃),但是在选择"之后我仍然没有看到我的主要表单。行"登录表单上的按钮,即使我在登录表单代码中以编程方式将DialogResult设置为OK。

下面的相关代码。

Program.cs的

static void Main()
{
    AppDomain.CurrentDomain.UnhandledException += Unhandled;
    frmLogin loginForm;
    using (loginForm = new frmLogin())
    {
        if (loginForm.ShowDialog() == DialogResult.OK)
        {
            HHSConsts.userName = loginForm.UserName;
            HHSConsts.pwd = loginForm.Password;
            HHSConsts.currentSiteNum = loginForm.SiteNumber;
            // TODO: Verify that these vals are valid
            Application.Run(new frmMain());
        }
    }
}

FRMLOGIN.CS

private void buttonClose_Click(object sender, EventArgs e)
{
    ExceptionLoggingService.Instance.WriteLog("Reached 
frmLogin.buttonClose_Click");
    this.DialogResult = DialogResult.Cancel; // <= necessary?
    this.Close();
}

private void buttonOK_Click(object sender, EventArgs e)
{
    ExceptionLoggingService.Instance.WriteLog("Reached 
frmLogin.buttonOK_Click");
    this.DialogResult = DialogResult.OK; 
    if (SanityCheck())
    {
        this.Close();
    }
    else
    {
        MessageBox.Show("You have not yet provided some key data; be 
sure to enter a username and a password");
    }
}

这是我在日志文件中看到的内容:

日期:2009/9/9 9:56:47 PM 消息:已到达frmLogin.buttonOK_Click 日期:2009年4月9日下午9:56:48 消息:来自应用程序范围的异常处理程序:System.NullReferenceException:NullReferenceException    在HHS.frmLogin.GetSiteNum()    在HHS.frmLogin.get_SiteNumber()    在HHS.Program.Main()

Merle Haggard演唱,&#34; 现在它又回到了密码室...... &#34;

更新2

我在GetSiteNum()中添加了一个消息框:

private string GetSiteNum()
{
    ExceptionLoggingService.Instance.WriteLog("Reached 
frmLogin.GetSiteNum()");
    String candidateSiteNum = 
listBoxSitesWithFetchedData.SelectedItem.ToString();
    // TODO: Remove after testing
    MessageBox.Show(String.Format("candidateSiteNum = {0}", 
candidateSiteNum));
    if (String.IsNullOrEmpty(candidateSiteNum))
    {
        candidateSiteNum = "03"; // TODO: Remove before deploying
    }
    return candidateSiteNum;
}

......而且我没有看到它,所以它已经爆发了:

String candidateSiteNum = listBoxSitesWithFetchedData.SelectedItem.ToString();

...选择&#34; OK&#34;此登录表单上的按钮。

3 个答案:

答案 0 :(得分:2)

这是docsApplication.Exit所说的内容:

  

通知所有消息泵必须终止,然后在处理完消息后关闭所有应用程序窗口。

这意味着它将启动一个很好的受控关闭 - 而不是立即退出,导致您的代码继续Application.Run,这显然会崩溃并烧毁。

一种选择是使用Environment.Exit代替,它将立即终止,但它是一个混乱的解决方案。另一种选择是在return之后立即Application.Exit,因此您永远不会到达Application.Run。但是,仍然不是很好。

而只是尝试:

static void Main()
{
    AppDomain.CurrentDomain.UnhandledException += Unhandled;
    frmLogin loginForm;
    using (loginForm = new frmLogin())
    {
        if (loginForm.ShowDialog() == DialogResult.OK)
        {
            NRBQConsts.userName = loginForm.UserName;
            NRBQConsts.pwd = loginForm.Password;
            NRBQConsts.currentSiteNum = loginForm.SiteNumber;
            Application.Run(new frmMain());
        }
    }
}

Main返回也将退出应用程序,因此不需要任何其他内容。

编辑:显然这不是你遇到的问题,但无论如何,这回答了标题中的问题。

答案 1 :(得分:2)

请勿针对您的登录表单致电Close(),只需设置DialogResult,如下所示。另请注意,在{ DialogResult.OK告诉我们好的时候,之后我才设置SanityCheck()

    private void buttonClose_Click(object sender, EventArgs e)
    {
        ExceptionLoggingService.Instance.WriteLog("Reached frmLogin.buttonClose_Click");
        this.DialogResult = DialogResult.Cancel; 
    }

    private void buttonOK_Click(object sender, EventArgs e)
    {
        ExceptionLoggingService.Instance.WriteLog("Reached frmLogin.buttonOK_Click");
        if (SanityCheck())
        {
            this.DialogResult = DialogResult.OK; 
        }
    }

您还应该确保在SanityCheck()函数中选择了ListBox中的项目:

    private bool SanityCheck()
    {
        if (listBoxSitesWithFetchedData.SelectedIndex == -1)
        {
            MessageBox.Show("You must select a site first!");
            return false;
        }

        bool pass = ((!(String.IsNullOrEmpty(textBoxUsername.Text.Trim())))
            && (!(String.IsNullOrEmpty(textBoxPwd.Text.Trim()))));
        if (!pass)
        {
            MessageBox.Show("You have not yet provided some key data; be sure to enter a username and a password");
        }

        return pass;
    }

答案 2 :(得分:1)

看起来您从未在“确定”按钮中设置“对话”结果。

设置对话框结果如下:

this.DialogResult = DialogResult.OK;

在您进行完整性检查后,在this.Close()解决问题之前,因为错误是由Null reff引起的。

您还需要在表单返回的其他位置设置取消的结果(或者我倾向于在表单加载时,假设失败,直到您知道它成功并返回。)