This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How check if given string is legal (allowed) file name under Windows?
I have searched about, spent some minutes googling, but i cant apply what i have found, to my context..
string appPath = Path.GetDirectoryName(Application.ExecutablePath);
string fname = projectNameBox.Text;
if (projectNameBox.TextLength != 0)
{
File.Create(appPath + "\\projects\\" + fname + ".wtsprn");
So, i am retrieving the projectNameBox.Text and creating a file with the text as filename, but if i include a :, or a \ or a / etc.. it will just crash, which is normal, as those are not allowed for a folder name..How can i check the text, before the file creation, and remove the characters, or even better, do nothing and advise the user that he can not use those characters?
Thanks in advance
string appPath = Path.GetDirectoryName(Application.ExecutablePath);
string fname = projectNameBox.Text;
bool _isValid = true;
foreach (char c in Path.GetInvalidFileNameChars())
{
if (projectNameBox.Text.Contains(c))
{
_isValid = false;
break;
}
}
if (!string.IsNullOrEmpty(projectNameBox.Text) && _isValid)
{
File.Create(appPath + "\\projects\\" + fname + ".wtsprn");
}
else
{
MessageBox.Show("Invalid file name.", "Error");
}
Alternative there is a regex example in the link provided in the first comment.
You can respond to the TextChanged event from your projectNameBox TextBox to intercept changes made to its contents. This means that you can remove all the invalid characters before creating your path later on.
To create the event handler, click on your projectNameBox control in the designer, click the Events icon in the Properties window, then double-click on the TextChanged event in the list that appears below. The following is a brief example of some code that strips out invalid characters:
private void projectNameBox_TextChanged(object sender, EventArgs e)
{
TextBox textbox = sender as TextBox;
string invalid = new string(System.IO.Path.GetInvalidFileNameChars());
Regex rex = new Regex("[" + Regex.Escape(invalid) + "]");
textbox.Text = rex.Replace(textbox.Text, "");
}
(You'll need a using statement for System.Text.RegularExpressions at the top of your file, too.)
Related
I'm new to C# and trying to understand how things work. So I created a two forms. First one has a textbox and the second one has a combobox with a button that sends offer help to that computer. From the text box I add computer names. once I click the OK button it loads all my computer names to the combobox.
string[] computerlist = txtComputers.Text.Split(new[]{'\n'}, StringSplitOptions.RemoveEmptyEntries);
frmHome _frmhome = new frmHome();
_frmhome.cbComputerList.Items.AddRange(computerlist);
_frmhome.ShowDialog();
_frmhome.Dispose();
When I select a computer from the dropbox and click Offer_help button, offer remote window comes up saying its trying to connect to the user but then fails.
private void Offerhelp_Click(object sender, EventArgs e)
{
CompName = cbComputerList.SelectedItem.ToString();
var _offerhelp = new ProcessStartInfo();
_offerhelp.FileName = "msra.exe";
_offerhelp.Arguments = String.Format("/offerRA" + " " + CompName);
Process.Start(_offerhelp);
}
I tried running in debug mode and I see that "CompName" variable is
"/offerRA Lab1\r"
if I remove the "\r" it actually works.
Can anyone tell me why this is happening? Also, Is there a way I can create a new class for the selected item and make it a global variable so I can use it say if I create 4-5 forms and use that computer name in all forms?
Thanks in advance.
Your line
string[] computerlist = txtComputers.Text.Split(new[]{'\n'}, StringSplitOptions.RemoveEmptyEntries);
Is the issue. \n is the newline operator, and \r is carriage return. Depending on OS / Program, you can use \r\n to determine a 'NewLine'.
Use
string[] computerlist = txtComputers.Text.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
Environment.NewLine will return the proper character.
EDIT: In terms of your comment, add a static property to your form:
class MyForm
{
public static string SelectedComputer { get; set;}
}
you can then reference this anywhere by
MyForm.SelectedComputer
Set this variable on your cbComputerList.SelectedIndexChanged event. Just check to make sure the value is greater than 0 then set it.
First thing first - I'm sorry for my poor English and I'm kinda new to this great community, so I'm really sorry if something is incorrect in my question.
In short - I've started with C# not so long ago (which means you find a lot of poor written code here) and now I'm aiming to create a dialogue system. Though I have some working sample, questions are:
How to make everything not this lame and improve the code;
Suggestions about improving performance;
Overall advices (maybe there is some more suitable tools for doing this);
Right now I use Finite-State Machine (FSM) as a general concept, so that every state is a dialogue scene. The last one is made of NPC quote and set of Player responds.
By now everything is pretty basic. Here I have my class for Player responds.
using System;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
namespace Testing
{
public class Player_Qoute : Label
{
public string Next_State { get; set; }//is used to tell, where to go next after choosing particular respond
}
It's inherited from Label and has one additional field - next stage number, which is added in function below:
private void NPC_Quote(string path, string specification, RichTextBox info)
{
StreamReader file = new StreamReader(path);//creating StremReader to read NPC quotes from .txt
string line = "";//Creating string variable to read from
try
{
while ((line = file.ReadLine()) != null)//readinf file line-by-line until the end
{
if (line.Contains(specification))//if line contains specified "tag"
{
line = line.Remove(0, specification.Length);//removing "tag" from line
info.Text += line + "\n";//adding NPC line to the output field
}
}
file.Close();
}
catch (Exception)
{
MessageBox.Show("Problem reading file");
}
}
This function parse through .txt file, searching for lines tagged "NPC_stage_n", where "n" - is a number of stage. This number is present at the end of every Player respond in .txt file and I put it in the "Next_Stage" field of Player_Quote objects.
The same idea is applied here, but now i dynamically create Player's responds (number of which varies from stage to stage). I'm facing some issues with appropriate placing of quotes on the GroupBox - sometimes they are missing a line or words, but I'm working on it:
void Quotes_Generation(string path, string specification, GroupBox parent)
{
parent.Controls.Clear();//deleting previous Player qoutes
int step = 0;//auxilary variable to separate quotes from each other by heigth
StreamReader file = new StreamReader(path);//StreamReader to read Player responds from .txt
string line = "";
while ((line = file.ReadLine()) != null)
{
if (line.Contains(specification))
{
Player_Qoute quote = new Player_Qoute();//inherited from Label;
quote.Name = "qoute_" + line.Remove(specification.Length, line.Length - specification.Length);
quote.Location = new Point(10, 20 + step);
quote.Size = new Size(360, 10);
quote.Text = line.Remove(0, specification.Length);//deleting "search tag" from text
quote.Text = quote.Text.Remove(quote.Text.Length-3, 3); //here we are deleting 3-digit number at the end of the string
//this number will show what is the next state of the dialogue if this Player respond is chosen.
quote.Next_State = line.Remove(0,line.Length - 3);//storing 3-digit number in Player_Quote property
using (Graphics g = CreateGraphics())//part of code which was borrowed from StackOverFlow and wasn't properly understood by me
{
SizeF size = g.MeasureString(quote.Text, quote.Font, 264);
quote.Height = (int)Math.Ceiling(size.Height);
quote.Text = quote.Text;
}
quote.MouseDown += new MouseEventHandler(this.Quote_Click);//creating event for choosing this respond
parent.Controls.Add(quote);//adding respond to GroupBox
step += (quote.Height+3);//increasing step
if (parent.Height < step)//enlarging GroupBox
{
parent.MaximumSize = new System.Drawing.Size(parent.Width, step + 50);
parent.Size = new System.Drawing.Size(parent.Width, step + 50);
}
}
}
file.Close();
}
And here is the Quote_Click event:
private void Quote_Click(object sender, EventArgs e)
{
Player_Qoute current = sender as Player_Qoute;//recognizing the sender
richTextBox1.Text += Player_Name + " - " + current.Text + "\n";//adding Player respond with Player name to RichTextBox
NPC_Quote(Application.StartupPath + "/Readme.txt", "NPC_stage_" + current.Next_State + ":", richTextBox1);//Adding new NPC line according to chosen respond
Quotes_Generation(Application.StartupPath + "/Readme.txt", "Player_stage_" + current.Next_State + ":", groupBox1);//refreshing responds according to previous actions
}
I'll appreciate all the advices!
I've created a Keyboard for my WPF application in XAML with the functionality of it done in the code behind C#. As of now, any key clicked (or touched), will display the respective key in a TextBox (as expected. However, when handling the HTML Code, the HTML Code gets displayed.
For reference, the button click:
private void btnQUOTATION_Click(object sender, RoutedEventArgs e)
{
HandleKeyboard(""");
}
The HandleKeyboard method:
private bool current spot = false;
private void HandleKeyboard(string key)
{
//Ternary operator
string valueSoFar = currentSpot ? txtBoxTest.Text : "";
string newValue = valueSoFar + key.ToString();
txtBoxTest.Text = newValue;
currentSpot = true;
}
Everything is fine and dandy with the other keys presented, except for quotation marks and apostrophes.
What I'm expecting in the TextBox txtBoxTest when the button for quotation marks is clicked (") is quote marks to show in the text box as quotation marks...instead of the HTML code it is showing now.
Since HandleKeyboard() cannot accept (""") or ("'") ... Is there a way to do this?
You could look to use the Encode and Decode HTML. You will need to use System.Web namespace.
e.g.
string key= "This is a "";
string deCodedKey = System.Web.HttpUtility.HtmlDecode(key);
If you put a breakpoint over the DeCodedKey line you should see it change back to ""
I have VS2010, C#. I use RichTextBox in a form. I set the DectectUrls property to True. I set a LinkClicked event.
I would like open a file link like this: file://C:\Documents and Settings... or file://C:\Program Files (x86)...
It doesn't works for path with spaces.
The source code:
rtbLog.SelectionFont = fnormal;
rtbLog.AppendText("\t. Open Path" + "file://" + PathAbsScript + "\n\n");
// DetectUrls set to true
// launch any http:// or mailto: links clicked in the body of the rich text box
private void rtbLog_LinkClicked(object sender, LinkClickedEventArgs e)
{
try
{
System.Diagnostics.Process.Start(e.LinkText);
}
catch (Exception) {}
}
Any suggestions?
Instead of using %20 (which some users may find "ugly" looking), you can use the UNICODE non-breaking space character (U+00A0). For example:
String fileName = "File name with spaces.txt";
FileInfo fi = new FileInfo(fileName);
// Replace any ' ' characters with unicode non-breaking space characters:
richTextBox.AppendText("file://" + fi.FullName.Replace(' ', (char)160));
Then inside your link click handler for the rich text box, you'd do the following:
private void richTextBox_LinkClicked(object sender, LinkClickedEventArgs e)
{
// Replace any unicode non-break space characters with ' ' characters:
string linkText = e.LinkText.Replace((char)160, ' ');
// For some reason rich text boxes strip off the
// trailing ')' character for URL's which end in a
// ')' character, so if we had a '(' opening bracket
// but no ')' closing bracket, we'll assume there was
// meant to be one at the end and add it back on. This
// problem is commonly encountered with wikipedia links!
if((linkText.IndexOf('(') > -1) && (linkText.IndexOf(')') == -1))
linkText += ")";
System.Diagnostics.Process.Start(linkText);
}
You should enclose the path with double quotes, e.g.:
"file://c:\path with spaces\..."
To add a double quote to a string, you must use an escape sequence \".
go to that particular folder and give the permission to write or make it shared from properties of that folder.
Finally, I use a replace (" ", "%20")
// http://social.msdn.microsoft.com/Forums/eu/Vsexpressvb/thread/addc7b0e-e1fd-43f4-b19c-65a5d88f739c
var rutaScript = DatosDeEjecucion.PathAbsScript;
if (rutaScript.Contains(" ")) rutaScript = "file://" + Path.GetDirectoryName(DatosDeEjecucion.PathAbsScript).Replace(" ", "%20");
rtbLog.AppendText(". Abrir ubicaciĆ³n: " + rutaScript + "\n\n");
The code for LinkClicked event:
private void rtbLog_LinkClicked(object sender, LinkClickedEventArgs e)
{
try
{
var link = e.LinkText.Replace("%20", " ");
System.Diagnostics.Process.Start(link);
}
catch (Exception)
{
}
}
Are there any automatic methods for trimming a path string in .NET?
For example:
C:\Documents and Settings\nick\My Documents\Tests\demo data\demo data.emx
becomes
C:\Documents...\demo data.emx
It would be particularly cool if this were built into the Label class, and I seem to recall it is--can't find it though!
Use TextRenderer.DrawText with TextFormatFlags.PathEllipsis flag
void label_Paint(object sender, PaintEventArgs e)
{
Label label = (Label)sender;
TextRenderer.DrawText(e.Graphics, label.Text, label.Font, label.ClientRectangle, label.ForeColor, TextFormatFlags.PathEllipsis);
}
Your code is 95% there. The only
problem is that the trimmed text is
drawn on top of the text which is
already on the label.
Yes thanks, I was aware of that. My intention was only to demonstrate use of DrawText method. I didn't know whether you want to manually create event for each label or just override OnPaint() method in inherited label. Thanks for sharing your final solution though.
# lubos hasko Your code is 95% there. The only problem is that the trimmed text is drawn on top of the text which is already on the label. This is easily solved:
Label label = (Label)sender;
using (SolidBrush b = new SolidBrush(label.BackColor))
e.Graphics.FillRectangle(b, label.ClientRectangle);
TextRenderer.DrawText(
e.Graphics,
label.Text,
label.Font,
label.ClientRectangle,
label.ForeColor,
TextFormatFlags.PathEllipsis);
Not hard to write yourself though:
public static string TrimPath(string path)
{
int someArbitaryNumber = 10;
string directory = Path.GetDirectoryName(path);
string fileName = Path.GetFileName(path);
if (directory.Length > someArbitaryNumber)
{
return String.Format(#"{0}...\{1}",
directory.Substring(0, someArbitaryNumber), fileName);
}
else
{
return path;
}
}
I guess you could even add it as an extension method.
What you are thinking on the label is that it will put ... if it is longer than the width (not set to auto size), but that would be
c:\Documents and Settings\nick\My Doc...
If there is support, it would probably be on the Path class in System.IO
You could use the System.IO.Path.GetFileName method and append that string to a shortened System.IO.Path.GetDirectoryName string.
Next code works for folders. I'm using it to display a download path!
public static string TrimPath(string path) {
string shortenedPath = "";
string[] pathParts = path.Split('\\');
for (int i = 0; i < pathParts.Length-1; i++) {
string part = pathParts[i];
if (pathParts.Length-2 != i) {
if (part.Length > 5) { //If folder name length is bigger than 5 chars
shortenedPath += "..\\";
}
else {
shortenedPath += part+"\\";
}
}
else {
shortenedPath += part+"\\";
}
}
return shortenedPath;
}
Example:
Input:
C:\Users\Sandra\Desktop\Proyectos de programaciĆ³n\Prototype\ServerClient\test
output:
C:\Users\..\..\..\..\..\test\