Run time/length info for all media files in a folder - c#

If there are multiple media files in a folder like so:
MediaFiles(folder)
-> file1.mp4
-> file2.mp4
...
When we select all the files and
Right Click -> Properties
In the Properties windows on the Details Tab there is a Length field that shows the total runtime of the media files together like this:
Is it possible to get this info using C#?

As indicated in this link, with the help of the Microsoft.WindowsAPICodePack-Shell nuget package, you can get the total length as follows;
static void Main(string[] args)
{
DirectoryInfo dir = new DirectoryInfo(#"C:\to\your\path");
FileInfo[] files = dir.GetFiles("*.mp4");
var totalDuration = files.Sum(v => GetVideoDuration(v.FullName));
}
public static double GetVideoDuration(string filePath)
{
using (var shell = ShellObject.FromParsingName(filePath))
{
IShellProperty prop = shell.Properties.System.Media.Duration;
var t = (ulong)prop.ValueAsObject;
return TimeSpan.FromTicks((long)t).TotalMilliseconds;
}
}

You can use windows media object and load the file and then get its properties.
Read the folders file and loop through with each file and load them and read the property you want and may be store in DB.
Please refer from Microsoft site go here to check the more detail

Related

Is there a way to publish a C# console app running on the .NET Framework with System.media Soundplayer?

When I publish my app and run it, it says that it couldn't find the path to sound.wav file and it crashes.
I put my sound files into a bin/Debug/sound folder, and use it like this in my code:
public void OpenInventory()
{
SoundPlayer inventory = new SoundPlayer("sound/selection2.wav");
inventory.Play();
try
{
var item = Item.itemList.SingleOrDefault(x => x.Amount == 0);
if (item != null)
{
Item.itemList.Remove(item);
}
var loot = Loot.lootList.SingleOrDefault(c => c.Amount == 0);
if (loot != null)
{
Loot.lootList.Remove(loot);
}
}
catch
{
inter.InventoryArray();
UseItem();
}
inter.InventoryArray();
UseItem();
}
You can embed the file as a resource and access it using a resource stream. Something like this:
strong resource name = "MyNamespace.Sound.selection2.wav";
var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
var inventory = new SoundPlayer(stream);
To embed the WAV file, change "Build Action" to "Embedded Resource" on the file properties in solution explorer.
The tricky part of using such embedded resources is figuring out the correct resource name. By default it uses a namespace-like name for the resource. So for example, if the default namespace for your app is "MyNamespace", the file is in a folder named "Sound", and the file is named "selection2.wav", then the resource will be named "MyNamespace.Sound.selection2.wav".
GetManifestResourceStream: https://learn.microsoft.com/en-us/dotnet/api/system.reflection.assembly.getmanifestresourcestream?view=netframework-4.8#system-reflection-assembly-getmanifestresourcestream(system-string)
SoundPlayer stream constructor: https://learn.microsoft.com/en-us/dotnet/api/system.media.soundplayer.-ctor?view=netframework-4.8#system-media-soundplayer-ctor(system-io-stream)
Embedded resource names: https://learn.microsoft.com/en-us/dotnet/core/resources/manifest-file-names

How to include file in Source Control and edit it later

I'm creating a game using C# and trying to incorporate a CSV for parsing previous scores into a leaderboard and also writing to the file when a player finishes their game.
This is the data stored relating to a score
If this was a sole project I would store the csv in the bin > Debug folder and pass the file path to a StreamReader. Although, this is a group project using Azure Devops/TFS as source control so I'm not too sure what way is best to do this.
I have tried storing the CSV in the Resources of the project but I didn't realise this embeds the file in the project and only allows for reading from the file.
The CSV is currently read like:
var file = Properties.Resources.highscores;
char[] splitter = "\r\n".ToCharArray();
string[] scoresCsv = Properties.Resources.highscores.Split(splitter);
foreach (string score in scoresCsv)
{
if(!String.IsNullOrEmpty(score))
{
var values = score.Split(',');
highScores.Add(new HighScore(values[0], Convert.ToInt32(values[1]), Convert.ToDateTime(values[2])));
}
}
this.highScores = highScores.OrderByDescending(x => x.Score).ToList();
Select the "Team Explorer" window and go to "Source Control Explorer"
Here you will see a global view of the project.
You can add files to your project in any folder you wish outside of the actual source. If you want to you can add your bin folder into the source control and keep that file in the bin folder.
Where-ever you put the file you just need to know the location to it from your project and you are able to map to it and edit it in runtime.
Another option is to create a folder in the C:\ProgramData folder for your game and you can write the leaderboards directly into their C drive when they run the game. People would be able to modify the leaderboards but, obviously the game is for learning purposes of coding and usually you wouldn't store the leaderboards on the client side anyway it would be on a server.
This assumes that the high score data is not shared, and stores it locally. It doesn't require the file to be added to source control.
public class ScoreFileHandler
{
private static string appPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "YourAppName");
private static string scoreFileName = "highscores.txt";
private static string filePath = Path.Combine(appPath, scoreFileName);
public string ReadFile()
{
if (!Directory.Exists(appPath))
{
Directory.CreateDirectory(appPath);
}
if (File.Exists(filePath))
{
return File.ReadAllText(filePath);
}
return string.Empty; // TODO - caller needs to handle this
}
public void WriteFile(string csvScoreData)
{
if (!Directory.Exists(appPath))
{
Directory.CreateDirectory(appPath);
}
File.WriteAllText(filePath, csvScoreData);
}
}

UWP Parse folder from absolute or relative path

I want to parse a folder that the user can choose.
But if I understand, absolute paths are not allowed in UWP because the disks are not the same following the media (xbox, windows phone, windows desktop, ...) ?
So, I have a class called Parser that can parse the path that the user picks but now, only the current folder can be parsed.
This doesn't work :
Parser parser = new Parser(#"C:\a\b\c");
parser.createTreeView(tree);
Help me please. Thank you in advance.
EDIT : This is my Parser class =>
public TreeViewItem Parse(DirectoryInfo directoryInfo)
{
try
{
var directoryNode = new TreeViewItem { Header = directoryInfo.Name };
Convention convention = new Convention();
foreach (var directory in directoryInfo.GetDirectories())
{
directoryNode.Items.Add(Parse(directory));
System.Diagnostics.Debug.WriteLine("test : " + directory.Name);
}
foreach (var file in directoryInfo.GetFiles())
{
if (file.Name.Contains(EConvention.INSTALL))
{
listFiles.Add(file.FullName);
}
TreeViewItem item = new TreeViewItem
{
Header = Path.GetFileNameWithoutExtension(file.FullName),
Tag = file.FullName
};
directoryNode.Items.Add(item);
}
return directoryNode;
}
catch (System.UnauthorizedAccessException e)
{
//MessageDialog dialog = new MessageDialog(""+e.Message);
dialogAsync(e.Message);
return new TreeViewItem();
}
}
public void CreateTreeView(TreeView tree)
{
DirectoryInfo dir = new DirectoryInfo(pathToParse);
System.Diagnostics.Debug.WriteLine("dir exists ? "+dir.Exists);
if (dir.Exists)
{
System.Diagnostics.Debug.WriteLine("dir existe");
TreeViewItem root = new TreeViewItem() { Header = dir.Name };
root.Tag = dir;
tree.Items.Add(Parse(dir));
}
}
UWP apps do not have permission to access all files on the device. Apps can access certain file system locations by default. Apps can also access additional locations through the file picker, or by declaring capabilities. For more info, please see File access permissions
Although, we can use DirectoryInfo in UWP apps, but it can only work with the folders that UWP apps can access by default such as the install directory and local folder etc. Most types in the System.IO namespaces for UWP apps have the similar limitation. While dealing with files or folders in UWP, one important rule is Skip the path: stick to the StorageFile.
You can use a Folder​Picker to let the user choose a folder and then add it to your app's FutureAccessList or MostRecentlyUsedList to keep track of it. You can learn more about using these lists in How to track recently-used files and folders. After this, you will be able to retrieve the StorageFolder from FutureAccessList or MostRecentlyUsedList whenever you want to use it.
Once you have the StorageFolder, you can then use GetFilesAsync() or GetFoldersAsync() method in your Parse instead of DirectoryInfo.GetDirectories or DirectoryInfo.GetFiles method.

How to get all files in a StorageFolder in Windows Phone Runtime?

I want to get all files in a folder and its sub folders. but a flat query like this:
var allFiles = await myFolder.GetFilesAsync(Windows.Storage.Search.CommonFileQuery.OrderByName);
throws a ArgumentException exception:
A first chance exception of type 'System.ArgumentException' occurred
Additional information: Value does not fall within the expected range.
before I query subfolders one by one, isn't there any other way?
You want all the files and folder which are a descendent of the root folder, not just the shallow enummeration. For most folders the only way to enumerate all the contents and its subfolders content is:
Use StorageFolder.GetFilesAsync() for the files
Use StorageFolder.GetFoldersAsync() to retrieve the all the subfolders
Repeat recursively for all the subfolders you find in step 2.
There is a workaround for this if you are looking for a particular type of media. The instructions are here. These few combinations of locations and CommonFile/FolderQuery options will give a device deep search for media and return the ordered results.
Use CommonFileQuery.OrderByName This is a deep query too so the result will contain all of files from all of subfolders
AND IT WORKS! ;)
MSDN says that you get System.ArgumentException if:
You specified a value other than DefaultQuery from the CommonFileQuery enumeration for a folder that's not a library folder.
https://msdn.microsoft.com/en-us/library/windows/apps/BR211591.aspx
That is strange! Looks like a bug in GetFilesAsync method with all CommaonFileQuery options except DefaultQuery. It is working fine with DefaultQuery.
var allFiles = await myFolder.GetFilesAsync(CommonFileQuery.DefaultQuery);
Hope this helps!
I had the same problem, solved it by preloading file paths recursively:
private static List<string> mContentFilenames = new List<string>();
private static void preloadContentFilenamesRecursive(StorageFolder sf)
{
var files = sf.GetFilesAsync().AsTask().ConfigureAwait(false).GetAwaiter().GetResult();
if (files != null)
{
foreach (var f in files)
{
mContentFilenames.Add(f.Path.Replace('\\','/'));
}
}
var folders = sf.GetFoldersAsync().AsTask().ConfigureAwait(false).GetAwaiter().GetResult();
if (folders != null)
{
foreach (var f in folders)
{
preloadContentFilenamesRecursive(f);
}
}
}
private static void preloadContentFilenames()
{
if (mContentFilenames.Count > 0)
return;
var installed_loc = Windows.ApplicationModel.Package.Current.InstalledLocation;
var content_folder = installed_loc.GetFolderAsync("Content").AsTask().ConfigureAwait(false).GetAwaiter().GetResult();
if (content_folder != null)
preloadContentFilenamesRecursive(content_folder);
}
private static bool searchContentFilename(string name)
{
var v = from val in mContentFilenames where val.EndsWith(name.Replace('\\', '/')) select val;
return v.Any();
}
No idea why downvoted, there is no other way to get full filelist in WP8.1. MSFT for some strange reason corrupts its apis from version to version. Some of calls now returns "not implemented".

How do I get build details in a custom workflow activity?

I need to add a custom activity to the default workflow template to increase assembly versions at the earliest point possible in the build process.
What I would like to achieve is to create and map the exact same workspace (that is be created further down in the workflow) inside my custom activity so that I can check out an xml file, increase the version number held within, write it back to the xml file and check the xml file back in.
I'm aware that this workspace will be created later on in the workflow but that will be too late in the build process for what I'm trying to achieve, so instead of moving any of the activities or duplicating them in a position above my custom activity (this should be ok as this workspace will be deleted and recreated again later)
I think the details I need are the BuildDirectory, WorkspaceName and SourcesDirectory. Can anyone tell me how to achieve the creation of the workspace or how obtain this data in code?
the build will be carried out on a build server, and I am using TFS 2010 and c#.
Thanks in advance
I followed the series of blog articles by Ewald Hofman as a primer and created a custom activity that does the check-out, update and check-in of a GlobalAssemblyInfo file that I parse the current version from. My task is inserted at the top of the "Update Drop Location" which is right after it does the "Get the build" portion of the workflow. I just use require the IBuildDetail and a File Mask as arguments from which you can pull out the VersionControlServer to be able to access TFS. My code is below:
protected override string Execute(CodeActivityContext context)
{
// Obtain the runtime value of the input arguments.
string assemblyInfoFileMask = context.GetValue(AssemblyInfoFileMask);
IBuildDetail buildDetail = context.GetValue(BuildDetail);
var workspace = buildDetail.BuildDefinition.Workspace;
var versionControl = buildDetail.BuildServer.TeamProjectCollection.GetService<VersionControlServer>();
Regex regex = new Regex(AttributeKey + VersionRegex);
// Iterate of the folder mappings in the workspace and find the AssemblyInfo files
// that match the mask.
foreach (var folder in workspace.Mappings)
{
string path = Path.Combine(folder.ServerItem, assemblyInfoFileMask);
context.TrackBuildMessage(string.Format("Checking for file: {0}", path));
ItemSet itemSet = versionControl.GetItems(path, RecursionType.Full);
foreach (Item item in itemSet.Items)
{
context.TrackBuildMessage(string.Format("Download {0}", item.ServerItem));
string localFile = Path.GetTempFileName();
try
{
// Download the file and try to extract the version.
item.DownloadFile(localFile);
string text = File.ReadAllText(localFile);
Match match = regex.Match(text);
if (match.Success)
{
string versionNumber = match.Value.Substring(AttributeKey.Length + 2, match.Value.Length - AttributeKey.Length - 4);
Version version = new Version(versionNumber);
Version newVersion = new Version(version.Major, version.Minor, version.Build + 1, version.Revision);
context.TrackBuildMessage(string.Format("Version found {0}", newVersion));
return newVersion.ToString();
}
}
finally
{
File.Delete(localFile);
}
}
}
return null;
}

Categories

Resources