As the title say.
I know how to do this in C# only, but when trying to do this with WPF I can't find out where or what to add to read the filename when the program starts.
public static void Main(string[] args)
{
if (Path.GetExtension(args[0]) == ".avi" || Path.GetExtension(args[0]) == ".mkv")
{
string pathOfFile = Path.GetFileNameWithoutExtension(args[0]);
string fullPathOfFile = Path.GetFullPath(args[0]);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1(pathOfFile, fullPathOfFile));
}
else
{
MessageBox.Show("This is not a supported file, please try again..");
}
}
Found the solution. Thanks for your help :)
I'll post what I did if anyone else needs it ..
In App.xaml i added Startup="Application_Startup
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="WpfApplication1.App"
StartupUri="MainWindow.xaml"
Startup="Application_Startup">
<Application.Resources>
<!-- Resources scoped at the Application level should be defined here. -->
</Application.Resources>
</Application>
And in App.xaml.cs i added these lines:
public static String[] mArgs;
private void Application_Startup(object sender, StartupEventArgs e)
{
if (e.Args.Length > 0)
{
mArgs = e.Args;
}
}
Last i had to add some information in the MainWindow class.
public MainWindow()
{
this.InitializeComponent();
String[] args = App.mArgs;
}
To get the data you want, you use System.IO.Path
Watch out for the Using statement. if you only use Ex. Path.GetFileNameWithoutExtension you will get a reference error. Use System.IO.Path when getting your data.
You need to find some entry point (like OnLoad event for your main window) and then access the command line arguments like so:
string[] args = Environment.GetCommandLineArgs();
Double-click the App.xaml file in Solution Explorer. You can add the Startup event. Its e.Args property gives you access to the command line arguments.
I know the topic is old but for someone searching for something similar it might be helpful. I was trying to add this feature to my program (starting the program by dropping a file on top of the EXE) and the solution was very simple and it came from here.
My program was just messing with a couple of cells in Excel file. So it was pretty obvious that it should run and do that stuff just by dropping the excel file on it.
So I added this into the Form constructor after the component initializing and it works flawlessly for me :
public Form1()
{
InitializeComponent();
string[] args = Environment.GetCommandLineArgs();
filePathTextBox.Text = (args.Length > 1 && (Path.GetExtension(args[1]) == ".xlsx" ||
Path.GetExtension(args[1]) == ".xls")) ? args[1] : "";
}
I noticed that the first argument in args is the Path of my program, so I tested and apparently the second argument is the file path of the file I'm dropping on the exe, that's why I'm using args[1].
I would like to be corrected if I'm wrong but for now everything is working fine with my program.
You can use this for Mediaelement.
public MainWindow()
{
this.InitializeComponent();
doubleclickevent();
}
private void doubleclickevent()
{
string[] args = Environment.GetCommandLineArgs();
string[] arr = new string[]
{
".MP4",
".MKV",
".AVI"
};
foreach (string element in args)
{
foreach (string s in arr)
{
if (element.EndsWith(s))
{
MediaElement.Source = new Uri(#element, UriKind.RelativeOrAbsolute);
MediaElement.LoadedBehavior = MediaState.Play;
}
else { return; }
}
}
}
When you drag and drop files from Windows onto an EXE the EXE is launched and provided the file names as command line arguments.
public MainWindow()
{
string[] args = Environment.GetCommandLineArgs();
foreach (var s in args)
{
//do something with s (the file name)
}
}
Related
I created an WPF application the use a viewer for file I set the application as default application for this application (filename.myapp), now if I try to open the file it will start the application but I need to know how to get this file location and name so I can use it in the application.
If I understood your question correctly you want to know the name of the file that was double-clicked/opened with your application associated.
It is the second item in the args array of your start up event:
private void Application_Startup(object sender, StartupEventArgs e)
{
...
if(e.Args.Length > 1)
{
var filename = e.Args[1]);
}
...
}
This is how I did it in the end:
var args = Environment.GetCommandLineArgs();
if (args.Length > 1)
{
var fileName= args[1];
}
I have a C# WPF application which I want to be able to open from another existing application, which was written in VB.net. As far as the c# application goes, I think I know how to get command line parameters that are passed to it two different ways, which I got while researching google and using others' answers.
App.xaml Header
<Application x:Class="ChallengeHandler.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ChallengeHandler"
Startup="Application_Startup">
App.xaml.cs Method 1
private void Application_Startup(object sender, StartupEventArgs e)
{
string[] args = Environment.GetCommandLineArgs();
if (args.Length < 1)
{
MessageBox.Show("No parameter provided. Failed to run.");
Shutdown();
}
else
{
MainWindow wnd = new MainWindow(args[0]);
wnd.Show();
}
}
The above method will result in the application opening but none of the data, which relies on the parameter, is populated. So the comboboxes and stuff in the views are just empty. That fails.
App.xaml.cs Method 2
private void Application_Startup(object sender, StartupEventArgs e)
{
if (e.Args.Length < 1)
{
MessageBox.Show("No parameter provided. Failed to run.");
Shutdown();
}
else
{
MainWindow wnd = new MainWindow(e.Args[0]);
wnd.Show();
}
}
This method just shows the error messagebox each time, as the args is empty.
I have a feeling the issue is when I'm trying to open the application from the VB.NET application and pass the string parameter to the c# app from there. But I am out of ideas on how to pass a string like a command line parameter from the VB.net code.
Calling from a VB.net Application
Dim sPath As String = Environment.GetFolderPath(Environment.SpecialFolder.Programs) + "\Microsoft\ChallengeHandler.appref-ms"
Dim pHelp As New ProcessStartInfo
If System.IO.File.Exists(sPath) Then
pHelp.FileName = sPath
pHelp.Arguments = "097"
pHelp.UseShellExecute = True
pHelp.WindowStyle = ProcessWindowStyle.Normal
Dim proc As Process = Process.Start(pHelp)
End If
I have tried the VB code without the
pHelp.UseShellExecute = True
pHelp.WindowStyle = ProcessWindowStyle.Normal
with no avail; I added them in the hope the shell execute would force the parameters as command line parameters. I have also tried this in VB:
2nd VB Method
Dim sPath As String = Environment.GetFolderPath(Environment.SpecialFolder.Programs) + "\Microsoft\ChallengeHandler.appref-ms"
If System.IO.File.Exists(sPath) Then
System.Diagnostics.Process.Start(sPath, "097")
End If
Any insight would be GREATLY appreciated! Thanks.
I see you're using "\Microsoft\ChallengeHandler.appref-ms". This is a ClickOnce application. Getting the parameters for a ClickOnce application is completely different from a normal application. You need to use ApplicationDeployment.CurrentDeployment.ActivationUri.Query and HttpUtility.ParseQueryString for retrieving them.
I believe to send them across you'll have to add them to the launch url by using "?param=value". I've only tried launching it from a web page, so I'm unsure if this is how it works.
The method you're currently using is valid for normal application. If you can locate the exe and launch that directly, you should be fine.
I created 2 projects: Line command C# invoker and a WPF Test application;
The invoker code on Program.cs:
namespace WPFInvoker
{
class Program
{
static void Main(string[] args)
{
Process.Start(#"C:\Users\...\bin\Debug\WPF_Test.exe", "example_parameter");
}
}
}
Then on the WPF App.xaml I have the startup event app_Startup and the main form MainWindow.xaml:
<Application x:Class="WPF_Test.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPF_Test"
Startup="app_Startup"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
And the App.xaml.cs code is:
namespace WPF_Test
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
void app_Startup(object sender, StartupEventArgs e)
{
if (e.Args != null && e.Args.Length > 0)
{
MessageBox.Show(e.Args[0]);
}
else
{
MessageBox.Show("e.Args is null");
}
}
}
}
When I open the WPFTest.exe with a double click shows a MessageBox with the message "e.Args is null":
Application without parameters
But if I open the WPFTest application through WPFInvoker:
Application with parameter
Finally I close the MessageBox and the MainWindow.xaml its shown.
I try to add command line support to my Winforms application so i changed this:
[STAThread]
static void Main(string[] args)
{
if (args.Length == 0)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
else
{
}
}
But i try to return string to the user in case the user insert the command MyExeFile.exe help to show the user all the command line options and i don't know how so i wonder maybe it's better to use other EXE file ?
You could see if the arguments contains "help". If it does, display a message to the user and then exit the app before loading the main form.
static void Main(string[] args)
{
if (args.ToList().Contains("help"))
{
MessageBox.Show("Help is on the way...");
return;
}
...
}
You'll need to add the following using directive:
using System.Linq;
If you want the help text to appear to show in a Console window, just create a form that looks like a console window.
Create a new Form, with a single TextBox in it, and configure the TextBox:
BackColor: Black
ForeColor: White
Dock: Fill
MultiLine: True
ReadOnly: True
Text: Whatever you want to show
Then show it using:
static void Main(string[] args)
{
if (args.ToList().Contains("help"))
{
new ConsoleLookalikeForm().ShowDialog();
return;
}
...
}
This took about 2 minutes to make:
This is a weird one! I am working on an application that reads vCard files, which contain contact etc. information for a person. Each file may contain separate 'sections' that each contain the details for one person, which are separated by BEGIN:VCARD [data here] END:VCARD.
To enable my users to view all of the different details, I've allowed my program to populate the textboxes in my app with the details and then open a new Window and do this with that one, but for each of the different sections in the file.
The problem comes about when my program opens when a vCard file has been double clicked in Explorer. It keeps looping through the vCard. I don't know what to do, but below is my problematic code:
public void readVcard(string fname)//Reads vCard and then loops through sections
{
try
{
using (StreamReader r = new StreamReader(fname))
{
string input = File.ReadAllText(fname);//read through file
String[] vArray = input.Split(new string[] { "BEGIN:VCARD" }, StringSplitOptions.None);
int i;
for (i = 1; i < vArray.Length; i++)
{
MainWindow a = new MainWindow();
a.parser(vArray[i]); //Parser is the function that populates the app
a.Show();
}
return;
}
}...
This function is called from here:
void MainWindow_Loaded(object sender, RoutedEventArgs e)//Processes a file when opened externally
{
if (Application.Current.Properties["ArbitraryArgName"] != null)
{
string fname = Application.Current.Properties["ArbitraryArgName"].ToString();
readVcard(fname);
}
}
If anyone could help, it would be greatly appreciated.
I think that Artyom is on the right track.
Every time you create another MainWindow and load it you will be getting the current applications argurment and jumping back in to readVcard, which will process the same vCard that you are already processing and open yet another MainWindow which will continue the process.
Consider moving all of the code you have inside of MainWindow_Loaded() to the Startup event for your application. That way it will only get called once when your program first loads, instead of every time you create a new window.
To do this you need to register for the event in your App.xaml file like so:
<Application x:Class="MyProgram.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="Application_Startup">
</Application>
And then in the code behind App.xaml you put your code for reading the vCard. Like this:
namespace MyProgram
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
if (Application.Current.Properties["ArbitraryArgName"] != null)
{
string fname = Application.Current.Properties["ArbitraryArgName"].ToString();
readVcard(fname);
}
}
}
}
When you create and show new MainWindow (a.Show()), the MainWindow_Loaded event fires again and it again calls a readVcard method. So there is an infinite loop.
Or may be not really infinite, because, I belive, some time later a StackOverflowException may happen.
You just need to review startup logic, so readVcard will launch not in the MainWindow_Loaded event, but, for example, in the Main method (in program.cs file). Or you may add some flag, which will be set when readVcard method first called.
I get it! I've now got the following code in App.xaml.cs:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
if (e.Args != null && e.Args.Count() > 0)
{
this.Properties["ArbitraryArgName"] = e.Args[0];
}
base.OnStartup(e);
if (Application.Current.Properties["ArbitraryArgName"] != null)
{
string fname = Application.Current.Properties["ArbitraryArgName"].ToString();
MainWindow mw = new MainWindow();
mw.readVcard(fname);
}
}
}
It works fine! Thanks everyone. BTW the following blog contains the command-line info I originally used if anyone needs it: http://blogs.msdn.com/b/avip/archive/2008/10/27/wpf-supporting-command-line-arguments-and-file-extensions.aspx.
I have so many issues with my project, i really don't know where to begin. First off, i get an error "an object reference is required for non-static field, method or property". It underlines retPath (the line: DriveRecursion_results.DriveRecursion(retPath);). I have no idea how to fix this.
THe other thing i'm still stumped on is how to populate a listview on my Windows Form. What i want is a list of files that need to be renamed (versus a list of all files in my list.)
Can anybody help? I have been struggling miserably with this for several hours now.
Here is my code:
Form1.cs:
namespace FileMigration
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
FolderSelect("Please select:");
}
public string FolderSelect(string txtPrompt)
{
//Value to be returned
string result = string.Empty;
//Now, we want to use the path information to population our folder selection initial location
string initialCheckoutPathDir = (#"C:\");
System.IO.DirectoryInfo info = new System.IO.DirectoryInfo(initialCheckoutPathDir);
FolderBrowserDialog FolderSelect = new FolderBrowserDialog();
FolderSelect.SelectedPath = info.FullName;
FolderSelect.Description = txtPrompt;
FolderSelect.ShowNewFolderButton = true;
if (FolderSelect.ShowDialog() == DialogResult.OK)
{
string retPath = FolderSelect.SelectedPath;
if (retPath == null)
{
retPath = "";
}
DriveRecursion_Results ds = new DriveRecursion_Results();
ds(retPath);
result = retPath;
//Close this form.
}
return result;
}
}
}
Here is DriveRecursion_Results.cs:
namespace FileMigration
{
public partial class DriveRecursion_Results : Form
{
public DriveRecursion_Results()
{
InitializeComponent();
}
private void fileOutput_SelectedIndexChanged(object sender, EventArgs e)
{
}
public void DriveRecursion(string retPath)
{
// string[] files = Directory.GetFiles(retPath, "*.*", SearchOption.AllDirectories);
string pattern = " *[\\~#%&*{}/<>?|\"-]+ *";
string replacement = "";
Regex regEx = new Regex(pattern);
string[] fileDrive = Directory.GetFiles(retPath, "*.*", SearchOption.AllDirectories);
List<string> filePath = new List<string>();
foreach (string fileNames in fileDrive)
{
if (regEx.IsMatch(fileNames))
{
filePath.Add(fileNames);
//I tried adding my listview (fileOptions) here but I cannot for some reason
}
}
}
}
}
ANY help would really be appreciated :( Does anybody have any ideas on how to change my code so it actually works?
Issue 1: your function is static. If it stops being such, this will work. This is because a static function does not have this hidden 'this' argument - the reference to object it acts upon. So, it can only access static data members, not regular ones.
You can't add the items to your listview from that level because the listview is non-static and the method DriveRecursion is static. I would start by changing the DriveRecursion method to be non-static or return a list of file paths.
You are not able to add items to your list view because you are trying to add them from a static method.
Since it is static there is no ListView because there isn't actually a Form to add things to. You will need to make DriveRecursion() not static in order to add things to the ListView.
Additionally, when you make DriveRecursion() not static, you will need a way to let Form1 know which DriveRecursion_Results class to populate.
Another approach you could take is having Form1 return retPath to DriveRecursion_Results.
Edit
Removed irrelevant parts of my original answer
I have copied your code exactly how you posted it. And then made the following changes to FolderSelect() in Form1.cs When I run this code. I can get the second window to pop up, but not the other window to close, because that will cause the application to quit.
Please make sure you have ds.Show() and do at some point call ds.DriveRecursion(retPath)
Modified FolderSelect(string) in Form1.cs:
private void FolderSelect( string txtPrompt )
{
//Value to be returned
string result = string.Empty;
//Now, we want to use the path information to population our folder selection initial location
string initialCheckoutPathDir = ( "C:\\" );
System.IO.DirectoryInfo info = new System.IO.DirectoryInfo( initialCheckoutPathDir );
FolderBrowserDialog FolderSelect = new FolderBrowserDialog();
FolderSelect.SelectedPath = info.FullName;
FolderSelect.Description = txtPrompt;
FolderSelect.ShowNewFolderButton = true;
if( FolderSelect.ShowDialog() == DialogResult.OK )
{
string retPath = FolderSelect.SelectedPath;
if( retPath == null )
{
retPath = "";
}
DriveRecursion_Results ds = new DriveRecursion_Results();
ds.DriveRecursion( retPath );
ds.Show();
result = retPath;
//Close this form.
}
return;
}