How can I turn on design mode in Gecko? - webbrowser-control

I am using Gecko browser in my program. I am trying to turn on design mode on this browser like that:
webBrowser1.Document.DomDocument.GetType().GetProperty("designMode").SetValue
(webBrowser1.Document.DomDocument, "On", null);
But it doesn't works. How can I do it?

nsIHTMLEditor is likely a per browser instance rather than a global instance (like things returned by Xpcom.GetService)
One can get a nsIEditor like this by (by supplying a Window instance)
var editingSession = Xpcom.CreateInstance<nsIEditingSession>("#mozilla.org/editor/editingsession;1");
nsIEditor editor = editingSession.GetEditorForWindow((nsIDOMWindow)Window.DomWindow);
Marshal.ReleaseComObject(editingSession);
(or you can just call the nsIEditor GeckoWebBrowser.Editor property.)
You may be able to cast this nsIEditor to a nsIHtmlEditor (although I have yet to try it)
GeckoWebBrowser browser = .....;
// Untested code
nsIHTMLEditor htmlEditor = (nsIHTMLEditor)browser.Editor;
The VB code from #GreenBear
Dim gEditor As nsIHTMLEditor:
gEditor = Gbrowser.Editor:
gEditor.DecreaseFontSize()

Related

Using a local image with EmbedBuilder

According to the Discord.NET documentation page for the EmbedBuilder class, the syntax (converted to VB) to add a local image to an EmbedBuilder object should look something like this:
Dim fileName = "image.png"
Dim embed = New EmbedBuilder() With {
.ImageUrl = $"attachment://{fileName}"
}.Build()
I'm trying to use something like this to add a dynamically created image to the EmbedBuilder, but I can't seem to get it to work properly. Here's basically what I've got:
Dim TweetBuilder As New Discord.EmbedBuilder
Dim DynamicImagePath As String = CreateDynamicImage()
Dim AttachURI As String = $"attachment:///" & DynamicImagePath.Replace("\", "/").Replace(" ", "%20")
With Builder
.Description = "SAMPLE DESCRIPTION"
.ImageUrl = AttachURI
End With
MyClient.GetGuild(ServerID).GetTextChannel(PostChannelID).SendMessageAsync("THIS IS A TEST", False, Builder.Build)
My CreateDynamicImage method returns the full path to the locally created image (e.g., C:\Folder\Another Folder\image.png). I've done a fair amount of "fighting"/testing with this to get past the Url must be a well-formed URI exception I was initially getting because of the [SPACE] in the path.
MyClient is a Discord.WebSocket.SocketClient object set elsewhere.
The SendMessageAsync method does send the Embed to Discord on the correct channel, but without the embedded image.
If I instead send the image using the SendFileAsync method (like so):
MyClient.GetGuild(ServerID).GetTextChannel(PostChannelID).SendFileAsync(DynamicImagePath, "THIS IS A TEST", False, Builder.Build)
the image is sent, but as a part of the message, rather than included as a part of the Embed (this is expected behavior - I only bring it up b/c it was a part of my testing to ensure that there wasn't a problem with actually sending the image to Discord).
I've tried using the file:/// scheme instead of the attachment:/// scheme, but that results in the entire post never making it to Discord at all.
Additionally, I've tried setting the ImageUrl property to a Web resource (e.g., https://www.somesite.com/someimage.png) and the Embed looks exactly as expected with the image and everything when it successfully posts to Discord.
So, I'm just wondering at this point if I'm just missing something, or if I'm just doing it completely wrong?
I cross-posted this to issue #1609 in the Discord.Net GitHub project to get a better idea of what options are available for this and received a good explanation of the issue:
The Embed (and EmbedImage) objects don't do anything with files. They simply pass the URI as configured straight into Discord. Discord then expects a URI in the form attachment://filename.ext if you want to refer to an attached image.
What you need to do is use SendFileAsync with the embed. You have two options here:
Use SendFileAsync with the Stream stream, string filename overload. I think this makes it clear what you need to do: you provide a file stream (via File.OpenRead or similar) and a filename. The provided filename does not have to match any file on disk. > So, for example:
var embed = new EmbedBuilder()
.WithImageUrl("attachment://myimage.png")
.Build();
await channel.SendFileAsync(stream, "myimage.png", embed: embed);
Alternatively, you can use SendFileAsync with the string filePath overload. Internally, this gets a stream of the file at the path, and sets filename (as sent to Discord) to the last part of the path. So it's equivalent to:
using var stream = File.OpenRead(filePath);
var filename = Path.GetFileName(filePath);
await channel.SendFileAsync(stream, filename);
From here, you can see that if you want to use the string filePath overload, you need to set embed image URI to something like $"attachment://{Path.GetFileName(filePath)}", because the attachment filename must match the one sent to Discord.
I almost had it with my code above, but I misunderstood the intention and usage of the method and property. I guess I thought the .ImageUrl property somehow "automatically" initiated a Stream in the background. Additionally, I missed one very important piece:
As it's an async method, you must await (or whatever the VB.NET equivalent is) on SendFileAsync.
So, after making my calling method into an async method, my code now looks like this:
Private Async Sub TestMessageToDiscord()
Dim Builder As New Discord.EmbedBuilder
Dim AttachmentPath As String = CreateDynamicImage() '<-- Returns the full, local path to the created file
With Builder
.Description = "SAMPLE DESCRIPTION"
.ImageUrl = $"attachment://{IO.Path.GetFileName(AttachmentPath)}"
End With
Using AttachmentStream As IO.Stream = IO.File.OpenRead(AttachmentPath)
Await MyClient.GetGuild(ServerID).GetTextChannel(PostChannelID).SendFileAsync(AttachmentStream, IO.Path.GetFileName(AttachmentPath), "THIS IS A TEST", False, Builder.Build)
End Using
End Sub
Now, everything works exactly as expected and I didn't have to resort to uploading the image to a hosting site and using the new URL (I actually had that working before I got the response on GitHub. I'm sure that code won't go to waste).
EDIT
Okay, so I still ended up going back to my separately hosted image option for one reason: I have a separate event method that modifies the original Embed object during which I want to remove the image and replace the text. However, when that event fired, while the text was replaced, the image was "moved" to the body of the Discord message. While I may have been able to figure out how to get rid of the image entirely, I decided to "drop back and punt" since I had already worked out the hosted image solution.
I've tried everyting I could, but I got stuck at the same point at where you are now.
My guesses are that Discord doesn't like the embedded images from https://cdn.discordapp.com/attachments, and only accepts the new files from https://media.discordapp.net. I might be wrong though, this is the way it worked for me.
I believe it's only a visual glitch, as I found if you send a link for an image from cdn.discordapp.com/attchments in your regular Discord client, it bugs out and shows an empty embed for some reason.
That would make sense since the default link used in an embedded image actually starts with https://cdn.discordapp.com/attachments/...
You could solve this issue by using https://media.discordapp.net, but it seems like Discord.net is configured to use the old domain.

Running multiple browser instances in the same test spec

If I have a single spec that is using page object model, how do I run multiple browser instance for that same spec?
For example I have spec:
it('should run multi browser', function() {
browser.get('http://example.com/searchPage');
var b2 = browser.forkNewDriverInstance();
b2.get('http://example.com/searchPage');
var b3 = browser.forkNewDriverInstance();
b3.get('http://example.com/searchPage');
SearchPage.searchButton.click();
b2.SearchPage.searchButton.click(); //fails here
b3.SearchPage.searchButton.click();
});
How do I reuse vars declared in the SearchPage page object for the other browser instances?
This is a really interesting question that is not covered in Using Multiple Browsers in the Same Test or in the interaction_spec.js.
The problem with page objects is that page object fields are usually defined with a globally available element or browser which in your case would always point to the first browser instance. But you basically need to call element() using a specific browser:
b2.element(by.id('searchInput'));
instead of just:
element(by.id('searchInput'));
FYI, element is just a shortcut for browser.element.
I am really not sure whether this is a reliable solution and would actually work, but you can redefine global element this way. Think about it as switching the search context to different browser instances:
SearchPage.searchButton.click();
global.element = b2.element;
SearchPage.searchButton.click();
global.element = b3.element;
SearchPage.searchButton.click();
global.element = browser.element;

Cannot read second page scanned via ADF

I have a Brother mutlifunction networked printer/scanner/fax (model MFC-9140CDN). I am trying to use the following code with WIA, to retrieve items scanned in with the document feeder:
const int FEEDER = 1;
var manager=new DeviceManager();
var deviceInfo=manager.DeviceInfos.Cast<DeviceInfo>().First();
var device=deviceInfo.Connect();
device.Properties["Pages"].set_Value(1);
device.Properties["Document Handling Select"].set_Value(1);
var morePages=true;
var counter=0;
while (morePages) {
counter++;
var item=device.Items[1];
item.Properties["Bits Per Pixel"].set_Value(1);
item.Properties["Horizontal Resolution"].set_Value(300);
item.Properties["Vertical Resolution"].set_Value(300);
var img=(WIA.ImageFile)item.Transfer();
var path=String.Format(#"C:\Users\user1\Documents\test_{0}.tiff",counter);
img.SaveFile(path);
var status=(int)device.Properties["Document Handling Status"].get_Value();
morePages = (status & FEEDER) > 0;
}
When the Transfer method is reached for the first time, all the pages go through the document feeder. The first page gets saved with img.SaveFile to the passed-in path, but all the subsequent pages are not available - device.Items.Count is 1, and trying device.Items[2] raises an exception.
In the next iteration, calling Transfer raises an exception -- understandably, because there are now no pages in the feeder.
How can I get the subsequent images that have been scanned into the feeder?
(N.B. Iterating through all the device properties, there is an additional unnamed property with the id of 38922. I haven't been able to find any reference to this property.)
Update
I couldn't find a property on the device corresponding to WIA_IPS_SCAN_AHEAD or WIA_DPS_SCAN_AHEAD_PAGES, but that makes sense because this property is optional according to the documentation.
I tried using TWAIN (via the NTwain library, which I highly recommend) with the same problem.
I have recently experienced a similar error with a HP MFC.
It seems that a property was being changed by the driver. The previous developer of the software I'm working on just kept reinitalisating the driver each time in the for loop.
In my case the property was 'Media Type' being set to FLATBED (0x02) even though I was doing a multi-page scan and needed it to be NEXT_PAGE (0x80).
The way I found this was by storing every property before I scanner (both device and item properties) and again after scanning the first page. I then had my application print out any properties that had changed and was able to identify my problem.
This is a networked scanner, and I was using the WSD driver.
Once I installed the manufacturer's driver, the behavior is as expected -- one page goes through the ADF, after which control is returned to the program.
(Even now, when I use WIA's CommonDialog.ShowSelectDevice method, the scanner is available twice, once using the Windows driver and once using the Brother driver; when I choose the WSD driver, I still see the issue.)
This bug did cost me hours...
So thanks a lot Zev.
I also had two scanners shown in the dialog for physically one machine. One driver scans only the first page and then empties the feeder without any chance to intercept. The other one works as expected.
BTW: It is not needed to initialize the scanner for each page. I call my routines for initialization prior to the Transfer() loop. Works just fine.
Another hickup I ran into was to first initialize page sizes, then the feeder. So if you do not get it to work, try switching the sequence how you change the properties for your WIA driver. As mentioned in the MSDN, some properties also influence others, potentially resetting your changes.
So praise to ZEV SPITZ for the answer on Aug. 09, 2015.
You should instantiate and setup device inside the 'while' loop. See:
const int FEEDER = 1;
var morePages=true;
var counter=0;
while (morePages) {
counter++;
var manager=new DeviceManager();
var deviceInfo=manager.DeviceInfos.Cast<DeviceInfo>().First();
var device=deviceInfo.Connect();
//device.Properties["Pages"].set_Value(1);
device.Properties["Document Handling Select"].set_Value(1);
var item=device.Items[1];
item.Properties["Bits Per Pixel"].set_Value(1);
item.Properties["Horizontal Resolution"].set_Value(300);
item.Properties["Vertical Resolution"].set_Value(300);
var img=(WIA.ImageFile)item.Transfer();
var path=String.Format(#"C:\Users\user1\Documents\test_{0}.tiff",counter);
img.SaveFile(path);
var status=(int)device.Properties["Document Handling Status"].get_Value();
morePages = (status & FEEDER) > 0;
}
I got this looking into this free project, which I believe is able to help you too: adfwia.codeplex.com

Detect if printer support duplex programmatically using obj-c

I have been stumped by this for the last few days. I need to detect if a printer support duplex printing.
I have had partial success using code like:
NSPrinter * printer = [NSPrinter printerWithName:pname];
[printInfo setPrinter:printer];
PMPrintSettings settings = printInfo.PMPrintSettings;
PMDuplexMode pmDuplexMode = 0;
OSStatus status = PMGetDuplex(settings, &pmDuplexMode);
supportsDuplex = (status >= 0);
But this only work if I captured a full printerConfig through an NSPrintPanel. What I need is a way to detect if a printer with a specific name support duplex without requiring the user to 1st open a panel. I would like to do if for any printer defined on the local Mac. Any help is appreciated!
In your code snippet, I doubt that it's correct to interpret positive status as indicating support. In general, any value other than zero (noErr) is a failure of some sort.
If you're confident that PMGetDuplex() returns an error for a print settings object when the printer doesn't support duplex, you can try this approach: create a session with PMCreateSession(), obtain a PMPrinter using PMPrinterCreateFromPrinterID() or by searching the array returned from PMSessionCreatePrinterList() for on which matches whatever criteria you want, set the session to use that printer using PMSessionSetCurrentPMPrinter(), create a print settings object with PMCreatePrintSettings(), call PMSessionDefaultPrintSettings() to initialize the print settings from the session, call PMSessionValidatePrintSettings() just for good measure, then call PMGetDuplex() and check the return value.
It might also be worth trying to set a duplex mode with PMSetDuplex() and check the return code and, possibly, calling PMSessionValidatePrintSettings() and checking if it changed that setting.

Coypu screenshot

On the end of a Scenario, I want to take a picture if it has failed. The following code does not work:
[AfterScenario]
public void AfterScenario()
{
if(ScenarioContext.Current.TestError != null)
{
WebBrowser.Driver.CaptureScreenShot(ScenarioContext.Current.ScenarioInfo.Title);
}
}
I think this may be due to the fact that I start my browser using Coypu (which has selenium wrapped). The driver does not have a 'captureScreenShot' method implemented. So my question is: how can i take a screenshot after a scenario, when i start up my browser using coypu?
The code for starting the browser is the following:
sessionConfiguration.Driver = typeof (SeleniumWebDriver);
sessionConfiguration.Browser = Drivers.Browser.Firefox;
As you say, this is not implemented in Coypu right now. Reason being I have simply never needed to take a screenshot since so far, and no one's asked till now.
To access the native driver (WebDriver in your case) use BrowserSession.Native then you can use WebDriver's GetScreenshot method. This would end up looking something like this (disclaimer: not tested):
var driver = (ITakesScreenshot) coypuBrowserSession.Native;
var screenshot = driver.GetScreenshot();
screenshot.SaveAsFile("c://screenshot.png", System.Drawing.Imaging.ImageFormat.Png);
I've opened an issue for you on github to have this added to Coypu's BrowserWindow API
This is now natively available in Coypu. You can find the documentation here:
https://github.com/featurist/coypu#screenshots