My question is: How do I add a windows context menu item for a specific application, not globally?
Quick Brief:
We use Access (groan) for our CRM system. We use a basic 'copy to local' process for multi-access. I have written a C# 'launcher' of which handles this much better than a .bat file (they click the launcher, the launcher downloads the db, launches the db and quits). I also currently use a C# console application to handle development, automating stuff like incrementing version number, moving files around etc.
My Question/Goal:
I want to combine the two programs into one but I don't want to hinder the launcher from it's main purpose by jarring the user asking if they want to develop or not. I use this launcher too as I am primarily an estimator, hence wanting to combine the two. I have read that you can add context menu items to Windows as a whole, but I want to be able to add a launch option into the context menu just for this application. i.e. right click on program, normal menu options but with the addition of "Development Mode", this opens the program with arguments that I can use to open the development window/console instead.
Things to note:
I have played around with holding a key on start but it can be vague when to press the key. Too early - you will end up typing "r" several times into the active window, too late - and it will miss the capture point.
I have also looked at having a button on the launcher that gives you the option to go into dev mode, but the launcher is only open for around a second so its really easy to miss.
Thanks in advance
EDIT: The launcher is made and run as a click-once app.
I dont really know about whether its possible to have a custom context for a specific program, as far as i know the context works with the extension. That being said, i think there are better ways to handle your problem. Have a look at this
static void Main(string[] args)
{
/* here normal flow of the launcher*/
if (args[0] == "-dev")
{
/*here de developer mode*/
Console.WriteLine("Developer mode activated");
}
}
The way to use it is simple, you make a shorcut, and where it says the shorcut target you will have something like this "C:\Users****\Documents\visual studio 2017\Projects\Test\Test\bin\Debug\Test.exe" and you should change it to something like this "C:\Users****\Documents\visual studio 2017\Projects\Test\Test\bin\Debug\Test.exe" -dev
Further to this I stumbled upon some code to make this work. Hopefully this will help someone in the future. I am doing this in WPF, but I am sure you could probably adapt this code to work elsewhere.
1) App.xaml - Adding the JumpList action
After (not inside) the Application.Resources property add the following and change to your liking (There are a lot of properties I haven't used for development sake, check out the link to learn more):
<Application.Resources>
...
</Application.Resources>
<JumpList.JumpList>
<JumpList ShowRecentCategory="False"
ShowFrequentCategory="False">
<JumpTask Title="Open Dev Mode"
Description="Use this to enter dev mode (admins only)"
Arguments="DevMode:true"/>
</JumpList>
</JumpList.JumpList>
This will create a "Task" in the jump list:
2) Create Global static class - this will allow you to store the variable for later use in other forms.
public static class Global
{
public static Boolean DevMode = false;
}
3) App.xaml.cs - Adding OnStartup handler
Inside the App class create an override method for OnStartup
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
Global.DevMode = Boolean.Parse(e.Args.FirstOrDefault().ToString().Split(':')[1]);
}
}
4) Read the variable in your form using Global.DevMode
private void Window_ContentRendered(object sender, EventArgs e)
{
if (Global.DevMode) RunYourDevScript();
}
As per a suggestion in a comment, that has gone for some reason. I am going to revert to keypress but use shift instead or "R".
Failing this, or if it causes problems it will look at creating a global context menu item for all programs, and just won't click it when I don't need to
Related
I'm creating a Xamarin.Forms App and want to use UITest to test the correct behavior of my View. The View does not only react on user input like button click or the like. Instead there are background operations which should lead to changes in the View like hiding one element and showing another element at this point. Another example is filling a ListView with elements which would be produced by a background operation. These changes would be made on the ViewModel whose properties are bound to the View.
Now I want to simulate the background operation and test that my View behaves correctly. But I can not manipulate my ViewModel while in the UITest project because I cannot reference Xamarin.Forms in the Test class.
It seems like it isn't intended to test the application this way. The whole app is a black box for the UITest and you can only interact through mouse and keyboard input with it.
How can I access internals of my app, the corresponding ViewModel for example.
I already searched for this problem but found nothing. Maybe I'm searching in the wrong direction.
Any help would be highly appreciated.
You can use a back door to access a method in a platform project, and from there you should be able to access Forms code since your app project references the Forms core project. See: https://developer.xamarin.com/guides/testcloud/uitest/working-with/backdoors/
Create backdoor method in Android project:
In MainActivity:
[Export("MyBackdoorMethod")]
// Can optionally take a parameter of string, int, or bool.
// Can optionally return string or Java.Lang.String.
public void MyBackdoorMethod()
{
// In through the backdoor - do some work.
}
To call the Android backdoor method from a test:
app.Invoke("MyBackdoorMethod");
Create backdoor method in iOS project:
In AppDelegate:
[Export("myBackdoorMethod:")] // notice the colon at the end of the method name
// Must take an NSString and return an NSString.
public NSString MyBackdoorMethod(NSString value)
{
// In through the backdoor - do some work.
}
To call the iOS backdoor method from a test:
app.Invoke("myBackdoorMethod:", "the value");
More details at the link, but this should suffice to get one going.
On iOS, you already have a method to achieve it called SendAppToBackground. You can also pass the time to be in the background with a TimeSpan object (wiki info). However, you cannot achieve this on Android.
Here is a sample to use it on your UITest project:
public void SendAppToBackground(IApp app, TimeSpan timeSpan)
{
if (OnAndroid)
{
return;
}
((iOSApp)app).SendAppToBackground(timeSpan);
app.Screenshot("Return from background state.");
return this;
}
I'm working on a Xamarin application, which I will at first have working on iOS, but plan to later expand to Android and other mobile platforms.
As such, I'm trying to keep as much common code in PCLs as possible.
My question: what is the best practise - in Xamarin.iOS for now - to initialize any dependent PCL code?
For now I have it in the RootViewController inside ViewDidLoad()
public override void ViewDidLoad()
{
base.ViewDidLoad();
_engine = new MyEngine();
View = new MainView(_engine);
}
Is this the right spot? I'd considered putting it in the ctor for the RootViewController, but there's a fair bit going on in the initialization code, which thus ran against "don't put heavy duty init code into a constructor".
Things that happen are:
Load app settings
If app is run for first time ever, load basic defaults
Initialise other PCL libraries, such as a TextToSpeech module, a state engine (hence the name of the class above), etc
Prepare a data grid based on XML or JSON input
Alternately, I though it should possibly go into the AppDelegate section, but that didn't sound right.
I'm still fairly new to mobile app dev in general and Xamarin in specific, though I've done C# native code for Windows for years. I just want to make sure I follow best practises, but there doesn't seem to be a "thou shalt" in this case.
Edit: I've extracted the solution based on #wishmaster's suggestions.
For iOS the Appdelegate method is the best place for initialization code. The appdelegate also provides multiple delegate methods to give you feedback on application lifecyle events such as the method "DidFinishLauchingWithOptions"
. if you have a lot of data to download or long running tasks that your app depends on I would suggest you take a look backgrounding for iOS.
A technique I have also used is for my first viewcontroller on IOS (or activity on Android) to display a splash screen and a loading indicator while i run some code to refresh the cache.
Using #wishmaster's pointers, this solution works like a charm:
In AppDelegate.cs
// in the global section put any data you may make available elsewhere
private var _engine;
public Engine => _engine;
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
/*
* Do whatever init needs to happen here, if you need to make this
* available elsewhere, ensure you have properties or accessors,
* as above.
*/
_engine = new MyEngine();
return true;
}
Then in RootViewController.cs using a similar approach to these examples in Obc-C or Swift you can access the information through a property pointing at the AppDelegate.
var myappdelegate = UIApplication.SharedApplication.Delegate as AppDelegate;
var engine = myappdelegate.Engine;
View = new MainView(engine);
The result resulted in a snappier start up of the application, because the initialisation now happens during the splash screen and no longer between splash screen and appearance of the UI.
I recently made a custom ribbon in Sitecore. The two buttons in it fire off a command which activate a Xaml application using SheerResponse.ShowModalDialog. These applications effect the state of a database being read by another component on the ribbon.
I either need to be able to fire a custom event or function from the Xaml application to make the other ribbon component, or I need to be able to make the component on the ribbon aware that it needs to re-render when the ModalDialogs close. I don't see any obvious events which would do this, and I've gone about as far as I can when looking through the raw code with DotPeek and I haven't seen anything which even looks promising.
Apparently, the answer was there the whole time and I had missed it.
SheerResponse has a five parameter version of ShowModalDialog which accepts a boolean as a final parameter. This means I can couple it with ClientPage.Start:
Context.ClientPage.Start(this, "Run", kv);
}
private void Run(ClientPipelineArgs args)
{
var id = args.Parameters["id"];
if(!args.IsPostBack)
{
string controlUrl = string.Format("{0}&id={1}", UIUtil.GetUri("control:AltDelete"), id);
SheerResponse.ShowModalDialog(controlUrl,"","","",true);
args.WaitForPostBack();
}
else
{
Logger.LogDebug("post back");
}
Logger.LogDebug("out of if");
}
In a program that I'm testing with Coded UI Tests, I've got a window that opens for only a second or so, and I want to verify that this window is opening.
Is there a way to freeze the program, or make it run slow so that the test is able to find that window?
As I already mentioned in my comment there isn't much (perhaps nothing) you can do by the CodedUi Test to catch the window, since this functionality is built into the application.
My suggestion is to make this property configurable. Some of the properties in the applications under test need to be configurable so it can be tested. Consider the following requirements:
The service is restarting every month.
The user is deleted after one year of inactivity.
How would you test them? Will you wait a month or a year to go by? Those kind of parameters have to be available for the Qa team, otherwise they cannot be tested. I know that with this approach you have to do changes to your app's code and build but I think is the only way to solve it.
How about adding a Thread.Sleep(100);
http://msdn.microsoft.com/en-us/library/d00bd51t
From what I understand, the best approach is to break up your tasks as small as possible. So for a UI test I did that opens a shortcut on my toolbar, clicks login on a popup within, then clicks a tab in the application, the code looks like this:
namespace CodedUITestProject1
{
/// <summary>
/// Summary description for CodedUITest1
/// </summary>
[CodedUITest]
public class CodedUITest1
{
public CodedUITest1()
{
}
[TestMethod]
public void CodedUITestMethod1()
{
// To generate code for this test, select "Generate Code for Coded UI Test" from the shortcut menu and select one of the menu items.
// For more information on generated code, see http://go.microsoft.com/fwlink/?LinkId=179463
this.UIMap.OpenWindow();
this.UIMap.ClickLogin();
this.UIMap.ClickDevelopment();
}
//snip
}
So then in the ClickDevelopment() method, I know that the program should be visible, so rather than just dive right into the method actions, I can throw a Thread.Sleep() to make it visible for a little while longer.
public void ClickDevelopment()
{
Thread.Sleep(10000);
#region Variable Declarations
WinClient uIDevelopmentClient = this.UIQualityTrack30Window.UIItemWindow.UIQualityTrack30Client.UIDevelopmentClient;
#endregion
// Click 'Development' client
Mouse.Click(uIDevelopmentClient, new Point(39, 52));
}
Use Playback.Wait(2000) instead of Thread.Sleep(2000);
Best possible method is to add polling mechanism.
As soon as you perform the action which will open the window, call a function which will keep checking whether the window appeared for say, 1 min or so.
Be sure to call this function as soon as you perform action.
So even if the window stays for 500 millisecond, the info will be captured.
We have done similar thing in our project.
Hey I am fairly new to the c# programming language and have enjoyed my experience so far. I normally develop applications in java but a need for the win32 library has lead me to c# so far the languages seem relatively similar. however a problem I am having at the moment is a simple piece of code that can be best explained in this example
I am trying to print a piece of string to console then display the windows form then print another piece of string to console. however the result i get is first string is printed then the form is displayed, i then have to close the form before the last string is printed. the question i would like to ask is is there anyway to get this working so the second print to console is displayed immediately after the form is displayed. im guessing it has something to do with threading but I am not entirely sure how to implement this
The solution is quite simple:
Just create a Windows Forms Application (when creating the project - which you probably did) and then go to Properties (in context menu "Project", it's the last item) and set "Output type" to "Console Application". The forms will work as before and furthermore the application will now open the console too. You can then freely write to or read from the console.
static class Program
{
[STAThread]
static void Main()
{
Console.WriteLine("first string");
var form = new Form1();
form.Show();
Console.WriteLine("the second string");
Application.Run();
}
}
It sounds like you want to be able to output messages to the console while the form is being displayed, correct? The basic issue is that as long as the form is visible, there must be a message loop running, handling events for the form. The message loop is inside Application.Run, so once you call it, it won't return until the form is closed (as you discovered).
So if you want to write to the console while the form is visible, you have a couple of options. One, as you mentioned, is to use multiple threads. Let your main thread run the message loop, and start up a second thread to write to the console. But that's not necessary--you can also write to the console from within an event handler, directly or indirectly. There's nothing wrong with doing a Console.WriteLine from within a button click handler. Or you can have your button handler call a method in your Program class, and do the writing there.
As for which solution is better, it would help to know more about what you're trying to accomplish. I assume that you don't just want to write stuff to the console--what else is it that you want to do while the form is being displayed?
My suggestion would be to start with a Console application. You can always open a WinForm from a console application...which would give you exactly what you're looking for. (you might want to think about multi-threading as well.
Hey everyone thanks for your answers I made some progress with what im trying to achieve but im not sure how correct or thread safe it is here is the code i got to run
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace Project1
{
class Class2
{
[STAThread]
static void Main()
{
Console.WriteLine("hello");
Class2 t = new Class2();
t.test();
Console.WriteLine("second string");
}
public void test()
{
Thread t = new Thread(new ThreadStart(StartNewStaThrea));
t.Start();
}
private void StartNewStaThrea()
{
Application.Run(new Form1());
}
}
}
pls let me know what you think of this solution
I know this is a super-old question, but I'm going to answer in hopes of karma. One interesting work-around that works well for this comes up if you're using Visual Studio (which is a fairly safe assumption). If you start a forms project in C# in Visual Studio, then make your appropriate forms, but then change the project type to a console application (by right clicking the project-->properties-->Console Application), it will still spawn your forms, but will also keep a Console open, now all you need to do is put one Console.Write statement before your form is created, and the other after, and maybe add a flush statement!
are you using form.showDialog() or form.show()?
form.showDialog() will block until the form is closed, while form.show() will not.
I would either start with a console app, and run the application from the static main function. This is from memory - I haven't had to mess with Winforms for years:
[STAThread]
static void Main()
{
Application.Run(new YourMainForm());
}
or
I would redirect Console.Out and shove that stream into a some sort of control like a text box or list box. This is a lot of code but doable... I have written this before for on-site debugging but don't have the code handy.
Why don't you just create a new windows form with multiline textbox and dock it to the form, set BackColor as Black ForeColor as White and create a public method to send text to that textBox.
If your aim is a one Form application this works pretty much brilliantly.