How to read MSI properties in c# - c#

I want to read properties of MSI in C# in desktop application.I am using following code:
public static string GetMSIProperty( string msiFile, string msiProperty)
{
string retVal= string.Empty ;
Type classType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
Object installerObj = Activator.CreateInstance(classType);
WindowsInstaller.Installer installer = installerObj as WindowsInstaller.Installer;
Database database = installer.OpenDatabase("C:\\DataP\\sqlncli.msi",0 );
string sql = String.Format("SELECT Value FROM Property WHERE Property=’{0}’", msiProperty);
View view = database.OpenView(sql);
Record record = view.Fetch();
if (record != null)
{
retVal = record.get_StringData(1);
}
else
retVal = "Property Not Found";
return retVal;
}
But I am getting error as System.Runtime.InteropServices.COMException was unhandled.
the sqlncli.msi file is physically placed at c:\DataP location. While debugging I found that database does not contain the data after installer.OpenDatabase() statement.
How can I resolve this issue and get MSI properties in C#?

Windows Installer XML's Deployment Tools Foundation (WiX DTF) is an Open Source project from Microsoft which includes the Microsoft.Deployment.WindowsInstaller MSI interop library. It's far easier and more reliable to use this to do these sorts of queries. It even has a LINQ to MSI provider that allows you to treat MSI tables as entities and write queries against them.
using System;
using System.Linq;
using Microsoft.Deployment.WindowsInstaller;
using Microsoft.Deployment.WindowsInstaller.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
using(var database = new QDatabase(#"C:\tfs\iswix.msi", DatabaseOpenMode.ReadOnly))
{
var properties = from p in database.Properties
select p;
foreach (var property in properties)
{
Console.WriteLine("{0} = {1}", property.Property, property.Value);
}
}
using (var database = new Database(#"C:\tfs\iswix.msi", DatabaseOpenMode.ReadOnly))
{
using(var view = database.OpenView(database.Tables["Property"].SqlSelectString))
{
view.Execute();
foreach (var rec in view) using (rec)
{
Console.WriteLine("{0} = {1}", rec.GetString("Property"), rec.GetString("Value"));
}
}
}
Console.Read();
}
}
}

I did it in following way:
String inputFile = #"C:\\Rohan\\sqlncli.msi";
// Get the type of the Windows Installer object
Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
// Create the Windows Installer object
WindowsInstaller.Installer installer = (WindowsInstaller.Installer)Activator.CreateInstance(installerType);
// Open the MSI database in the input file
Database database = installer.OpenDatabase(inputFile, 0);
// Open a view on the Property table for the version property
View view = database.OpenView("SELECT * FROM _Tables");
// Execute the view query
view.Execute(null);
// Get the record from the view
Record record = view.Fetch();
while (record != null)
{
Console.WriteLine(record.get_StringData(0) + '=' + record.get_StringData(1) + '=' + record.get_StringData(2) + '=' + record.get_StringData(3));
record = view.Fetch();
}
And its working for me.

The SQL string is incorrect. It should be:
SELECT `Value` FROM `Property` WHERE `Property`.`Property` = ’{0}’

I was trying to re-use this code, and the only change I had to make to get the code posted by Devashri to work is this line:
string sql = String.Format("SELECT `Value` FROM `Property` WHERE `Property`='{0}'", msiProperty);
Watch out for the single quotes!

as of 04/2020 it would be
Type installerType { get; set; }
WindowsInstaller.Installer installerObj { get; set; }
...
installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
installerObj = (WindowsInstaller.Installer)Activator.CreateInstance(installerType);
var installer = installerObj as WindowsInstaller.Installer;
...
private void lnkSelectMsi_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
WindowsInstaller.Database msiDatabase = installerObj.OpenDatabase(txtMsiPath.Text, 0);
readMsiTableColumn(msiDatabase, cmbTable.Text, cmbColumn.Text);
}
private void readMsiTableColumn(WindowsInstaller.Database msiDatabase, string table)
{
WindowsInstaller.View msiView = null;
Record record = null;
string s = string.Empty;
try
{
msiView = msiDatabase.OpenView($"Select * from _Columns");
msiView.Execute();
record = msiView.Fetch();
int k = 0;
while (record != null)
{
if (record.StringData[1].Equals(table, StringComparison.OrdinalIgnoreCase))
{
k++;
s += $"{record.StringData[3],-50} ";
}
record = msiView.Fetch();
}
s += nl;
s += "".PadRight(50 * k, '-') + nl;
msiView.Close();
msiView = msiDatabase.OpenView($"Select * from {table}");
msiView.Execute();
record = msiView.Fetch();
while (record != null)
{
string recordValue = string.Empty;
for (int i = 1; i < record.FieldCount + 1; i++)
{
try { recordValue += $"{record.StringData[i],-50} "; }
catch (Exception ex) { recordValue += $"{i}. err {ex.Message}; "; }
}
s += recordValue + nl;
record = msiView.Fetch();
}
msiView.Close();
txtRes.Text = s;
}
catch (Exception ex) { txtRes.Text = ex.Message; }
}

Related

Trying to get data from wsdl using c#

I have this c# code where i am trying to get data from a wsdl in visual studio .
The code is okay but when i try to get the data to written on notepad it just shows an empty space :
WindowsService1.ServiceReference1.GetModifiedBookingsOperationResponse getModbkgsResp;
using (var proxy = new WindowsService1.ServiceReference1.InventoryServiceClient())
{
int noofBookings = 1;
getModbkgsResp = proxy.GetModifiedBookings(getModBkgsReq);
WindowsService1.ServiceReference1.Booking[] bookings = new WindowsService1.ServiceReference1.Booking[noofBookings];
getModbkgsResp.Bookings = new WindowsService1.ServiceReference1.Booking[noofBookings];
getModbkgsResp.Bookings = bookings;
if (getModbkgsResp.Bookings != null)
{
for (int i = 0; i < bookings.Length; i++)
{
Booking bk = new WindowsService1.ServiceReference1.Booking();
getModbkgsResp.Bookings[i] = bk;
if (bk != null )
{
bookingSource = bk.BookingSource;
if (bk.BookingId == Bookingcode)
{
this.WriteToFile("Booking Source =" + bookingSource + "");
}
else
{
this.WriteToFile("Sorry could not find your source of booking");
}
}
else
{
this.WriteToFile("Looks like source is null " );
}
}
}
else
{
this.WriteToFile("ERROR: Booking details not returned from GetModifiedBookings! " +StartDate);
}
}
I'm not sure why you are using the new keyword to create items that should have been retrieved from the service. Naturally anything created with new will be initialized with default values and will not contain any data that was retrieved from the service.
My guess is your code should look more like this:
using (var proxy = new WindowsService1.ServiceReference1.InventoryServiceClient())
{
var response = proxy.GetModifiedBookings(getModBkgsReq);
if (response.Bookings == null)
{
this.WriteToFile("ERROR: Booking details not returned from GetModifiedBookings! " +StartDate);
return;
}
var booking = response.Bookings.SingleOrDefault( b => b.BookingId == bookingCode);
if (booking == null)
{
this.WriteToFile("Sorry could not find your source of booking");
return;
}
var bookingSource = booking.BookingSource;
this.WriteToFile("Booking Source =" + bookingSource + "");
}

c# using advanced datagridview (ADGV) filter without BindingSource

I am using the advanced DataGridView (ADGV) found here to add filtering capabilities to my application.
The code for filtering or sorting is mentioned as:
private void advancedDataGridView1_SortStringChanged(object sender, EventArgs e)
{
this.stockHistoryBindingSource.Sort = advancedDataGridView1.SortString;
}
private void advancedDataGridView1_FilterStringChanged(object sender, EventArgs e)
{
this.stockHistoryBindingSource.Filter = advancedDataGridView1.FilterString;
}
But I can't use this because in my project I am reading an XML file and binding it to my ADGV with this code:
void QueryFoos()
{
IEnumerable<FooViewData> query =
from foo in XmlFiles.FOO.Root.Descendants("foo")
select new FooViewData
{
ID = Convert.ToInt32(foo.Attribute("id").Value),
Num = Convert.ToInt32(foo.Attribute("num").Value),
...
};
advancedDataGridView1.DataSource = query.OrderBy(n => n.ID).ThenBy(r => r.Num).ToList();
}
I tried a code like this but I am not surprised that it is throwing exception in my face:
BindingSource x = (BindingSource)this.advancedDataGridView1.DataSource;
x.Filter = advancedDataGridView1.FilterString;
this.advancedDataGridView1.DataSource = x;
Is there some work around to use the filtering and sorting of the ADGV ?
As it turns out I had this same problem today and was looking for solutions. Basically the problem is that ADGV was written to be used with a DataTable and not a list of objects.
This solution works for me however your mileage may vary.
What I ended up doing was using dynamic linq to perform the filter on the list of objects myself. The hack part was me converting the filter string that ADGV produces and converting it to a string that dynamic linq expects.
We start with some data. I have a class named DataPointGridViewModel that looks like this:
public class DataPointGridViewModel
{
public int DataPointId { get; set; }
public string Description { get; set; }
public bool InAlarm { get; set; }
public DateTime LastUpdate { get; set; }
public double ScalingMultiplier { get; set; }
public decimal Price { get; set; }
}
The data could be anything. This is the data that you will be filtering on in the grid. Obviously you will have your own data class. You need to replace this DataPointGridViewModel clas with your own model/data object.
Now, here is the code example code you need to add. I have also got a sample project on github here: I have a working version of this code on github: here
Here is the code you need to add:
List<DataPointGridViewModel> m_dataGridBindingList = null;
List<DataPointGridViewModel> m_filteredList = null;
private void dataGridView2_FilterStringChanged(object sender, Zuby.ADGV.AdvancedDataGridView.FilterEventArgs e)
{
try
{
if ( string.IsNullOrEmpty(dataGridView2.FilterString) == true )
{
m_filteredList = m_dataGridBindingList;
dataGridView2.DataSource = m_dataGridBindingList;
}
else
{
var listfilter = FilterStringconverter(dataGridView2.FilterString);
m_filteredList = m_filteredList.Where(listfilter).ToList();
dataGridView2.DataSource = m_filteredList;
}
}
catch (Exception ex)
{
Log.Error(ex, MethodBase.GetCurrentMethod().Name);
}
}
And this is the function to convert the ADGV filter string to the Dynamic Linq filter string:
private string FilterStringconverter(string filter)
{
string newColFilter = "";
// get rid of all the parenthesis
filter = filter.Replace("(", "").Replace(")", "");
// now split the string on the 'and' (each grid column)
var colFilterList = filter.Split(new string[] { "AND" }, StringSplitOptions.None);
string andOperator = "";
foreach (var colFilter in colFilterList)
{
newColFilter += andOperator;
// split string on the 'in'
var temp1 = colFilter.Trim().Split(new string[] { "IN" }, StringSplitOptions.None);
// get string between square brackets
var colName = temp1[0].Split('[', ']')[1].Trim();
// prepare beginning of linq statement
newColFilter += string.Format("({0} != null && (", colName);
string orOperator = "";
var filterValsList = temp1[1].Split(',');
foreach (var filterVal in filterValsList)
{
// remove any single quotes before testing if filter is a num or not
var cleanFilterVal = filterVal.Replace("'", "").Trim();
double tempNum = 0;
if (Double.TryParse(cleanFilterVal, out tempNum))
newColFilter += string.Format("{0} {1} = {2}", orOperator, colName, cleanFilterVal.Trim());
else
newColFilter += string.Format("{0} {1}.Contains('{2}')", orOperator, colName, cleanFilterVal.Trim());
orOperator = " OR ";
}
newColFilter += "))";
andOperator = " AND ";
}
// replace all single quotes with double quotes
return newColFilter.Replace("'", "\"");
}
...and finally the sort function looks like this:
private void dataGridView2_SortStringChanged(object sender, Zuby.ADGV.AdvancedDataGridView.SortEventArgs e)
{
try
{
if (string.IsNullOrEmpty(dataGridView2.SortString) == true)
return;
var sortStr = dataGridView2.SortString.Replace("[", "").Replace("]", "");
if (string.IsNullOrEmpty(dataGridView2.FilterString) == true)
{
// the grid is not filtered!
m_dataGridBindingList = m_dataGridBindingList.OrderBy(sortStr).ToList();
dataGridView2.DataSource = m_dataGridBindingList;
}
else
{
// the grid is filtered!
m_filteredList = m_filteredList.OrderBy(sortStr).ToList();
dataGridView2.DataSource = m_filteredList;
}
}
catch (Exception ex)
{
Log.Error(ex, MethodBase.GetCurrentMethod().Name);
}
}
Finally, you will need the Dynamic Linq library from here
You can use Nuget to bring it into your project:
Install-Package System.Linq.Dynamic
DataTable OrignalADGVdt = null;
private void advancedDataGridView1_FilterStringChanged(object sender, Zuby.ADGV.AdvancedDataGridView.FilterEventArgs e)
{
Zuby.ADGV.AdvancedDataGridView fdgv = advancedDataGridView1;
DataTable dt = null;
if (OrignalADGVdt == null)
{
OrignalADGVdt = (DataTable)fdgv.DataSource;
}
if (fdgv.FilterString.Length > 0)
{
dt = (DataTable)fdgv.DataSource;
}
else//Clear Filter
{
dt = OrignalADGVdt;
}
fdgv.DataSource = dt.Select(fdgv.FilterString).CopyToDataTable();
}
Here follow my code sample for filter advanced datagrid
string myFilter = "(Convert([myCol],System.String) IN ('myfilter'))"
dg.LoadFilterAndSort(myFilter, "");
and to clear filter
dg.CleanFilter();

"RPC Server is unavailable" when exporting Outlook contacts to CSV

I am exporting Outlook contacts with a custom form to CSV from a specific Contacts folder. This folder is not the default location. It is a large folder with almost 7,000 contacts. This is a shared mailbox in Office 365, but we can't use the Outlook or Graph APIs because of the custom data.
My code below works fine, except that after iterating through 200-800 contacts, I get this error: "RPC Server is unavailable. (Exception from HRESULT: 0x800706BA)."
I also tried exporting the folder to a .pst and accessing that folder on my local machine. The result is essentially the same. UPDATE: I've been watching Outlook.exe in the task manager, and it steadily increases its memory consumption to around 300MB before crashing. I've tried the same code on a laptop running Office 2010, and I get an "Out of Memory" error.
I get the error whether Outlook is open or closed, but closing Outlook during program operation will immediately trigger this error. Outlook either starts (or restarts) following this error. I've read a number of SO posts and articles related to this error, but I'm not sure exactly what's going on. Any help is appreciated.
UPDATE: Code has been updated to use for loops instead of foreach loops per Dmitry Streblechenko's suggestion.
using System;
using Microsoft.Office.Interop.Outlook;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
namespace OutlookContacts
{
class Program
{
static void Main(string[] args)
{
var encoding = Encoding.UTF8;
string csvPath = #"myCSVPath";
Application outlook = new Application();
NameSpace ns = outlook.GetNamespace("MAPI");
MAPIFolder sharedContacts;
string recipientName = "myEmail#myDomain";
StringBuilder headerRow = new StringBuilder();
Recipient recip = ns.CreateRecipient(recipientName);
StreamWriter writer = new StreamWriter(csvPath, false, encoding);
recip.Resolve();
if (recip.Resolved)
{
try
{
//EntryID and StoreID of my folder
sharedContacts =
ns.GetFolderFromID(
"myEntryID",
"myStoreID"
);
Items contacts = sharedContacts.Items;
//Writing header row
ContactItem first = contacts.GetFirst();
var properties = first.ItemProperties;
for(int i = 0; i < properties.Count; i++)
{
try
{
headerRow.Append(string.Format("\"{0}\",", properties[i].Name));
}
catch (System.Exception ex)
{
headerRow.Append(string.Format("{0},", ex.Message));
}
}
headerRow.AppendLine(Environment.NewLine);
WriteToCSV(writer, headerRow);
Console.WriteLine("Header row written;");
Marshal.ReleaseComObject(properties);
Marshal.ReleaseComObject(first);
//Writing Records
for (int i = 1; i <= contacts.Count; i++)
{
object o = contacts[i];
if (o is ContactItem)
{
ContactItem contact = (ContactItem)o;
if (contact != null)
{
Console.Write(contact.FullName);
StringBuilder dataRow = new StringBuilder();
ItemProperties contactProps = contact.ItemProperties;
for (int j = 0; j < contactProps.Count; j++)
{
ItemProperty property = contactProps[j];
try
{
if (property.Value == null)
{
string value = "null,";
dataRow.Append(value);
}
//else if (property.Name == "Attachments")
//{
// //Attachment file names
// string attachment = "";
// for (int k = 1; k < contact.Attachments.Count; k++)
// {
// attachment = (string.Format("\"{0}\"; ", contact.Attachments[k].FileName));
// dataRow.Append(attachment);
// }
// dataRow.Append(",");
//}
else
{
string value = property.Value.ToString();
value = value.Replace("\r\n\r\n\r\n", "\r\n")
.Replace("\r\n\r\n", "\r\n")
.Replace("\"", "'");
value = (string.Format("\"{0}\",", value));
dataRow.Append(value);
}
}
catch (System.Exception ex)
{
string value = string.Format("{0}: {1},", property.Name, ex.Message);
dataRow.Append(value);
}
Marshal.ReleaseComObject(property);
}
dataRow.Append(Environment.NewLine);
WriteToCSV(writer, dataRow);
Marshal.ReleaseComObject(contactProps);
Marshal.ReleaseComObject(contact);
}
Marshal.ReleaseComObject(o);
counter++;
Console.WriteLine(": Written " + counter);
}
}
}
catch (System.Exception ex)
{
Console.WriteLine(dataRow.ToString(), ex.Message);
Console.ReadKey();
}
}
}
static void WriteToCSV(StreamWriter writer, StringBuilder row)
{
var data = row.ToString();
writer.WriteAsync(data);
}
}
}
Looks like you are running out of RPC channels. You need to avoid using foreach loops (they tend to keep all collection members referenced until the loop exits) and explicitly release all COM objects are soon as you are done with them.
Off the top of my head:
for(int i = 1; i <= contacts.Count; i++)
{
obejct o = contacts[i];
ContactItem contact = o as ContactItem;
if (o != null)
{
ItemProperties properties = contact.ItemProperties;
StringBuilder newLine = new StringBuilder();
for (int j = 1; j <= properties.Count; j++)
{
ItemProperty property = properties[j];
var value = "";
if (property.Value == null)
{
value = "null,";
Console.WriteLine(value);
newLine.Append(value);
}
else
{
value = property.Value.ToString() + ",";
newLine.Append(value);
}
Marshal.ReleaseComObject(property);
}
newLine.Append(Environment.NewLine);
WriteToCSV(writer, newLine);
Marshal.ReleaseComObject(properties);
Marshal.ReleaseComObject(contact);
}
Marshal.ReleaseComObject(o);
}

NullReferenceException when creating a table with DateTime Column(SMO, C#)

My application is used to copy tables from one database and duplicate them to another, I'm using smo and C#. My code:
private static void createTable(Table sourcetable, string schema, Server destinationServer,
Database db)
{
Table copiedtable = new Table(db, sourcetable.Name, schema);
createColumns(sourcetable, copiedtable);
copiedtable.AnsiNullsStatus = sourcetable.AnsiNullsStatus;
copiedtable.QuotedIdentifierStatus = sourcetable.QuotedIdentifierStatus;
copiedtable.TextFileGroup = sourcetable.TextFileGroup;
copiedtable.FileGroup = sourcetable.FileGroup;
copiedtable.Create();
}
private static void createColumns(Table sourcetable, Table copiedtable)
{
foreach (Column source in sourcetable.Columns)
{
Column column = new Column(copiedtable, source.Name, source.DataType);
column.Collation = source.Collation;
column.Nullable = source.Nullable;
column.Computed = source.Computed;
column.ComputedText = source.ComputedText;
column.Default = source.Default;
if (source.DefaultConstraint != null)
{
string tabname = copiedtable.Name;
string constrname = source.DefaultConstraint.Name;
column.AddDefaultConstraint(tabname + "_" + constrname);
column.DefaultConstraint.Text = source.DefaultConstraint.Text;
}
column.IsPersisted = source.IsPersisted;
column.DefaultSchema = source.DefaultSchema;
column.RowGuidCol = source.RowGuidCol;
if (server.VersionMajor >= 10)
{
column.IsFileStream = source.IsFileStream;
column.IsSparse = source.IsSparse;
column.IsColumnSet = source.IsColumnSet;
}
copiedtable.Columns.Add(column);
}
}
The project perfectly well works with North wind database, however, with some tables from AdventureWorks2014 database I get the following inner exception at copiedtable.Create();:
NullReferenceException: Object reference not set to an instance of an object.
I suspect, that AdventureWorks datetime column may be causing the problem (Data is entered like: 2008-04-30 00:00:00.000)
I have solved this problem myself and it was quite interesting. I couldn't find any null values neither in the Table itself, nor in it's columns.
Then I realized, that AdventureWorks2014 DB used User defined Data Types and XML Schema collections. As I haven't copied them, they couldn't be accessed and the creation of the table failed. It was only necessary to copy XML Schema Collections and User Defined Data Types to second database:
private static void createUserDefinedDataTypes(Database originalDB, Database destinationDB)
{
foreach (UserDefinedDataType dt in originalDB.UserDefinedDataTypes)
{
Schema schema = destinationDB.Schemas[dt.Schema];
if (schema == null)
{
schema = new Schema(destinationDB, dt.Schema);
schema.Create();
}
UserDefinedDataType t = new UserDefinedDataType(destinationDB, dt.Name);
t.SystemType = dt.SystemType;
t.Length = dt.Length;
t.Schema = dt.Schema;
try
{
t.Create();
}
catch(Exception ex)
{
throw (ex);
}
}
}
private static void createXMLSchemaCollections(Database originalDB, Database destinationDB)
{
foreach (XmlSchemaCollection col in originalDB.XmlSchemaCollections)
{
Schema schema = destinationDB.Schemas[col.Schema];
if (schema == null)
{
schema = new Schema(destinationDB, col.Schema);
schema.Create();
}
XmlSchemaCollection c = new XmlSchemaCollection(destinationDB, col.Name);
c.Text = col.Text;
c.Schema = col.Schema;
try
{
c.Create();
}
catch(Exception ex)
{
throw (ex);
}
}
}

Edit video metadata tags of MP4 files

I want to edit following video tags of MP4 files like Title, Subtitle, Rating, Coment, Author. I have search alot and find solution
Taglib sharp. But taglib sharp only edit title and comment. I also explore Directshow and UltraD3lib but my problem is
still there. If anybody have example or any opensource library then please share with me.
Here is a couple short methods I use to update my Video library files
Movie is a POCO object with the name, IMDB number, file name, year.. properties
ADOHelper is a class that I use to simplify ADO DB/SQL calls
With the code below I get the following icons on my videos
And when I look at the properties of the video I get the following
private static void UpdateActors(Movie found, FileInfo movie)
{
var sql = $"SELECT n.primaryName FROM Principals p Inner join Names n on p.nconst = n.nconst where tconst = '{found.IMDB}'";
var table = ADOHelper.ReturnDataTable(Conn, sql, CommandType.Text);
var value = (from DataRow row in table.Rows select row[0].ToString()).ToList();
var f = TagLib.File.Create(movie.FullName);
f.Tag.Artists = value.ToArray();
f.Tag.AlbumArtists = value.ToArray();
f.Save();
}
private static string UpdateGenre(Movie found, FileInfo movie)
{
var returned = string.Empty;
try
{
var sql = $"SELECT Genre FROM TitleGenre where TitleId = '{found.IMDB}' order by sort";
var table = ADOHelper.ReturnDataTable(Conn, sql, CommandType.Text);
var f = TagLib.File.Create(movie.FullName);
f.Tag.Genres = (from DataRow row in table.Rows select row[0].ToString()).ToArray();
returned = table.Rows[0][0].ToString();
f.Save();
}
catch (Exception e)
{
Console.WriteLine(found.FilePath + " : " + e.Message);
}
return returned;
}
private static int UpdateYear(Movie found, FileInfo movie)
{
var returned = 0;
try
{
var f = TagLib.File.Create(movie.FullName);
var sql = $"SELECT startYear FROM Titles where tconst = '{found.IMDB}'";
var table = ADOHelper.ReturnDataTable(Conn, sql, CommandType.Text);
f.Tag.Year = uint.Parse(table.Rows[0][0].ToString());
returned = (int)f.Tag.Year;
f.Tag.Title = found.Name;
f.Save();
}
catch (Exception e)
{
Console.WriteLine(found.FilePath + " : " + e.Message);
}
return returned;
}
private static string UpdateName(Movie found, FileInfo movie, string description)
{
var returned = string.Empty;
try
{
var f = TagLib.File.Create(movie.FullName);
f.Tag.Title = description;
returned = description;
f.Save();
}
catch (Exception e)
{
Console.WriteLine(found.FilePath + " : " + e.Message);
}
return returned;
}
private static void UpdatePicture(Movie found, FileInfo movie)
{
try
{
var poster = $"{PosterPath}\\{found.IMDB}.jpg";
if (File.Exists(poster))
{
var f = TagLib.File.Create(movie.FullName);
IPicture picture = new Picture(poster);
f.Tag.Pictures = new[] { picture };
f.Save();
}
else
{
using (var writer = new StreamWriter("G:\\NeedPicture.txt", true))
writer.WriteLine($"{found.IMDB} : {found.Name} No Picture");
}
}
catch (Exception e)
{
Console.WriteLine(found.FilePath + " : " + e.Message);
}
}
Hope this helps

Categories

Resources