I am new to C# and am very green! I have a C# Application that i would like to download a Report from a Reserved.ReportViewerWebControl.axd and save it to a specific location, I found this code
var theURL = "http://TEST/TEST/Pages/TEST.aspx?&FileName=TEST&rs:Command=GetResourceContents";
WebClient Client = new WebClient
{
UseDefaultCredentials = true
};
byte[] myDataBuffer = Client.DownloadData(theURL);
var filename = "test.csv";
var fileStructureLocal = #"C:\Users\%UserName%\TEST\Downloads".Replace("%UserName%", UserName);
var fileStructureNetwork = "\\\\TEST\\TEST\\TEST\\TEST";
var fileLocation = fileStructureLocal + "\\" + filename;
if (System.IO.File.Exists(fileLocation) == true)
{
//DO NOTHING
}
else
{
System.IO.File.WriteAllBytes(fileLocation, myDataBuffer);
//File.WriteAllBytes("c:\\temp\\report.pdf", myDataBuffer);
//SAVE FILE HERE
}
it works but i get the Source Code and not the CSV file. I know the URL i get when i execute the reports in the normal browser has a session ID and a Control ID. I can copy that URL and put it at "theURL" and i get a 500 internal server error. I know i am all mixed up not sure what i need to do, but am trying many things. This was the closest i got...lol Sad i know. This is the URL I get when i execute it in the Browser.
http://test/test/Reserved.ReportViewerWebControl.axd?%2fReportSession=brhxbx55ngxdhp3zvk5bjmv3&Culture=1033&CultureOverrides=True&UICulture=1033&UICultureOverrides=True&ReportStack=1&ControlID=fa0acf3c777540c5b389d67737b1f866&OpType=Export&FileName=test&ContentDisposition=OnlyHtmlInline&Format=CSV
How would i get this to download the file from a button click in my App and save it in my location.
Your target web page uses a SSRS ReportViewer control to manage the rendering of the reports, this control relies heavily on ASP.Net Session State to render the report in the background via calls to the Reserved.ReportViewerWebControl.axd resource handler.
This means that to use this axd link that you have identified you must first trigger the content to be created and cached within the session context before it can be downloaded, and then you must download it from the same context.
We can't just run the page once and figure out the URL, we have to find a way to do this programatically using the same session between requests.
The ReportViewer control does this via javascript when the download button is clicked, which means there is no simple link to Reserved.ReportViewerWebControl.axd to scrape from the html.
This means we have to execute the same script manually or simulate the user clicking the link.
This solution will go into some screen-scraping techniques (UX Automation) to simulate clicking the export button and capturing the result but I would avoid this if you can.
You really should attempt to contact the developer directly for guidance, they may have implemented some simple URL parameters to export directly without having to automate the interface.
The concept is relatively simple:
Create a web browser session to the report page
Click on the export to CSV button
this will try to open another link in a new window which we need to suppress!
Capture the url from the new window
Download the export file using the same session context
We can't use the web browser control for this, because it's interface is UI driven.
We can't use HttpWebRequest or WebClient to execute the javascript against the HTMl DOM, we have to use a Web Browser to achieve this.
The other issue that comes up is that we cannot simply use the WebBrowser NewWindow or FileDownload events on the control as these events do not provide information such as the Url for the new windows or the file download source or target.
Instead we must reference the internal COM Browser (effectively IE) and use the native NewWindow3 event to capture the url to Reserved.ReportViewerWebControl.axd so we can download it manually.
I use these main references to explain the technique
Get URL for WebBrowser.NewWindow Event
automated filedownload using webbrowser without url
Finally, as I mentioned above, we cannot use the Web Browser to directly download the file from the URL as it will popup the SAVE AS dialog in a new web browser or save directly to the configured Downloads folder.
As described in the reference article we use the GetGlobalCookies method from Erika Chinchio which can be found in the excellent article provided by #Pedro Leonardo (available here)
I've put all this into a simple console app that you can run, just change the url to your report, the title of the export link and the save path:
The following is how I obtained the link that I wanted to download, the exact link title and composition will vary depending on the implementation:
class Program
{
[STAThread]
static void Main(string[] args)
{
SaveReportToDisk("http://localhost:13933/reports/sqlversioninfo", "CSV (comma delimited)", "C:\\temp\\reportDump.csv");
}
/// <summary>
/// Automate clicking on the 'Save As' drop down menu in a report viewer control embedded at the specified URL
/// </summary>
/// <param name="sourceURL">URL that the report viewer control is hosted on</param>
/// <param name="linkTitle">Title of the export option that you want to automate</param>
/// <param name="savepath">The local path to save to exported report to</param>
static void SaveReportToDisk(string sourceURL, string linkTitle, string savepath)
{
WebBrowser wb = new WebBrowser();
wb.ScrollBarsEnabled = false;
wb.ScriptErrorsSuppressed = true;
wb.Navigate(sourceURL);
//wait for the page to load
while (wb.ReadyState != WebBrowserReadyState.Complete) { Application.DoEvents(); }
// We want to find the Link that is the export to CSV menu item and click it
// this is the first link on the page that has a title='CSV', modify this search if your link is different.
// TODO: modify this selection mechanism to suit your needs, the following is very crude
var exportLink = wb.Document.GetElementsByTagName("a")
.OfType<HtmlElement>()
.FirstOrDefault(x => (x.GetAttribute("title")?.Equals(linkTitle, StringComparison.OrdinalIgnoreCase)).GetValueOrDefault());
if (exportLink == null)
throw new NotSupportedException("Url did not resolve to a valid Report Viewer web Document");
bool fileDownloaded = false;
// listen for new window, using the COM wrapper so we can capture the url
(wb.ActiveXInstance as SHDocVw.WebBrowser).NewWindow3 +=
(ref object ppDisp, ref bool Cancel, uint dwFlags, string bstrUrlContext, string bstrUrl) =>
{
Cancel = true; //should block the default browser from opening the link in a new window
Task.Run(async () =>
{
await DownloadLinkAsync(bstrUrl, savepath);
fileDownloaded = true;
}).Wait();
};
// execute the link
exportLink.InvokeMember("click");
//wait for the page to refresh
while (!fileDownloaded) { Application.DoEvents(); }
}
private static async Task DownloadLinkAsync(string documentLinkUrl, string savePath)
{
var documentLinkUri = new Uri(documentLinkUrl);
var cookieString = GetGlobalCookies(documentLinkUri.AbsoluteUri);
var cookieContainer = new CookieContainer();
using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = documentLinkUri })
{
cookieContainer.SetCookies(documentLinkUri, cookieString);
var response = await client.GetAsync(documentLinkUrl);
if (response.IsSuccessStatusCode)
{
var stream = await response.Content.ReadAsStreamAsync();
// Response can be saved from Stream
using (Stream output = File.OpenWrite(savePath))
{
stream.CopyTo(output);
}
}
}
}
// from Erika Chinchio which can be found in the excellent article provided by #Pedro Leonardo (available here: http://www.codeproject.com/Tips/659004/Download-of-file-with-open-save-dialog-box),
[System.Runtime.InteropServices.DllImport("wininet.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)]
static extern bool InternetGetCookieEx(string pchURL, string pchCookieName,
System.Text.StringBuilder pchCookieData, ref uint pcchCookieData, int dwFlags, IntPtr lpReserved);
const int INTERNET_COOKIE_HTTPONLY = 0x00002000;
private static string GetGlobalCookies(string uri)
{
uint uiDataSize = 2048;
var sbCookieData = new System.Text.StringBuilder((int)uiDataSize);
if (InternetGetCookieEx(uri, null, sbCookieData, ref uiDataSize,
INTERNET_COOKIE_HTTPONLY, IntPtr.Zero)
&&
sbCookieData.Length > 0)
{
return sbCookieData.ToString().Replace(";", ",");
}
return null;
}
}
The reason I advise to talk to the developer before going down the screen scraping rabbit hole is that as a standard when I use the report viewer control I always try to implement the SSRS native rc: and rs: URL parameters or atleast make sure I provide a way to export reports directly via url.
you cannot use these parameters out of the box, they are designed to be used when you are querying the SSRS Server directly, which your example does not.
I didn't come up with this on my own, no idea which resource I learnt it from but that means there is a chance others have come up with a similar conclusion. I implement this mainly so I can use these concepts throughout the rest of the application. But also when reports are concerned, one of the reasons we choose SSRS and RDLs as a reporting solution is it's versatility, we write the report definition, the controls allow users to consume them however they need to. If we have limited to ability for the user to export reports, we have really under utilized the framework.
Related
I'm currently developing a Xamarin.iOS App that gets a document from a web service that should then be edited offline on the tablet after being downloaded to the internal storage.
The most common answer was to use the UIDocumentInteractionController. However if I use the UIDocumentInteractionController then I can only create a copy of my original file and open this copy. To get it back into my app I have to make the user select the document from the 'UIDocumentPickerViewController'.
Is there a better way to make the `UIDocumentInteractionController' not create and open a copy of the original, or to at least get the url from the new documentcopy?
Code to open the file:
public void OpenFile()
{
var url = NSUrl.FromFilename(FilePath);
var controller = new UIDocumentInteractionController();
controller.Url = url;
controller.PresentOpenInMenu(table.Frame, table, true);
}
If that is not Possible: Are there different tools or controlls i could use to open and edit a MS-Office file directly?
Is there an API to use Onenote OCR capabilities to recognise text in images automatically?
If you have OneNote client on the same machine as your program will execute you can create a page in OneNote and insert the image through the COM API. Then you can read the page in XML format which will include the OCR'ed text.
You want to use
Application.CreateNewPage to create a page
Application.UpdatePageContent to insert the image
Application.GetPageContent to read the page content and look for OCRData and OCRText elements in the XML.
OneNote COM API is documented here: http://msdn.microsoft.com/en-us/library/office/jj680120(v=office.15).aspx
When you put an image on a page in OneNote through the API, any images will automatically be OCR'd. The user will then be able to search any text in the images in OneNote. However, you cannot pull the image back and read the OCR'd text at this point.
If this is a feature that interests you, I invite you to go to our UserVoice site and submit this idea: http://onenote.uservoice.com/forums/245490-onenote-developers
update: vote on the idea: https://onenote.uservoice.com/forums/245490-onenote-developer-apis/suggestions/10671321-make-ocr-available-in-the-c-api
-- James
There is a really good sample of how to do this here:
http://www.journeyofcode.com/free-easy-ocr-c-using-onenote/
The main bit of code is:
private string RecognizeIntern(Image image)
{
this._page.Reload();
this._page.Clear();
this._page.AddImage(image);
this._page.Save();
int total = 0;
do
{
Thread.Sleep(PollInterval);
this._page.Reload();
string result = this._page.ReadOcrText();
if (result != null)
return result;
} while (total++ < PollAttempts);
return null;
}
As I will be deleting my blog (which was mentioned in another post), I thought I should add the content here for future reference:
Usage
Let's start by taking a look on how to use the component: The class OnenoteOcrEngine implements the core functionality and implements the interface IOcrEngine which provides a single method:
public interface IOcrEngine
{
string Recognize(Image image);
}
Excluding any error handling, it can be used in a way similar to the following one:
using (var ocrEngine = new OnenoteOcrEngine())
using (var image = Image.FromFile(imagePath))
{
var text = ocrEngine.Recognize(image);
if (text == null)
Console.WriteLine("nothing recognized");
else
Console.WriteLine("Recognized: " + text);
}
Implementation
The implementation is far less straight-forward. Prior to Office 2010, Microsoft Office Document Imaging (MODI) was available for OCR. Unfortunately, this no longer is the case. Further research confirmed that OneNote's OCR functionality is not directly exposed in form of an API, but the suggestions were made to manually parse OneNote documents for the text (see Is it possible to do OCR on a Tiff image using the OneNote interop API? or need a document to extract text from image using onenote Interop?. And that's exactly what I did:
Connect to OneNote using COM interop
Create a temporary page containing the image to process
Show the temporary page (important because OneNote won't perform the OCR otherwise)
Poll for an OCRData tag containing an OCRText tag in the XML code of the page.
Delete the temporary page
Challenges included the parsing of the XML code for which I decided to use LINQ to XML. For example, inserting the image was done using the following code:
private XElement CreateImageTag(Image image)
{
var img = new XElement(XName.Get("Image", OneNoteNamespace));
var data = new XElement(XName.Get("Data", OneNoteNamespace));
data.Value = this.ToBase64(image);
img.Add(data);
return img;
}
private string ToBase64(Image image)
{
using (var memoryStream = new MemoryStream())
{
image.Save(memoryStream, ImageFormat.Png);
var binary = memoryStream.ToArray();
return Convert.ToBase64String(binary);
}
}
Note the usage of XName.Get("Image", OneNoteNamespace) (where OneNoteNamespace is the constant "http://schemas.microsoft.com/office/onenote/2013/onenote" ) for creating the element with the correct namespace and the method ToBase64 which serializes an GDI-image from memory into the Base64 format. Unfortunately, polling (See What is wrong with polling? for a discussion of the topic) in combination with a timeout is necessary to determine whether the detection process has completed successfully:
int total = 0;
do
{
Thread.Sleep(PollInterval);
this._page.Reload();
string result = this._page.ReadOcrText();
if (result != null)
return result;
} while (total++ < PollAttempts);
Results
The results are not perfect. Considering the quality of the images, however, they are more than satisfactory in my opinion. I could successfully use the component in my project. One issue remains which is very annoying: Sometimes, OneNote crashes during the process. Most of the times, a simple restart will fix this issue, but trying to recognise text from some images reproducibly crashes OneNote.
Code / Download
Check out the code at GitHub
not sure about OCR, but the documentation site for onenote API is this
http://msdn.microsoft.com/en-us/library/office/dn575425.aspx#sectionSection1
In my asp.net 4.0 application I have a word document residing on the back end. When the user choses to print a letter, using ASPose I am filling in the mail merge fields behind the scenes,
I am opening a browser window and displaying a PDF via the code below in Page_Load. I would like to tell it to print so that it opens up the standard Printer Dialog, prints if the user says to do so, then closes that browser window. How can I invoke the print (local printer) from this point?
using (FileStream sourceStream = new FileStream(pdfFilePath, FileMode.Open, FileAccess.Read))
{
using (var memoryStream = new MemoryStream())
{
sourceStream.CopyTo(memoryStream);
byte[] b = memoryStream.ToArray();
Response.AddHeader("content-disposition", "inline;filename=" + Path.GetFileName(pdfFilePath));
Response.ContentType = System.Net.Mime.MediaTypeNames.Application.Pdf;
Response.OutputStream.Write(b, 0, b.Length);
}
}
One not-so-pretty solution to direct send a command to a printer involves using a Java Applet. In that case, you could generate an URL to your document and pass it as parameter to the applet using Javascript. I use this solution in one of my applications, but I should warn you that is very prone to fail in case of browser security configurations or an outdated JRE.
As you are sending a PDF to the printer, you should use the PDDocument class to load the PDF document and then send it to a PrinterJob:
PrinterJob printerJob = PrinterJob.getPrinterJob();
printerJob.setPrintService("MyPrinterName");
URL uri = new URL("http://example.com/docs/doc.pdf");
PDDocument docPdf = PDDocument.load(uri);
docPdf.silentPrint(printerJob);
In this case you need to know the name of the printer in the client, which ou can obtain using Java as well:
public String[] getPrinters() {
PrintService[] printers = PrintServiceLookup.lookupPrintServices(null, null);
String[] printerNames = new String[impressoras.length];
for (int i = 0; i < printers.length; i++) {
printerNames[i] = printers[i].getName();
}
return printerNames;
}
Remember that you can call any method of the Applet using Javascript, searching in the web you can find how to do it.
Once you obtain the printers from the clent, you could use your own Printer Dialog, so the user could select which printer he/she wants to use.
Some resources you may find useful:
Creating Java Applets: http://docs.oracle.com/javase/tutorial/uiswing/components/applet.html
Invoking Applet Methods From JavaScript Code:http://docs.oracle.com/javase/tutorial/deployment/applet/invokingAppletMethodsFromJavaScript.html
Is there an API to use Onenote OCR capabilities to recognise text in images automatically?
If you have OneNote client on the same machine as your program will execute you can create a page in OneNote and insert the image through the COM API. Then you can read the page in XML format which will include the OCR'ed text.
You want to use
Application.CreateNewPage to create a page
Application.UpdatePageContent to insert the image
Application.GetPageContent to read the page content and look for OCRData and OCRText elements in the XML.
OneNote COM API is documented here: http://msdn.microsoft.com/en-us/library/office/jj680120(v=office.15).aspx
When you put an image on a page in OneNote through the API, any images will automatically be OCR'd. The user will then be able to search any text in the images in OneNote. However, you cannot pull the image back and read the OCR'd text at this point.
If this is a feature that interests you, I invite you to go to our UserVoice site and submit this idea: http://onenote.uservoice.com/forums/245490-onenote-developers
update: vote on the idea: https://onenote.uservoice.com/forums/245490-onenote-developer-apis/suggestions/10671321-make-ocr-available-in-the-c-api
-- James
There is a really good sample of how to do this here:
http://www.journeyofcode.com/free-easy-ocr-c-using-onenote/
The main bit of code is:
private string RecognizeIntern(Image image)
{
this._page.Reload();
this._page.Clear();
this._page.AddImage(image);
this._page.Save();
int total = 0;
do
{
Thread.Sleep(PollInterval);
this._page.Reload();
string result = this._page.ReadOcrText();
if (result != null)
return result;
} while (total++ < PollAttempts);
return null;
}
As I will be deleting my blog (which was mentioned in another post), I thought I should add the content here for future reference:
Usage
Let's start by taking a look on how to use the component: The class OnenoteOcrEngine implements the core functionality and implements the interface IOcrEngine which provides a single method:
public interface IOcrEngine
{
string Recognize(Image image);
}
Excluding any error handling, it can be used in a way similar to the following one:
using (var ocrEngine = new OnenoteOcrEngine())
using (var image = Image.FromFile(imagePath))
{
var text = ocrEngine.Recognize(image);
if (text == null)
Console.WriteLine("nothing recognized");
else
Console.WriteLine("Recognized: " + text);
}
Implementation
The implementation is far less straight-forward. Prior to Office 2010, Microsoft Office Document Imaging (MODI) was available for OCR. Unfortunately, this no longer is the case. Further research confirmed that OneNote's OCR functionality is not directly exposed in form of an API, but the suggestions were made to manually parse OneNote documents for the text (see Is it possible to do OCR on a Tiff image using the OneNote interop API? or need a document to extract text from image using onenote Interop?. And that's exactly what I did:
Connect to OneNote using COM interop
Create a temporary page containing the image to process
Show the temporary page (important because OneNote won't perform the OCR otherwise)
Poll for an OCRData tag containing an OCRText tag in the XML code of the page.
Delete the temporary page
Challenges included the parsing of the XML code for which I decided to use LINQ to XML. For example, inserting the image was done using the following code:
private XElement CreateImageTag(Image image)
{
var img = new XElement(XName.Get("Image", OneNoteNamespace));
var data = new XElement(XName.Get("Data", OneNoteNamespace));
data.Value = this.ToBase64(image);
img.Add(data);
return img;
}
private string ToBase64(Image image)
{
using (var memoryStream = new MemoryStream())
{
image.Save(memoryStream, ImageFormat.Png);
var binary = memoryStream.ToArray();
return Convert.ToBase64String(binary);
}
}
Note the usage of XName.Get("Image", OneNoteNamespace) (where OneNoteNamespace is the constant "http://schemas.microsoft.com/office/onenote/2013/onenote" ) for creating the element with the correct namespace and the method ToBase64 which serializes an GDI-image from memory into the Base64 format. Unfortunately, polling (See What is wrong with polling? for a discussion of the topic) in combination with a timeout is necessary to determine whether the detection process has completed successfully:
int total = 0;
do
{
Thread.Sleep(PollInterval);
this._page.Reload();
string result = this._page.ReadOcrText();
if (result != null)
return result;
} while (total++ < PollAttempts);
Results
The results are not perfect. Considering the quality of the images, however, they are more than satisfactory in my opinion. I could successfully use the component in my project. One issue remains which is very annoying: Sometimes, OneNote crashes during the process. Most of the times, a simple restart will fix this issue, but trying to recognise text from some images reproducibly crashes OneNote.
Code / Download
Check out the code at GitHub
not sure about OCR, but the documentation site for onenote API is this
http://msdn.microsoft.com/en-us/library/office/dn575425.aspx#sectionSection1
I've been working on a WebCrawler written in C# using System.Windows.Forms.WebBrowser. I am trying to download a file off a website and save it on a local machine. More importantly, I would like this to be fully automated. The file download can be started by clicking a button that calls a javascript function that sparks the download displaying a “Do you want to open or save this file?” dialog. I definitely do not want to be manually clicking “Save as”, and typing in the file name.
I am aware of HttpWebRequest and WebClient’s download functions, but since the download is started with a javascript, I do now know the URL of the file. Fyi, the javascript is a doPostBack function that changes some values and submits a form.
I’ve tried getting focus on the save as dialog from WebBrowser to automate it from in there without much success. I know there’s a way to force the download to save instead of asking to save or open by adding a header to the http request, but I don’t know how to specify the filepath to download to.
I think you should prevent the download dialog from even showing. Here might be a way to do that:
The Javascript code causes your WebBrowser control to navigate to a specific Url (what would cause the download dialog to appear)
To prevent the WebBrowser control from actually Navigating to this Url, attach a event handler to the Navigating event.
In your Navigating event you'd have to analyze if this is the actual Navigation action you'd want to stop (is this one the download url, perhaps check for a file extension, there must be a recognizable format). Use the WebBrowserNavigatingEventArgs.Url to do so.
If this is the right Url, stop the Navigation by setting the WebBrowserNavigatingEventArgs.Cancel property.
Continue the download yourself with the HttpWebRequest or WebClient classes
Have a look at this page for more info on the event:
http://msdn.microsoft.com/en-us/library/system.windows.forms.webbrowser.navigating.aspx
A similar solution is available at
http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/d338a2c8-96df-4cb0-b8be-c5fbdd7c9202/?prof=required
This work perfectly if there is direct URL including downloading file-name.
But sometime some URL generate file dynamically. So URL don't have file name but after requesting that URL some website create file dynamically and then open/save dialog comes.
for example some link generate pdf file on the fly.
How to handle such type of URL?
Take a look at Erika Chinchio article on http://www.codeproject.com/Tips/659004/Download-of-file-with-open-save-dialog-box
I have successfully used it for downloading dynamically generated pdf urls.
Assuming the System.Windows.Forms.WebBrowswer was used to access a protected page with a protected link that you want to download:
This code retrieves the actual link you want to download using the web browser. This code will need to be changed for your specific action. The important part is this a field documentLinkUrl that will be used below.
var documentLinkUrl = default(Uri);
browser.DocumentCompleted += (object sender, WebBrowserDocumentCompletedEventArgs e) =>
{
var aspForm = browser.Document.Forms[0];
var downloadLink = browser.Document.ActiveElement
.GetElementsByTagName("a").OfType<HtmlElement>()
.Where(atag =>
atag.GetAttribute("href").Contains("DownloadAttachment.aspx"))
.First();
var documentLinkString = downloadLink.GetAttribute("href");
documentLinkUrl = new Uri(documentLinkString);
}
browser.Navigate(yourProtectedPage);
Now that the protected page has been navigated to by the web browser and the download link has been acquired, This code downloads the link.
private static async Task DownloadLinkAsync(Uri documentLinkUrl)
{
var cookieString = GetGlobalCookies(documentLinkUrl.AbsoluteUri);
var cookieContainer = new CookieContainer();
using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = documentLinkUrl })
{
cookieContainer.SetCookies(this.documentLinkUrl, cookieString);
var response = await client.GetAsync(documentLinkUrl);
if (response.IsSuccessStatusCode)
{
var responseAsString = await response.Content.ReadAsStreamAsync();
// Response can be saved from Stream
}
}
}
The code above relies on the GetGlobalCookies method from Erika Chinchio which can be found in the excellent article provided by #Pedro Leonardo (available here),
[System.Runtime.InteropServices.DllImport("wininet.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)]
static extern bool InternetGetCookieEx(string pchURL, string pchCookieName,
System.Text.StringBuilder pchCookieData, ref uint pcchCookieData, int dwFlags, IntPtr lpReserved);
const int INTERNET_COOKIE_HTTPONLY = 0x00002000;
private string GetGlobalCookies(string uri)
{
uint uiDataSize = 2048;
var sbCookieData = new System.Text.StringBuilder((int)uiDataSize);
if (InternetGetCookieEx(uri, null, sbCookieData, ref uiDataSize,
INTERNET_COOKIE_HTTPONLY, IntPtr.Zero)
&&
sbCookieData.Length > 0)
{
return sbCookieData.ToString().Replace(";", ",");
}
return null;
}