WPF application on different computer not displaying window - c#

I have developed a program for Windows 7 and it runs on my computer as it should (in release mode). However, when I copy and paste the project folder to my external HDD and try it on a different computer, it 'runs' but nothing really shows up. I will try to post relevant code:
class App : Application
{
[STAThread()]
static void Main()
{
new App();
}
/// <summary>
/// Starts application with splash screen
/// </summary>
public App()
{
StartupUri = new System.Uri("SplashScreen.xaml", UriKind.Relative);
Run();
}
}
Even though this screen is never visible, my MessageBox is shown.
//constructor
public SplashScreen()
{
//generated method
InitializeComponent();
System.Windows.MessageBox.Show("WHY ME??");
mw = new MainWindow();
mw.Show();
}
After the splash screen, the main window should open, but it doesn't AND this MessageBox never shows up.
public MainWindow()
{
//Windows generated
InitializeComponent();
System.Windows.MessageBox.Show("WHY ME??");
}
As I mentioned, the program runs as it is supposed to in both release and debug mode, but then when I bring it to another computer it only shows "WHY ME??" once instead of twice like it should. Any ideas?

Turns out there was a lot wrong with my code. One of the largest problems I had was hard-coded file paths to the computer it was running on. However, what really helped me with all computer-migration related problems was adding the following code to each class:
In Constructor:
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Create handling function:
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
System.Windows.MessageBox.Show(e.ExceptionObject.ToString());
}
It is slow and tetious however it does a pretty good job of assisting in locating source of problems. So there was multiple things wrong with my program, but adding the above code helped solve a lot of issues.

Related

C# Monogame - passing arguments on startup

So I want to have a winforms GUI for my game... But I can't seem to find a GUI lib that is tested to work with Monogame. That's why I have another plan:
Create a WinForms Project to act as a startup for my game.
Then, when the user clicks "Start Game" in that project's main form, the winforms project should look for my Monogame project executable and start it, then the form should close.
However I want to pass an argument from the WinForms exe to the Monogame exe. This has the purpose of somewhat preventing users from starting the game through the Monogame exe and use the Winforms "Starter" instead. Which leads to step #4.
If no argument is passed to the Monogame project it should close.
So should I do it like in console applications, pass a string array to the main void of the Monogame app like this:
using System;
namespace myGame
{
#if WINDOWS || LINUX
/// <summary>
/// The main class.
/// </summary>
public static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
using (var game = new Game1())
game.Run();
if (args[0] != "startFromWinForms")
{
// Find a way to close or
// on the other hand I think
// it will throw an exception??
}
}
}
#endif
}
How would you do that? What approach do you recommend? Also code examples/ideas explained would be great!
Let's take a step back and look at your original requirement.
I want to have a winforms GUI for my game ... when the user clicks "Start Game" [the game will start]
I just tried a simple solution that I think solves your problem without needing to create 2 projects. All I had to do was:
Create a new MonoGame Windows project.
Add a WinForms form (Form1) to it.
Write the following code..
In the Main() method:
[STAThread]
static void Main()
{
var form = new Form1();
if (form.ShowDialog() == DialogResult.OK)
{
using (var game = new Game1())
game.Run();
}
}
And in the Form1 button click event:
private void StartGameButton_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.OK;
}
And that's it. You don't need to pass anything on the command line. You'll only have 1 exe and it meets all of the requirements. MonoGame works exactly as it does now and the WinForms code stays isolated from the game.
Like this?
[STAThread]
static void Main(string[] args)
{
if (args[0] == "startFromWinForms")
{
using (var game = new Game1())
game.Run();
}
}
If you have an argiment, you will start your game, otherwise nothing happens

Static variable initialized in App_Launching suddenly null

Windows Phone 8 project. I have a class that holds a reference to an image. I initialize said reference in the Launching event handler in the app class:
private void Application_Launching(object sender, LaunchingEventArgs e)
{
TheClass.Load();
}
//Elsewhere...
class TheClass
{
static private int[] s_Pixels = null;
static public void Load()
{
BitmapImage bi = new BitmapImage(new Uri("/res/image.png", UriKind.Relative));
bi.CreateOptions = BitmapCreateOptions.BackgroundCreation;
bi.ImageOpened += OnImageLoaded;
bi.ImageFailed += OnImageFailed;
}
private static void OnImageLoaded(object o, RoutedEventArgs a)
{
BitmapImage bi = o as BitmapImage;
s_Pixels = new WriteableBitmap(bi).Pixels;
}
// And consumers call this one:
static public WriteableBitmap GetImage()
{
if (s_Pixels == null)
SendDebugReport();
}
}
This code works fo me. And yet I'm getting those debug reports, indicating that s_Pixels is null. I can't reproduce it, but my users obviously can. There's a code path that leads to GetImage() being called without a prior call to Load().
It's Load that's not being called, not that I call Load and OnImageLoaded never happens.
There are no other assignments to s_Pixels anywhere.
I do check for image loading errors. There's an ImageFailed event handler that leaves a log trace. It's never invoked, and why would it be - the image in question is in the app's resources.
How is that even possible? How can a Windows Phone app initialize and load without Launching being invoked?
Application_Launching is only called when your application starts anew. If you send it to the background, and the system eventually tombstones it, and then the user reactivates it, your static data will be gone, but Launching will not be called. Instead, you will get a call to Application_Activated.
So, basically, you need to run all static initialization both on the Launching and on the Activated methods.
You can most probably reproduce the problem your users are seeing by forcing the tombstoning of your app with Visual Studio: Check the "Tombstone upon deactivation while debugging" on the Debug tab of your project's options, run the app under debugger, press the Windows key when the app is running, and the switch back to the app.

App Freezes When Screensaver Settings Changed In Windows 7 - System.Threading.Timer The Culprit?

I have a C#/TCP/Winform app that's been running for quite some time, but one of my users has discovered an issue that I can replicate easily, but that I can't seem to solve.
If the app is open on Windows 7 and the user then changes any option in their screensaver settings - be it the screensaver being used or the time - the app freezes and the UI becomes non-responsive. Clicking anywhere on the form just gets the system "ding."
When the app is run through Visual Studio in debug mode, the problem ceases to exist, but once out of the confines of VS, goes back to freezing.
After some tinkering and testing, I seem to have narrowed down my problem to a System.Threading.Timer that runs once every second. I've been steadily paring down what the timer does and discovered that even if the timer's event does nothing, it still locks the app. If I disable the timer in the code or cancel the timer in the app prior to changing the Screensaver settings, then the app will return to functional after a screensaver change (though it still seems to freeze for about 2-3 seconds).
This code here, seems to be all that is necessary to make the app freezable (within the WinForm code):
/// <summary>
/// Starts the countdown timer for unit alerts
/// </summary>
private void startCountDownTimer()
{
Object timeState = new object();
this._timerCall = new System.Threading.TimerCallback(this.countDown);
this._countdownTimer = new System.Threading.Timer(_timerCall, timeState, 0, 1000);
}
/// <summary>
/// Invokes the countdown logic for unit alerts
/// </summary>
/// <param name="state"></param>
private void countDown(Object state)
{
// REMOVED AND STILL FREEZING
}
Note that this freeze happens even with the contents of countDown commented out so that the timer is doing nothing other than firing once per second.
If I launch process and then attach a remote debugger to it, there is nothing in the output that indicates that anything is wrong with the application. The form actually still fires events like "Activated":
*** MAIN WINDOW ACTIVATED ***
*** MAIN WINDOW ACTIVATED ***
However nothing else seems to be firing and the application has to be either killed or shut down via EndTask. If EndTask is used while the debugger is still attached, I suddenly get errors:
A first chance exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll
===================================
ERR: Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
at System.Windows.Forms.Control.BeginInvoke(Delegate method, Object[] args)
at System.Windows.Forms.Control.BeginInvoke(Delegate method)
at Wcsg.UI.Windows.CadClient.client_MessageReceived(TcpMessageReceivedEventArgs mrea) in C:\Users\---------\Documents\Visual Studio 2010\Projects\Dispatch-DEVELOPMENT\CadClient\Forms\CadClientForm.cs
at Wcsg.Net.Tcp.WcsgTcpClient.processStream(Int32 count)
at Wcsg.Net.Tcp.WcsgTcpClient.performSocketRead(IAsyncResult ar)
---------------------
The errors that I do finally get would seem to be linked to the closing of the form while it finally gets around to processing the messages on the socket.
I'm looking for any sort of direction to look here.
* EDIT *
I was asked about the Main method in the program when the expected workaround (see answer) didn't work. Here is the Main code:
[STAThread]
static void Main(String[] args)
{
// check for other running CadClients
bool createdNew = _mutex.WaitOne(TimeSpan.Zero, false);
if (createdNew) // first-run, launch Status Monitor on load
{
List<String> newArgs = new List<string>(args);
newArgs.Add("-SM");
args = newArgs.ToArray();
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
AppDomain currentDomain = AppDomain.CurrentDomain;
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
// try to catch issue 13445 -- see testing notes
CadClient cc = new CadClient(args);
CadExceptionHandler ceh = new CadExceptionHandler(ref cc);
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(ceh.CurrentDomain_UnhandledException);
Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(ceh.Application_ThreadException);
Application.Run(cc);
}
* EDIT *
I should probably add the Splashscreen code as well:
private void showSplashScreen()
{
WaitCallback wcb = new WaitCallback(doSplashScreen);
ThreadPool.QueueUserWorkItem(wcb);
}
private void doSplashScreen(object state)
{
if (this._splash == null)
this._splash = new SplashForm(this);
this._splash.FormClosed += new FormClosedEventHandler(_splash_FormClosed);
this._splash.Show();
while (this._splash != null && !this._splash.WorkDone)
Application.DoEvents();
this._splash.Close();
}
The method showSplashScreen() is called within the main form's constructor - originally before and now after the InitializeComponents() call. The splash screen displays updates its display while the main app validates some security. Then it turns into a login screen and then displays more udpates while the main app loads data from the server. Once the main form indicates (via event) that it has completed its work, the SplashScreen is closed.
Used the comment from #HansPassant and found that the showSplash method for our splash/login screen was not being called before Application.Run, but WAS being called before our main form's InitializeComponent method. Moved this.showSplash to the line immediately below InitializeComponent() and recompiled and the problem seems to be gone.

Application.Current "null" in console application

I'm currently trying to use a WPF component that makes use of Application.Current from a WPF application, however due to several reasons I never call Application.Run (nor is that an option). The result is a NullReferenceException.
I'm basically trying to display multiple instances of the same WPF window from what would be a console application.
Any advice (and code samples in C#/F#) would be welcome!
Thanks in advance
Just to offer an alternative solution.
It is possible to keep an application running without any windows open. To me this feels less 'hackish'. :) http://msdn.microsoft.com/en-us/library/system.windows.application.shutdownmode.aspx
public class AppCode : Application
{
// Entry point method
[STAThread]
public static void Main()
{
AppCode app = new AppCode();
app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
app.Run();
...
app.Shutdown();
}
}
EDIT:
Ok this got a bit cumbersome. Application.Run will block, so it needs to run in its own thread.
When it does run in its own thread, any interaction between your main thread and your ui thread had best be done by Application.Current.Dispatcher.Invoke. Here is some working code, that assumes you have a class that inherits from Application. I'm using a modified App.xaml/App.xaml.cs that a WPF project template creates for you, to get nice handling of ResourceDictionaries for free.
public class Program
{
// Entry point method
[STAThread]
public static void Main()
{
var thread = new System.Threading.Thread(CreateApp);
thread.SetApartmentState(System.Threading.ApartmentState.STA);
thread.Start();
// This is kinda shoddy, but the thread needs some time
// before we can invoke anything on the dispatcher
System.Threading.Thread.Sleep(100);
// In order to get input from the user, display a
// dialog and return the result on the dispatcher
var result = (int)Application.Current.Dispatcher.Invoke(new Func<int>(() =>
{
var win = new MainWindow();
win.ShowDialog();
return 10;
}), null);
// Show something to the user without waiting for a result
Application.Current.Dispatcher.Invoke(new Action(() =>
{
var win = new MainWindow();
win.ShowDialog();
}), null);
System.Console.WriteLine("result" + result);
System.Console.ReadLine();
// This doesn't really seem necessary
Application.Current.Dispatcher.InvokeShutdown();
}
private static void CreateApp()
{
App app = new App();
app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
app.Run();
}
}
The following is the intended behavior of Application class:
The first open window is the MainWindow.
The only window in the list becomes the MainWindow (if others are to
be removed).
Application Class is designed to exit if no windows are present in
windows list.
Check this link.
So basically you cannot run an Application, without any window open. Keep a window open but hidden.
If I have misunderstood your problem, then perhaps the following similar cases might help:
Managing Application Resources when WPF is Hosted.
When running unit tests in Visual Studio 2008

Displaying a form locks up mono

I've got a mono app written in c# and executed on a Mac using "mono myapp.exe"
The app itself is a "Windows Application" when viewed from the project properties, but it doesn't always show a window. In program.cs, there is a static Main:
static void Main(string[] args) {
UserClient client = new UserClient();
client.Start(args);
}
public class UserClient {
public void Start(string[] args) {
// Talk to server, listen for instructions, etc.
....
// Launch the "Stay Alive" thread
// Just a thread that Sleeps/Loops watching for an exit command; mainly used to keep the process alive
}
}
Inside the UserClient's Start method, there is a piece of code that continuously monitors a server which gives it instructions to do things. One of the things it does is optionally displays a message using a windows form.
When the server instructs the process to display a message, it instantiates a form, displays it using frm.ShowDialog() and then after 30 seconds, a timer on the form runs Close() and the frm then gets disposed. However, when this happens, on my Mac I see an application title bar saying "mono" and a new icon on my dock bar for the mono app. After about 2 minutes the mono process in Activity Monitor shows "Not Responding." This eventually will prevent the user from logging out, shutting down, etc. (because Mac OS can't kill mono gracefully).
ON THE OTHER HAND... if the server never tells the process to display that form, everything runs fine and dandy: a dock icon never shows up (which is good!), mono title bar never shows up and the mono process continues to run happily, not preventing the system from shutting down or rebooting.
Anyone experienced this or have ideas on what's causing it? My guess is that it's a new GUI thread being created by the form which isn't ever being shutdown and is somehow causing a lockup, though I'm unsure of how to handle it.
Thanks for any suggestions.
Update:
Here's some code to easily reproduce and see this happening. I realize that this seems kind of "non-standard." Having said that, the below works perfectly in a Windows environment and provides the desired result of not showing an icon in the task area except when showing a message. Currently, using Application.Run and simply doing frm.ShowDialog() produce exactly the same result.
In the end what we need is to be able to display the form, then destroy the form and any associated icon from the dock. I suspect the GUI is starting a thread which isn't ever being disposed, which is why the dock icon remains. Is there a way to make sure the GUI thread is taken care of?
static class Program {
static void Main() {
StartupClass s = new StartupClass();
s.start();
}
}
public class StartupClass {
Thread stayAliveThread;
public void start() {
// Stay alive thread
stayAliveThread = new Thread(stayAliveLoop);
stayAliveThread.Start();
// This shows a form and would normally be used to display temporary and brief messages to the user. Close the message and you'll see the undesired functionality.
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
Application.Exit();
Application.ExitThread();
}
/// <summary>
/// Keep the app alive.
/// </summary>
private void stayAliveLoop() {
while (true) {
Thread.Sleep(10000);
// In the real project this method monitors the server and performs other tasks, only sometimes displaying a message.
}
}
}
I feel I'm missing several things. Most notably
[STAThread]
static void Main(string[] args) { //....
Also see this answer: Windows Forms and ShowDialog problem
I can't see anything like initializing message loop for windowed application. I.e. in windows forms case something like Application.Run(). If you do not have it, no wonder application freezes. In any case, posting more code could be helpful, as stated in comment.
In the end, I couldn't resolve this. I created a process that launched another app which displayed the message form. Not really a true answer, but the solution I had to go with.

Categories