I'm trying to duplicate the functionality in this sample app from here : http://code.msdn.microsoft.com/windowsapps/Licensing-API-Sample-19712f1a
into an app I'm writing. I've started with working on implementing the ability to buy a consumable item.
What I've done so far:
1.) Copy the function body into the event handler for my "buy" button.
2.) Copy the WindowsStoreProxy.xml from the working sample to replace the one in my project.
3.) Double and triple checked that trial mode is false.
Note:
CurrentAppSimulator.RequestProductPurchaseAsync("product2");
Does not bring up the gui to select a return code in my project code (it did in the sample). Changing "product2" to "2" fixed that problem. However, when the awaited RequestProductPurchaseAsync returns, the following expression:
licenseInformation.ProductLicenses["2"].IsActive
is still false when in the sample says it should be true, so my code never succeeds.
Are you reading the WindowsStoreProxy.xml into the Simulator?
StorageFolder proxyDataFolder = await Package.Current.InstalledLocation.GetFolderAsync("data");
StorageFile proxyFile = await proxyDataFolder.GetFileAsync("WindowsStoreProxy.xml");
await CurrentAppSimulator.ReloadSimulatorAsync(proxyFile);
Related
As the title says, I have my Bot created inside the Bot Framework Composer and would like to be able to manually call (BeginDialogAsync) those dialogs in C# inside something like a bot component where I have access to DialogContext.
Some context: The whole reason why I would want this is because, for whatever reason, there doesn't seem to be a way to use the composer action "Begin a new dialog" where I can assign it a property containing the name of the Dialog I wish to Start(Even though it has an "expression" type of input). The alternative is to predefine 60 different "Begin a new dialog" actions, which is not feasible.
I have googled this extensively and have found several solutions however none of them seem to be working for the newest version of Bot Framework Composer 2.x and Bot Framework SDK 4.x
Things I have tried usually revolved around loading the ".dialog" file using ResourceExplorer. My last ditch attempt was to load and cast that ".dialog" file as AdaptiveDialog, however that just throws the error:
Could not create an instance of type Microsoft.Bot.Builder.Dialogs.Dialog. Type is an interface or abstract class and cannot be instantiated.
Sample code:
private void startDialogTest(DialogContext dc, CancellationToken cancellationToken, string dialogName)
{
var dialogResource = _resourceExplorer.GetResource($"{dialogName}.dialog");
var composerDialog = _resourceExplorer.LoadType<AdaptiveDialog>(dialogResource);
dc.Dialogs.Add(composerDialog);
dc.BeginDialogAsync(dialogName, cancellationToken: cancellationToken);
}
I understand why it happened because there is simply not enough information and it does not know what the heck to deserialize that Json into since Dialog is an abstract class.
If anybody has a sample code or a github link that does what I want I would be very grateful.
I have found a solution to my problem a few days ago.
The reason why assiging a property to "Begin a new dialog" action did not work is not because the "expression input" itself didn't work but because doing it that way skips 1 crucial step for hoping to another dialog to even work at all.
Inside that dialog json root(Click "Show code" option) you need to define an array containing the names of all dialogs you wish to be able to jump to.
Example:
Let's assume we have dialogs named TestDialogA, TestDialogB and TestDialogC.
We want dialog TestDialogA to be able to able to start TestDialogB or TestDialogC. The way to do this is to open the json code of TestDialogA and at the root define a property called "dialogs" where you will insert TestDialogB and TestDialogC, like so:
{
"$kind": "Microsoft.AdaptiveDialog",
----------------------------------------------------------- Insert Here
"dialogs": [
"TestDialogB",
"TestDialogC"
],
---------------------------------------------------------- Insert Here
"$designer": {
"id": "s8Uwor",
"name": "TestDialogA",
"comment": ""
}
This is actually what "Begin a new dialog" is suppose to do and is what it does when you manually hardcode/select a dialog but it does not do that if you send it a property containing the value of the Dialog you wish to jump to.
Likely to do with it having to know what dialog "Begin a new dialog" will jump to during compile time and not runtime as then it is too late.
This is a crucial step as without it TestDialogA does not even know that TestDialogB and TestDialogC exist. Same goes if you wish to jump to TestDialogA from TestDialogB.
Has anyone seen any documentation on the WebView2 DevToolsProtocolHelper?
In another question I asked (How do I programmatically add a file to a fileupload control from a windows form to a webpage) it was suggested that I download and use the Microsoft.Web.WebView2.DevToolsProtocolExtensions. At first it seemed like it was going to be very straight forward to use but not so much.
Win forms App using c# and webview2
DevToolsProtocolHelper helper = webView21.CoreWebView2.GetDevToolsProtocolHelper()
Task<DOM.Node> t = helper.DOM.GetDocumentAsync();
Task<int> querySelectorResponse = helper.DOM.QuerySelectorAsync(t.Result.NodeId, "#fileupload");
_ = helper.DOM.SetFileInputFilesAsync(new string[] { filename }, querySelectorResponse.Result);
These 4 lines of code should get the document and search for the node fileupload. I get nothing but errors and I have not seen any real examples or documentation on this.
Any help would be greatly appreciated.
**** UPDATE *****
DevToolsProtocolHelper helper = webView21.CoreWebView2.GetDevToolsProtocolHelper();
DOM dom = helper.DOM;
DOM.Node t = await dom.GetDocumentAsync(-1,true);
int querySelectorResponse = await dom.QuerySelectorAsync(t.NodeId, "#fileupload");
_ = helper.DOM.SetFileInputFilesAsync(new string[] { filename }, t.NodeId);
Here is the latest version of my code and it seems I have made progress. When I used CEFSHARP, the IDs I got back from Document and the #fileUpload were always the same and it worked in uploading the file.
With this code above, I am getting IDs but they are always different and I am not getting the file to upload.
Another update, when I run this code (from a button click on the winform) a second time, I do get the proper ID (504) for the int querySelectorResponse = await dom.QuerySelectorAsync(t.NodeId, "#fileupload") line of code. Again, still not getting the file to upload to the page.
Again, any help would be greatly appreciated
The GetDevToolsProtocolHelper documentation is the 'How to' article on Using Chromium DevTools Protocol in WebView2.
Separately, you cannot use Task.Result with WebView2 tasks which I see you doing in the above code. WebView2 can only be used from the UI thread its created on and requires that UI thread to communicate task completions. You should be able to use await instead.
Failing to raise an azure VM from a marketplace image programatically.
The code:
var linuxVM = await _azure.VirtualMachines.Define(linuxVmName)
.WithRegion(Region)
.WithExistingResourceGroup(rgName)
.WithNewPrimaryNetwork("10.0.0.0/28")
.WithPrimaryPrivateIPAddressDynamic()
.WithoutPrimaryPublicIPAddress()
.WithSpecificLinuxImageVersion(new ImageReference())
.WithRootUsername(userName)
.WithRootPassword(password)
.WithSize(VirtualMachineSizeTypes.StandardNC6sV3)
.WithPlan(new PurchasePlan("nvidia", "ngc-base-version-20-10-1", "ngc_azure_17_11"))
.CreateAsync();
In Azure I've enabled "Want to deploy programmatically? Get started" for the given image (as explained here).
There are several options as to the method that selects the image, not sure which method should be used and with which parameters. Tried several combinations, but all returned misc error messages.
Did not find code samples more detailed this (which does not explain how to use an image from the marketplace).
Edit:
The code above returns this exception:
Microsoft.Rest.Azure.CloudException: 'This resource was created without a plan. A new plan cannot be associated with an update.'
Another attempt with more populated parameters causes the same exception:
.WithSpecificLinuxImageVersion(new ImageReference(new ImageReferenceInner(
publisher: "nvidia",
offer: "ngc_azure_17_11",
sku: "ngc-base-version-20-10-1"
)))
The missing parameter was the image's version. The code to raise the image looks like so:
var vm = await _azure.VirtualMachines.Define(linuxVmName)
.WithRegion(_region)
.WithExistingResourceGroup(_rgName)
.WithNewPrimaryNetwork("10.0.0.0/28")
.WithPrimaryPrivateIPAddressDynamic()
.WithoutPrimaryPublicIPAddress()
.WithSpecificLinuxImageVersion(new ImageReference(new ImageReferenceInner(
publisher: "nvidia",
offer: "ngc_azure_17_11",
sku: "ngc-base-version-20-10-1",
version: "20.10.1"
)))
.WithRootUsername(userName)
.WithRootPassword(password)
.WithSize(VirtualMachineSizeTypes.StandardNC6sV3)
.WithPlan(new PurchasePlan("nvidia", "ngc-base-version-20-10-1", "ngc_azure_17_11"))
.CreateAsync();
The version can be found in the UI:
It's also possible to get all the image's details via CLI:
Get-AzVMImageOffer -Location "West Europe" -PublisherName nvidia
A fuller guide can be found here
Edit
I found out, that the requirements for showing a notification consist of setting a content-title, a context-text and a small icon. The last of which I do not do. Unfortunately, I don't know, how to provide a small icon especially in unity.
Original Question
I'm currently trying to show a notification from a unity-instance via android. I want to show the notification, when the user enters a specific gps-area. Thus, the script should run, when the app is paused. That's why I want to use the android-functionality.
With this code, I currently try to show the notification manually:
public void createNotification(){
NotificationManagerCompat nManager = NotificationManagerCompat.from(curContext);
NotificationCompat.Builder builder = new NotificationCompat.Builder(curContext, CHANNEL_ID)
.setContentTitle("Stuff")
.setContentText("MoreStuff")
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
nManager.notify(1551, builder.build());
}
The context is stored in a static variable and is set, when calling the method.
The function is called in C# with:
PluginInstance.Call("createNotification");
The PluginInstance works, the function can be called, but I get the error:
AndroidJavaException: java.lang.NoClassDefFoundError: Failed resolution of: Landroidx/core/app/NotificationManagerCompat
I found the solution for my problem: I used the Unity Android Jar-Resolver in which I provided the *Dependencies.xml (Where the * presents the Name of my project). In the *Dependenices.xml I specified: <androidPackage spec="androidx.appcompat:appcompat:1.1.0"> and run through the steps, provided in the Tutorial of the Resolver.
Afterwards, multiple dependencies appeared in my /Assets/Plugin/Android-Folder, which were successfully transferred to the app, when building it.
I am coming back to work on a BOT that scraped data from a site once a day for my personal use.
However they have changed the code during COVID and now it seems they are loading in a lot of the content with Ajax/JavaScript.
I thought that if I did a WebRequest and obtained the response HTML from a URL, it should match the same content that I see in a browser (FF/Chrome) when I right click and "view source". I thought the actual DOM and generated source code would come later when those files were loaded as onload events fired, scripts lazily loaded and so on.
However the source HTML I obtain with my BOT is NOT the same as the HTML I see when viewing the source code. So my regular expressions that find certain links are not available to me.
Why am I seeing a difference between "view source" and a download of the HTML?
I can only think that when the page loads, SCRIPTS run that load other content into the page and that when I view source I am actually seeing a partial generated source rather than the original source code. Therefore is there a way I can call the page with my BOT, wait X seconds before obtaining the response to get this "onload" generated HTML?
Or even better a way for MY BOT (not using someone elses), to view generated source.
This BOT runs as a web service. I can find another site to scrape but it's just painful when I have all the regular expressions working on the source I see, except it's NOT the source my BOT obtains.
A bit confused at why my browser is showing me more content with a view source (not generated source), than my BOT gets when making a valid request.
Any help would be much appreciated this is almost an 8 year project that I have been doing on/off and this change has ruined one of the core parts of the system.
In response to OP's comment, here is the Java code for how to click at different parts on the screen to do this:
You could use Java's Robot class. I just learned about it a few days ago:
// Import
import java.awt.Robot;
// Code
void click(int x, int y, int btn) {
Robot robot = new Robot();
robot.mouseMove(x, y);
robot.mousePress(btn);
robot.mouseRelease(btn);
}
You would then run the click function with the x and y position to click, as well as the button (MouseEvent.BUTTON1, MouseEvent.BUTTON2, etc.)
After stringing together the right positions (this will vary depending on the screen) you could do just about anything.
To use shortcuts, just use the keyPress and keyRelease functions. Here is a good way to do this:
void key(int keyCode, boolean ctrl, boolean alt, boolean shift) {
if (ctrl)
robot.keyPress(KeyEvent.VK_CONTROL);
if (alt)
robot.keyPress(KeyEvent.VK_ALT);
if (shift)
robot.keyPress(KeyEvent.VK_SHIFT);
robot.keyPress(keyCode);
robot.keyRelease(keyCode);
if (ctrl)
robot.keyRelease(KeyEvent.VK_CONTROL);
if (alt)
robot.keyRelease(KeyEvent.VK_ALT);
if (shift)
robot.keyRelease(KeyEvent.VK_SHIFT);
}
Thus, something like Ctrl+Shift+I to open the inspect menu would look like this:
key(KeyEvent.VK_I, true, false, true);
Here are the steps to copy a website's code (from the inspector) with Google Chrome:
Ctrl + Shift + I
Right click the HTML tag
Select "Edit as HTML"
Ctrl + A
Ctrl + C
Then, you can use the technique from this StackOverflow to get the content from the clipboard:
Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
String text = (String) c.getData(DataFlavor.stringFlavor);
Using something like FileOutputStream to put the info into a file:
FileOutputStream output = new FileOutputStream(new File( PATH HERE ));
output.write(text.getBytes());
output.close();
I hope this helps!
I have seemed to have fixed it by just turning on the ability to store cookies in my custom HTTP (Bot/Scraper) class, that was being called from the class trying to obtain the data. Probably the site has a defense system to prevent visitors requesting pages and not the JS/CSS with a different session ID on each request.
However I would like to see some other examples because if it is just cookies then they could use JavaScript to test for JavaScript e.g an AJAX call to log if JS is actually on or some DOM manipulation to determine if you are really Human or not which would break it again.
Every site uses different methods to prevent scrapers, email harvesters, job rapists, link harvesters etc inc working out the standard time between requests for 100% verifiable humans and BOTS and then using those values to help determine spoofed user-agents etc. I wrote a whole system to stop BOTS at my last place of work and its a layered approach, just glad the cookies being enabled solved it on this site but it could easily be beefed up with other tricks to test for BOTS vs HUMANS.
I do know some Java, enough to work out what is going on anyway. My BOT is in C#.