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.
Related
I have an app in which the user needs to access certain files in a user set and selected folder.
The folder and files paths need to be easily accessed (short simple path).
I use the Properties Settings to hold the Folder and File paths, but for some reason each time I re-start the program the Folder and File paths are lost.
I have followed and checked the program and all seems to be OK (except something I am missing, apparently).
I attach here the program snippet in two parts: The search for path and the setting in case path / file not found. (removed exception handling to save on lines)
public Main() //part of Main, stripped off exception handling)
{
//..........
dataFolder = Properties.Settings.Default.dataFolder;
if (!Directory.Exists(dataFolder))
{
SetDataFolder();
}
configFile = Properties.Settings.Default.configFile;
if (!File.Exists(configFile))
{
SetConfigFile();
}
dataFile = Properties.Settings.Default.dataFile;
if (!File.Exists(dataFile))
{
SetDataFile();
}
loadParamsFromFile(configFile); //Load the previously saved controls.
public String SetDataFolder()
{
FolderBrowserDialog dialog = new FolderBrowserDialog();
DialogResult folder = dialog.ShowDialog();
if (folder == DialogResult.OK)
{
dataFolder = dialog.SelectedPath;
Directory.CreateDirectory(dataFolder);
dataFolder = Path.GetFullPath(dataFolder);
Properties.Settings.Default.dataFolder = dataFolder;
Properties.Settings.Default.Save();
return dataFolder;
}
else return null;
}
private string SetDataFile()
{
dataFile = $"{dataFolder}\\{textBoxSampleID.Text.Replace("/r", "").Trim()}.txt";
File.Create(dataFile).Close();
Properties.Settings.Default.dataFile = dataFile;
Properties.Settings.Default.Save();
return dataFile;
}
private string SetConfigFile()
{
configFile = $"{dataFolder}\\electroplating.cfg";
File.Create(configFile).Close();
Properties.Settings.Default.configFile = configFile;
Properties.Settings.Default.Save();
return configFile;
}
Check out this question:
How to change application settings (Settings) while app is open?
I would suggest using Path.Combine() for the construction of the file paths.
If it still doesn't work, you could also try using the registry for storing the values.
string dataFilePath = Path.Combine(dataFolder, textBoxSampleID.Text.Replace("/r", "").Trim());
RegistryKey key = Registry.LocalMachine.CreateSubKey(#"SOFTWARE\Company");
if (key != null)
{
key.SetValue("dataFilePath", dataFilePath);
}
You could then use string dataFilePath = (string)key.GetValue("dataFilePath") to get the value out of the registry.
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
I want to open a html page (in AppData/Roaming folder and not in the project/solution) with IIS/IIS Express in the default browser on click of a button. I have been able to find the default browser using the following:-
//This method is used to get the default browser
private static string GetDefaultBrowserPath()
{
string urlAssociation = #"Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http";
string browserPathKey = #"$BROWSER$\shell\open\command";
RegistryKey userChoiceKey = null;
string absBrowserPath = "";
const string exeSuffix = ".exe";
FileInfo browserPath;
try
{
//reading default browser path from userChoiceLKey
userChoiceKey = Registry.CurrentUser.OpenSubKey(urlAssociation + #"\UserChoice", false);
//If user choice was not found, try machine default
if (userChoiceKey == null)
{
//reading default browser path from Win XP registry key
var browserKey = Registry.ClassesRoot.OpenSubKey(#"HTTP\shell\open\command", false);
//if browser path not found, try Win Vista (and newer) registry key
if (browserKey == null)
{
browserKey =
Registry.CurrentUser.OpenSubKey(
urlAssociation, false);
}
var path = browserKey.GetValue(null);
browserKey.Close();
return path.ToString();
}
else
{
//if user defined browser choice was found
string progId = (userChoiceKey.GetValue("ProgId").ToString());
userChoiceKey.Close();
//looking up the path of the executable
string concreteBrowserKey = browserPathKey.Replace("$BROWSER$", progId);
var kp = Registry.ClassesRoot.OpenSubKey(concreteBrowserKey, false);
try
{
absBrowserPath = kp.GetValue(null).ToString().ToLower().Replace("\"", "");
if (!absBrowserPath.EndsWith(exeSuffix))
{
absBrowserPath = absBrowserPath.Substring(0, absBrowserPath.LastIndexOf(exeSuffix, StringComparison.Ordinal) + exeSuffix.Length);
browserPath = new FileInfo(absBrowserPath);
}
}
catch (Exception)
{
throw;
}
kp.Close();
return absBrowserPath;
}
}
catch(Exception ex)
{
return "";
}
}
After locating the default browser, I want to open a html page located in AppData/Roaming folder with IIS. How can this be achieved?
Edit: I am thinking of first publishing the pages with the IIS using ServerManager class of Microsoft.Web.Administration and then trying to open it.
is this a right approach? Once published, how would it be possible to open that page(a locally published site now) on click of some button?
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
I have a utility programs’s EXE file, when i run this file there is a winform only and there is button when we click on it, it run windows’s notepad. Now I want to hijack this program’s command to run notepad and instead of running notepad I want to run MS Word. I know C# and VB.NET. What I need to do this ?
You can try to add in folder with this program your own program called notepad.exe that should do only one thing: run word.
If you want to do it programatically in C then you should read this page - maybe it helps: Intercepted: Windows Hacking via DLL Redirection
You can use a trick to replace programs with another by making changes to the registry. This will work even if the program you are running uses absolute paths to run notepad. It overrides any instance of the running program with the chosen one no matter where it resides. And you won't have to patch the file. The key you'd be interested in is:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
Add a key with the name of the program and add a Debugger string with the path to the program you want to replace it with. Of course you need to have permissions to make the necessary modifications. This page explains how you can replace Windows Notepad with another program. You can apply the same process here.
Though you'll probably not want to have this permanent change, so you can write up a program to temporarily add/change the key, run your program then change it back. Here's a complete one I just whipped up to temporarily replace Notepad with Word for a demonstration. Seems to work perfectly fine (though as always, use at your own risk). Just make all the necessary changes to fit your situation.
using System.Diagnostics;
using Microsoft.Win32;
namespace ProgramLauncher
{
class Program
{
// change the following constants as needed
const string PROGRAM_NAME = #"notepad.exe";
const string REPLACEMENT_PATH = #"C:\Program Files (x86)\Microsoft Office\Office12\WINWORD.EXE";
const string RUNNING_PATH = #"C:\Windows\notepad.exe";
// root key
const string KEY = #"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options";
static void Main(string[] args)
{
using (var rootKey = Registry.LocalMachine.OpenSubKey(KEY, RegistryKeyPermissionCheck.ReadWriteSubTree))
{
var oldPath = default(string);
var needsRestoration = false;
try
{
oldPath = BackupKey(rootKey, PROGRAM_NAME, REPLACEMENT_PATH);
needsRestoration = true;
Process.Start(RUNNING_PATH).WaitForExit();
}
finally
{
if (needsRestoration)
RestoreKey(rootKey, PROGRAM_NAME, oldPath);
}
}
}
static string BackupKey(RegistryKey rootKey, string programName, string newPath)
{
Debug.Assert(rootKey != null);
Debug.Assert(!string.IsNullOrEmpty(programName));
Debug.Assert(!string.IsNullOrEmpty(newPath) && System.IO.File.Exists(newPath));
if (newPath.Contains(" "))
newPath = string.Format("\"{0}\"", newPath);
using (var programKey = rootKey.CreateSubKey(programName, RegistryKeyPermissionCheck.ReadWriteSubTree))
{
var oldDebugger = programKey.GetValue("Debugger") as string;
programKey.SetValue("Debugger", newPath, RegistryValueKind.String);
return oldDebugger;
}
}
static void RestoreKey(RegistryKey rootKey, string programName, string oldPath)
{
Debug.Assert(rootKey != null);
Debug.Assert(!string.IsNullOrEmpty(programName));
if (oldPath != null)
{
using (var programKey = rootKey.OpenSubKey(programName, RegistryKeyPermissionCheck.ReadWriteSubTree))
programKey.SetValue("Debugger", oldPath);
}
else
{
rootKey.DeleteSubKey(programName);
}
}
}
}