Windows Explorer Context Menu click function is not working - c#

I want to let the users to select only the following extension files: .jpg,.png, .tiff, .gif, .png. using Windows Explorer Context Menu I followed this link:http://www.codeproject.com/Articles/15171/Simple-shell-context-menu?msg=4779433#xx4779433xx and I could register and un-register successfully for .jpg file.
When I click on the command fileCopytoDirAnothing is happening i.e the function is not working. (I followed the same approach using console application with my function it works).
Where & How should i call the function during the 'fileCopytoDirA click?? Any help?
![enter image description here][1]
Code to register in the registry:
InitializeComponent();
string menuCommand = string.Format("\"{0}\" \"%L\"", Application.Current);
FileShellExtension.Register("OISjpegfile", "fileCopytoDirA", "fileCopytoDirA", menuCommand);
Function to be executed during click:
static void fileCopytoDirA(string filePath)
{
try
{
File.Copy(filePath, System.IO.Path.Combine(#"C:\Test\Directories\", System.IO.Path.GetFileName(filePath)), true);
}
catch (Exception ex)
{
MessageBox.Show(string.Format("An error occurred: {0}", ex.Message));
return;
}
}
Function to un register the registry entries during WPF application close:
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
FileShellExtension.Unregister("OISjpegfile", "fileCopytoDirA");
}
[1]: http://i.stack.imgur.com/eAN5F.png
Edit afterMetadingsanswer:
App()
{
InitializeComponent();
string menuCommand = string.Format("\"{0}\" \"%L\"", System.Reflection.Assembly.GetExecutingAssembly().Location);
FileShellExtension.Register("OISjpegfile", "fileCopytoDirA", "fileCopytoDirA", menuCommand);
}
[STAThread]
public static void Main(string args)
{
if (string.IsNullOrEmpty(args))
{
// Run your Main Form
// (blocks until Form1 is closed)
Window3 window = new Window3();
App app = new App();
app.Run(window);
}
else
{
// Run the context menu action
fileCopytoDirA(args);
}
// exit
}
static void fileCopytoDirA(string args)
{
try
{
File.Copy(args, System.IO.Path.Combine(#"C:\Test\Directories\", System.IO.Path.GetFileName(args)), true);
}
catch (Exception ex)
{
MessageBox.Show(string.Format("An error occurred: {0}", ex.Message));
return;
}
}

The (simple) registry setting is that your application is executed by arguments, as it would be called in a console:
app.exe "TheJpegFile.jpg"
So the entry point is static void Main(string args), from there you can call fileCopytoDirA(args). There is no magic way Explorer calls a function by its name. You can either implement the COM interfaces, as for example this project does, or you go the quick and dirty way, by redirecting your Main; if there is not an argument, run the (windows forms) application - if there is an argument, do the action and exit:
using System;
using System.Windows.Forms;
public static class Program {
public static void Main(string args) {
if (string.IsNullOrEmpty(args)) {
// Run your Main Form
// (blocks until Form1 is closed)
Application.Run(new Form1());
}
else {
// Run the context menu action
fileCopytoDirA(args);
}
// exit
}
}
The FileShellExtension.Register function is defined as
public static void Register(string fileType,
string shellKeyName, string menuText, string menuCommand)
So the arguments are
string fileType - the HKC registry key for the file extension
string shellKeyName - just a registry key name for Explorer to distinguish shell extensions
string menuText - what the user can see in Explorer's context menu
string menuCommand - the shell command Explorer executes just like you can do in a console or by a link
P.S: In WPF it's similar, but you create new YourApp class (derived from System.Windows.Application) and then call Run.
Assuming Application.xaml looks like
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window1.xaml">
</Application>
and your application class is in namespace WpfApplication1 named App, and you have a Window1.xaml, the q'n'd looks like
namespace WpfApplication1
{
public partial class App : Application
{
App()
{
InitializeComponent();
}
[STAThread]
static void Main(string args)
{
if (string.IsNullOrEmpty(args)) {
// Run your Main Form
// (blocks until Form1 is closed)
Window1 window = new Window1();
App app = new App();
app.Run(window);
}
else {
// Run the context menu action
fileCopytoDirA(args);
}
// exit
}
static void fileCopytoDirA(string args) {
// this your part ;)
}
}
}
Btw. I took the WPF Main part from this source and it seems to be important that you remove the StartupURI="Window1.xaml" attribute from your Application.xaml, that it looks now like
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Application>

Related

Launching a WPF window from a Console application

I'm trying to use a WPF window as a message popup that will close once a task has been performed. All the documentation I've seen says that this can't be done with a messageBox, that's why I'm going with the WPF. I found one code snip that allowed me to open the WPF window but it wouldn't progress the application to the next process. Below is the last code example I found that I thought showed promise but the window isn't opening -
[STAThread]
static void Main(string[] args)
{
try
{
string filePath = "my new directory";
var popup = new PopupTest();
popup.Dispatcher.BeginInvoke
(System.Windows.Threading.DispatcherPriority.Normal,
(Action)(() =>
{
popup.Show();
}));
// Do some console application stuff
do
{
Directory.CreateDirectory(filePath);
} while (!Directory.Exists(filePath));
popup.Close();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
}
}
The cs.xaml file is just the default
/// Interaction logic for PopupTest.xaml
/// </summary>
public partial class PopupTest : Window
{
public PopupTest()
{
InitializeComponent();
}
}
I feel like this should be simpler than I'm making it. Anything that can point me in the right direction is appreciated.
You need to reference the WPF assemblies and create and run a System.Windows.Application on the STA thread:
[STAThread]
static void Main(string[] args)
{
var app = new System.Windows.Application();
app.Run(new PopupTest());
}
The Run method blocks and doesn't return until the app is shut down.
If you want to do some stuff while the app is running, you need to do this on another thread:
[STAThread]
static async Task Main(string[] args)
{
Task t = Task.Run(() =>
{
string filePath = "my new directory";
do
{
Directory.CreateDirectory(filePath);
} while (!Directory.Exists(filePath));
});
var app = new System.Windows.Application();
app.Run(new MainWindow());
await t;
}

WPF has no entry point

I'm using SharpDevelop and had by my bad moved the App.xaml to an Subdirectory.
When i try to start/debug the Application, C# says, that my Application has no entry points or a static main method (CS5001).
An Edit < Undo or an movint to the default main folder will be not working.
Whats wrong?
Edit
On Project-Settings, no Classes/Methods are listened:
App.xaml
<Application x:Class="SongManager.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="Boot">
</Application>
App.xaml.cs
using System;
using System.Windows;
using SmuleTools;
namespace SongManager {
public partial class App : Application {
private Account user;
public App() {
}
public Account getAccount() {
return this.user;
}
[STAThread]
private void Boot(object sender, StartupEventArgs e) {
Login login = new Login();
login.AuthSuccess((Object result) => {
this.user = (Account) result;
Manager window = new Manager(this);
window.Show();
login.Close();
});
login.Show();
}
}
}
The Solution is a little bit tricky, but easy.
After moving the main .xaml file, the Build action will be lost - These are not in the Project/Compiler settings!
Step-by-Step:
(red mark) Click on your .xaml file (for sample, App.xaml)
(blue mark) Go to the Properties window (on the right side!)
(green mark) Change Other > Build action to ApplicationDefinition
Screenshot
That is it!
Try to add a Main() method to your App class:
[STAThread]
public static void Main()
{
App application = new App();
application.Run();
}
By default, there should be one generated when you build the application.

Debugging and logging windows service

I am learning basics of windows service. I have created a very simple one.
using System.ServiceProcess;
namespace WindowsServiceBasic
{
public partial class OmerService : ServiceBase
{
public OmerService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
System.Diagnostics.Debugger.Launch();
WriteLog("START");
}
protected override void OnStop()
{
System.Diagnostics.Debugger.Launch();
WriteLog("STOP");
}
private void WriteLog(string durum)
{
eventLog1.WriteEntry(performanceCounter1.RawValue.ToString());
}
}
}
using System;
using System.IO;
using System.ServiceProcess;
namespace WindowsServiceBasic
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
private static void Main()
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new OmerService()
};
ServiceBase.Run(ServicesToRun);
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
if (e != null && e.ExceptionObject != null)
{
string createText = e.ToString();
File.WriteAllText(#"c:\omerlog.txt", createText);
}
}
}
}
The first time my service (AServis) starts successfully but when I click the restart it crashes. Since my service is very simple It should have been worked properly. I try to log the error, put try catch but I could not find anything. I am trying to attach process, it debugs stop event but after stop debug suddenly finishes and start process crashes. Could you please help me what is the reason and how can I debug and log error.
Thanks in advance
I saw that it was stuck in
public OmerService()
{
InitializeComponent();
}
I could see the issue adding System.Diagnostics.Debugger.Launch(); statement.
public OmerService()
{
System.Diagnostics.Debugger.Launch();
InitializeComponent();
}
The standard trick I use in this situation is to add a call to System.Diagnostics.Debugger.Break in my start up code. Now, when you start the service as normal (through the Service Control Manager (SCM)), the call to the Break will cause Windows to launch the JIT debugger, which should prompt you to choose the debugger you wish to attach to the process (e.g., Visual Studio), which will then enable you to debug your code as normal.
Also see this: Easier way to debug a Windows service.

WPF window is not opening?

i am working with wpf application ,i have changed my entry point Main() to another file ,there is no error but MainWindow.xaml is not opening .Code is :
class AppStart : Application
{
[STAThread()]
static void Main()
{
//Console.WriteLine("New entry point added");
new App();
}
public void App()
{
StartupUri = new System.Uri("MainWindow.xaml", UriKind.Relative);
Run();
}
}
Can anyone explain what could be the reason?
Solved it i was using wrong constructor name ..it should be AppStart() but i was writing App()..

How to make an application HAVE a form but not BE a form?

I want my C# .NET application to have a form but not be a form.
When I normally startup a windows forms application, it's like the form is the master of everything else that follows:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
Instead, I'd like to startup my program, which is then able to show a form, but is not a form itself. In other words, I don't want the master controller of the applicatin being the form, I'd like it instead to be a non-visual logical container, which has the capability to show forms, but isn't a form itself.
I'm not sure if I'm posing the question in a clear way, but I'd like to hear thoughts.
You can just use Application.Run() to get a message-loop running. But you'll need to do something to listen for input - perhaps a systray etc.
You could use an ApplicationContext instead. That gets you the necessary message loop that will keep a form alive, once you decide to create one. Make your Program class look similar to this:
static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
AppContext = new ApplicationContext();
Application.Run(AppContext);
}
public static void Quit() {
AppContext.ExitThread();
}
public static ApplicationContext AppContext;
}
Beware that the app will not close automatically when you close the last window. Calling ExitThread explicitly is required.
It's fairly common to create a separate Bootstrapper component which you could move the display of the main form to:
using System;
using System.Windows.Forms;
namespace Example
{
internal static class Program
{
[STAThread]
private static void Main()
{
new Bootstrapper().Run();
}
}
public class Bootstrapper
{
public void Run()
{
// [Application initialization here]
ShowView();
}
private static void ShowView()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
As Mark_Gravell alluded to, Application.Run() blocks until the Form1 closes. You can open your forms on a separate thread, but that thread will be basically consumed by the form. And when you want the exe to exit, you'll have to manually kill each thread. See the following code. (It doesn't create a console window. I got this by creating a default WinForms app and changing the Program class)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApplication1
{
static class Program
{
static List<Thread> threads = new List<Thread>();
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
for (int i = 0; i < 10; i++)
{
StartThread();
System.Threading.Thread.Sleep(500);
}
//kill each thread so the app will exit, otherwise, the app won't close
//until all forms are manually closed...
threads.ForEach(t => t.Abort());
}
static void StartThread()
{
Thread t = new Thread(ShowForm);
threads.Add(t);
t.Start();
}
static void ShowForm()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
Create the app as a console app and then call Application.Run as Marc said when you need a form.
You can also create your own ApplicationContext
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(AppController.Instance);
}
And within AppController.cs
namespace MyApplication
{
public class AppController
{
static AppController _AppController;
public LoginWIndow LoginWIndow;
//Constructor
public void AppController()
{
//Do what you will here, Start login form, bind events, w.e :)
if(true) //Your check
{
ShowLoginWindow();
}
}
public void ShowLoginWindow()
{
LoginWIndow = new LoginWIndow();
LoginWIndow.ClosedForm += new FormClosedEventHander(ExitApplication);
LoginWIndow.Show();
}
public void ExitApplication(Object Sender, FormClosedEventArgs Args)
{
//Some shutdown login Logic, then
Application.Exit();
}
static AppController Instance
{
get
{
if(_AppController == null)
{
_AppController = new AppController();
}
return _AppController;
}
}
}
}

Categories

Resources