In my program I have a string which contains URLs separated by /n (One per line)
Let's say the string is called "links". I want to take this string and generate a HTML file that will automatically open in my default browser which will make each URL a hyperlink (one per line). How would I make such a report not using any third party components using WPF C# 4.0? I want the report to be generated by clicking a button called "Export".
There are plenty of ways to do this, but here is a quick and dirty example (debugging may be necessary since I wrote this on the fly). [Edit: Now uses Uri objects to formulate the actual address.]
private void export_Click(object sender, RoutedEventArgs e)
{
string tempFileName = "list.html";
string links = "http://www.google.com/#sclient=psy&hl=en&site=&source=hp&q=test+me&aq=f&aqi=&aql=&oq=&gs_rfai=&pbx=1&fp=ddfbf15c2e2f4021\nhttp://www.testme.com/Test-Prep.html?afdt=Q3RzePF0jU8KEwja-5WM7PqkAhUUiZ0KHaoG_wcYASAAMJbwoAM4MEC4w6uX7dS53gdQlvCgA1CEra8PUJzr_xNQg73wFVCKttweUJStzNoBUNv67ZsD";
List<Uri> uriCollection = new List<Uri>();
foreach (string url in links.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries))
{
uriCollection.Add(new Uri(url));
}
// Create temporary file.
using (TextWriter writer = new StreamWriter(tempFileName))
{
try
{
writer.WriteLine("<html>");
writer.WriteLine("<head><title>Links</title></head>");
writer.WriteLine("<body>");
writer.WriteLine("<p>");
foreach (Uri uri in uriCollection)
{
writer.WriteLine("{1}<br />", uri.OriginalString, uri.Host);
}
writer.WriteLine("</p>");
writer.WriteLine("</body>");
writer.WriteLine("</html>");
}
catch (Exception ex)
{
System.Diagnostics.Trace.TraceError(ex.Message);
}
finally
{
writer.Close();
}
}
// Open browser with temporary file.
if (File.Exists(tempFileName))
{
System.Diagnostics.Process.Start(tempFileName);
}
}
The 'Export' button is wired to the event 'export_Click'. I hard-coded the the string with '\n''s for the example. Simply break these apart using split and write a temporary file creating the HTML you need. Then, once the file is completed, you can open it using the Process.Start() method.
Ideally this can be done using DataBinding and other elements available in WPF if the need to open a browser window was not required. This would also remove any external dependencies the program may have.
Related
I'm trying to iteratively (part of automation):
Create backup of the projects in solution (physical files on the filesystem)
Using Microsoft.Build programmatically load and change projects inside of the solution (refernces, includes, some other properties)
Build it with console call of msbuild
Restore projects (physically overriding patched versions from backups)
This approach works well for first iteration, but for second it appears that it does not load restored projects and trying to work with values that I patched on the first iteration. It looks like projects are cached: inside of the csproj files I see correct values, but on the code I see previously patched values.
My best guess is that Microsoft.Build is caching solution/projects in the context of the current process.
Here is code that is responsible to load project and call method to update project information:
private static void ForEachProject(string slnPath, Func<ProjectRootElement> patchProject)
{
SolutionFile slnFile = SolutionFile.Parse(slnPath);
var filtredProjects = slnFile
.ProjectsInOrder
.Where(prj => prj.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat);
foreach (ProjectInSolution projectInfo in filtredProjects)
{
try
{
ProjectRootElement project = ProjectRootElement.Open(projectInfo.AbsolutePath);
patchProject(project);
project.Save();
}
catch (InvalidProjectFileException ex)
{
Console.WriteLine("Failed to patch project '{0}' with error: {1}", projectInfo.AbsolutePath, ex);
}
}
}
There is Reload method for the ProjectRootElement that migh be called before iteraction with content of the project.
It will enforce Microsoft.Build to read latest information from the file.
Code that is working for me:
private static void ForEachProject(string slnPath, Func<ProjectRootElement> patchProject)
{
SolutionFile slnFile = SolutionFile.Parse(slnPath);
var filtredProjects = slnFile
.ProjectsInOrder
.Where(prj => prj.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat);
foreach (ProjectInSolution projectInfo in filtredProjects)
{
try
{
ProjectRootElement project = ProjectRootElement.Open(projectInfo.AbsolutePath);
project.Reload(false); // Ignore cached state, read actual from the file
patchProject(project);
project.Save();
}
catch (InvalidProjectFileException ex)
{
Console.WriteLine("Failed to patch project '{0}' with error: {1}", projectInfo.AbsolutePath, ex);
}
}
}
Note: It better to use custom properties inside of the project and provide it for each msbuild call instead of physical project patching. Please consider it as better solution and use it if possible.
In my project, I have the player info being saved out to a JSON file. I am encrypting the information before I save it but if the player goes into the file and happens to delete one character of the file, when the game loads, because it depends upon that file, the game freezes up. I do have it so that a new player info is created if no file is detected, but if the file is there and they mess with it, is there any way of detecting that and correcting it before the game tries to load it. I am using JSONUtility built into Unity.
Use a try/catch when loading the JSON file
try
{
JsonUtility.FromJSON(...)
}
catch (FileNotFoundException e)
{
Print("The file was not found: '{e}'");
}
catch (DirectoryNotFoundException e)
{
Print("The directory was not found: '{e}'");
}
catch (IOException e)
{
Print("The file could not be opened: '{e}'");
}
However, this shouldn't be that important. If a player is trying to mess with the game files and you are worried about the program crashing, you shouldn't because that player shouldn't have been editing game files.
I think using both hashing and try/catch checking would be the better solution
You can just try to open the file then compare its hash with the hash you saved in the last game session:
private void LoadSave()
{
try
{
JsonUtility.FromJson("filename", ...);
string oldHash = PlayerPrefs.GetString("importantSaveFileHash");
string newHash = CalculateMd5("filename");
if (oldHash == null || oldHash == newHash)
{
//recalculate hash every time you change the save file
//you can also encrypt this hash for better security
PlayerPrefs.SetString("importantSaveFileHash", newHash);
//RESULT: Save file is cool!
}
else
{
//RESULT: Save file was modified!
}
}
catch (Exception e)
{
//RESULT: broken file
}
}
private static string CalculateMd5(string filename)
{
using (var md5 = MD5.Create())
{
using (var stream = File.OpenRead(filename))
{
var hash = md5.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
}
}
Btw you can just use PlayerPrefs to store all the game state (I know that sometimes its important to have visible and readable save file) - choose what you need)
UPD: its not good to store game state in PlayerPrefs - use any another way instead (read comments)
I have an sql statements that selects a table of data that i want to export to excel in the .xls format,
i added this table to a grid view then rendered that grid view to create an html writer and write it on excel file using asp.net.
But i keep having this warning that the file format and extension does not match.
The issue is that the file you are creating is not a genuine Excel file. It's HTML with a .xls extension.
Please, i need to know what is the best way to export these selected data to the xls file without the warning.
I Have also tried exporting from the dataTable directly, but i still get the warning when tying to open the excel.
// these namespaces need to be added to your code behind file
using System.Configuration;
using System.Data.SqlClient;
using System.Data;
namespace MySpot.UserPages
{
public partial class Journal : System.Web.UI.Page
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["MySpotDBConnStr"].ConnectionString);
DataTable dt = new DataTable();
// regular page_load from .aspx file
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
}
}
// added a button with ID=btnDownload and double clicked it's onclick event to auto create method
protected void btnDownload_Click(object sender, EventArgs e)
{
string queryStr = "SELECT * from table";
SqlDataAdapter sda = new SqlDataAdapter(queryStr, conn);
sda.Fill(dt);
ExportTableData(dt);
}
// this does all the work to export to excel
public void ExportTableData(DataTable dtdata)
{
string attach = "attachment;filename=journal.xls";
Response.ClearContent();
Response.AddHeader("content-disposition", attach);
Response.ContentType = "application/ms-excel";
if (dtdata != null)
{
foreach (DataColumn dc in dtdata.Columns)
{
Response.Write(dc.ColumnName + "\t");
//sep = ";";
}
Response.Write(System.Environment.NewLine);
foreach (DataRow dr in dtdata.Rows)
{
for (int i = 0; i < dtdata.Columns.Count; i++)
{
Response.Write(dr[i].ToString() + "\t");
}
Response.Write("\n");
}
Response.End();
}
}
}
}
http://blogs.msdn.com/b/vsofficedeveloper/archive/2008/03/11/excel-2007-extension-warning.aspx
The current design does not allow you to open HTML content from a web site in Excel unless the extension of the URL is .HTM/.HTML/.MHT/.MHTML. So ASP pages that return HTML and set the MIME type to something like XLS to try to force the HTML to open in Excel instead of the web browser (as expected) will always get the security alert since the content does not match the MIME type. If you use an HTML MIME type, then the web browser will open the content instead of Excel. So there is no good workaround for this case because of the lack of a special MIME type for HTML/MHTML that is Excel specific. You can add your own MIME type if you control both the web server and the client desktops that need access to it, but otherwise the best option is to use a different file format or alert your users of the warning and tell them to select Yes to the dialog.
I'm looking for a free tool or dlls that I can use to write my own code in .NET to process some web requests.
Let's say I have a URL with some query string parameters similar to http://www.example.com?param=1 and when I use it in a browser several redirects occur and eventually HTML is rendered that has a frameset and a frame's inner html contains a table with data that I need. I want to store this data in the external file in a CSV format. Obviously the data is different depending on the querystring parameter param. Let's say I want to run the application and generate 1000 CSV files for param values from 1 to 1000.
I have good knowledge in .NET, javascript, HTML, but the main problem is how to get the final HTML in the server code.
What I tried is I created a new Form Application, added a webbrowser control and used code like this:
private void FormMain_Shown(object sender, EventArgs e)
{
var param = 1; //test
var url = string.Format(Constants.URL_PATTERN, param);
WebBrowserMain.Navigated += WebBrowserMain_Navigated;
WebBrowserMain.Navigate(url);
}
void WebBrowserMain_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
if (e.Url.OriginalString == Constants.FINAL_URL)
{
var document = WebBrowserMain.Document.Window.Frames[0].Document;
}
}
But unfortunately I receieve unauthorizedaccessexception because probably frame and the document are in different domains. Does anybody has an idea of how to work around this and maybe another brand new approach to implement functionality like this?
Thanks to the Noseratio's comments I managed to do that with the WebBrowser control. Here are some major points that might help others who have similar questions:
1) DocumentCompleted event should be used. For Navigated event body of the document is NULL.
2) Following answer helped a lot: WebBrowserControl: UnauthorizedAccessException when accessing property of a Frame
3) I was not aware about IHTMLWindow2 similar interfaces, for them to work correctly I added references to following COM libs: Microsoft Internet Controls (SHDocVw), Microsoft HTML Object Library (MSHTML).
4) I grabbed the html of the frame with the following code:
void WebBrowserMain_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (e.Url.OriginalString == Constants.FINAL_URL)
{
try
{
var doc = (IHTMLDocument2) WebBrowserMain.Document.DomDocument;
var frame = (IHTMLWindow2) doc.frames.item(0);
var document = CrossFrameIE.GetDocumentFromWindow(frame);
var html = document.body.outerHTML;
var dataParser = new DataParser(html);
//my logic here
}
5) For the work with Html, I used the fine HTML Agility Pack that has some pretty good XPath search.
Hi I'm trying to save a file from a Java Webstart Application.
public class Main {
public static void main(String[] args) {
try {
FileSaveService fos = (FileSaveService) ServiceManager.lookup("javax.jnlp.FileSaveService");
//open Dialog
FileContents fc = fos.saveFileDialog("c:/data", null, new ByteArrayInputStream("Hallo Welt".getBytes()), "name.txt");
System.out.println("FileContents: " + fc);
} catch (UnavailableServiceException e) {
System.err.println("***" + e + "***");
} catch (IOException e) {
System.err.println("***" + e + "***");
}
//wait a minute
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
}
System.exit(0);
}
}
Everything works except that the dialog that comes up looks like a "open" file dialog, not like a "save" file dialog:
Any help would be appreciated.
The File-Open-dialog is necessary. You first need to let the user choose where to save the data. Thus a previous call to openFileDialog is absolute necessary for a jnlp-application. You are not allowed to directly save to a specific location like c:
If you follow the mentioned link (http://docs.oracle.com/javase/6/docs/technotes/guides/javaws/developersguide/examples.html#FileSaveService) you should be successful.
EDIT:
for clarification.
Saving via javax.jnlp.FileSaveService does exactly need one call. For instance calling saveFileDialog() like this should be sufficient:
fss.saveFileDialog(null, null, new ByteArrayInputStream("Hallo Welt".getBytes() ), "newFileName.txt");
The necessity of one User-Dialogue is due to the anonymizing nature of jnlp, where your application should not get any hint about the user-filesystem.
However, I have to admit, that this was not your question.
Your main trouble comes from the java app everytime presenting the "open-dialogue" instead of the "save-dialogue".
This should not happen! If I may humbly assume from your snippet where you call fos.saveFileDialog: did you just initialize fos by the FileOpenService instead of the FileSaveService?
More details on the FileSaveService can be found here: http://docs.oracle.com/javase/7/docs/jre/api/javaws/jnlp/javax/jnlp/FileSaveService.html
This seems to be fixed in JRE bersion 1.7.0_21-b11 Java HotSpot(TM) 64-Bit Server VM
And there it is: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=2227257