dynamically add hyperlink or button to open local file? - c#

I am trying to make a button or hyperlink to open local html file. I have tried everything but none of them are not working. have tried to use LinkButton, Button and Hyperlink. Below is the code what I have tried.
byte[] buffer = (byte[])data.GetValue(i);
File.WriteAllBytes(#"C:\test.html", buffer);
//LinkButton sysInfo = new LinkButton();
//sysInfo.Text = "Please click to see more info";
//sysInfo.CommandName = "ID";
//sysInfo.CommandArgument = id.ToString();
//sysInfo.Command += new CommandEventHandler(sysInfo_Click);
//sysInfo.Click += new EventHandler(this.sysInfo_Click);
HyperLink link = new HyperLink();
link.Target = "_blank";
link.Text = "Please click to see more information";
link.Attributes.Add("onclick", "window.open('" + ResolveUrl("file:///c:/test.html") + "');");
link.NavigateUrl = ResolveUrl("file:///c:/test.html");
fieldCl.Controls.Add(link);
//sysInfo.Click += new EventHandler(sysInfo_Click);
//sysInfo.CommandName = "ID";
//sysInfo.CommandArgument = id.ToString();
//sysInfo.Command += new CommandEventHandler(sysInfo_Click);
What I was trying to do is there are bytes for html in sql server and retrieve the bytes to create file on C: local. Then I want to open the local html file on new window.
It seems ok to retrieve bytes and create a file. But when I used the hyperlink, it does not do anything. I heard that it won't allow me to open the local file. So I have tried to use the button instead but when I used a button and create Click event, it didnt even go into the Click event.
If there is anyway to just open the file without saving, that would be great but if can't, that's fine.

I would just get your link into a string. It would just need to be: c:\\test.html
Once you get your link into a string I would try: System.Diagnostics.Process.Start(link);
If that is not working, I would place a break in your code and grab the content of the string - paste that into your address bar and see what happens.

Related

Copy to ClipBoard and paste Clipboard data to whatsapp message Textbox

I am trying to paste text, image and pdf documents to clipboard first and then to whatsapp textbox control.
1) For Text.
Clipboard.SetText(message);
Ctrl + v pastes the text into the whatsapp textbox.
2) For Image
var imagePath = "E:\Downloads_SSD\goodmorning.jpg";
Clipboard.SetImage(Image.FromFile(#imagePath ));
Ctrl + v pastes the Image into whatsapp.
3) For Documents.
StringCollection paths = new StringCollection();
paths.Add(#"E:\Downloads_SSD\Hatred-in-the-belly_-Politics-behind-the-appropriation-of-Dr-Ambedkars-writings.pdf");
Clipboard.SetFileDropList(paths);
Ctrl + v works when copying into a folder, but does not work for copying into whatsapp message textbox.
How do I make it to work in case of pdf documents.
To directly answer your question - copying & pasting .pdf files from the clipboard will not work - that is not the way WhatsApp web does it. Surprisingly there is a way to achieve something similar which does not involve pasting.
Basically you have to trigger a click event on that clip-button and run some javascript.
You did not mention what programing language you are using so I will use what works for me. In this example I am using C# PuppeteerSharp.
// load your pdf bytes here
byte[] fileBytes = YourFunctionToGetFileBytes("https://link-to-pdf-file");
if (fileBytes != null)
{
// first, we get the clip-button
var clipImage = _whatsAppPage.QuerySelectorAsync("div[data-testid=\"conversation-clip\"]").Result;
// focus and click on that button
await clipImage.FocusAsync();
Thread.Sleep(600);
await clipImage.ClickAsync();
Thread.Sleep(600);
// wait for the documents button to become available
await _whatsAppPage.WaitForSelectorAsync("li[data-testid=\"mi-attach-document\"]");
// this is where the real magic happens
// see the next block of code for full details
await SetPdfBlobFile(fileBytes, "test-file-name.pdf", "document.querySelector(\"li[data-testid='mi-attach-document']\").querySelector(\"input[type='file']\")");
Thread.Sleep(600);
// after the pdf is finally set, we need to wait for the send button to become available
await _whatsAppPage.WaitForSelectorAsync("div[role=\"button\"][aria-label=\"Send\"]");
var sendButtonPic = _whatsAppPage.QuerySelectorAsync("div[role=\"button\"][aria-label=\"Send\"]").Result;
Thread.Sleep(600);
await sendButtonPic.ClickAsync();
Thread.Sleep(1600);
}
If you inspect the "documents" button, you will see it contains a hidden input button which is in reality the one responsible for loading your files. My "SetPdfBlobFile" function is simply targeting that input button.
Please note that the next code block is basically setting our .pdf file into that hidden "input" file element. You must understand that it is not possible to simply set the "value" field of the input button to the path of your .pdf file. But it is possible to set a .pdf file from a blob. Here's the code for accomplishing that:
private async Task<Newtonsoft.Json.Linq.JToken> SetPdfBlobFile(byte[] pdfBytes, string fileName, string selector)
{
var pasteResults = await _whatsAppPage.EvaluateFunctionAsync(#"(pdfBytes, fileName) => {
return new Promise(async (resolve, reject) => {
// logic to create our blob
const base64Response = await fetch(pdfBytes);
const pdfBlob = await base64Response.blob();
try {
const fileInput = " + selector + #";
const dataTransfer = new DataTransfer();
// create a new file using our pdf blob
const file = new File([pdfBlob], fileName, { type: 'application/pdf' });
// add our file to the hidden input button
dataTransfer.items.add(file);
fileInput.files = dataTransfer.files;
// our file has been added to the hidden input button
// but lastly we need to trigger a 'change' event
// so WhatsApp loads the send button
fileInput.dispatchEvent(new window.Event('change', { bubbles: true }));
resolve(true);
} catch (ex) {
resolve(ex.message);
}
});
}"
, "data:application/pdf;base64," + Convert.ToBase64String(pdfBytes), fileName);
return pasteResults;
}
That's it! Have fun sending .pdf files!

How to paste image from clipboard to Outlook email Body?

Here is my situation.
I've made a Application Windows Form which is editing an Excel sheet depending on what the user is doing (buttons / toggle / text box / etc..).
Once the edtion is complete the new Excel file is generated.
My programm then selects a range of cells, and copies it.
It goes to Clipboard.
I've done multiple tests (if(){}else{} / saving into a .jpg / etc..) and everything is checked true.
I don't want to ATTACH my image.
I don't want to save it, even temporarily, then paste it in the body through the saved .jpg file.
I "just" want to make a Ctrl+V, into my Outlook eMail Body.
here's how i get the image from my clipboard ("MessageBody" is declared at the top as a public string so that i can call it through different regions):
public void ReadData()
{
Excel excel = new Excel(#"E:\c#\Project#XX\Resources\TEST.xlsx", 1);
excel.CopyRange(0, 0, 32, 12);
IDataObject iData = Clipboard.GetDataObject();
if (iData.GetDataPresent(DataFormats.Bitmap))
{
Bitmap MessageBody = (iData.GetData(DataFormats.Bitmap, true) as Bitmap);
//pbx.Image = Image;
//image.Save(#"E:\c#\Project#XX\Resources\bitmap1.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
//MessageBody = image;
}
excel.Close();
excel.Quit();
}
Here's my message building code :
private void flatCustButton013_Click(object sender, EventArgs e)
{
ReadData();
string MessageSubject = $"SomeSubject";
Outlook.MailItem newMail = (Outlook.MailItem)application.CreateItem(Outlook.OlItemType.olMailItem);
newMail.Subject = MessageSubject;
newMail.BodyFormat = Outlook.OlBodyFormat.olFormatHTML;
MessageHTMLBody = "<html><body>SomeText.<img src="cid:MessageBody"</img></body></html>";
newMail.HTMLBody = MessageHTMLBody;
//newMail.Body = System.Windows.Input.ApplicationCommands.Paste;
//newMail.Display(false);
//newMail.BodyFormat = Outlook.OlBodyFormat.olFormatHTML; ;
//newMail.HTMLBody = System.Windows.Input.ApplicationCommands.Paste;
//newMail.Body = MessageBody;
newMail.To = ToAddress;
newMail.SentOnBehalfOfName = FromAddress;
newMail.CC = CcAddress;
newMail.BCC = BccAddress;
//System.Windows.Input.ApplicationCommands.Paste;
//wrdEdit = application._Inspector.WordEditor
newMail.Send();
}
In the previous version, people had to open an Excel file, change the Cells manually, and then click a button (with a macro in VB).
It would open a Outlook eMail item (display:true) with the image pasted already, then just needed to click "Send" and it was ok.
My 2.0 version is meant to automatise this by just click a "Send //Generated Excel Sheet//"Button.
Here's the macro code in VB :
Sub SendMail()
Dim Messager As New Outlook.Application
Dim Mail As Outlook.MailItem
Dim WrdEdit
Range("my_range").CopyPicture
Set Messager = New Outlook.Application
Set Mail = Messager.CreateItem(olMailItem)
With Mail
.To = "some folks"
.CC = "some folks"
'.BCC = ""
.Subject = "SomeSubject"
.Display
.HTMLBody = Mess + .HTMLBody
End With
Set WrdEdit = Messager.ActiveInspector.WordEditor
WrdEdit.Application.Selection.Paste
Set WrdEdit = Nothing
Set Messager = Nothing
Set Mail = Nothing
ActiveWorkbook.Close SaveChanges:=False
End Sub
But i don't get why i would pass through the Inspector (which i have no knowledge about) if i'm succeeding in retrieving the clipboard image.
I found a way by adding an attachment from a local saved file to the mail and displaying it into the body with HTML.
Like so :
newMail.BodyFormat = Outlook.OlBodyFormat.olFormatHTML;
Outlook.Attachment attachment = newMail.Attachments.Add(#"path.imageformat", Outlook.OlAttachmentType.olEmbeddeditem, null, $"someTitle");
string imagecid = "whatever";
attachment.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x3613041E", imagecid);
newMail.HTMLBody = String.Format("<body><img src=\"cid:{0}\"></body>", imageCid);
the "http://schemas.microsoft.com/mapi/proptag/0x3712001E" code is here : http://www.outlookcode.com/codedetail.aspx?id=1915.
And it works.
However, i really don't like having urls in my code, is there another way ?
And also, it looks like whatever i put into my 'imagecid' string nothing changes.
I'm trying hard to understand what i did with the code, and not just letting it work as it is.
Looks like i need some authorisation from Office to work through an application ? And especially when i want to paste image in a body (which can contain other stuff than just pixel data).
If i did not need this autorization with the VB script, i suppose, it is because i had to "physicly/humanly" press "Send Mail" button in Outlook ?
Are there any other possibilities ? I'm still using a file though to paste in my body, can't i just make a Ctrl+C Ctrl+V programmatically ? :(

How do you save and preview an HTML file from temp folder?

I'm developing an HTML editor in C# where you can edit your code in the FastColoredTextBox.dll component. You will have this option in the MenuStrip called "Preview in browser" and there will be a drop down item called "Chrome" and "Iexplore" etc. I want it instead of saving the file, i want it to make a file in the Temp folder and preview it. and after we've modified the code again, the file will update as we preview it again. This is what i have so far:
string location = null;
string sourcecode = FastColoredTextBox1.Text;
location = System.IO.Path.GetTempPath() + "\\TempSite.html";
using (StreamWriter writer = new StreamWriter(location, true))
{
writer.Write(sourcecode);
writer.Dispose();
}
try
{
System.Diagnostics.Process.Start("chrome.exe", location);
}
catch (Exception ex)
{
Interaction.MsgBox(ex.Message);
}
How do you achieve this?
Q: How do you save and preview an HTML file from temp folder?
A: You're already doing precisely that :)
Q: Why does my browser keep re-displaying the original image?
A: Because your browser is reading the html from cache.
SOLUTION:
Give your new file a different name. For example:
location = System.IO.Path.GetTempPath() + Path.GetTempFileName() + ".html";
... OR ...
location = Path.GetTempPath() + Guid.NewGuid().ToString() + ".html";
You can also simply hit <F5> to refresh, <Ctl-Shift-Del> to clear cache, or disable cache in your browser.

How to make 2 process access the same path?

I'm using c#. I'm receiving an error about a path is currently accessed by other processes. What my system is trying to do is to access the path: #"C:\temps\" + client_ids + "_" + rown + ".pdf" and use the same path for attachment before sending it to client's email.
here's what I've done so far. I comment out some of my code because I'm not sure what to do.
FileStream fs = null;
using (fs = new FileStream(#"C:\\temps\\" + client_ids + "_" +
rown + ".pdf",
FileMode.Open,FileAccess.Read,FileShare.ReadWrite))
{
TextReader tr = new StreamReader(fs);
//report.ExportToDisk
//(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat,tr);
//report.Dispose();
//Attachment files = new Attachment(tr);
//Mailmsg.Attachments.Add(files);
//Clients.Send(Mailmsg);
}
you can make temp copy of file before you use it in mail attachment and then use the copy instead of the original file
You cannot attach a file to an email if that file is open. You must close (save) the file first.
While #ali answer is technically correct, it is unnecessary. Why go through the overhead of creating a copy of the file which then needs to be deleted, etc.?
Assuming I understand what you are trying to do correctly, simply move your code for mail to after the file is successfully created and saved. And, I don't think you need the overhead of either the filestream or the textreader. As long as your report object can save the file to disk someplace, you can attach that file to your email message and then send it.
While I do not claim to know anything about how Crystal Decisions handles exports, etc. Perhaps something like this would work:
(I got this code from: https://msdn.microsoft.com/en-us/library/ms226036(v=vs.90).aspx)
private void ExportToDisk (string fileName)
{
ExportOptions exportOpts = new ExportOptions();
DiskFileDestinationOptions diskOpts =
ExportOptions.CreateDiskFileDestinationOptions();
exportOpts.ExportFormatType = ExportFormatType.RichText;
exportOpts.ExportDestinationType =
ExportDestinationType.DiskFile;
diskOpts.DiskFileName = fileName;
exportOpts.ExportDestinationOptions = diskOpts;
Report.Export(exportOpts);
}
You will need to change the ExportFormatType property.
Then, simply attach the file to your email and send:
Attachment Files = new Attachment(filename);
Mailmsg.Attachments.add(files);
Clients.Send(Mailmsg);

Text boxes are not filling when the Form Loads, Windows Form Application

I am doing following on form Load,
I am searching for a file and if file not exist then
Fill in some textboxes on the form.
Create a file name, data.txt
Take data from text boxes and write it in the file.
The problem is that the textboxes are not filling with text. I am running the program every time with deleting the file, so that the 1st condition gets true. But still the textboxes on the form remains empty. I am using Visual Studio 2012.
I am using following code under, InitializeComponent();
string folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
// Combining the base folder with specific folder....
string path= Path.Combine(folder, "CRM");
// Checking if folder exists and if not, create it
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
if (!File.Exists(path + "\\data.txt"))
{
txtBoxLimitPerMinute.Text = "300";
txtBoxSenderName.Text = "Sender Name";
txtBoxToEmail.Text = "some email id";
txtBoxSMTPHost.Text = "host name";
string data = txtBoxSenderName.Text + "," + txtBoxSubject.Text + "," + txtBoxToEmail.Text + "," + txtBox_HtmlPath.Text + "," + txtBoxUnsubscribe.Text + "," + txtBoxSMTPHost.Text + ";
using (FileStream fs = new FileStream(path+ "\\data.txt", FileMode.Create))
{
using (StreamWriter w = new StreamWriter(fs))
{
w.WriteLine(data);
}
}
}
As you have written your code under IntializeComponent() method then make sure after code which you written, Textbox values are not assigned back to string.empty value. (i.e Textbox values are not being overwrite like as below)
E.g.
this.txtBoxLimitPerMinute.Text = String.Empty;
And Also write your code after this.Controls.Add(this.txtBoxLimitPerMinute); because when controls add to form it will reset to default value. So, you need to write your code after all controls have added in forms or four textboxs added in form.
But I suggest to write code after IntializeComponent() call.
I will suggest you to write you code after InitializeComponent()
because InitializeComponent() method creates the object of your text boxes and other controls so I will suggest you to perform any operation on controls after their creation.
Write your code after InitializeComponent()
then use this.txtBoxLimitPerMinute.Text = "300";

Categories

Resources