Related
I'm working on a .NET MAUI project in the context of MVVM architecture and I created two .txt files (15.txt and 19.txt) inside directory Resources\Raw. I set the files' Build action to MauiAsset. Each of
these two files contain topology for a matrix of color-coded fields.
What were I expecting: to read the text file's content without obtaining System.IO.FileNotFoundException' in System.Private.CoreLib.dll and to be able to use (invoke) the reader method more than once in a successfull manner.
I experience the following behaviour: in case the mentioned exception is not checked under Debug -> Windows -> Exception Setings -> Common Language Runtime Exceptions then the textfile's content is successfully obtained via the reader method as it's evident by looking at the graphical changes on one of my ContentPages (a matrix of fields appears with plenty of differently colored fields), however at the moment of its invokation an System.IO.FileNotFoundException' in System.Private.CoreLib.dllemerges as part of the logs (alerting message is absent).
However, if the aforementioned exception is checked under Debug -> Windows -> Exception Setings -> Common Language Runtime Exceptions
then my application does not even start succesfully.
Inside class GameViewModel:
/// <summary>
/// event handler method for choosing 15 as tablesize and reading appropriate table
/// </summary>
private async void GameViewModel_ButtonSmallTableClick(object? sender, System.EventArgs e)
{
await Navigation.PushAsync(new GamePage
{
BindingContext = _gameViewModel
});
Stream fileStream = await FileSystem.Current.OpenAppPackageFileAsync("15.txt");
await _gameModel.LoadGameAsync(fileStream);
_gameViewModel.GameTableNumRows = 15;
_gameViewModel.GameTableNumCols = 15;
_gameViewModel.GenerateFields();
}
/// <summary>
/// event handler method for choosing 19 as tablesize and reading appropriate table
/// </summary>
private async void GameViewModel_ButtonLargeTableClick(object? sender, System.EventArgs e)
{
await Navigation.PushAsync(new GamePage
{
BindingContext = _gameViewModel
});
Stream fileStream = await FileSystem.Current.OpenAppPackageFileAsync("19.txt");
await _gameModel.LoadGameAsync(fileStream);
_gameViewModel.GameTableNumRows = 19;
_gameViewModel.GameTableNumCols = 19;
_gameViewModel.GenerateFields();
}
Here's the method definition inside class GameModel:
/// <summary>
/// Loading colored matrix.
/// </summary>
/// <param name="fileStream">Type of Stream.</param>
public async Task LoadGameAsync(System.IO.Stream fileStream)
{
if (_dataAccess == null)
throw new InvalidOperationException("No data access is provided.");
var loadResult = await _dataAccess.LoadAsync(fileStream);
_gameTable = loadResult.Item1;
_player = loadResult.Item2;
_guards = loadResult.Item3;
IsWon = false;
}
Finally, here's the persistence-related method:
/// <summary>
/// Loading file
/// </summary>
/// <param name="path">Filepath.</param>
/// <returns>Gametable, Player, list of Guards.</returns>
public async Task<(UInt16[,], Player, List<Guard>)> LoadAsync(String path)
{
try
{
using (StreamReader reader = new StreamReader(path))
{
String[] gameFieldTypes;
String line = await reader.ReadLineAsync() ?? String.Empty;
Int32 tableSize = Int32.Parse(line);
UInt16[,] table = new UInt16[tableSize, tableSize];
Player player = new Player();
List<Guard> guards = new List<Guard>();
for (Int32 i = 0; i < tableSize; i++)
{
line = await reader.ReadLineAsync() ?? String.Empty;
gameFieldTypes = line.Split(' ');
for (Int32 j = 0; j < tableSize; j++)
{
if (gameFieldTypes[j] == "Empty")
{
table[j, i] = 0;
}
if (gameFieldTypes[j] == "Wall")
{
table[j, i] = 1;
}
if (gameFieldTypes[j] == "Guard")
{
table[j, i] = 2;
Guard guard = new Guard();
guard.X = j;
guard.Y = i;
guards.Add(guard);
}
if (gameFieldTypes[j] == "Player")
{
table[j, i] = 3;
player.X = j;
player.Y = i;
}
if (gameFieldTypes[j] == "Exit")
{
table[j, i] = 4;
}
}
}
return (table, player, guards);
}
}
catch
{
throw new GameDataException();
}
}
EDIT:
Here's the emerging exception: System.IO.FileNotFoundException' in System.Private.CoreLib.dll
Could not find file 'C:\WINDOWS\system32\SuspendedGame'.'
Line throwing exception inside method LoadAsync():
using (StreamReader reader = new StreamReader(path))
And here's the class within which the phrase "SuspendedGame" appears.
public class StoredGameBrowserModel
{
private IStore _store; // persistence
/// <summary>
/// Event of container being changed.
/// </summary>
public event EventHandler? StoreChanged;
public StoredGameBrowserModel(IStore store)
{
_store = store;
StoredGames = new List<StoredGameModel>();
}
/// <summary>
/// Query of the list of stored colored-field matrices.
/// </summary>
public List<StoredGameModel> StoredGames { get; private set; }
/// <summary>
/// Updating stored resource files.
/// </summary>
public async Task UpdateAsync()
{
if (_store == null)
return;
StoredGames.Clear();
// loading saved files
foreach (String name in await _store.GetFilesAsync())
{
if (name == "SuspendedGame") // we do not want to load this particular saved file
continue;
StoredGames.Add(new StoredGameModel
{
Name = name,
Modified = await _store.GetModifiedTimeAsync(name)
});
}
// arranging elements according to their date
StoredGames = StoredGames.OrderByDescending(item => item.Modified).ToList();
OnSavesChanged();
}
private void OnSavesChanged()
{
StoreChanged?.Invoke(this, EventArgs.Empty);
}
}
Solution:
inserting the following code at the beginning of the method body of LoadAsync():
if (!String.IsNullOrEmpty(_basePath))
path = Path.Combine(_basePath, path);
Reasoning:
the prefix library path was missing from the content of the method parameter.
class Login
{
Account hesap = new Account(); // problem!?
TestData testData = new TestData(); // *
Hash hash = new Hash(); // *
int count= 0;
string userId, password; // problem !?
private void ozellikLogin()
{
hesap.HesapId = "326785";
sayac++;
if (count> 3)
{
Console.WriteLine("You entered 3 times incorretly!");
Environment.Exit(0);
}
if (userId == "" && password == "")
{
Console.WriteLine("Spaces aren't allowed!");
}
else if (userId.Length >= 6 || password.Length >= 8)
{
Console.WriteLine("You must enter a max of 6 digits and a maximum of 8 characters!");
}
else
{
if (userId == "bartu" && password == "1999")
{
Console.WriteLine("Giris Basarili!");
}
else
{
Console.WriteLine("Account number or password is wrong!");
}
}
}
User will enter their account number and password to connect to the system. and the entered password value will be hashed with the SHA256 hash algorithm, the auth.txt file will be opened and compared with the hash value next to the account number, it will be verified if it is equal. and will enter the system.
class Hash
{
private string Hashing(HashAlgorithm hashing,string inputBytes)
{
byte[] sourceBytes = hashing.ComputeHash(Encoding.UTF8.GetBytes(inputBytes));
StringBuilder stringBuilder = new StringBuilder("__Hash__");
for (int i = 0; i < sourceBytes.Length; i++)
{
stringBuilder.AppendLine(sourceBytes[i].ToString("x2"));
}
return stringBuilder.ToString();
}
private bool Karsilastir(string hash, string hesapId)
{
string hashTxt = "";
string[] satirlar = { };
try
{
satirlar = System.IO.File.ReadAllLines(#"C:\Users\bartu\Desktop\auth.txt");
}
catch (Exception e)
{
Console.WriteLine("Hata!", e.Message);
}
foreach (string i in satirlar)
{
string[] parcala = i.Split(',');
if (parcala[0].Equals(hesapId))
{
hashTxt = parcala[1];
break;
}
}
StringComparer karsilastir = StringComparer.OrdinalIgnoreCase;
return karsilastir.Compare(hashTxt, hash) == 0;
}
public bool Kontrol(string raw, string hesapId)
{
using (SHA256 sha256 = SHA256.Create())
{
string hash = Hashing(sha256, raw);
if (Karsilastir(hash, hesapId))
{
return true;
}else
{
return false;
}
}
}
}
auth.txt (example)
326785,af5e6187ff2fad1155074dd08b65a3b433432c0514e4422b5fafe8f9e664b0f7
400129,85c3016208d1854f7e8f1fa4e424cfd41ae5003b8d475947148951a93e3108af
388000,2b2282a5836e88e5ea443c4a0921c1ff19ba62df32402ce07db8ddf2946a0334
201005,9aba965a0939fde3b41dcb9ca45d146435fac718e016f08491ae57bddb3049b0
If the hash value of the password entered from the screen is not the same as in auth.txt, "User account number or password was entered incorrectly, try again" will be displayed.
If the same user logs in 3 times in 5 minutes, it will remain locked for 24 hours.
Only 6 digits should be entered in the account number field on the screen to connect to the system, and only 8 letters in length, small letters and numbers should be allowed for the password.
class Login
{
Account hesap = new Account(); // problem!?
TestData testData = new TestData(); // *
Hash hash = new Hash(); // *
int count= 0;
string userId, password; // problem !?
private void ozellikLogin()
{
hesap.HesapId = "326785";
sayac++;
if (count> 3)
{
Console.WriteLine("You entered 3 times incorretly!");
Environment.Exit(0);
}
if (userId == "" && password == "")
{
Console.WriteLine("Spaces aren't allowed!");
}
else if (userId.Length >= 6 || password.Length >= 8)
{
Console.WriteLine("You must enter a max of 6 digits and a maximum of 8 characters!");
}
else
{
if (userId == "bartu" && password == "1999")
{
Console.WriteLine("Giris Basarili!");
}
else
{
Console.WriteLine("Account number or password is wrong!");
}
}
}
And my TestDataClass
public class TestData
{
public void CustomerTest()
{
Customer ismailBorazan = new Customer("326785", "ismail Borazan","IsmB1982","TR610003200013900000326785",350.00,"TR300003200016420000326785",8000.00,null,0);
Musteri kamileHursitgilogullari = new Musteri("400129", "kamile Hurşitgilogullari", "12Hrst34", "TR610008324560000000400129", 2980.45, null, 0,null,0);
Customer zebercetBak = new Customer("388000", "Zebercet Bak", "Zb123456", "TR610007222250001200388000", 19150.00, "TR300007222249000001388000", 52.93, "TR300008222266600002388000", 2850.00);
Customer nazGulUcan = new Customer("201005", "Naz Gül Uçan", "Mordor99", "TR610032455466661200201005", 666.66, null, 0,"TR300032455410080003201005", 10000.00);
ListCustomer.customer.Add(ismailBorazan);
ListCustomer.customer.Add(kamileHursitgilogullari);
ListCustomer.customer.Add(zebercetBak);
ListCustomer.customer.Add(nazGulUcan);
if (File.Exists(#"C:\Users\bartu\Desktop\client.txt"))
return;
}
private void YazClientTxt()
{
try
{
var path = #"C:\Users\bartu\Desktop\client.txt"; // dosya yolu
StreamWriter fs = new StreamWriter(path); // dosyaya yazma
foreach (Customer item in ListCustomer.customer)
{
if (item.IbanTr != null)
{
fs.WriteLine(item.HesapNo, item.IbanTr, item.MiktarIbanTr);
//fs.WriteLine("{0}", "{1}", "{2}", item.HesapNo, item.IbanTr, item.MiktarIbanTr);
}
if (item.IbanEuro != null)
{
fs.WriteLine(item.HesapNo, item.IbanEuro, item.MiktarIbanEuro);
}
if (item.IbanUsd != null)
{
fs.WriteLine(item.HesapNo, item.IbanUsd, item.MiktarIbanUsd);
}
}
}
catch (Exception e)
{
Console.WriteLine("Hata!", e.Message);
}
}
}
My question may sound like it was too long at first, but I mentioned it for detailed understanding. I found it difficult to do the necessary checks while logging in to the login.cs class and could not find any examples.
This is a solution that doesn't persist every user login attempt, so every login attempt is kept in memory. It can be however changed without too much effort, so the login state can be persisted on file, disk, database, etc...
I started with an enumerated type with all the possible results of a login attempt:
/// <summary>
/// Possible result states of a login.
/// </summary>
internal enum LoginStatus : byte
{
Undefined = 0,
Success,
Failed,
UserLocked
}
Then I created a class whose instances are to keep the login status of an user, with all the properties needed to execute validation checks:
/// <summary>
/// Keeps the user current login status.
/// </summary>
internal class UserLoginStatus
{
/// <summary>
/// Used ID.
/// </summary>
public string UserId { get; set; }
/// <summary>
/// Signals the user is locked and cannot attempt any login for MINUTES_BEFORE_UNLOCK time.
/// </summary>
public bool UserIsLocked { get; set; }
/// <summary>
/// Number of failed attempts at login.
/// </summary>
public int FailedLoginCount { get; set; }
/// <summary>
/// Timestamp of the last login of the user.
/// </summary>
public DateTime? LastLoginTimeStamp { get; set; }
/// <summary>
/// Timestamp of the first login of the user.
/// </summary>
public DateTime? FirstLoginTimeStamp { get; set; }
}
The class LoginManager (static because it was easier for me) implements the login logic with all the necessary validation checks in the AttemptLogin function. A dictionary is used to keep all the failing attempt of a user to login. After a successful attempt at login, the entry for that user is removed from the dictionary:
/// <summary>
/// Manages users login attempts.
/// </summary>
internal static class LoginManager
{
/// <summary>
/// Time range in between a user is not allowed to input the credentials ATTEMPTS_BEFORE_LOCK times.
/// </summary>
private const double LOGIN_ATTEMPTS_SPAN_MINUTES = 5.0f;
/// <summary>
/// Number of login attempts before a user lock occours.
/// </summary>
private const byte ATTEMPTS_BEFORE_LOCK = 3;
/// <summary>
/// Minutes necessary before a user unlock is possible.
/// </summary>
private const int MINUTES_BEFORE_UNLOCK = 24 * 60;
/// <summary>
/// Dictionary holding the login status for each user.
/// </summary>
private static Dictionary<string, UserLoginStatus> _usersLogins = new Dictionary<string, UserLoginStatus>();
/// <summary>
/// Login logic.
/// </summary>
/// <param name="userId">User ID.</param>
/// <param name="password">User password.</param>
/// <param name="message">Login result description.</param>
public static LoginStatus AttemptLogin(string userId, string password, out string message)
{
message = null;
// 1) Get a current time timestamp.
var currentTime = DateTime.Now;
// 2) Check if we have an entry in the _usersLogins dictionary, if not, create it.
if (!_usersLogins.TryGetValue(userId, out UserLoginStatus userLogin))
{
// Create a new login status.
userLogin = new UserLoginStatus()
{
UserId = userId,
UserIsLocked = false,
FirstLoginTimeStamp = currentTime,
LastLoginTimeStamp = currentTime,
FailedLoginCount = 0
};
// Add a new login status for this user in the _usersLogins dictionary.
_usersLogins.Add(userId, userLogin);
}
// 3) Check if the user is locked.
if (userLogin.UserIsLocked)
{
// Check if the user can be unlocked.
var minutesSinceLastLogin = (currentTime - userLogin.LastLoginTimeStamp.Value).TotalMinutes;
if (minutesSinceLastLogin >= MINUTES_BEFORE_UNLOCK)
{
// Unlock the user by resetting his status.
userLogin.UserIsLocked = false;
userLogin.FailedLoginCount = 0;
userLogin.FirstLoginTimeStamp = currentTime;
userLogin.LastLoginTimeStamp = currentTime;
// Go on with the input validation...
}
else
{
// No, user can't be unlocked yet.
message = "User is locked out and must wait 24h before the next login attempt.";
userLogin.FailedLoginCount++;
return LoginStatus.UserLocked;
}
}
// ***************
// Validate input
// ***************
bool passwordOk = true;
// VALIDATION RULE A) Validation of non-empty userId.
if (passwordOk && string.IsNullOrEmpty(userId))
{
message = "Spaces aren't allowed in username.";
passwordOk = false;
}
// VALIDATION RULE B) Validation of non-empty password.
if (passwordOk && string.IsNullOrEmpty(password))
{
message = "Spaces aren't allowed in password.";
passwordOk = false;
}
// VALIDATION RULE C) Validation on userId and password length.
if (passwordOk && (userId.Length > 6 || password.Length > 8))
{
message = "You must enter a max of 6 digits (username) and a maximum of 8 characters (password).";
passwordOk = false;
}
// VALIDATION RULE D) Validation on lowercase characters.
if (passwordOk && userId.Any(char.IsUpper))
{
message = "UserId can't contain uppercase characters.";
passwordOk = false;
}
// VALIDATION RULE N) TODO....
// Effective password check.
if (passwordOk && !HashingManager.Kontrol(password, userId))
{
message = "Incorrect user/password.";
passwordOk = false;
}
if (!passwordOk)
{
// Validation failed.
userLogin.LastLoginTimeStamp = currentTime;
userLogin.FailedLoginCount++;
// Get the minutes passed since the first attempt.
var minsSinceFirstLogin = (currentTime - userLogin.FirstLoginTimeStamp.Value).TotalMinutes;
if (userLogin.FailedLoginCount == ATTEMPTS_BEFORE_LOCK && minsSinceFirstLogin <= LOGIN_ATTEMPTS_SPAN_MINUTES)
{
message += string.Format("\nUser is now locked out and must wait {0} minutes for the next login attempt.", MINUTES_BEFORE_UNLOCK);
userLogin.UserIsLocked = true;
return LoginStatus.UserLocked;
}
else
{
// If the user reached the maximum number of attemps, but waited more
// than LOGIN_TIME_SPAN_MINUTES, then reset his status to let him
// attempt the login for the next 3 times.
if (userLogin.FailedLoginCount == ATTEMPTS_BEFORE_LOCK)
{
userLogin.FirstLoginTimeStamp = currentTime;
userLogin.FailedLoginCount = 1;
}
}
// User still has some more attempts before being locked out.
return LoginStatus.Failed;
}
// The user successfully logged in.
// Remove the user from the login status dictionary.
_usersLogins.Remove(userId);
message = "User successfully logged in.";
return LoginStatus.Success;
}
}
These are your hashing functions, I just changed something in the Hashing function (the AppendLine was adding a newline character after every charater in the hash):
internal static class HashingManager
{
private static string Hashing(HashAlgorithm hashing, string sourceString)
{
byte[] sourceBytes = hashing.ComputeHash(Encoding.UTF8.GetBytes(sourceString));
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < sourceBytes.Length; i++)
{
stringBuilder.Append(sourceBytes[i].ToString("x2"));
}
return stringBuilder.ToString();
}
private static string GetHashedPasswordForUser(string userId)
{
string[] authlines;
try
{
authlines = File.ReadAllLines(#"auth.txt");
}
catch (Exception e)
{
Console.WriteLine("Hata!", e.Message);
return null;
}
if (authlines is null || authlines.Length == 0)
{
Console.WriteLine("We also have a problem here!");
return null;
}
foreach (var auth in authlines)
{
var authTokens = auth.Split(',');
if (authTokens[0].Equals(userId))
return authTokens[1];
}
return null;
}
public static bool Kontrol(string rawPassword, string userId)
{
var hashedPw = GetHashedPasswordForUser(userId);
if (string.IsNullOrWhiteSpace(hashedPw))
{
// The user does not have an entry in the auth file.
return false;
}
using (SHA256 sha256 = SHA256.Create())
{
var hashedRawPw = Hashing(sha256, rawPassword);
StringComparer karsilastir = StringComparer.OrdinalIgnoreCase;
return karsilastir.Compare(hashedPw, hashedRawPw) == 0;
}
}
}
I tested it in a console application with this code:
do
{
Console.Write("User: ");
var userId = Console.ReadLine();
Console.Write("Password: ");
var pw = Console.ReadLine();
switch (LoginManager.AttemptLogin(userId, pw, out string message))
{
case LoginStatus.Failed:
Console.WriteLine(message);
break;
case LoginStatus.Success:
Console.WriteLine(message);
break;
case LoginStatus.UserLocked:
Console.WriteLine(message);
break;
}
Console.WriteLine();
}
while (true);
i have done a RPN class to calculate strings which end-user input like
"1.0+3/2-tan(45)/(1+1)+sin(30)*abs(-1)+Abs(-10)"
Then, I want to parsing conditional statements and multi-parameters function such as "if(1>2,3/3,2*1)","max(1,2,3,4)"
So, my questions how to use IF-ELSE in the RPN?
Here's my code: enter link description here
For if(1>2,3/3,2*1) you would first evaluate the three argument from right to left and push their resuls on the stack so that it looked like this:
top-of-stack->false
1
2
Then if would be implemented in the RPN engine something like (pseudo-code):
void DoIf()
{
if (pop()) // pop result of "if" evaluation
{
var result = pop(); // pop "true" result from stack
pop(); // discard "false" result
push(result); // push back "true" result
}
else
{
pop(); // discard "true" result, leaving "false" result on stack
}
}
As for multi-parameter functions, there should be no special handling needed. Just evaluate and push all arguments (right to left, typically). The implementation of the function should pop off the required number of arguments and then push its result (if any).
i try to parse multi-parameters function such as if\Max before RPN.Parse()
public class MultiParameterFunctionParser
{
public readonly List<string> Funcs = new List<string> {"IF", "MAX"};
public string Parse(string exp)
{
while (IsFunction(exp,out var index,out var funcName))//
{
var parameters = GetParameters(exp, index, funcName, out var before, out var after);
var list = GetParameterList(parameters);
var value = Evaluate(list, funcName);
exp= $"{before}({value}){after}";
}
return exp;
}
/// <summary>
/// Is Exp Contains a function?
/// </summary>
/// <param name="exp"></param>
/// <param name="index"></param>
/// <param name="funcName"></param>
/// <returns></returns>
private bool IsFunction(string exp, out int index, out string funcName)
{
index = -1;
funcName = "";
foreach (var func in Funcs)
{
var idx = exp.IndexOf($"{func}(", StringComparison.CurrentCultureIgnoreCase);
if (idx == -1 || idx + 3 >= exp.Length - 1)
continue;
index = idx;
funcName = func;
break;
}
return index != -1 && index + 3 < exp.Length - 1;
}
/// <summary>
/// Get Parameters' string
/// </summary>
/// <param name="exp">8+if(12,sin(90),0)+1.2</param>
/// <param name="index">2 if's start index</param>
/// <param name="before">8+</param>
/// <param name="after">+1.2</param>
/// <returns>12,sin(90),0</returns>
private static string GetParameters(string exp,int index, string funcName, out string before, out string after)
{
before = exp.Substring(0, index);
index += funcName.Length + 1;
var leftCount = 1; // '(' count
var rightCount = 0;// ')' count
var results = "";
while (index < exp.Length && leftCount != rightCount)
{
var c = exp[index];
if (c.Equals('('))
leftCount++;
else if (c.Equals(')'))
rightCount++;
if (leftCount > rightCount)
results += c;
else
break;
index++;
}
after = exp.Substring(index + 1, exp.Length - index - 1);
return results;
}
/// <summary>
/// Parse Parameter string to list.
/// </summary>
/// <param name="exp">MAX(1,-1),1,0</param>
/// <returns>{"MAX(1,-1)","1","0"}</returns>
private static List<string> GetParameterList(string exp)
{
var count = exp.Length;
for (var i = count - 1; i > -1 && exp.Length > 0; i--)
{
var c = exp[i];
if (c != ',')
continue;
var after = exp.Substring(i + 1);
var before = exp.Substring(0,i);
if (after.Count(a => a == '(').Equals(after.Count(a => a == ')')))
{
exp = before + '#' + after;
}
}
var results = exp.Split('#').ToList();
return results;
}
private static double Evaluate(List<string> parameters, string funcName)
{
if (funcName.Equals("MAX", StringComparison.CurrentCultureIgnoreCase))
return EvaluateMax(parameters);
if (funcName.Equals("IF", StringComparison.CurrentCultureIgnoreCase))
return EvaluateIF(parameters);
return 0;
}
private static double EvaluateIF(List<string> parameters)
{
if (parameters == null || parameters.Count != 3)
throw new Exception("EvaluateIF parameters.Count()!=3");
var results = new List<double>();
foreach (var parameter in parameters)
{
var rpn = new RPN();
rpn.Parse(parameter);
var obj = rpn.Evaluate();
if (obj == null)
{
throw new Exception("EvaluateIF Not Number!");
}
if (obj.ToString().Equals("true", StringComparison.CurrentCultureIgnoreCase))
{
results.Add(1);
}
else if (obj.ToString().Equals("false", StringComparison.CurrentCultureIgnoreCase))
{
results.Add(-1);
}
else
{
if (double.TryParse(obj.ToString(), out var d))
results.Add(d);
else
throw new Exception("EvaluateIF Not Number!");
}
}
return results[0] >= 0 ? results[1] : results[2];
}
private static double EvaluateMax(IEnumerable<string> parameters)
{
var results = new List<double>();
foreach (var parameter in parameters)
{
var rpn = new RPN();
rpn.Parse(parameter);
var obj = rpn.Evaluate();
if (double.TryParse(obj.ToString(), out var d))
results.Add(d);
}
return results.Count > 0 ? results.Max() : 0;
}
}
It would be nice if this worked, but alas it doesn't.
List<string> items = new List<string>();
items.Add("a ");
bool useTrim = true;
if (items.Contains("a", useTrim)) {
Console.WriteLine("I'm happy");
}
I ended up implementing it as an extension method below. But I was wondering if anyone else had any elegant ideas other than creating a comparer class or looping through.
/// <summary>
/// Determines whether an element in the List of strings
/// matches the item. .Trim() is applied to each element
/// for the comparison
/// </summary>
/// <param name="value">a list of strings</param>
/// <param name="item">the string to search for in the list</param>
/// <returns>true if item is found in the list</returns>
public static bool ContainsTrimmed(this List<string> value, string item) {
bool ret = false;
if ((value.FindIndex(s => s.Trim() == item)) >= 0) {
ret = true;
}
return ret;
}
Well you'll either need to loop through it each time, or create another list of just the trimmed values, and use that for searching. (Heck, you could create a HashSet<string> if you only need to know whether or not a trimmed value is present.)
However, if you want to stick to just a single list, then rather than using FindIndex I'd use Any from LINQ:
if (items.Any(x => x.Trim() == item))
Note that even if you do want to keep your ContainsTrimmed method, you can simplify it to just:
return value.FindIndex(s => s.Trim() == item) >= 0;
I would suggest creating a custom IEqualityComparer to supply to the overloaded function Contains.
This is exactly the reason why this overload exists.
class TrimmedEqualityComparer : IEqualityComparer<string>
{
public bool Equals(string x, string y)
{
if (x == null && y != null || x != null && y == null)
return false;
if (x == null && y == null)
return true;
return x.Trim() == y.Trim();
}
public int GetHashCode(string obj)
{
return obj != null ? obj.GetHashCode() : 0;
}
}
You call it like this.
var strs = new string[] {"a ", "b ", "c"};
if (strs.Contains("b", new TrimmedEqualityComparer()))
Console.WriteLine("I'm happy");
I wrote a Windows Service Code to convert AVI to WMV file.
I'm using XviD, and Windows Media 9, in a Windows Vista.
The service starts converting, and stops before completing the job, with a WMENC_ENCODER_STOPPED status, but the file was not fully converted. And the resulting file stays locked to this application forever, until I stop the service. And when I do so, that resulting file is automatically deleted.
Can anyone, please, help? It is important !!
EDIT: This program works constantly, executing conversion tasks. If a file fails to convert as described above, and I use the function GC.WaitForPendingFinalizers(), I still have the locking problem. But the service goes on, and pick another task. Succeeding or failing this new task, when I use GC.WaitForPendingFinalizers(), the first one is unlocked, and automatically deleted.
public WMENC_ENCODER_STATE EncoderStatus
{
get { return _encoderStatus; }
set { _encoderStatus = value; }
}
IWMEncFile2 File;
IWMEncAudioSource[] SrcAud;
IWMEncVideoSource2[] SrcVid;
IWMEncSourceGroup2[] SrcGrp;
WMEncoder glbEncoder = new WMEncoder();
WMEncProfile2[] Pro = null;
IWMEncSourceGroupCollection SrcGrpColl = null;
public WMVEnconder(ConvertGroup[] sourceGroup, string targetFile, string profilefile)
{
glbEncoder.OnStateChange += new _IWMEncoderEvents_OnStateChangeEventHandler(Encoder_OnStateChange);
glbEncoder.OnError +=new _IWMEncoderEvents_OnErrorEventHandler(Encoder_OnError);
// Creates source group.
SrcGrpColl = glbEncoder.SourceGroupCollection;
int[] intProVBRModeAudio = new int[sourceGroup.Length];
int[] intProVBRModeVideo = new int[sourceGroup.Length];
Int32[] intProContentType = new int[sourceGroup.Length];
Pro = new WMEncProfile2[sourceGroup.Length];
for (int i = 0; i < Pro.Length; i++)
{
Pro[i] = new WMEncProfile2();
Pro[i].LoadFromMemory(profilefile);
intProContentType[i] = Pro[i].ContentType;
intProVBRModeAudio[i] = (int)Pro[i].get_VBRMode(WMENC_SOURCE_TYPE.WMENC_AUDIO, 0);
intProVBRModeVideo[i] = (int)Pro[i].get_VBRMode(WMENC_SOURCE_TYPE.WMENC_VIDEO, 0);
}
SrcGrp = new IWMEncSourceGroup2[sourceGroup.Length];
for (int i = 0; i < SrcGrp.Length; i++)
SrcGrp[i] = (IWMEncSourceGroup2)SrcGrpColl.Add(i.ToString());
SrcAud = new IWMEncAudioSource[sourceGroup.Length];
SrcVid = new IWMEncVideoSource2[sourceGroup.Length];
for (int i = 0; i < sourceGroup.Length; i++)
{
if (intProContentType[i] == 1)
{
SrcAud[i] = (WMEncoderLib.IWMEncAudioSource)SrcGrp[i].AddSource(WMENC_SOURCE_TYPE.WMENC_AUDIO);
SrcAud[i].SetInput(sourceGroup[i].AudioFile, "", "");
SrcAud[i].MarkIn = sourceGroup[i].AudioMarkin;
SrcAud[i].MarkOut = sourceGroup[i].AudioMarkout;
}
else if (intProContentType[i] == 16)
{
SrcVid[i] = (WMEncoderLib.IWMEncVideoSource2)SrcGrp[i].AddSource(WMENC_SOURCE_TYPE.WMENC_VIDEO);
SrcVid[i].SetInput(sourceGroup[i].VideoFile, "", "");
SrcVid[i].MarkIn = sourceGroup[i].VideoMarkin;
SrcVid[i].MarkOut = sourceGroup[i].VideoMarkout;
}
else if (intProContentType[i] == 17)
{
SrcAud[i] = (WMEncoderLib.IWMEncAudioSource)SrcGrp[i].AddSource(WMENC_SOURCE_TYPE.WMENC_AUDIO);
SrcAud[i].SetInput(sourceGroup[i].AudioFile, "", "");
SrcVid[i] = (WMEncoderLib.IWMEncVideoSource2)SrcGrp[i].AddSource(WMENC_SOURCE_TYPE.WMENC_VIDEO);
SrcVid[i].SetInput(sourceGroup[i].VideoFile, "", "");
SrcAud[i].MarkIn = sourceGroup[i].AudioMarkin;
SrcAud[i].MarkOut = sourceGroup[i].AudioMarkout;
SrcVid[i].MarkIn = sourceGroup[i].VideoMarkin;
SrcVid[i].MarkOut = sourceGroup[i].VideoMarkout;
}
else
throw new Exception("erro - não suporta este tipo de profile");
SrcGrp[i].set_Profile(Pro[i]);
if (i + 1 < sourceGroup.Length)
SrcGrp[i].SetAutoRollover(-1, (i + 1).ToString());
}
File = (IWMEncFile2)glbEncoder.File;
File.LocalFileName = targetFile;
glbEncoder.PrepareToEncode(true);
}
/// <summary>
/// Inicia os processos do codificador.
/// </summary>
public void Start()
{
glbEncoder.Start();
}
/// <summary>
/// Pára os processos do codificador.
/// </summary>
public void Stop()
{
glbEncoder.Stop();
}
/// <summary>
/// Elimina as configurações atuais.
/// </summary>
public void Reset()
{
glbEncoder.Reset();
}
/// <summary>
/// Evento deflagrado pela mudança no estado do codificador.
/// </summary>
/// <param name="enumState">Enumerador indicador do estado do codificador.</param>
private void Encoder_OnStateChange(WMEncoderLib.WMENC_ENCODER_STATE enumState)
{
_encoderStatus = enumState;
string strRunState = "";
switch (enumState)
{
case WMENC_ENCODER_STATE.WMENC_ENCODER_STARTING :
strRunState = "Encoder Starting";
break;
case WMENC_ENCODER_STATE.WMENC_ENCODER_RUNNING:
strRunState = "Encoder Running";
break;
case WMENC_ENCODER_STATE.WMENC_ENCODER_END_PREPROCESS:
strRunState = "Encoder End Preprocess";
break;
case WMENC_ENCODER_STATE.WMENC_ENCODER_PAUSING:
strRunState = "Encoder Pausing";
break;
case WMENC_ENCODER_STATE.WMENC_ENCODER_PAUSED:
strRunState = "Encoder Paused";
break;
case WMENC_ENCODER_STATE.WMENC_ENCODER_STOPPING:
strRunState = "Encoder Stopping";
break;
case WMENC_ENCODER_STATE.WMENC_ENCODER_STOPPED:
strRunState = "Encoder Stopped";
break;
}
_strEncoderStatus = strRunState;
}
/// <summary>
/// Evento deflagrado pela ocorrência de um erro durante o processo de codificação.
/// </summary>
/// <param name="hr">Valor numérico do erro que ocorreu.</param>
private void Encoder_OnError(int hr)
{
string errorReceived = "";
switch (hr)
{
case -1074600792:
errorReceived = "The starting time must be greater than zero and less than the ending time.";
break;
case -1074600793:
errorReceived = "The ending time must be greater than the starting time and less than the file duration.";
break;
case -1074600804:
errorReceived = "The video capture device is in use and cannot be opened.";
break;
case -1074600808:
errorReceived = "The video capture driver returned an unrecoverable error.";
break;
case -1074600809:
errorReceived = "The video capture device did not start.";
break;
case -1074600813:
errorReceived = "The video capture window was not created.";
break;
case -1074600820:
errorReceived = "The specified operation is not allowed when the file is being archived.";
break;
case -1074600825:
errorReceived = "The archive file name is not properly specified.";
break;
case -1074600831:
errorReceived = "The specified operation is not allowed when the encoder engine is not running.";
break;
case -1074600833:
errorReceived = "Inverse telecine cannot be specified when the frame rate does not equal 30 frames per second.";
break;
case -1074600834:
errorReceived = "Internal problems are preventing the preview or postview.";
break;
case -1074600835:
errorReceived = "One or more required codecs cannot be found.";
break;
case -1074600840:
errorReceived = "The display size or color setting has changed since the encoding session was defined.";
break;
}
try
{
if (Directory.Exists(#"C:\MediaDNA_V2\Data\Conversion\Exception"))
{
MediaDNAException mdnaException = new MediaDNAException(Modulo.CONVERSION, 0, "C_110018", TipoErro.INFORMACAO, new Exception(errorReceived),
ErrorMessageConstants.C_110018, new object[] { hr.ToString("X") });
ExceptionManager.RegisterException(mdnaException, #"C:\MediaDNA_V2\Data\Conversion\Exception");
}
}
catch { }
}
#region IDisposable Members
/// <summary> Release everything. </summary>
public void Dispose()
{
glbEncoder.Stop();
glbEncoder.Reset();
GC.SuppressFinalize(this);
CloseInterfaces();
}
#endregion
/// <summary>
/// Fecha as interfaces utilizadas pelo codificador.
/// Obs: O processador precisa estar "STOPPED" para executar este processo.
/// </summary>
private void CloseInterfaces()
{
if (glbEncoder != null)
{
if (File != null)
Marshal.FinalReleaseComObject(File);
if (Pro != null)
{
for (int i = 0; i < Pro.Length; i++)
Marshal.FinalReleaseComObject(Pro[i]);
Pro = null;
}
if (SrcVid != null)
{
for (int i = 0; i < SrcVid.Length; i++)
Marshal.FinalReleaseComObject(SrcVid[i]);
SrcVid = null;
}
if (SrcAud != null)
{
for (int i = 0; i < SrcAud.Length; i++)
Marshal.FinalReleaseComObject(SrcAud[i]);
SrcAud = null;
}
if (SrcGrpColl != null)
Marshal.FinalReleaseComObject(SrcGrpColl);
if (SrcGrpColl != null)
Marshal.FinalReleaseComObject(SrcGrpColl);
if (glbEncoder != null)
Marshal.FinalReleaseComObject(glbEncoder);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
}
I attached my function which I converted wav file to wma.
Make sure that you do encoder.Stop(); and encoder.Reset(); and off-course release all your com object.
I'm pretty sure that once you will released your COM object your issue will be fixed.
// Create a WMEncoder object.
WMEncoder encoder = new WMEncoder();
// Retrieve the source group collection.
IWMEncSourceGroupCollection srcGrpColl = encoder.SourceGroupCollection;
// Add a source group to the collection.
IWMEncSourceGroup srcGrp = srcGrpColl.Add("SG_1");
// Add a video and audio source to the source group.
IWMEncSource srcAud = srcGrp.AddSource(WMENC_SOURCE_TYPE.WMENC_AUDIO);
srcAud.SetInput(wavFileName, "", "");
// Specify a file object in which to save encoded content.
IWMEncFile file = encoder.File;
file.LocalFileName = wmaFileName;
// Create a profile collection object from the WMEncoder object.
encoder.ProfileCollection.ProfileDirectory =
string.Format("{0}Profiles", Request.PhysicalApplicationPath);
encoder.ProfileCollection.Refresh();
IWMEncProfileCollection proColl = encoder.ProfileCollection;
// Create a profile object
IEnumerator profEnum = proColl.GetEnumerator();
IWMEncProfile profile = null; ;
IWMEncProfile2 newProfile = null;
while (profEnum.MoveNext())
{
profile = (IWMEncProfile)profEnum.Current;
if (profile.Name == "WavToWma")
{
// Load profile
newProfile = new WMEncProfile2();
newProfile.LoadFromIWMProfile(profile);
// Specify this profile object as the profile to use in source group.
srcGrp.set_Profile(newProfile);
}
}
// Start the encoding process.
// Wait until the encoding process stops before exiting the application.
encoder.PrepareToEncode(true);
encoder.Start();
while (encoder.RunState != WMENC_ENCODER_STATE.WMENC_ENCODER_STOPPED)
{
Thread.Sleep(500);
}
encoder.Stop();
encoder.Reset();
try
{
#region Release com objects
if (file != null)
Marshal.FinalReleaseComObject(file);
if (profile != null)
Marshal.FinalReleaseComObject(profile);
if (newProfile != null)
Marshal.FinalReleaseComObject(newProfile);
if (srcAud != null)
Marshal.FinalReleaseComObject(srcAud);
if (srcGrp != null)
Marshal.FinalReleaseComObject(srcGrp);
if (srcGrpColl != null)
Marshal.FinalReleaseComObject(srcGrpColl);
if (proColl != null)
Marshal.FinalReleaseComObject(proColl);
if (encoder != null)
Marshal.FinalReleaseComObject(encoder);
// GC collect is explicitly called because of a memory leak issue of WMEncoder.
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
#endregion
}
catch { }
}