How to pass an argument to the EventHandler - c#

No it's not that kind of basic question. I am doing a application and got a scenerio like, the file will be downloaded then it will be uploaded to the FTP server, then the local copy will be deleted, then one entry will be placed in a dictionary for that filename. So, the code is below
public void download_This_WebPage(string url, string cookies_String, string local_Saving_File_Name_With_Path)
{
WebClient wb = new WebClient();
wb.Headers.Add(HttpRequestHeader.Cookie, cookies_String);
// Below I want to pass this local_File _Path to the event handler
wb.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(wb,);
wb.DownloadFileAsync(new Uri(url), local_Saving_File_Name_With_Path + ".html");
}
public void data_Download_Completed(Object sender, System.ComponentModel.AsyncCompletedEventArgs args)
{
//use the file name to upload the file to FTP
}
public FTP_Completed
{
// Delete the file
}
But, I dont know how to pass that filename to the event handler of download_Completed. Can anybody guide me in this
EDIT:
Thank you for the answers from "Darin" and "Frederic". Is there any general way to pass the custom data to the (already defined)event handler like below
void main_Fn()
{
string my_Data = "Data";
some_object a = new some_object();
some_Object.click_event += new eventHandler(click_Happened);
(Assume that the event passes two ints, I also want to pass the string "my_Data"
to "click_Happened")
some_object.start();
}
void click_Happened(int a, int b)
{
// I want to get the string "my_Data" here.
}
In short how to trick the signature?

You can pass the file name in the userToken argument to DownloadFileAsync(). When the operation finishes, it will be available in the UserState property of the AsyncCompletedEventArgs argument passed to data_Download_Completed():
string filename = local_Saving_File_Name_With_Path + ".html";
wb.DownloadFileAsync(new Uri(url), filename, filename);
Then:
public void data_Download_Completed(Object sender,
System.ComponentModel.AsyncCompletedEventArgs args)
{
string filename = (string) args.UserState;
// Now do something with 'filename'...
}

You could use the 3-rd argument of the DownloadFileAsync method which allows you to pass an UserState to the completed handler:
// subscribe to the completed event
wb.DownloadFileCompleted += data_Download_Completed;
string file = local_Saving_File_Name_With_Path + ".html";
wb.DownloadFileAsync(new Uri("url"), file, file);
and inside the handler:
public void data_Download_Completed(Object sender, AsyncCompletedEventArgs args)
{
// extract the filename from the UserState of the args
string file = args.UserState as string;
...
}

Related

dictionary error item with the same key has already been added

I'm trying to read every #define in a C++ header, and display an editor for each of the values, so I can quickly redefine the constants.
I'm trying to parse the file, getting each item on the left side to be key. I want to display the value on the left, edit the values and save back out. Currently, when I save my file it messes up the format.
This is the code i currently have :
private String header;
private Dictionary<String, String> tokens;
private String file = Properties.Settings.Default.path_location;
public TextBox elf_naparm_zombie_developer;
public harrs_gsh_editor(string file)//TextBox elf_naparm_zombie_developer
{
Properties.Settings.Default.path_location = file;
Properties.Settings.Default.Save();
loadweapon();
// this.elf_naparm_zombie_developer = elf_naparm_zombie_developer;
}
public void loadweapon()
{
this.tokens = File.ReadLines(this.file)
.Select(line => Regex.Match(line, #"^\s*#define\s+(.+?)(\s+(.+?))?((\s*//)|$)"))
.Where(m => m.Success && m.Groups[3].Success)
.ToDictionary(m => m.Groups[1].Value, m => m.Groups[3].Value);
}
public String Search(String name)
{
foreach (KeyValuePair<String, String> pair in tokens)
{
if (pair.Key == name)
return pair.Value;
}
return null;
}
public void Set(String key, String val)
{
tokens[key] = val;
}
public void Save(String file)
{
using (StreamWriter sw = new StreamWriter(File.OpenWrite(file)))
{
sw.Write(header);
foreach (KeyValuePair<String, String> pair in tokens)
{
sw.Write("\r\n" + pair.Key + "#define " + pair.Value);
}
}
}
public void Save()
{
this.Save(file);
}
The issue I have is when I save it back, it messes up the file and removes the #define. What im trying to do is just change the value and write it back to the program with changed value
this is the file i want to edit
So what im trying to do is load up the selected key and display the value witch i have managed to do with this code i created but the issue im having is writing it back
the code i use to load and populate the text box
namespace Harry_s_Template_Editor
{
public partial class Form1 : Form
{
harrs_gsh_editor elfghc;
string path = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + #"/hb21_zm_ai_napalm.gsh";
public Form1()
{
InitializeComponent();
elfghc = new harrs_gsh_editor(path);//TextBox elf_naparm_zombie_developer
elf_naparm_zombie_developer = elf_naparm_zombie_developer;
// MessageBox.Show(path);
}
private void button1_Click(object sender, EventArgs e)
{
elfghc.loadweapon();
this.elf_naparm_zombie_developer.Text = elfghc.Search("NAPALM_ZOMBIE_DEVELOPER_DEBUG_PRINTS");
elfghc.Set("NAPALM_ZOMBIE_DEVELOPER_DEBUG_PRINTS", elf_naparm_zombie_developer.Text);
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
elfghc.Set("NAPALM_ZOMBIE_DEVELOPER_DEBUG_PRINTS", elf_naparm_zombie_developer.Text);
elfghc.Save(path);
}
}
}
when i save out the file i now get this error when i try to load the program again
error
thanks in advance Yuki
file when saved back
Original answer:
Why are you writing it back to the file in this order: sw.Write("\r\n" + pair.Key + "#define " + pair.Value);? Shouldn't the #define come first on the line after \r\n? I would have thought it should be something like this: sw.Write("\r\n#define " + pair.Key + " " + pair.Value);
New answer (the question has changed)
There are two problems with what you are doing:
You are writing key/value pairs back to a file, ignoring the headers and credits that were in the original file. If you're happy to strip those out then that's fine, but it sounds like this is important to you. So instead you need to read the file, find the keys in the file, then update the values and save the updated file back to disk. That's a harder problem than simply writing a bunch of key/value pairs to a file.
The second issue is the way you are writing the file back to disk. According to this MSDN page, File.OpenWrite has the following behaviour:
The OpenWrite method opens a file if one already exists for the file
path, or creates a new file if one does not exist. For an existing
file, it does not append the new text to the existing text. Instead,
it overwrites the existing characters with the new characters. If you
overwrite a longer string (such as “This is a test of the OpenWrite
method”) with a shorter string (such as “Second run”), the file will
contain a mix of the strings (“Second runtest of the OpenWrite
method”).
So this is why you're getting a mangled file. You're overwriting the first N bytes with your updated key/value pairs, and the rest of the file is duplicated data from the original file. You probably want to use the following instead, which will overwrite the original file entirely:
using (StreamWriter sw = new StreamWriter(file, false))

Creating txt file cannot access file being used by another process

I'm trying to make a service that creates a text file, as a tutorial project.
However when I debug it, I get The process cannot access the file C:\myfilepath.OnStart.txt because it is being used by another process.
I'm expecting it to keep creating the file in a format like OnStart(n).txt
public void OnDebug()
{
OnStart(null);
}
protected override void OnStart(string[] args)
{
Timer t = new Timer(WriteTxt, null, 0, 5000);
}
public static void WriteTxt(Object i)
{
System.IO.File.Create(AppDomain.CurrentDomain.BaseDirectory + "OnStart.txt");
}
When creating the file you're mistakenly leaving it open which is why you can't access it next time and receive an error. You must call .Dispose() after you've created it to let go of the reference to the file like this:
File.Create(AppDomain.CurrentDomain.BaseDirectory + "OnStart.txt").Dispose();
If you want to keep creating files then they'll need a different name each time. You could keep a global variable to keep track of this or possibly pass a value into the Write method.
Global variable method
// Keeps track of the last file number with this global variable
private int fileCount;
public void OnDebug()
{
OnStart(null);
}
protected override void OnStart(string[] args)
{
fileCount = 0; // Or whatever you want to start with
Timer t = new Timer(WriteTxt, null, 0, 5000);
}
public static void WriteTxt(Object i)
{
// Creates the file name eg: OnStart1.txt
var fileName = string.Format("OnStart{0}.txt", fileCount);
// Use Path.Combine to make paths
var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
// Create the file
File.Create(filePath).Dispose();
// Adds 1 to the value
fileCount++;
}
Results:
OnStart0.txt
OnStart1.txt
OnStart2.txt
...
...
OnStart4999.txt

Window Phone 8.1: Confusing about file location and writing data

I'm trying to read and write data with json file.
I created some class.
public class SimpleTask{...}
public class DayTask{...}
public class DataModel
{
...
private async Task GetSimpleTaskAsync()
{
if (_daytask.Count != 0)
return;
string fileName = "a.json";
Uri appUri = new Uri("ms-appx:///"+ fileName);
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(appUri);
string jsonText = await FileIO.ReadTextAsync(file);
JsonObject jsonObject = JsonObject.Parse(jsonText);
JsonArray jsonArray = jsonObject["DayTasks"].GetArray();
foreach (JsonValue daytaskValue in jsonArray)
{
JsonObject daytaskObject = daytaskValue.GetObject();
ObservableCollection<SimpleTask> simpletask = new ObservableCollection<SimpleTask>();
foreach (JsonValue simpletaskValue in daytaskObject["Tasks"].GetArray())
{
JsonObject simpletaskObject = simpletaskValue.GetObject();
simpletask.Add(new SimpleTask( simpletaskObject["StartTime"].GetString(),
simpletaskObject["EndTime"].GetString(),
simpletaskObject["Description"].GetString()));
}
DayTask daytask = new DayTask(daytaskObject["Day"].GetString(),simpletask);
this.DayTasks.Add(daytask);
}
}
}
As you can see, i have a method that gets data form a.json file. I created a.json file:
In the MainPage.xaml.cs, there is a method which calls GetDayTaskAysnc() method and retrieves data :
private async void ReadData1(object sender, TappedRoutedEventArgs e)
{
string test = String.Empty;
var daytask = await DataModel.GetDayTaskAsync();
foreach (var tasks in daytask)
{
test += String.Format("Day:{0}:\n", tasks.Day);
foreach (var simpletask in tasks.Tasks)
{
test += String.Format("\tStart Time: {0}\n", simpletask.StartTime);
test += String.Format("\tEnd Time: {0}\n", simpletask.EndTime);
test += String.Format("\tDescription Time: {0}\n", simpletask.Description);
}
}
TextBlock.Text = test;
}
It worked fine ! But i want to write data to the same file, so i added data in hardcore way:
private List<DayTask> creatList()
{
List<DayTask> DayTasks = new List<DayTask>();
ObservableCollection<SimpleTask> simpletask1 = new ObservableCollection<SimpleTask>();
simpletask1.Add(new SimpleTask("6AM","7AM","Breakfast"));
simpletask1.Add(new SimpleTask("8AM", "9AM", "Game"));
ObservableCollection<SimpleTask> simpletask2 = new ObservableCollection<SimpleTask>();
simpletask2.Add(new SimpleTask("6AM", "7AM", "Sleep"));
simpletask2.Add(new SimpleTask("8AM", "9AM", "School"));
DayTasks.Add(new DayTask ("3/8/2014",simpletask1));
DayTasks.Add(new DayTask("4/8/2014", simpletask2));
return DayTasks;
}
private async void WriteData(object sender, TappedRoutedEventArgs e)
{
string json = "a.json";
List<DayTask> daytasks = creatList();
var serializer = new DataContractJsonSerializer(typeof(List<DayTask>));
var stream = await ApplicationData.Current.LocalFolder.OpenStreamForWriteAsync(json, CreationCollisionOption.ReplaceExisting);
using (stream)
{
serializer.WriteObject(stream, daytasks);
}
TextBlock.Text = "Write to Json file succeeded";
}
When i ran my app with window phone emulator, Firstly, it wrote to the file. Then i clicked read data button to ensure data written correctly, the emulator showed data from a.json file without being modified by WriteData() method. I continued to creat the second read data method:
private async void ReadData2(object sender, TappedRoutedEventArgs e)
{
string test = String.Empty;
string json = "a.json";
string content = String.Empty;
List<DayTask> mytasks = new List<DayTask>();
var deserializer = new DataContractJsonSerializer(typeof(List<DayTask>));
var stream = await ApplicationData.Current.LocalFolder.OpenStreamForReadAsync(json);
using (stream)
{
mytasks = (List<DayTask>)deserializer.ReadObject(stream);
}
foreach (var tasks in mytasks)
{
test += String.Format("Day:{0}:\n", tasks.Day);
foreach (var simpletask in tasks.Tasks)
{
test += String.Format("\tStart Time: {0}\n", simpletask.StartTime);
test += String.Format("\tEnd Time: {0}\n", simpletask.EndTime);
test += String.Format("\tDescription Time: {0}\n", simpletask.Description);
}
}
TextBlock.Text = test;
}
I deployed my app several times, and this is my result:
ReadData2() : 'System.IO.FileNotFoundException'
WriteData() -> ReadData1(): Data from a.json was shown
WriteData() -> ReadData2(): Data from creatList() was shown
WriteData() -> ReadData1(): Data from a.json was shown -> ReadData2(): Data from creatList() was shown
So that, i have some question:
Do i have 2 json files, one i created by adding into my project and the other one i created when ran WriteData() method ? What is their paths ?
If my file is data.json in DataSource folder, how can i write data to it ? I can read data from it using uri like GetSimpleTaskAsync() but i don't know how to write to it correctly. (I tried to convert object into string to write but can't read it again, i guess i wrote it in wrong way)
Sorry for my long post and my bad english :) Thank you very much
But i want to write data to the same file, so i added data in hardcore way:
Your are making confusion between ms-appx:/// and ms-appdata:/// folders (or ApplicationData.Current.LocalFolder )
The ms-appx folder is read-only. You can't write to it. (or you could edit your app code without passing through the certification process)
The file you wrote must be into the ms-appdata folder.

ASP.NET "one time cache" for file

I'm trying to implement what I'd call a "one time cache" for specific files in my ASP.NET 3.5 site. Upon request, the file is downloaded from a remote file server onto the web server, then served up by my page. The problem arises when I go to delete it. If I delete the file in the OnUnload method, the client doesn't have time to retrieve it. Is there some way of detecting the download of a file and deleting it immediately after it is first accessed? My code is like this:
private bool _deleteFlag = false;
private string _deleteFile = string.Empty;
protected void Page_Load(object sender, EventArgs e) {
if (!string.IsNullOrEmpty(Request.QueryString["file"])) {
_deleteFlag = Request.QueryString["file"].Contains(#"cache/");
_deleteFile = Request.QueryString["file"];
}
}
protected override void OnUnload(EventArgs e) {
if (_deleteFlag) {
// Can't delete here; the client is still trying to retrieve it.
System.IO.File.Delete(Server.MapPath(_deleteFile));
}
base.OnUnload(e);
}
I'm leaning towards writing an IHttpHandler that overrides the file request, but that feels like overkill.
Try this:
When you add your file, insert it into the HttpRuntimeCache and set the Key to the FileName and set the TimeOut to say 10 seconds. Then on the CacheItemRemoved callback, delete the file. It's not exact, but it should roughly meet your use case.
public static object LoadFile()
{
var filename = ParseFileNameFromHttpRequest();
var a = loadFileSomeHow(filename);
HttpRuntime.Cache.Insert(
filename ,
a,
null,
System.Web.Caching.Cache.NoAbsoluteExpiration,
new TimeSpan(0, 0, 0,10,0,0),
CacheItemPriority.Default,
new CacheItemRemovedCallback(DeleteFile));
return a;
}
public void DeleteFile(String key, object value,
CacheItemRemovedReason removedReason)
{
File.Delete(key);
}
For more info: http://msdn.microsoft.com/en-us/library/vstudio/7kxdx246(v=vs.100).aspx

c# identifier expected?

I am trying to create a program to copy all the files from one directory to another. But I am running in a basic issue. It says indentifier expected when I try to compile on line 52.
public bool RecursiveCopy()
{
string origDir = #"D:\Documents and Settings\Dub\My Documents\HoN Updates\test";
string destDir = #"C:\Games\HoN";
bool status = false;
//get all the info about the original directory
var dirInfo = new DirectoryInfo(origDir);
//retrieve all the _fileNames in the original directory
var files = dirInfo.GetFiles(origDir);
//always use a try...catch to deal
//with any exceptions that may occur
try
{
//loop through all the file names and copy them
foreach (string file in Directory.GetFiles(origDir))
{
var origFile = new FileInfo(file);
var destFile = new FileInfo(file.Replace(origDir, destDir));
//copy the file, use the OverWrite overload to overwrite
//destination file if it exists
System.IO.File.Copy(origFile.FullName, destFile.FullName, true);
//TODO: If you dont want to remove the original
//_fileNames comment this line out
File.Delete(origFile.FullName);
status = true;
}
Console.WriteLine("All files in " + origDir + " copied successfully!");
}
catch (Exception ex)
{
status = false;
//handle any errors that may have occurred
Console.WriteLine(ex.Message);
}
return status;
}
public string origDir = #"D:\Documents and Settings\Dub\My Documents\HoN Updates\test"; // ERROR HERE
public string destDir = #"C:\Games\HoN"; // ERROR HERE
private static void RecursiveCopy(origDir, destDir)
{
Console.WriteLine("done");
Console.ReadLine();
}
You did not give type identifiers to your argument list here
static void RecursiveCopy(origDir, destDir)
should be
static void RecursiveCopy(string origDir, string destDir)
Your method RecursiveCopy has two parameters listed without their types. It should be this:
static void RecursiveCopy(string origDir, string destDir)
Here is your problem:
static void RecursiveCopy(origDir, destDir)
You don't specify the types for the parameters, perhaps you intended the following:
static void RecursiveCopy(string origDir, string destDir)
There are more issues however that I've noticed. It's possible you're still working on these, but from what you've posted:
You never call your RecursiveCopy method. Perhaps you meant to call it from Main() instead of declaring an overload with two parameters?
You declare two public fields origDir and destDir but then never use them. Instead you create two local variables in RecursiveCopy() and use these instead. Did you intend to create parameters or use the public fields instead?
Your copy is not actually true to its name of "recursive".
cYou are missing the parameter types in the RecursiveCopy method declaration. Just Change
static void RecursiveCopy(origDir, destDir)
to
static void RecursiveCopy(String origDir, String destDir)
and all is fine.

Categories

Resources