How can I sendKeys to the Windows Explorer with Selenium - c#

A link on the page opens the file explorer of Windows.
Now I would like to send c:\temp\file1.txt to it.
Picture of Windows Explorer:
How can I do that?
What I tried is:
string BaseWindow = _webDriver.CurrentWindowHandle;
IJavaScriptExecutor jsExec = (IJavaScriptExecutor)_webDriver;
Thread.Sleep(1000);
jsExec.ExecuteScript("arguments[0].value = 'C:\\temp\\file1.txt'; ", BaseWindow);
which did not break the script actually but it didn't give the proper effect either.

Finally!! got it to work:
for all those people struggeling with the same thing... here is the solution:
you've got to switch to the active element then use sendkeys.

I got this:
System.Diagnostics.Process.Start("explorer.exe", "C:\\test.csv\"");
However that literally opens the Excel file. (which is also nice to know how to do that in automation by the way)
But I need to select a file in the Explorer (see 'pic of Windows Explorer')
I also tried this:
System.Diagnostics.Process.Start("explorer.exe /select", "C:\test.csv"");
Discovering this brought better results still not mission accomplished.
var FilePath = "'C:\\test.csv\'";
System.Diagnostics.Process.Start("Explorer.exe", #"/select,""" + FilePath + "\"");

Related

Manipulating "filename" of file dialog opened using a "print to pdf" option

I have over a thousand e-mails that need to be converted to individual PDFs. The code I've written is able to process the faux-print job up to the "Save PDF As..." Dialog Box.
I need to manipulate the filename in that dialog to the original filename. I cannot find a way to post a string to the filename section of the dialogbox, since this is an unconventional method posting on a separate process.
How do I send this information to an active dialog window that is unrelated to the process the application is calling?
public static void Main(string[] args)
{
string folderIn = Path.GetDirectoryName(#"Z:\Files up to 3-6-13\");
string folderOut = Path.GetDirectoryName(#"c:\users\athomas\desktop\Output");
string[] fileList = Directory.GetFiles(folderIn);
foreach(var fileName in fileList)
{
Console.WriteLine(fileName);
Process p = new Process();
ProcessStartInfo info = new ProcessStartInfo(fileName);
info.Verb = "Print";
info.CreateNoWindow = true;
info.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(info);
// This is where I need to say something like
// SaveDialog.SaveAs(fileName.SafeFileName)
if(p.HasExited == false)
{
p.WaitForExit(1000);
}
}
Console.ReadLine();
}
You are asking basically about hacking around, which means there is no safe way to do that. The possible way may look like this:
1) You enumerate windowses shown on the screen, via EnumWindows
2) You use for every window GetWindowText to find a Title of the Dialog you are searching for.
3) Ocassionaly there may be more then one dialog, Murphy's law is always there, so may be even with the same title. You can reduce collision risk by
3.a Call GetWindowLong with HWND of "dialog" you found
3.b Call GetParent to get HWND of parent window, that you already know
If you can avoid or may not care about case of window style&title collision, just jump over point (3)
4) Once you found your dialog, run over its HWND EnumChildWindows to get all controls of it
5) Find the contrlol you interested in via some attribute (usually Class_ID)
6) Execute SetWindowtext to set the text you like.
As I said before, there are several places were this process can fail.
For example:
You may happen to have multiple dialogs on the screen in the same moment
You may download a new version of PDF processor, and in SaveAs dialog may have something changed, so your code will break.
But considering that you are hacking, you may assume your own risks.
An excellent tool, may be the best tool, for window investigation on Windows, is probably Spy ++, which is available within visual studio installation. Using it you can try to find some unique attributes of a textbox of that dialog where you want to put the text in. Having that in your hands you can reliably query dialog's children collection to find the textbox.
After you mentioned .msg, I did a Google Search on the .msg file format and I was surprised to find it was well documented. It is an OLESS file, and there are APIs for loading those. I even found a CodeProject C# sample that was able to load an email I just saved from Outlook 2013!
It will be a bit of work since you will have to write code to "render" message how you see fit. Ex: It gives you the body, the recipients, and the attachments. You would have to decide what to do with the attachments and code that up. Then find a PDF library. But at least it is a programmatic solution, rather than relying on hacking the UI.
Also: A Google search for .MSG to PDF returned loads of tools to do this. One is a forum post referring to an Adobe Product called "Acrobat PDFMaker" so maybe you don't even need to write code.
Sorry to post 2 answers. I have a solution to the exact problem of prompting for the file. These instructions vary slightly based on the version of Windows, but you will get the idea:
Add a new printer that uses PDF printer driver
When it asks for the "port" click "Add Port" then "Local Port"
Enter in a file name. Ex: "C:\Users\Myself\MyPdf.pdf"
Complete the printing wizard as usual.
I tested this with the XPS printer and it worked
When you print to this printer, it writes to that exact file: No prompting! You will have to monitor the file (I suggest FileSystemWatcher) or poll for when the file is closed or something like that. After that, you can move the file elsewhere.

Unable to open PDF programmatically

I'm struggling to open a PDF file inside of Unity. Currently, my application will open up the folder location instead of opening the actual PDF itself.
I've tried using both System.Diagnostics.Process.Startand Application.OpenURL but they all act the same.
Right now, my code looks like:
Application.OpenURL(Application.dataPath + "/PDFS/" + pdfFile);
Now when I hard code in the file location like below, it opens up the PDF correctly:
Application.OpenURL("C:\\Users\\user\\Documents\\Locator\\Assets\\PDFS\\foo.pdf");
Normally I'd leave it hard coded, but I need to allow one button to open any PDF. How can I resolve this?
The string output of the two lines below are most likely not equal.
Application.OpenURL(Application.dataPath + "/PDFS/" + pdfFile);
Application.OpenURL("C:\\Users\\user\\Documents\\Locator\\Assets\\PDFS\\foo.pdf");
Ensure the paths are the same and you should get the result you expect.
See the documentation for Application.OpenURL here:
http://docs.unity3d.com/ScriptReference/Application-dataPath.html
If you read to the bottom, you'll notice:
"Note that the string returned on a PC will use a forward slash as a folder separator."
This likely the reason why you're getting different results.
Also note that the value of Application.OpenURL changes based on the platform.
string pdfURL = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority) + HttpRuntime.AppDomainAppVirtualPath + "Documents/keyboard-shortcuts-Visual-Studio-Code.pdf";
it return below url and run in browser
http://localhost:1727/Documents/keyboard-shortcuts-Visual-Studio-Code.pdf
thanks
upendra

c# playing movie in windows media player "Not" embedded

I have looked around, everything I find is talking about embedding it.
I do not want to embed it. I want to click a button and launch windows media player seperatly.
For example, I have a location saved in XML file. I have a right click to click Play. It pulls the location. like so.
int dd = dataGridView1.CurrentRow.Index;
string eLoc = dataGridView1.Rows[dd].Cells[4].Value.ToString();
if (eLoc == "")
{
MessageBox.Show("You have not saved a location for this movie","Movie Play",MessageBoxButtons.OK,MessageBoxIcon.Information);
}
else
{
MessageBox.Show(eLoc);
ProcessStartInfo ps = new ProcessStartInfo("wmplayer.exe", eLoc.ToString());
Process.Start(ps);
}
As you can see, I have a pop up to view, what the string is.
It is this. I added %20 to replace spaces, thinking that was the problem but it isn't.
As you can see it pulls the full location. All I get back from windows media player is this.
Any ideas? To me it seems like this should be working..
I got it working now. It was the spaces causing the errors, I changed to this, and works perfect now.
ProcessStartInfo ps = new ProcessStartInfo("wmplayer.exe", "\""+eLoc+"\"");
It should be working, in fact on my computer and with a different path it does work, I suspect the file is damaged like jfs suggested.

Webdriver: File Upload

Is there a way to interact with a File Upload box in webdriver? The form field where the path gets put in is read only so I can't write to that.
You can do this without injecting JavaScript. You just need to get hold of the form field and type into it. Something like (using the Ruby API):
driver.find_element(:id, 'upload').send_keys('/foo/bar')
You can set the value of your input field using JavaScript. Considering that the id of the field is fileName the following example will set the value of the input to the file C:\temp\file.txt:
String script = "document.getElementById('fileName').value='" + "C:\\\\temp\\\\file.txt" + "';";
((IJavaScriptExecutor)driver).ExecuteScript(script);
In this example, driver is your WebDriver instance.
Please note that you have to use four backslashes (\) for Windows-like paths because you are required to pass double back-slashes to the JavaScript so you have to escape both with two additional slashes. The other option is to use a forward slash (e.g. "C:/tmp/file.txt") and that should also work.
For C#, SendKeys() works but you have to use \ in your file path instead of /
For example, the follow works :
string filePath = #"drive:\path\filename.filextension";
driver.FindElement(By.Id("fileInput")).SendKeys(filePath);
But the following doesn't work :
string filePath = "drive:/path/filename.filextension";
driver.FindElement(By.Id("fileInput")).SendKeys(filePath);
The problem I found is the upload dialog hangs the webdriver until closed.
That is, the element.click which invokes the upload dialog does not return until that upload dialog is closed. To be clear, upload dialog means an OS-native file selection.
Here is my solution (it's a bit complicated but *shrug* most workarounds for selenium webdriver problems must get complicated).
# presumes webdriver has loaded the web page of interest
element_input = webdriver.find_element_by_css_selector('input[id="uploadfile"]')
handle_dialog(element_input, "foobar.txt")
def handle_dialog(element_initiating_dialog, dialog_text_input):
def _handle_dialog(_element_initiating_dialog):
_element_initiating_dialog.click() # thread hangs here until upload dialog closes
t = threading.Thread(target=_handle_dialog, args=[element_initiating_dialog] )
t.start()
time.sleep(1) # poor thread synchronization, but good enough
upload_dialog = webdriver.switch_to_active_element()
upload_dialog.send_keys(dialog_text_input)
upload_dialog.send_keys(selenium.webdriver.common.keys.Keys.ENTER) # the ENTER key closes the upload dialog, other thread exits
Using python 2.7, webdriver 2.25.0, on Ubuntu 12, with firefox.
I am in search of 3rd party libraries too,
Unless there is no any other Window Then this works for me :
in C# add reference for System.Windows.Forms
using System.Windows.Forms;
string url = "http://nervgh.github.io/pages/angular-file-upload/examples/image-preview/";
string path = #"C:\Users\File_Path";
IWebDriver d = new ChromeDriver();
d.Navigate().GoToUrl(url);
d.FindElement(By.XPath("//input[#type='file']")).Click();
hread.Sleep(5000);
System.Windows.Forms.SendKeys.SendWait(path);
System.Windows.Forms.SendKeys.SendWait(#"{Enter}");
in my case i can upload file like solution that write hear but dialog window stuck the process, the driver cant reference to close this window, so i kill him manually:
foreach (var p in Process.GetProcessesByName("chrome"))
if (p.MainWindowTitle.ToLower().Contains("open"))
p.Kill();
We can use following (ruby API)
#driver.find_element(:xpath, "html/body/div[1]/div[2]/div[1]/form/div[4]/div[7]/table/tbody/tr[1]/td[2]/input").send_keys "C:\\Users\\Public\\Pictures\\Sample Pictures\\Chrysanthemum.jpg"
This is helped me to upload image.

Is it possible to save data in another process with a C# app?

I have the following code:
p.StartInfo.FileName = "notepad.exe";
p.StartInfo.Arguments = "somefile.txt";
p.Start();
When "somefile.txt" is opened in notepad, its text will be modified. I want to save the new text in a temp file with the C# app automatically.
Is it possible to access this text and save it with C#?
It is sorta possible, you could use P/Invoke to call the SendMessage() method and generate the WM_COMMAND messages for the Edit + Select-All and Edit + Copy menu commands. That puts all text on the clip board, readily accessible to your program. You'll need to use the Spy++ utility to find out what the command identifiers are. Looks like 25 and 769 when I look at it on Win7.
There's a more direct way to discover the commands. In Visual Studio choose File + Open + File and select c:\windows\notepad.exe. Open the Menu node and double-click the "1" resource. That opens the menu editor, select Edit + Select-All and look at the Properties window for the ID.
Of course, this technique is specific to Notepad. The command IDs will be different for another program. As will be the code you need to find the proper window handle. Using Process.MainWindowHandle is treacherous at best, you don't know what specific instance of the process you need to select.
It would be very difficult to look at the text in-memory in the notepad process. It could be done, but it depends on the internal memory layout of notepad and your process may need administrative privileges depending on how the memory pages are protected.
Why not use a FileSystemWatcher to detect when the file has been modified, and then read the file in directly using c#?
http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx
Copy the somefile.txt before you start notepad to a temporary file/folder. Start notepad using this temporary file. And wait for Notepad to exit.
Then you can examine if the file is changed (checksum?).
Probably delete the file after the processing, or your system will be full with temp files.
You can bring notepad window to front and send CTRL+S. You will need to use pinvoke for that.
I really don't understand why you would want to use notepad?
If you need a user to edit a text file, and then your app take some action on the text itself, why not just give the user the ability to edit the text right in your app?
What does notepad give you that the TextBox control doesn't have?
Try something like this
using System.Windows.Forms;
using System.IO;
TextBox myEditor = new TextBox();
myEditor.Multiline = true;
myEditor.ScrollBars = ScrollBars.Vertical;
myEditor.AcceptsReturn = true;
myEditor.AcceptsTab = true;
myEditor.WordWrap = true;
// Get the text from the file.
StreamReader sr = new StreamReader("SomeFile.txt"))
myEditor.Text = sr.ReadToEnd();

Categories

Resources