#c# #winforms
#c# #winforms
Вопрос:
Я хочу реализовать изменение текущего пользователя в моем приложении. У меня есть следующий код:
public class Framework
{
private MainForm mainForm = null;
... // other fields
public virtual void run()
{
if (appInitializer!=null)
{
ISecurityManager securityManager = appInitializer.SecurityManager;
if (securityManager!=null)
{
if (securityManager.DoLogin())
{
RegisterDefaultActionsGroup();
InitializePlugins(appInitializer.Plugins);
// Apply rights for user
ActionsManager.Inst.ApplySecurity(securityManager, securityManager.CurrentUser);
mainForm = new MainForm();
mainForm.Text = appInitializer.ApplicationTitle;
if (appInitializer.ApplicationIcon != null)
{
mainForm.Icon = appInitializer.ApplicationIcon;
}
CorrectFormSizes(mainForm);
Context[Constants.MainForm] = mainForm;
MenuManager.Inst.FillMenu(DefaultGroups.MAIN_MENU, mainForm.MainMenu, ActionClick);
if(appInitializer.IsHaveToCreatePanelInfo) PanelInfoManager.Inst.FillInfo(mainForm);
if (appInitializer.IsHaveToCreateToolBar)
{
MenuManager.Inst.FillToolbar(DefaultGroups.MAIN_TOOLBAR, mainForm.MainToolStrip, ActionClick);
}
mainForm.MainToolStrip.Visible = mainForm.MainToolStrip.Items.Count > 0;
NotifyPluginsAboutShowing(appInitializer.Plugins);
Application.Run(mainForm);
}
}
}
}
...//other methods
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Framework framework = new Framework(new EArchiveInitializer());
framework.run();
}
}
В кнопке для изменения пользователя у меня есть:
Framework.Instance.MainForm.MainMenuStrip.Items.Clear();
Framework.Instance.run();
Но я получил ошибку: Starting a second message loop on a single thread is not a valid operation. Use Form.ShowDialog instead.
Я знаю, что это означает эту ошибку, но я не могу переписать свой код. Можете ли вы мне помочь?
Спасибо.
РЕШЕНИЕ: перепишите последнюю строку в run
методе:
if (!Application.MessageLoop)
Application.Run(mainForm);
else
mainForm.Show();
Спасибо, Джонатан.
Комментарии:
1. Можете ли вы запустить другую копию программы (
Process.Start
) и уничтожить текущую копию? Если вы хотите избежать переписывания всего своего кода для поддержки нескольких пользователей, это может быть самый простой способ сделать это.2. запуск второго экземпляра в другом потоке может помочь
3. @Merlyn Morgan-Graham: Нет, потому что приложение запускается примерно через 10-15 секунд.
Ответ №1:
Проблема на самом деле довольно проста, проблема в том, что вы вызываете приложение.Запустите дважды (первый при загрузке, второй при нажатии кнопки)
Быстрым решением для этого было бы иметь приложение.Сначала запустите ApplicationContext вместо формы и из вашего общедоступного метода virtual void run() загрузите требуемую форму.
public class Framework
{
private MainForm mainForm = null;
... // other fields
public virtual void run()
{
if (appInitializer!=null)
{
ISecurityManager securityManager = appInitializer.SecurityManager;
if (securityManager!=null)
{
if (securityManager.DoLogin())
{
RegisterDefaultActionsGroup();
InitializePlugins(appInitializer.Plugins);
// Apply rights for user
ActionsManager.Inst.ApplySecurity(securityManager, securityManager.CurrentUser);
mainForm = new MainForm();
mainForm.Text = appInitializer.ApplicationTitle;
if (appInitializer.ApplicationIcon != null)
{
mainForm.Icon = appInitializer.ApplicationIcon;
}
CorrectFormSizes(mainForm);
Context[Constants.MainForm] = mainForm;
MenuManager.Inst.FillMenu(DefaultGroups.MAIN_MENU, mainForm.MainMenu, ActionClick);
if(appInitializer.IsHaveToCreatePanelInfo) PanelInfoManager.Inst.FillInfo(mainForm);
if (appInitializer.IsHaveToCreateToolBar)
{
MenuManager.Inst.FillToolbar(DefaultGroups.MAIN_TOOLBAR, mainForm.MainToolStrip, ActionClick);
}
mainForm.MainToolStrip.Visible = mainForm.MainToolStrip.Items.Count > 0;
NotifyPluginsAboutShowing(appInitializer.Plugins);
mainForm.Show();
}
}
}
}
...//other methods
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MyHiddenContext());
}
}
public class MyHiddenContext
: ApplicationContext
{
private static Form activeFormInstance;
public MyHiddenContext()
{
this.RunFramework();
}
public void RunFramework()
{
Framework framework = new Framework(new EArchiveInitializer());
this.framework.run();
activeFormInstance = Framework.Instance.MainForm;
}
public static void ChangeUser()
{
activeFormInstance.Close();
activeFormInstance.Dispose();
Framework.Instance.MainForm.MainMenuStrip.Items.Clear();
Framework.Instance.run();
}
}
Не цитируйте меня о том, что код действительно работает, но это больше для того, чтобы дать представление о том, в какую сторону идти. Проблема в том, что вы не можете вызвать приложение.Запуск более одного раза, поэтому принципал должен иметь содержащий экземпляр или контекст (в любом таком смысле, форме, консоли и т. Д.)
Комментарии:
1. Большое спасибо. Я добавил решение, о котором идет речь.