UWP: GetFileAsync on a partial path? - c#

I'm trying to get a single file in an UWP based on its partial name. Basically, I want to select a file that starts with "latest_" in a given folder.
Right now I can do that with that command:
var previousInfo = (await rootFolder.GetFilesAsync()).Where(file => file.DisplayName.StartsWith("latest_")).FirstOrDefault();
I suppose this code is not very efficient if there are a lot of files in the folder...
Is there a simpler way to do this? Like:
var previousInfo2 = await rootFolder.GetFileAsync("latest_*");
Or:
var previousInfo2 = await rootFolder.GetFileAsync(#"latest_*");
Right now this code is throwing an exception (invalid parameter). And the MSDN documentation about this function is very light: it just says that the function takes a string as parameter...
Thanks!

You can do this by using Advanced Query Syntax and in fact, you can filter/search by many more file metadata. Below is an example for search based on File Name.
var queryOptions = new QueryOptions();
queryOptions.ApplicationSearchFilter = "System.FileName:latest_*";
StorageFileQueryResult queryResult = rootFolder.CreateFileQueryWithOptions(queryOptions);
var files = await queryResult.GetFilesAsync();

Related

How to get text out of ElementHandle?

Using PuppeteerSharp, I am trying to get the text of the element.
ElementHandle elementHandle = await page.XPathAsync("//html/body/div[1]/section/div/section/h2")[0];
Now that I have the element handle, how do I actually get the text from it? I don't see any obvious methods. I would have expected TextAsync or something similar, but I don't see it.
Using PuppeteerSharp 5.0.
You can call EvaluateFunction passing that ElementHandle as an argument
var content = await Page.EvaluateFunctionAsync<string>("e => e.textContent", elementHandle);
If you have many scenarios like that, you can build an extension method to solve that for you ;)
#Botan, thank you!
I have tried (in VB.NET) and found:
(Await elementhandle.GetPropertyAsync("innerText")).ToString
result: "JSHandle:foo", but
(Await elementhandle.GetPropertyAsync("innerText")).RemoteObject.Value.ToString
result: "foo"
If your are after a strongly typed API for use with Puppeteer Sharp then you can use PuppeteerSharp.Dom which is available on Nuget.org.
// Add using PuppeteerSharp.Dom to access the extension methods
ElementHandle elementHandle = await page.XPathAsync("//html/body/div[1]/section/div/section/h2")[0];
// Create a strongly typed HtmlHeadingElement object
var headingElement = elementHandle.ToDomHandle<HtmlHeadingElement>();
// You'll now have context specific methods relevant to HtmlHeadingElement
//Get TextContent via the async method
var textContext = await headingElement.GetTextContentAsync();
var innerText = await headingElement.GetInnerTextAsync();
There's a number of QuerySelector extension methods also, so you can avoid the ToDomHandle method if you are using a query selector.
var element = await page.QuerySelectorAsync<HtmlElement>("#myElementId");
There are more examples on the GitHub page.

Updating a file in GitHub repository using Octokit

I am trying to develop a windows forms application that can create, update and delete files in a GitHub repository using Octokit.
public Form1()
{
InitializeComponent();
var ghClient = new GitHubClient(new ProductHeaderValue("Octokit-Test"));
ghClient.Credentials = new Credentials("-personal access token here-");
// github variables
var owner = "username";
var repo = "repository name";
var branch = "master";
// create file
//var createChangeSet = ghClient.Repository.Content.CreateFile(owner,repo,"path/file2.txt",new CreateFileRequest("File creation", "Hello World!", branch));
// update file
var updateChangeSet = ghClient.Repository.Content.UpdateFile(owner, repo,"path/file2.txt", new UpdateFileRequest("File update","Hello Universe!", "SHA value should be here", branch));
}
Firstly, I managed to create a file (check the commented out code), which is fully functional. Then I tried to update that file using,
var updateChangeSet = ghClient.Repository.Content.UpdateFile(owner, repo,"path/file2.txt", new UpdateFileRequest("File update","Hello Universe!", "SHA value should be here", branch));
As you can see, in this situation, I have to get the sha value since the requirement for the "UpdateFileRequest" is,
UpdateFileRequest(string message, string content, string sha, string branch)
How can I receive this Sha value for my file from GitHub?
I am following this tutorial but when I try "createChangeSet.Content.Sha"(without commenting out createChangeSet), it draws a red line underneath "Content" and says,
Task<RepositoryChangeSet> does not contain a definition for 'Content' and no extention method 'Content' accepting a first argument of type Task<RepositoryChangeSet> could be found
I looked at GitHub Documentation and it says I should use,
GET /repos/:owner/:repo/contents/:path
to return the contents of a file or directory in a repository so I assume I will be able to obtain the sha value this way.
How can I implement this method to receive the sha value for my file in the repository so I can use that value to update the file?
I had the same problem and to get the sha you will need to get the existing file first and with this file you also get the last commit sha, which can be used to update the file.
Full demo code:
var ghClient = new GitHubClient(new ProductHeaderValue("Octokit-Test"));
ghClient.Credentials = new Credentials("//...//");
// github variables
var owner = "owner";
var repo = "repo";
var branch = "branch";
var targetFile = "_data/test.txt";
try
{
// try to get the file (and with the file the last commit sha)
var existingFile = await ghClient.Repository.Content.GetAllContentsByRef(owner, repo, targetFile, branch);
// update the file
var updateChangeSet = await ghClient.Repository.Content.UpdateFile(owner, repo, targetFile,
new UpdateFileRequest("API File update", "Hello Universe! " + DateTime.UtcNow, existingFile.First().Sha, branch));
}
catch (Octokit.NotFoundException)
{
// if file is not found, create it
var createChangeSet = await ghClient.Repository.Content.CreateFile(owner,repo, targetFile, new CreateFileRequest("API File creation", "Hello Universe! " + DateTime.UtcNow, branch));
}
I'm not sure if there is a better way to do it - if the searched file is not found an exception is thrown.
But it seems to work that way.

Api for working with a classes as OOP?

I'm writing a 3rd party app that needs to read in .cs files and be able to manipulate classes, then ultimately save back to file.
The type of code I am looking at would be something like:
var classManager = new classManager();
var classes = classManager.LoadFromFile(filePath);
var class = classes[0]; // Just illustrating more than 1 class can exist in a file
var prop = new ClassProperty {Type=MyType.GetType() };
prop.AddGet("return x+y < 50");
//stuff like prop.ReadOnly = true;
class.AddProperty(prop);
var method = new ClassMethod {signature="int id, string name"};
method.MethodBody = GetMethodBodyAsString(); //not writing out an entire method body here
class.AddMethod(method);
class.SaveToFile(true); //Format code
Does such a library exist?
The .NET Compiler Platform Roslyn is what you're looking for. It supports parsing and editting cs files. Check out this post for an example

Modify programatically csproj files with Microsoft.Build.Evaluation (instead of Engine)

I would like to read, modify and write back csproj files.
I've found this code, but unfortunately Engine class is depreciated.
Engine engine = new Engine()
Project project = new Project(engine);
project.Load("myproject.csproj");
project.SetProperty("SignAssembly", "true");
project.Save("myproject.csproj");
So I've continued based on the hint I should use Evaluation.ProjectCollection instead of Engine:
var collection = new ProjectCollection();
collection.DefaultToolsVersion = "4.0";
var project = new Project(collection);
// project.Load("myproject.csproj") There is NO Load method :-(
project.FullPath = "myproject.csproj"; // Instead of load? Does nothing...
// ... modify the project
project.Save(); // Interestingly there is a Save() method
There is no Load method anymore. I've tried to set the property FullPath, but the project still seems empty. Missed I something?
(Please note I do know that the .csproj file is a standard XML file with XSD schema and I know that we could read/write it by using XDocument or XmlDocument. That's a backup plan. Just seeing the .Save() method on the Project class I think I missed something if I can not load an existing .csproj. thx)
I've actually found the answer, hopefully will help others:
Instead of creating a new Project(...) and trying to .Load(...) it, we should use a factory method of the ProjectCollection class.
// Instead of:
// var project = new Project(collection);
// project.FullPath = "myproject.csproj"; // Instead of load? Does nothing...
// use this:
var project = collection.LoadProject("myproject.csproj")
Since i can't comment:
This won't work in .net core without first setting the MSBuild.exe path variable. The code to do so can be found here
https://blog.rsuter.com/missing-sdk-when-using-the-microsoft-build-package-in-net-core/
and is written here
private static void SetMsBuildExePath()
{
try
{
var startInfo = new ProcessStartInfo("dotnet", "--list-sdks")
{
RedirectStandardOutput = true
};
var process = Process.Start(startInfo);
process.WaitForExit(1000);
var output = process.StandardOutput.ReadToEnd();
var sdkPaths = Regex.Matches(output, "([0-9]+.[0-9]+.[0-9]+) \\[(.*)\\]")
.OfType<Match>()
.Select(m => System.IO.Path.Combine(m.Groups[2].Value, m.Groups[1].Value, "MSBuild.dll"));
var sdkPath = sdkPaths.Last();
Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", sdkPath);
}
catch (Exception exception)
{
Console.Write("Could not set MSBUILD_EXE_PATH: " + exception);
}
}

A failing minimal example of executing JS in Win 8.1 Chakra with C#

I'm attempting to execute a tiny piece of JS via the following code (utilising the Native class from the Chakra Host example from MSDN):
var runtime = default(JavaScriptRuntime);
Native.ThrowIfError(Native.JsCreateRuntime(JavaScriptRuntimeAttributes.None, JavaScriptRuntimeVersion.VersionEdge, null, out runtime));
var context = default(JavaScriptContext);
Native.ThrowIfError(Native.JsCreateContext(runtime, (Native.IDebugApplication64)null, out context));
Native.ThrowIfError(Native.JsSetCurrentContext(context));
var script = #"var bob = 1;";
var result = default(JavaScriptValue);
var contextCookie = default(JavaScriptSourceContext);
Native.ThrowIfError(Native.JsRunScript(script, contextCookie, "source", out result));
The problem is that it returns a "ScriptCompile" error with no additional details that I'm able to spot.
Is anyone able to reveal what I've missed / done dumb / gotten confused over?
I doubt you're still wrestling with this... but I just did and figured out the answer.
If you look in jsrt.h you'll see that all the native functions use a wchar_t when using string parameters, however the DllImport attribute doesn't specify the charset, so it defaults to ANSI.
I did a find/replace in the Native.cs file and changed all the DllImport attributes to read...
[DllImport("jscript9.dll", CharSet = CharSet.Unicode)]
... and now my code works fine. I've sent a pull request to the sample owner on GitHub to get this fixed up. The update is currently in my fork at https://github.com/billti/chakra-host
Try adding this to your AssemblyInfo.cs file:
[module: DefaultCharSet(CharSet.Unicode)]
I modified my implementation of Native.ThrowIfError to, in the case of a ScriptCompile error, get some values out of the errorObject. Like so:
var message = errorObject
.GetProperty("message")
.ToString();
var source = errorObject
.GetProperty("source")
.ToString();
var line = (int)errorObject
.GetProperty("line")
.ToDouble();
var column = (int)errorObject
.GetProperty("column")
.ToDouble();
var length = (int)errorObject
.GetProperty("length")
.ToDouble();
throw new JavaScriptParseException(error, message, source, line, column, length);
This should get you more information at least.

Categories

Resources