I need to upload a file in a website using watin. The problem is that setting the direction of the file, like this:
browser.FileUpload(Find.ById("ctl00_cpContent_FileUpload1")).Set(DIRECCION_XML + "plantilla.txt");
doesnt work. Because this, I need to handle the windows popup that appear and fill the direction of the file to upload. I dont know how to do it... I were searching info of FileUploadHandler, but i cant get it.
There is more option than that? Pls, help me with a possible code to do it.
Really thanks
The FileUploadHandler works great. I have it running in production mode with thousands of files being uploaded every day and I haven't had any issues with it so far.
This is the way it needs to be implemented:
EDIT: (I forgot to include the uploadDialog object)
IntPtr hwndTmp = (IntPtr)FindWindow("#32770","Select file(s) to upload"); // or whatever the window text says when you are opening that upload window)
Window uploadDialog = new Window(hwndTmp);
UploadFileDialogHandler uploadFile = new UploadFileDialogHandler(_toBeSent.FileToSent);
_browser.AddDialogHandler(uploadFile);
uploadFile.HandleDialog(uploadDialog);
uploadFile = null;
That will take care of the upload process. when you need to upload the file just those lines will take care of everything (loop thru all open dialogs, find the right one, find the text field, enter the name for you and click the Ok button. On top of that you need to create another class that will be the UploadFileDialogHandler:
public class UploadFileDialogHandler : BaseDialogHandler
{
private const int WmSettext = 0x000C;
private string fileName;
private bool _processed = false;
public override bool HandleDialog(Window window)
{
var button = GetOpenButton(window);
if (button != null)
{
if (_processed == false)
{
var fileNameHandle = NativeMethods.GetChildWindowHwnd(window.Hwnd, "Edit");
var fileNameHwnd = new Hwnd(fileNameHandle);
fileNameHwnd.SetFocus();
_processed = true;
//MessageBox.Show("About to send " + fileName);
fileNameHwnd.SendString(fileName);
button.Click();
}
return true;
}
else
{
return false;
}
}
public UploadFileDialogHandler(string file)
{
fileName = "";
fileName = file;
//MessageBox.Show("Setting filename: " + fileName);
}
public override bool CanHandleDialog(Window window)
{
return GetOpenButton(window) != null;
}
private WinButton GetOpenButton(Window window)
{
var windowButton = new WindowsEnumerator().GetChildWindows(window.Hwnd, w => w.ClassName == "Button" && new WinButton(w.Hwnd).Title == "&Open").FirstOrDefault();
if (windowButton == null)
return null;
else
return new WinButton(windowButton.Hwnd);
}
}
}
You can just copy and paste that class inside your program and with the 4 lines of code above it will take care of the rest for you. In case you need more information there's a good amount of information on the WatIn file source code but it could be a little bit challenging to follow if you don't understand the Windows API.
Hope this helps.
This command work for me fine: browser.FileUpload(Find.ById("FormImage")).Set("C:\\Pictures\\11.PNG");
Try it
Related
I want the embedded GeckoFx 60 to download a file and then open it with the default app.
By default it seems like GeckoFx does not do anything when the client requests to download a file.
To handle the download request I enabled an event handler:
LauncherDialog.Download += LauncherDialog_Download;
Then I found two possibilities to download or open a file via the HelperAppLauncher.
This one saves the requested file to a temp folder and opens it:
private void LauncherDialog_Download(object sender, LauncherDialogEvent e)
{
// direct open, file will be stored in C:\Users\Username\AppData\Local\Temp\
e.HelperAppLauncher.LaunchWithApplication(null, false);
}
I did not find a way to configure the save path. This other possible solution allows me to set the save path myself:
private void LauncherDialog_Download(object sender, LauncherDialogEvent e)
{
nsILocalFileWin objTarget = Xpcom.CreateInstance<nsILocalFileWin>("#mozilla.org/file/local;1");
var downloadPath = #Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\CustomFolder\\" + e.Filename;
using (nsAString tmp = new nsAString(downloadPath))
{
objTarget.InitWithPath(tmp);
}
e.HelperAppLauncher.SaveToDisk(objTarget, false);
Task.Run(() =>
{
Thread.Sleep(3000);
System.Diagnostics.Process.Start(downloadPath);
});
}
That Task.Run() works, but is quite ugly and error prone. I could not find a better solution though. I tried adding a WebProgressListener like this:
var webProgressListener = new WebProgressListener();
webProgressListener.OnStatusChangeCallback+= OnStatusChangeCallback;
e.HelperAppLauncher.SetWebProgressListener(webProgressListener);
webProgressListener.IsListening is true, but my method OnStatusChangeCallback is never called. Am I doing something wrong? Is there a newer way?
How can I get notified that the download is completed?
Or how do I set the path for LaunchWithApplication?
Not the best solution but here is my solution :
Task.Run(() =>
{
long sizefirst = 0;
while (true)
{
Thread.Sleep(1000);
if (File.Exists(downloadPath))
{
if (sizefirst == 0)
{
sizefirst = new FileInfo(downloadPath).Length;
continue;
}
long len_now = new FileInfo(downloadPath).Length;
if (len_now > sizefirst)
{
sizefirst = len_now;
continue;
}
else
{
System.Diagnostics.Process.Start(downloadPath);
break;
}
}
}
});
In my web application which has some automation process to download the files from the website. To achieve that I used selenium c# chrome driver.
Sample code snippets
public void Download(string name,string pass)
{
try
{
ChromeOptions options = new ChromeOptions();
options.AddArguments("--proxy-server=http://192.168.5.62:8095");
options.AddUserProfilePreference("safebrowsing.enabled", true);
options.AddUserProfilePreference("disable-popup-blocking", "true");
options.AddUserProfilePreference("download.default_directory",#"C:\Temp");
using (var driver = new ChromeDriver(HostingEnvironment.ApplicationPhysicalPath, options)){
//driver.findElement(By.xpath("//a/u[contains(text(),'Re-Submit')]")).click();
driver.FindElementById("save").Click();
}
}
catch (Exception ex)
{
Logger.LogWriter("LAS", ex, "CusDataLogic", "Download");
}
}
above code (not complete code) works fine and save file properly. But I need to rename that file downloading or after download. Have any possible way to rename that file?
Edited: Please don't mark this as a duplicate. I'm asking for C#, not python. I saw that question too. but it not helped to me
watching directory is not always good, because sometime saved filename is different than filename in URL.
go to chrome download page and loop until all download complete, you can see below how to select special element #shadow-root with CSS selector
using (var driver = new ChromeDriver(HostingEnvironment.ApplicationPhysicalPath, options)))
{
//driver.findElement(By.xpath("//a/u[contains(text(),'Re-Submit')]")).click();
driver.FindElementById("save").Click();
// wait 5 second until download started
Thread.Sleep(5000);
// Go to chrome download page
driver.Navigate().GoToUrl("chrome://downloads/");
string oldName = "";
bool downloadcomplete = false;
string cssNames = "downloads-manager /deep/ downloads-item /deep/ [id='name']";
string cssDlProgress = "downloads-manager /deep/ downloads-item /deep/ [class*='show-progress']";
while (!downloadcomplete)
{
var progressElements = driver.FindElements(By.CssSelector(cssDlProgress));
// check until no download progress bar
if (progressElements.Count() == 0)
{
oldName = driver.FindElement(By.CssSelector(cssNames)).Text;
downloadcomplete = true;
}
else
{
// download still in progress, wait.
Thread.Sleep(1000);
}
}
// download complete
// remove downloaded file
driver.FindElement(By.CssSelector("downloads-manager /deep/ downloads-item /deep/ [id='remove']")).Click();
// rename
File.Move(#"C:\Temp\" + oldName, #"C:\Temp\newname.ext");
}
The Snippet Below Will wait Until File downloaded Then return FilePath I Wrote this as an extension method :
public static string GetDonwloadedFileName(this IWebDriver driver)
{
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
js.ExecuteScript("window.open()");
var allWinowHandles = driver.WindowHandles;
foreach (var winHandle in allWinowHandles)
{
//Switch to second window
if (!winHandle.Equals(driver.CurrentWindowHandle))
{
driver.SwitchTo().Window(winHandle);
}
}
// navigate to chrome downloads
driver.Navigate().GoToUrl("chrome://downloads");
IJavaScriptExecutor downloadWindowExecutor = (IJavaScriptExecutor)driver;
// Wait for Download till 100% completion
double percentageProgress = (double)0;
while (percentageProgress != 100)
{
try
{
percentageProgress = (long)downloadWindowExecutor.ExecuteScript("return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('#progress').value");
Thread.Sleep(100);
}
catch (Exception)
{
break;
}
}
string fileTitle = (string)downloadWindowExecutor.ExecuteScript("return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('#show').getAttribute('title')");
downloadWindowExecutor.ExecuteScript("window.close()");
return fileTitle;
}
Then You can use file Path to rename it to whatever you need
This is a piece of code for genrating mail which works until I didnt attach path as a parameter . the thing is if I attach the path it didnt throw any error(no logs). Just the page started being unresponsive,and debugger not even jump to next line.
any help wil help me to understand my mistake . Thanks
public ActionResult Mailsending(string list)
{
try
{
string strIdeas = string.Empty;
string Certpath = System.Configuration.ConfigurationManager.AppSettings["UploadPath"];
List<int> list = new List<int>();
List<string> pramAttachment = new List<string>();
pramAttachment.Add(Server.MapPath(Certpath) + "MyPdf.pdf"); ///Path of the generated pdf.
Submitidlist = new CommonBL().GetSubmiidListForGenerateMail();
new CommonBL().UpdateIsGenerateStatus(ideaidlist, UserID);
foreach (var item in ideaidlist)
{
strIdeas = strIdeas + item.ToString() + ",";
}
GenerateMyPDF(list); //Here pdf is generating
string path = GenerateMail(strIdeas.TrimEnd(','));
if (path != string.Empty)
{
new CommonBL().AddGenerateImagePath(path, UserId);
new MailSender().SendMail((int)eMailType.GenerateMail, null, pramAttachment); // here path is added as parameter,and after this debugger not jump out of this scope.
}
return Json("Mail generated Successfully."); ///no message showing
}
catch (Exception ex)
{
return Json("Error");
}
}
Edit :
public class MailSender : IDisposable
{
public bool SendMail(short mailId, List<KeyValuePair<string, string>> parameters, List<string> attachmentsPath = null);
}
Possibly still leaving lock on the generated PDF, so MailSender is not able to access it due to that exclusive lock. Can you send emails with files previously generated?
adding a point which apparently is also an answer of this question, is :
After debugging whole code, I found that my smtp server is not allowing to send me a mail, so even if the above code is right, it shows processing.
So if anyone is working with above code will work fine.
An update : Now it works fine after configuring my mail service from control panel. So if any one wants to take reference from this can go ahead . the code is fine .
I'm new to C# and I'm trying to implement a button.visible true/false based on the contents of a txt file. Everything I've written to date is unstable at best. This is for a Winform stand alone application in the main dialog box.
In an ideal world it seems it should be simpler. I want the code to open Permissions.txt, which I know I am successfully accessing as the MessageBox will show the first name in the list, and compare the Environment.UserName with all of the names in the .txt file. Once the button is displayed it opens a new dialog box.
Anyone willing to teach a newcomer. I've been searching for a while and I don't see it.
I have also tried working with File.Readlines with no success.
Thank you in advance for any assistance you're willing to provide.
Frank Pytel
public void hideWidget()
{
//gets the users login name from the system
string newName = userNameOnly();
// Read the file and display it line by line.
System.IO.StreamReader file =
new System.IO.StreamReader(dataFolder + "\\Permissions.txt");
//This next bit called Original Code works on my local when I access it, when accessed from a server, but not for other users.
//Original code
//while ((line = file.ReadLine()) != null)
//{
// if (line == newName)
// {
// WidgetForm.Visible = true;
// }
// else
// {
// WidgetForm.Visible = false;
// }
// //MessageBox.Show(line);
// counter++;
//}
//file.Close();
//This is where I am at currently. Again it's not picking up all of the names in the .txt file.
while (file.ReadLine() != null)
{
//string line;
string line = file.ReadLine();
if (newName == file.ReadLine())
{
WidgetForm.Visible = false;
}
else
{
WidgetForm.Visible = true;
}
int counter = 0;
//MessageBox.Show(line);
//MessageBox.Show(file.ReadLine());
counter ++;
}
//file.Close();
}
EDITED....
Also if there is anyone that could possibly explain how string line; is being set to my user name. That is how it should have been set, but I've never told it line == newName in the original code. I thought that is what the While is for. To check to see if they are equal..
FINAL EDIT.
Here is what I got to work. Thanks #Bedford.
This portion goes directly below the Form1 class
string[] lines = File.ReadAllLines(dataFolder + "\\Permissions.txt");
This is the logic behind the hideWidget() button
public void hideWidget()
{
//Make all userNames available to the logic
string newName = userNameOnly();
//variable to decide if userExists is true/false
bool userExists;
//Loop through all of the userNames in the file and see if it matches the userName login
while (lines != null)
{
//Decide to make the button available if userExists does exist in the file
if (lines != null)
{
userExists = lines.Any(ln => ln == newName);
WidgetForm.Visible = userExists;
}
//Do nothing if the userName does not match anyone in the Permissions.txt file. The button default Visible is false
else
{
}
return;
}
}
I'm posting this snippet so that others might benefit from it. Thanks again #Bedford. This NEWB really appreciates the assistance. HAGD!! :-)
You can read all the lines from a file with the File.ReadAllLines static method, and then use a LINQ query to check whether any of the lines match the user name:
string[] lines = File.ReadAllLines(Path.Combine(dataFolder, "Permissions.txt"));
bool userExists = lines.Any(ln => ln == newName); // or any comparison you like
// use the bool variable to set the visibility
WidgetForm.Visible = userExists;
I am trying to do following with c#.
1) Open Firefox Browser-->Tools-->Options-->General Tab--->Downloads--->Always ask me where to save file.
I want to do this whole process in my application with c#. I want that when download window opens, the radio button in "Always ask me where to save file" option gets checked automatically.
I have tried from various links, but all is in vain.
Here is the full code, console application.
Summary: preferences file is located in application roaming folder, something like this on windows 7:
C:\Users\MYNAME\AppData\Roaming\Mozilla\Firefox\Profiles\d9i9jniz.default\prefs.js
We alter this file so that it includes "user_pref("browser.download.useDownloadDir", false);"
Restart firefox, and done. Only run this application when firefox is not running.
static void Main(string[] args)
{
if (isFireFoxOpen())
{
Console.WriteLine("Firefox is open, close it");
}
else
{
string pathOfPrefsFile = GetPathOfPrefsFile();
updateSettingsFile(pathOfPrefsFile);
Console.WriteLine("Done");
}
Console.ReadLine();
}
private static void updateSettingsFile(string pathOfPrefsFile)
{
string[] contentsOfFile = File.ReadAllLines(pathOfPrefsFile);
// We are looking for "user_pref("browser.download.useDownloadDir", true);"
// This needs to be set to:
// "user_pref("browser.download.useDownloadDir", false);"
List<String> outputLines = new List<string>();
foreach (string line in contentsOfFile)
{
if (line.StartsWith("user_pref(\"browser.download.useDownloadDir\""))
{
Console.WriteLine("Found it already in file, replacing");
}
else
{
outputLines.Add(line);
}
}
// Finally add the value we want to the end
outputLines.Add("user_pref(\"browser.download.useDownloadDir\", false);");
// Rename the old file preferences for safety...
File.Move(pathOfPrefsFile, Path.GetDirectoryName(pathOfPrefsFile) + #"\" + Path.GetFileName(pathOfPrefsFile) + ".OLD." + Guid.NewGuid().ToString());
// Write the new file.
File.WriteAllLines(pathOfPrefsFile, outputLines.ToArray());
}
private static string GetPathOfPrefsFile()
{
// Get roaming folder, and get the profiles.ini
string iniFilePath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + #"\Mozilla\Firefox\profiles.ini";
// Profiles.ini tells us what folder the preferences file is in.
string contentsOfIni = File.ReadAllText(iniFilePath);
int locOfPath = contentsOfIni.IndexOf("Path=Profiles");
int endOfPath = contentsOfIni.IndexOf(".default", locOfPath);
int startOfPath = locOfPath + "Path=Profiles".Length + 1;
int countofCopy = ((endOfPath + ".default".Length) - startOfPath);
string path = contentsOfIni.Substring(startOfPath, countofCopy);
string toReturn = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + #"\Mozilla\Firefox\Profiles\" + path + #"\prefs.js";
return toReturn;
}
public static bool isFireFoxOpen()
{
foreach (Process proc in Process.GetProcesses())
{
if (proc.ProcessName == "firefox")
{
return true;
}
}
return false;
}
What have you tried?
Firefox settings are stored in your profile, so I'd guess you can change the contents of the given file. Type about:config to find the setting you're looking for, I guess it's in the browser.download tree, alter it (after you made sure the browser isn't running) and you should be good to go.