Add command line option to my WPF application - wpf

I want to add command line options to my WPF application but in case command line is sent into my EXE file i don't want the UI open but only command line options.
Is it possible to do something like this ?
public partial class MainWindow : MetroWindow
{
public MainWindow()
{
string[] args = Environment.GetCommandLineArgs();
if (args.Length > 1)
{
this.Hide();
ParseArgs(args);
}
else
{
InitializeComponent();
}
}
private void ParseArgs(string[] args)
{
// bla bla
}
}

You should do this in your app.xaml.
I explain :
You put an application startup method handler(instead of using the startup uri). Here you can parse the cl arguments and then set StartupUri = MainWindow.xaml which will open your window. and if you won't open main window then you don't set startup uri.

This Replacing WPF entry point is what you want to do.
In there you can get the command line arguments and decide if you want to show the main window or not.
If you need to write output that is shown in the command line when the application is run, you need to do something like this :
Right click on the project, "Properties", "Application" tab, change "Output Type" to "Console Application", and then it will also have a console.
However, once you do that then you will have a console window pop up even if you start the application not from a command line. There is no way to have it both ways - either the application is a command line application which can launch a window, or it is a window application which cannot write to the console which started it. It is a limitation in Windows - the bit that decides it is in the PE header.
This question discusses this point in great detail, and offers several hacks to achieve what you want.
You might want to actually search for your problems, because I count at least 5 SO questions dedicated to this (new) topic already.

Related

WPF main window not showing for Debug build

I'm working on a C# project with WPF in Visual Studio. My application was building and running perfectly yesterday. As far as I know, I haven't made any changes to the build process.
Today, when I try to run a Debug build, it builds and deploys correctly, and a process starts, but the application startup window never displays (not even in the Windows Taskbar). I tried to attach the Visual Studio Debugger to the process as recommended in this (external) link, but the process is grayed out in the Visual Studio > Debug > Attach to Process... popup. It does not display even if I browse to the Debug folder and double-click the *.exe file.
The unusual thing about this is that if I run in Release rather than Debug, everything works fine. I've checked the Project > Properties > Debug configurations; Debug and Release are identical (I just used the defaults when I created the project). Other projects also work fine in both Debug and Release build. I tried comparing the *.csproj and *.sln files, but I couldn't find any significant differences.
I've tried searching for this, but it's really difficult to find anything useful. This question is unrelated, since the window does not even appear in the taskbar in my case. If I try to include the word "debug," I get a flood of questions about redirecting output to the console, which is not my problem.
I'm not sure what code/configurations are relevant to this question, so please let me know if you need more info about the setup.
Edit 1:
I tried putting a break in the InitializeComponent() method in the auto-generated part of my App class:
public partial class App : System.Windows.Application {
private bool _contentLoaded;
/// <summary>
/// InitializeComponent
/// </summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
#line 5 "..\..\App.xaml"
this.StartupUri = new System.Uri("Views\\MainWindow.xaml", System.UriKind.Relative);
#line default
#line hidden
System.Uri resourceLocater = new System.Uri("/MyProject;component/app.xaml", System.UriKind.Relative);
#line 1 "..\..\App.xaml"
System.Windows.Application.LoadComponent(this, resourceLocater);
#line default
#line hidden
}
/// <summary>
/// Application Entry Point.
/// </summary>
[System.STAThreadAttribute()]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")]
public static void Main() {
MyProject.App app = new MyProject.App();
app.InitializeComponent();
app.Run();
}
}
This will break for either Debug or Release if the code is between if(_contentLoaded) { and _contentLoaded = true; but everywhere else in the method, I get "The breakpoint will not currently be hit. No executable code of the debugger's target code type is associated with this line." I get the same message if I try to put a breakpoint anywhere in the Main() method.
Even though Debug breaks at the certain interval mentioned above, it still does not display if I continue.
Edit 2:
Things are starting to get weird. Since the project is backed up in Git, I rolled all the way back to the first commit and to several others along the way. I still couldn't get anything to display for Debug, but Release still worked fine. I even tried deleting the local repo and recloning it, but no success. The stranger part about this is that everything runs fine from the backup folder. Why does the folder name make a difference?
I never found out what caused the issue to occur in the first place, but I was eventually able to come up with two workable solutions.
As described in the edit: Copying the solution directory to another directory and running it from there works for some reason.
For some reason, running Debug|Any CPU didn't work, but running either Debug|x86 or Debug|x64 did.
It's unlikely that someone else will run into my exact situation, but I'm leaving my solutions here for posterity. Maybe someone else can benefit from this.

Batch command to change an icon of the currently running window

In my working environment I can have up to 10 command prompt windows open, each one set up to work in a different context. Having all of them open, I find myself having to switch between several of them to find the right one that I want to work with.
I am already setting different foreground and background colors of each window based on some criteria, but it would be much more easier to distinguish between them by having a different colored icon in the taskbar. That way, I would not even have to maximize/bring them to focus to find the right one from the get-go.
Is there a way that I can change the taskbar icon of the currently running command prompt window programmatically by executing batch commands in it?
There is no "built-in" way to do that, like there is the color command from cmd.exe to change the colors.
You could either search the internet for some utilitiy, or roll your own, for example in C#, by invoking the SetConsoleIcon Win32 API. Note however, that this API is not officially documented, YMMV.
using System;
using System.Drawing;
using System.Runtime.InteropServices;
class Program
{
[DllImport("kernel32.dll", SetLastError = true)]
private static extern uint SetConsoleIcon(IntPtr iconHandle);
static void Main(string[] args)
{
if (args[0].Equals("--reset", StringComparison.OrdinalIgnoreCase))
{
SetConsoleIcon(IntPtr.Zero);
}
else
{
// Use this to load an icon from an icon file instead:
// var icon = new Icon(args[0]); // load from .ico file
// Extract icon from given executable/dll.
using (var icon = Icon.ExtractAssociatedIcon(args[0]))
{
if (icon != null)
SetConsoleIcon(icon.Handle);
}
}
}
}
You should be able to compile this using csc.exe setconico.cs (assuming you named the file setconico.cs). This will generate setconico.exe, which you can use like this:
Set the current console icon of the console you run this in, to the icon of notepad.exe
c:\> setconico.exe c:\windows\notepad.exe
You might also be able to write the above code in PowerShell, if you don't want to compile a separate utility.

Detect Win+Tab Task View

On Windows 10, you can press Win+Tab to get a "Task View" view of all your windows. I'm trying to check if this is active at any given time. I have tried using a Low Level Keyboard Hook with WH_KEYBOARD_LL but this only allows me to detect the keypress, not if the switcher is active. I've looked at the Windows DWM API and haven't found anything else either.
I have also tried using EnumWindows() and EnumChildWindows(GetDesktopWindow(), ...) and did not find any difference in the output between having the task view shown and hidden.
Is there any accurate method to detect if this is being shown?
Here's a solution that works very consistently with my version of Windows (1709 build 16299.125) and doesn't require the processor-heavy approach of a call to EnumChildWindows:
bool isTaskView() {
//Get foreground window's name
HWND fgWindow = GetForegroundWindow();
TCHAR windowName[MAX_PATH] = L"";
GetWindowText(fgWindow, windowName, MAX_PATH);
//Compare with magic string name of Task View's window
std::wstring nameStr(windowName);
return nameStr == L"Task View";
}

Loading Application With Different Title on Load

Not sure if this is at all possible, but is there any way that, as soon as I start my application, that the title bar will change? So there is always a different title?
So, say my application title is called: Test Application: Instance 1, then ext time I load the application, the title will change to: Test Application: Instance 2, etc.
I am using Visual Studio Express 2015 for Windows Desktop.
I have just started this project, so has the default form load function:
namespace Application
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}
}
This doesn't work = Form.load
I don't know what else to try or if it is at all possible.
So, I don't know if it is possible, because how do you know when to stop it counting? Or maybe only stop once it hits 10 application hits?
Basically, I want the same form, but a different title name.
Provide a handler for the Load event on your main form and set the Text property to the title you desire:
string newTitle = MethodWhichGeneratesTitleText();
this.Text = newTitle;
In this method you can check your database, config file or other sources that help you determine the title you need.

WPF MessageBox in App.xaml.cs stops MainWindow initialisation so app never appears but is (apparently) running correctly

There's no error message and no indication why it is not displaying the window. The app initialises App.xaml.cs: App() {} and I can step through the App.xaml file. It gets the startup uri and then... silence. No output in the Output window and no unhandled exception and no window, I can't find where to put a breakpoint to debug as it isn't hitting the start of MainWindow.xaml.cs.
Really confused.
This was working 20m ago.
In that time all I did was add Windows.Office.Interop.Outlook reference. I removed the reference and rebuilt but still the same. Would that cause this problem? Has anyone seen this before? Google isn't helping!
EDIT :
App.xaml.cs:
public App()
{
using (var dbContext = new DBEntities())
{
if (!db.Exists())
{
try
{
db.Database.Create();
MessageBox.Show("Database created"); // this is the problem!!
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
I've added App.xaml.cs, I found that the problem was using a MessageBox to give info (this is still in development!). I'd been meaning to get rid of it and eventually did and my problem went away. This meant I could find relevent Goolge results:
MSDN query and answer for exactly my problem
I will be adding an 'loading window' in between app load and main window load eventually in which I will be able to feedback information using Bindings etc.
Fixed error by removing the MessageBox.Show(..) call. The selected answer from the MSDN URL given in the question states:
"I performed a test based on your description, the applicationi stop at the method : USER32!GetMessageW+0x33, calling USER32!NtUserGetMessage"
I assume this is what was occurring in my case, although I didn't test it.
What happens if you create a new window and set that as the StartupUri?
You also might want to create a new project and make sure that the namespaces referenced in the App.xaml in your existing app haven't somehow been inadvertently edited.

Resources