I'm creating a media player.
So far I can open a file type with my C# application by double clicking on the file. But I want to open multiple files by selecting them and opening them at once..
My code goes as follows:
App.xmal.cs
protected override void OnStartup(StartupEventArgs e)
{
if (e.Args != null && e.Args.Length > 0)
{
this.Properties["ArbitraryArgName"] = e.Args[0];
}
base.OnStartup(e);
}
MainWindow.xmal.cs
if (Application.Current.Properties["ArbitraryArgName"] != null)
{
string fname = Application.Current.Properties["ArbitraryArgName"].ToString();
if (fname.EndsWith(".mp3") || fname.EndsWith(".wma") || fname.EndsWith(".wav") || fname.EndsWith(".mpg") ||
fname.EndsWith(".mpeg") || fname.EndsWith(".mp4") || fname.EndsWith(".wmv") )
{
doubleclicktrack(fname);
}
else
{
this.Close();
}
}
This code works fine with one file, but how to change this in order to open multiple files at once by selecting multiple files and opening them at once (by pressing enter key).
You will have to look into developing shell extensions in order to achieve what you want. Just by using the registry to associate file types with your app, you are limited to passing just one file per command, which will end up opening your app once per file (which you have confirmed).
I guess you could also implement your app to allow only one instance running globally. That way, whenever a command comes in to open one more file, you could for example add it to a playlist or something.
Note that shell extensions have to be written in C++, Microsoft strongly advises to avoid managed code for this purpose.
You can find the documentation starting point here: https://msdn.microsoft.com/en-us/library/windows/desktop/bb776778(v=vs.85).aspx
FileOpenPicker can do that (Code for UWP or Windows 8.1 desktop, with Windows 8.1 phone it's a bit trickier):
private static readonly string[] FileTypes = {
"aac", "adt", "adts", "mp3", "m3a", "m4a", "mpr", "3gp", "3g2",
"flac", "wav", "wma" };
...........
FileOpenPicker picker = new FileOpenPicker();
picker.SuggestedStartLocation = PickerLocationId.MusicLibrary;
foreach (String fileType in FileTypes)
picker.FileTypeFilter.Add("." + fileType);
var list = await picker.PickMultipleFilesAsync();
FYI Your manifest must declare "Music Library" in Capabilities
Related
C# Windows Forms.
I have successfully used Application Settings to save and load user settings for the values of controls on my form.
I have a checkbox and code where I can set whether this happens automatically (at application start and close), or not.
I also have a menu so I can load them and save them during runtime.
This is all using the default user.config.
Example.
In Application settings I have (for one of the items, which is a radio button called RbBitRate6Mbps):
Name: BitRate6Mbps
Type: String
Scope: User
Value: False
To save the settings I have a menu item, Save Defaults. This runs:
if (RbBitRate6Mbps.Checked == true)
{
Settings.Default["BitRate6Mbps"] = "True";
}
else
{
Settings.Default["BitRate6Mbps"] = "False";
}
Settings.Default.Save();
To load the settings back in I have a menu item, Load Defaults. This runs:
if (Settings.Default["BitRate6Mbps"].ToString() == "True")
{
RbBitRate6Mbps.Checked = true;
}
else
{
RbBitRate6Mbps.Checked = false;
}
There are about 10 other controls I save and load (text boxes, check boxes and radio buttons), in the rest of the above code.
This is all working with no issues.
Now I would like to have several sets of these settings, each will contain some identical values and some different ones.
Each will have a different file name and be saved into a custom location (which will be the app folder, by default).
I do not mind what format the file is (xml, ini, etc), but if it is the same as the default, this would be good.
I have created new menu items, Save Custom Settings and Load Custom Settings.
I have added a SaveFileDialog and a LoadFileDialog to hopefully be used for the above.
But if these are not necessay, that is good too.
This is where I have become stuck.
I have been searching for days for a clear example of how to do this.
I have been unable to find much. What I have found, I have been unable to understand the documentation.
I am thinking loading the settings back in will be the easier part?
But I also think, for saving the file, using:
Settings.Default.Save();
Will not accomplish my aims as it will just write to the default user.config file ?
Is what I want to do possible?
If so does anyone have any instructions and example code?
Update. I have installed a new Settings Provider and it is working well. It saves the XML to the app folder. I have also set up INI files to save the settings. Using both a custom path and custom file name. It allows for multiple INI files to be created. This also works extremely well.
Edit: Updated code (and instructions) so it is no longer necessary to create any custom folder manually. If it does not exist, it will be created.
The XML Settings Provider developers project is located here:
Settings Providers on Github
The INI file developers project (and demo) is located here:
C# WinForms Ini File demo on Github
Below are the instructions for setting up the new Settings Provider with an XML file and following that are the instructions for saving the settings to INI files (both types can be used in the same project at the same time, as I am doing here):
Using a new Settings Provider to save settings in an XML file:
1.
Setup the Application Settings (in Solution Explorer, right-click on the App. Then Select: Properties. Then open: Settings).
Name: txtFullName
Type: String
Scope: User
Value: John Doe
Name: txtSchool
Type: String
Scope: User
Value: Oxford
Name: txtClass
Type: String
Scope: User
Value: 4B
Name: chkActiveStudent
Type: bool
Scope: User
Value: True
2.
Install, from NuGet the new Settings Provider (in Solution Explorer, right-click on: References. Then Select: Manage NuGet Packages. Then search for: PortableSettingsProvider. Install it).
3.
In Program.cs modify static void Main(). Add to it the lines below.
//PortableSettingsProvider.SettingsFileName = "portable.config";
//PortableSettingsProvider.SettingsDirectory = "c:\\\testconfig\\\school";
//System.IO.Directory.CreateDirectory(PortableSettingsProvider.SettingsDirectory);
PortableSettingsProvider.ApplyProvider(Properties.Settings.Default);
If accepting the default settings (the config file, portable.config, will be created in the applications folder), a properly edited static void Main() entry would look like the below.
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//PortableSettingsProvider.SettingsFileName = "portable.config";
//PortableSettingsProvider.SettingsDirectory = "c:\\testconfig\\school";
//System.IO.Directory.CreateDirectory(PortableSettingsProvider.SettingsDirectory);
PortableSettingsProvider.ApplyProvider(Properties.Settings.Default);
Application.Run(new MyTestApp());
}
3a.
To choose a different filename and location, remove the comments (//) and change to your preference for filename and location (double slashes are needed between the folder names). In this example I use settings.config as the filename and c:\testconfig\school as the path). In this case a properly edited static void Main() entry would look like the below.
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
PortableSettingsProvider.SettingsFileName = "settings.config";
PortableSettingsProvider.SettingsDirectory = "c:\\testconfig\\school";
System.IO.Directory.CreateDirectory(PortableSettingsProvider.SettingsDirectory);
PortableSettingsProvider.ApplyProvider(Properties.Settings.Default);
Application.Run(new MyTestApp());
}
3b.
If you would like the settings directory to be created in a subfolder of the applications working directory, then change the code to include the subfolder name (in this example I use settings.config as the filename and Settings as the subfolder). In this case a properly edited static void Main() entry would look like the below.
static void Main()
{
Application.EnableVisualStyles();
PortableSettingsProvider.SettingsFileName = "settings.config";
var strSettingsDirectory = Directory.GetCurrentDirectory() + "\\Settings";
System.IO.Directory.CreateDirectory(strSettingsDirectory);
PortableSettingsProvider.SettingsDirectory = strSettingsDirectory;
PortableSettingsProvider.ApplyProvider(Properties.Settings.Default);
Application.Run(new MyTestApp());
}
4.
Still in Program.cs, add the following line to the bottom of the existing using section.
using Bluegrams.Application;
5.
On the form create some controls (these will correspond to the Application Settings made in step 1).
TextBox. Name: txtFullName
TextBox. Name: txtSchool
Textbox. Name: txtClass
Checkbox. Name: chkActiveStudent
Button. Name: btnLoadSettings Text: Load Config
Button. Name: btnSaveSettings Text: Save Config
6.
Enter the code for the Load Config buttons click events (btnLoadSettings).
private void btnLoadSettings_Click(object sender, EventArgs e)
{
txtName.Text = Properties.Settings.Default.txtName.ToString();
txtSchool.Text = Properties.Settings.Default.txtSchool.ToString();
txtClass.Text = Properties.Settings.Default.txtClass.ToString();
if (Properties.Settings.Default.chkActiveStudent == true)
{
chkActiveStudent.Checked = true;
}
else
{
chkActiveStudent.Checked = false;
}
}
7.
Enter the code for the Save Config buttons click events (btnSaveSettings).
private void btnSaveSettings_Click(object sender, EventArgs e)
{
Properties.Settings.Default.txtName = txtName.Text;
Properties.Settings.Default.txtSchool = txtSchool.Text;
Properties.Settings.Default.txtClass = txtClass.Text;
if (chkActiveStudent.Checked == true)
{
Properties.Settings.Default.chkActiveStudent = true;
}
else
{
Properties.Settings.Default.chkActiveStudent = false;
}
Properties.Settings.Default.Save();
}
8.
That’s it.
Run the app.
Load the settings using the first button).
Make some changes to the text on the controls.
Save them using the second button.
If you have not created a custom filename and/or path then in your app folder there should be a new file: portable.config.
Mine is located at: C:\Users\flakie\source\repos\TestApp\TestApp\bin\Debug
You can open the file in an txt/xml editor to verify the values were set.
If you run the app again, and load settings, you should see the new values.
The Code for Saving Settings to Multiple INI Files
The following instructions are easier to implement.
They do not require you to set-up the Application Settings as they are not used.
The settings will be saved in 1 or more INI files.
The path can be changed on-the-fly (though a default is set), as can the file name for the INI file.
Again it will be using the applications own folder as the default destination (for the INI files).
You will need to modify the Form.cs file only.
The demo (from the link above) is easy to understand and was enough to provide me with the knowledge to create this example (and I am a C# novice).
9.
Install, from NuGet, the INI files package (in Solution Explorer, right-click on: References. Then Select: Manage NuGet Packages. Then search for: PeanutButter.INI. Install it).
10.
In your Form.cs file (Form1.cs if you have not changed the name), add the following line to the bottom of the existing using section.
using PeanutButter.INIFile;
11.
In your Form.cs file, directly under the line, public partial class Form1 : Form, add the following single line of code.
private IINIFile _loadedConfig;
It should look like the below.
public partial class Form1 : Form {
private IINIFile _loadedConfig;
12.
On the form create two more buttons.
Button. Name: btnOpenIniFile Text: Open INI
Button. Name: btnSaveIniFile Text: Save INI
13.
Enter the code for the Open INI buttons click event (btnOpenIniFile).
private void btnOpenIniFile_Click(object sender, EventArgs e) {
using(OpenFileDialog OpenFileIni = new OpenFileDialog()) {
var strSettingsDirectory = Directory.GetCurrentDirectory() + "\\Settings";
System.IO.Directory.CreateDirectory(strSettingsDirectory);
OpenFileIni.InitialDirectory = strSettingsDirectory;
OpenFileIni.Filter = "INI File|*.ini";
OpenFileIni.RestoreDirectory = true;
OpenFileIni.CheckFileExists = true;
OpenFileIni.CheckPathExists = true;
OpenFileIni.Title = "Open an INI Settings File";
if (OpenFileIni.ShowDialog() == DialogResult.OK)
{
_loadedConfig = new INIFile(OpenFileIni.FileName);
txtName.Text = _loadedConfig.HasSetting("UserSettings", "txtName") ? _loadedConfig["UserSettings"]["txtName"] : "";
txtSchool.Text = _loadedConfig.HasSetting("UserSettings", "txtSchool") ? _loadedConfig["UserSettings"]["txtSchool"] : "";
txtClass.Text = _loadedConfig.HasSetting("UserSettings", "txtClass") ? _loadedConfig["UserSettings"]["txtClass"] : "";
if (_loadedConfig["UserSettings"]["chkActiveStudent"] == "Checked")
{
chkActiveStudent.Checked = true;
}
else
{
chkActiveStudent.Checked = false;
}
}
}
}
14.
Enter the code for the Save INI buttons click event (btnSaveIniFile).
private void btnSaveIniFile_Click(object sender, EventArgs e)
{
using (SaveFileDialog SaveFileIni = new SaveFileDialog())
{
var strSettingsDirectory = Directory.GetCurrentDirectory() + "\\Settings";
System.IO.Directory.CreateDirectory(strSettingsDirectory);
SaveFileIni.InitialDirectory = strSettingsDirectory;
SaveFileIni.Filter = "INI File|*.ini";
SaveFileIni.Title = "Save an INI Settings File";
if (SaveFileIni.ShowDialog() == DialogResult.OK)
{
_loadedConfig = new INIFile(SaveFileIni.FileName);
_loadedConfig["UserSettings"]["txtName"] = txtName.Text;
_loadedConfig["UserSettings"]["txtSchool"] = txtSchool.Text;
_loadedConfig["UserSettings"]["txtClass"] = txtClass.Text;
if (chkActiveStudent.Checked == true)
{
_loadedConfig["UserSettings"]["chkActiveStudent"] = "Checked";
}
else
{
_loadedConfig["UserSettings"]["chkActiveStudent"] = "UnChecked";
}
_loadedConfig.Persist();
}
}
}
15.
That’s it. Run the app.
Make some changes to the text on the textbox controls. Save them using the Save INI button.
You will be prompted for a file name. It can be anything you like (but in this example I used the name of the person I setup in the first textbox.
You do not need to enter the ini file extension. You can change the location if you wish.
Make some more changes to the text in the textBoxes but do not save them.
Click on the Open INI button. Browse to the ini file you just saved and open it.
The text you just modified, without saving, should now be changed to the text you saved into the ini file.
Use OpenExeConfiguration function to read settings and then Add/Update key values before Save it back. Finally you can ConfigurationManager.RefreshSection to refresh settings of a particular section.
Example at Link
static void AddUpdateAppSettings(string key, string value)
{
try
{
var configFile = ConfigurationManager
.OpenExeConfiguration(ConfigurationUserLevel.None);
var settings = configFile.AppSettings.Settings;
if (settings[key] == null)
{
settings.Add(key, value);
}
else
{
settings[key].Value = value;
}
configFile.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(configFile.AppSettings.SectionInformation.Name);
}
catch (ConfigurationErrorsException)
{
Console.WriteLine("Error writing app settings");
}
}
I have a Xamarin Project where I generate a .pdf file from scratch and save it in my local storage. This works perfectly fine and can find it and open it in the disk where I saved it. However, I need to open the .pdf file immediately after creation programmatically.
I already tried different variations using Process and ProcessStartInfo but these just throw errors like "System.ComponentModel.Win32Exception: 'The system cannot find the file specified'" and "'System.PlatformNotSupportedException'".
This is basically the path I am trying to open using Process.
var p = Process.Start(#"cmd.exe", "/c start " + #"P:\\Receiving inspection\\Inspection Reports\\" + timestamp + ".pdf");
I also tried ProcessStartInfo using some variations but I'm getting the same errors all over and over.
var p = new Process();
p.StartInfo = new ProcessStartInfo(#"'P:\\Receiving inspection\\Inspection Reports\\'" + timestamp + ".pdf");
p.Start();
The better way is that use LaunchFileAsync method to open file with browser. You could create FileLauncher DependencyService to invoke uwp LaunchFileAsync method from xamarin share project.
Interface
public interface IFileLauncher
{
Task<bool> LaunchFileAsync(string uri);
}
Implementation
[assembly: Dependency(typeof(UWPFileLauncher))]
namespace App14.UWP
{
public class UWPFileLauncher : IFileLauncher
{
public async Task<bool> LaunchFileAsync(string uri)
{
var file = await Windows.Storage.StorageFile.GetFileFromPathAsync(uri);
bool success = false;
if (file != null)
{
// Set the option to show the picker
var options = new Windows.System.LauncherOptions();
options.DisplayApplicationPicker = true;
// Launch the retrieved file
success = await Windows.System.Launcher.LaunchFileAsync(file, options);
if (success)
{
// File launched
}
else
{
// File launch failed
}
}
else
{
// Could not
}
return success;
}
}
}
Usage
private async void Button_Clicked(object sender, EventArgs e)
{
await DependencyService.Get<IFileLauncher>().LaunchFileAsync("D:\\Key.pdf");
}
Please note if you want to access D or C disk in uwp, you need add broadFileSystemAccess capability. for more please refer this .
Update
If the UWP files are network based, not local zone based, you could use Xamarin.Essentials to open file with browser. And you must specify the privateNetworkClientServer capability in the manifest. For more please refer this link.
I have a problem with the below code. I want to scan a document by clicking a button in a WinForms C# application.
I use WIA, Visual studio and the scanner Fujitsu N7100A working with Windows 8. I am following a tutorial online for using WIA.
But the program doesn't run as expected. It seems to break down at the Transfer method.
// Create a DeviceManager instance
var deviceManager = new DeviceManager();
// Create an empty variable to store the scanner instance
DeviceInfo firstScannerAvailable = null;
// Loop through the list of devices to choose the first available
AddLogs(deviceManager.DeviceInfos.Count.ToString(), filename);
foreach (DeviceInfo d in deviceManager.DeviceInfos)
{
if (d.Type == WiaDeviceType.ScannerDeviceType)
{
firstScannerAvailable = d;
}
}
// Connect to the first available scanner
var device = firstScannerAvailable.Connect();
// Select the scanner
var scannerItem = device.Items[0];
// Retrieve a image in JPEG format and store it into a variable
var imageFile = (ImageFile)scannerItem.Transfer(FormatID.wiaFormatPNG);
//Save the image in some path with filename
var path = #"C:\Documents\scan.png";
if (File.Exists(path))
{
File.Delete(path);
}
// Save image !
imageFile.SaveFile(path);
I just have to remove the addition of lines in the file of log.
This is much more of a workaround since i have no idea about your scanner.
I would assume that all scanners has a drive where they store their scanned documents, like mine, So i would suggest that you read all available drives loop through them check for DriveType and VolumeLabel and then read it's files and copy the document where you want
Something like this :
foreach (var item in DriveInfo.GetDrives())
{
//VolumeLabel differs from a scanner to another
if (item.VolumeLabel == "Photo scan" && item.DriveType == DriveType.Removable)
{
foreach (var obj in Directory.GetFiles(item.Name))
{
File.Copy(obj, "[YOUR NEW PATH]");
break;
}
break;
}
}
Finaly a TWAIN application work with this scanner. I will work with that. I don't said why do that work with TWAIN and not with WIA but that the reality. Sorry for this waste of time. Thank you for the answers. Have a nice day.
I am currently solving this very problem. It seems the N7100A driver sets the Pages property of the device to 0, which should mean continous scanning, but the transfer method is unable to handle this value. You must set that property to 1:
var pages = 1;
// Not all devices have this property, but Fujitsu N7100A has.
device.Properties["Pages"]?.set_Value(ref pages);
I think the problem is here
var scannerItem = device.Items[0];
as WIA indexes are NOT zero based so it should be 1 instead
var scannerItem = device.Items[1];
I have a Winform program I wrote for a university so they could run test files.
The program is targeted at .NET 4.5 and was developed and run on Windows 7.
To make the running of files easy for the technicians I added the ability to save the paths to the test files. The file path is stored in a settings file (ProgSettings.settings) under the variable "RunNames".
When the save button is pressed I run a validation to ensure the test file at the end of the path exists and is valid before adding it to the RunNames list:
/*
*Function: SaveButton_Click(sender, e)
*Notes: responds to the button click "Save"
* tries to save file (if valid) to settings
*/
private void SaveButton_Click(object sender, EventArgs e)
{
if (ValidateFile(TrackFileName.Text))
{
string displayName = updateLinkNames(TrackFileName.Text).ToUpper();
if (!ListOfTracks.Items.Contains(displayName))
{
ListOfTracks.Items.Add(displayName);
runNames.Add(TrackFileName.Text);
}
updateSettings();
}
}
/*
*Function: ValidateFile(fileName)
*Notes: called from save button click
* checks validity of the file path
*/
private bool ValidateFile(string fileName)
{
fileName = fileName.ToUpper();
FileToRun.FileName = fileName;
validFile = System.IO.File.Exists(fileName);
if(fileName != null && fileName != "" && fileName.EndsWith(".TXT") && validFile)
{
return true;
}
else
{
return false;
}
}
/*
*Function: updateSettings()
*Notes: updates the settings with the valid path
*/
private void updateSettings()
{
string value = String.Join(",", runNames.Select(i => i.ToString()).ToArray());
ProgSettings.Default.RunNames = value;
ProgSettings.Default.Save();
}
(For those of you unfamiliar with .settings they store the basic types available on C#, there are ways to include arrays as well but the simplest solution is to concatenate the different parts of the array in a string with a separator - in my case ",").
Then when I load the program again I populate a list of checkboxes using the a getSavedFiles() function below.
private List<string> getSavedFiles()
{
string localRunNames = ProgSettings.Default.RunNames.ToUpper();
string[] arr = localRunNames.Split(',').Select(s => Convert.ToString(s)).ToArray();
return arr.Cast<String>().ToList();
}
The settings works correctly on both my work computer and my personal laptop I did testing on. However, now the program is in use at the university they are saying that after shutting down the computer the next time the run the program all the saved file paths are gone.
Is this due to how to how the university managers users accounts on the computer? Or is there some other reason for this?
Was there another alternative to storing setting information for cases where .settings files don't work? (The only other solution I can think of is having the program write a config.txt file which I would prefer not to do encase the application is used somewhere it won't having writing permissions)
Below is a link to a question about the best practice to save application settings:
Best practice to save application settings
Using c#, Windows Store App, VS 2013
Try to open File Picker, using next simple code:
private async void OkBtnClick(IUICommand command)
{
if (this.EnsureUnsnapped())
{
FileOpenPicker fop = new FileOpenPicker();
fop.FileTypeFilter.Add(".png");
fop.FileTypeFilter.Add(".jpg");
fop.FileTypeFilter.Add(".jpeg");
fop.ViewMode = PickerViewMode.Thumbnail;
fop.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
StorageFile requestedFile = await fop.PickSingleFileAsync();
if (requestedFile != null)
{
//TODO:
}
}
}
internal bool EnsureUnsnapped()
{
// FilePicker APIs will not work if the application is in a snapped state.
// If an app wants to show a FilePicker while snapped, it must attempt to unsnap first
bool unsnapped = ((ApplicationView.Value != ApplicationViewState.Snapped)
|| ApplicationView.TryUnsnap());
if (!unsnapped)
{
Extensions.NotifyUser("Cannot unsnap app...", statusNotificationBlock);
}
return unsnapped;
}
Also add capability in appmanifest file for Pictures Library:
But during running got exception : System.UnauthorizedAccessException on line StorageFile requestedFile = await fop.PickSingleFileAsync();.
Question: Why I got this exception if all required access provided, Also i try to launch VS2013 with Administrator rights - result - same.
For creating this code use this article