C# Mono Linux - Grab contents of global clipboard - c#

I am trying to simply "grab" text from the clipboard and put into a variable. I'm having a lot of trouble doing this. I've tried to use
Gtk.Clipboard.Get(Gdk.Atom.Intern("PRIMARY", true))
The code that I have so far, just returns "Gtk.Clipboard" to TextBox entry1.
Gtk.Clipboard clipboard = Gtk.Clipboard.Get(Gdk.Atom.Intern("PRIMARY", true));
string textClip = clipboard.ToString ();
entry1.Text = textClip;
So I am unable to do anything productive with this.

Try this piece of code to get text from system clipboard;
Gtk.Clipboard clipboard = Gtk.Clipboard.Get(Gdk.Atom.Intern("CLIPBOARD", false));
var text = clipboard.WaitForText();
For more information mono documentation

You could also have used the klipper DBus-interface.
That way, you can avoid a dependency on GTK#.
Here's the code for the Klipper DBus-Interface (a bit large for stackoverflow): https://pastebin.com/HDsRs5aG
And the abstract class:
https://pastebin.com/939kDvP8
And the actual clipboard-code (requires Tmds.Dbus - for handling DBus)
using System.Threading.Tasks;
namespace TestMe
{
using NiHaoRS; // TODO: Rename namespaces to TestMe
public class LinuxClipboard
: GenericClipboard
{
public LinuxClipboard()
{ }
public static async Task TestClipboard()
{
GenericClipboard lc = new LinuxClipboard();
await lc.SetClipboardContentsAsync("Hello KLIPPY");
string cc = await lc.GetClipboardContentAsync();
System.Console.WriteLine(cc);
} // End Sub TestClipboard
public override async Task SetClipboardContentsAsync(string text)
{
Tmds.DBus.ObjectPath objectPath = new Tmds.DBus.ObjectPath("/klipper");
string service = "org.kde.klipper";
using (Tmds.DBus.Connection connection = new Tmds.DBus.Connection(Tmds.DBus.Address.Session))
{
await connection.ConnectAsync();
Klipper.DBus.IKlipper klipper = connection.CreateProxy<Klipper.DBus.IKlipper>(service, objectPath);
await klipper.setClipboardContentsAsync(text);
} // End using connection
} // End Task SetClipboardContentsAsync
public override async Task<string> GetClipboardContentAsync()
{
string clipboardContents = null;
Tmds.DBus.ObjectPath objectPath = new Tmds.DBus.ObjectPath("/klipper");
string service = "org.kde.klipper";
using (Tmds.DBus.Connection connection = new Tmds.DBus.Connection(Tmds.DBus.Address.Session))
{
await connection.ConnectAsync();
Klipper.DBus.IKlipper klipper = connection.CreateProxy<Klipper.DBus.IKlipper>(service, objectPath);
clipboardContents = await klipper.getClipboardContentsAsync();
} // End Using connection
return clipboardContents;
} // End Task GetClipboardContentsAsync
} // End Class LinuxClipBoardAPI
} // End Namespace TestMe
AsyncEx is required in the abstract class for synchronizing in the get/set property.
AsyncEx not required for the actual clipboard handling, as long as you don't want to utilize the get/set clipboard contents in a synchronous context.
Note: klipper must be running (which it is, if you use KDE).

Related

C# Invalid FORMATETC structure when using GetTextAsync

I'm trying to make a progam which automatically searches for the word I copied in a file and then replaces that word in the clipboard with the line on which it was found in my file. I successfully setup an Eventhandler to see when the clipboard changes. I'm now trying to implement a way of reading my file.
After trying to use the StringReader the Exception is thrown:
Invalid FORMATETC structure occurred.
This is my code right now:
public partial class MainWindow : System.Windows.Window
{
string line;
string currentClipboardContent;
string expectedClipboardContent;
string vocabularygerman = Properties.Resources.vocabularygerman;
string vocabularyfrench = Properties.Resources.vocabularyfrench;
int lineNumber;
public MainWindow()
{
InitializeComponent();
Windows.ApplicationModel.DataTransfer.Clipboard.ContentChanged += new EventHandler<object>(this.TrackClipboardChanges_EventHandler);
}
private async void TrackClipboardChanges_EventHandler(object sender, object e)
{
DataPackageView dataPackageView = Windows.ApplicationModel.DataTransfer.Clipboard.GetContent();
if (dataPackageView.Contains(StandardDataFormats.Text))
{
currentClipboardContent = await dataPackageView.GetTextAsync();
if (expectedClipboardContent != currentClipboardContent)
{
Thread.Sleep(500);
using (var reader = new StringReader(vocabularygerman))
{
lineNumber = 0;
while ((line = reader.ReadLine()) != null)
{
lineNumber++;
if (line.Contains(currentClipboardContent))
{
System.Windows.Forms.Clipboard.SetDataObject(lineNumber);
break;
}
}
}
expectedClipboardContent = System.Windows.Forms.Clipboard.GetText();
}
}
}
Everything worked fine until I tried to use the StringReader. I'm thinking of ditching the stringreader altogether and using a streamreader, but I am not able to use my vocabularygerman.txt file in my resources.
StringReader does not implement the IDataObject interface so SetDataObject method wont like that as it depends on that interface being present.
Try
Clipboard.SetText(lineNumber.ToString())
instead if you need the StringReader.
PS: use await for async calls

Error when creating ServiceBus Queue using Azure.Messaging.ServiceBus.Administration

I am (trying) to use this code to create ServiceBus Queue:
using Azure.Messaging.ServiceBus;
using Azure.Messaging.ServiceBus.Administration;
...
class blabla
{
private string connectionString = "Endpoint=sb://XXXX.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=XXXYYY";
private string queueName = "testqueue";
...
public doit()
{
var adminClient = new ServiceBusAdministrationClient(connectionString);
bool queueExists = adminClient.QueueExistsAsync(queueName).Result;
if (!queueExists)
{
var options = new CreateQueueOptions(queueName)
{
DefaultMessageTimeToLive = TimeSpan.FromDays(2),
LockDuration = TimeSpan.FromSeconds(45),
MaxDeliveryCount = 8,
MaxSizeInMegabytes = 2048
};
options.AuthorizationRules.Add(new SharedAccessAuthorizationRule(
"allClaims",
new[] { AccessRights.Manage, AccessRights.Send, AccessRights.Listen }));
QueueProperties createdQueue = adminClient.CreateQueueAsync(options).Result;
}
}
}
but constantly getting this error:
System.AggregateException: One or more errors occurred. (SubCode=40900. Conflict. You're requesting an operation that isn't allowed in the resource's current state. To know more visit https://aka.ms/sbResourceMgrExceptions. . TrackingId:bc79fd98-73c8-4301-b6b9-05d0eae6ed6a_G17, SystemTracker:xxx.servicebus.windows.net:yyy, Timestamp:2021-05-09T00:24:57
Status: 409 (Conflict)
ErrorCode: 40900
Using old (NET) way with NamespaceManager from Microsoft.ServiceBus works with no problems.
var namespaceManager = NamespaceManager.CreateFromConnectionString(connectionString);
if (!namespaceManager.QueueExists(queueName))
{
namespaceManager.CreateQueue(queueName);
}
So, does anyone knows what am I doing wrong here?
*
Below is the updated working code, you need to make sure you have shared access policy with full access.
using Azure.Messaging.ServiceBus.Administration;
using System;
using System.Threading.Tasks;
namespace ServiceBusDemo
{
class Program
{
private static string connectionString = "Endpoint=sb://ns-servicebusshu.servicebus.windows.net/;SharedAccessKeyName=fullAccess;SharedAccessKey=oB+IsK8Aqp0/xfXnF9HCz6x9pqPIOysTXaJofSmHEYs=";
private static string queueName = "testqueue";
async static Task Main(string[] args)
{
await doit();
}
public static async Task doit()
{
var adminClient = new ServiceBusAdministrationClient(connectionString);
bool queueExists = await adminClient.QueueExistsAsync(queueName);
if (!queueExists)
{
var options = new CreateQueueOptions(queueName)
{
DefaultMessageTimeToLive = TimeSpan.FromDays(2),
LockDuration = TimeSpan.FromSeconds(45),
MaxDeliveryCount = 8,
MaxSizeInMegabytes = 2048
};
options.AuthorizationRules.Add(new SharedAccessAuthorizationRule("allClaims", new[] { AccessRights.Manage, AccessRights.Send, AccessRights.Listen }));
QueueProperties createdQueue = await adminClient.CreateQueueAsync(options);
}
}
}
}
Once you ran the application its successfully created the queue as below :
Maybe it's not your case... But if you have a TOPIC with the same name that you try to create your new QUEUE, QueueExistsAsync will return false, but you'll be spitted with this bizarre error at creation time. The fix is easy... changing the queue name or deleting the offending topic.
Sorry for the confusion.
My code (and Rahul Shukla as well) is working now (????).
I had to create a few new shared access policies with full access (????).
The third created started working (??).
The previous 2 I created are still not working (????).
There are no differences between the 3 policies created. Hence the question marks in my answer.
Posted question on MS NET SB forum about 1 out of 3 policies working. No answer/acknowledgment so far.

How to get list of files from a specific GitHub repo given a link in C#?

How can I get a list of file from GitHub link?
For example, from this GitHub repository link: https://github.com/crs2007/ActiveReport/tree/master/ActiveReport/SQLFiles
We can see that there are SQL text files:
I would like to get a list of these files:
CorruptionIssues.sql
DBAlert.sql
DataBaseInfo.sql
DatabaseDefaultLogin.sql
DatabaseFiles.sql
Deadlock.sql
DefaultTrace.sql
DiskInfo.sql
InstalledPrograms.sql
.etc...sql
How can I do that?
You should be able to use GitHub Contents API
By making a request like:
curl https://api.github.com/repos/crs2007/ActiveReport/contents/ActiveReport
Github will return JSON containing directory contents.
You can do this in C# in multiple ways, using something like Octokit is probably recommended as they ironed out most issues you're likely to encounter. In case you can't use an external library, the example below shows how to use plain HttpClient to achieve the same, albeit with a lot more plumbing involved:
class Program
{
static void Main()
{
Task.Factory.StartNew(async () =>
{
var repoOwner = "crs2007";
var repoName = "ActiveReport";
var path = "ActiveReport";
var httpClientResults = await ListContents(repoOwner, repoName, path);
PrintResults("From HttpClient", httpClientResults);
var octokitResults = await ListContentsOctokit(repoOwner, repoName, path);
PrintResults("From Octokit", octokitResults);
}).Wait();
Console.ReadKey();
}
static async Task<IEnumerable<string>> ListContents(string repoOwner, string repoName, string path)
{
using (var client = GetGithubHttpClient())
{
var resp = await client.GetAsync($"repos/{repoOwner}/{repoName}/contents/{path}");
var bodyString = await resp.Content.ReadAsStringAsync();
var bodyJson = JToken.Parse(bodyString);
return bodyJson.SelectTokens("$.[*].name").Select(token => token.Value<string>());
}
}
static async Task<IEnumerable<string>> ListContentsOctokit(string repoOwner, string repoName, string path)
{
var client = new GitHubClient(new ProductHeaderValue("Github-API-Test"));
// client.Credentials = ... // Set credentials here, otherwise harsh rate limits apply.
var contents = await client.Repository.Content.GetAllContents(repoOwner, repoName, path);
return contents.Select(content => content.Name);
}
private static HttpClient GetGithubHttpClient()
{
return new HttpClient
{
BaseAddress = new Uri("https://api.github.com"),
DefaultRequestHeaders =
{
// NOTE: You'll have to set up Authentication tokens in real use scenario
// NOTE: as without it you're subject to harsh rate limits.
{"User-Agent", "Github-API-Test"}
}
};
}
static void PrintResults(string source, IEnumerable<string> files)
{
Console.WriteLine(source);
foreach (var file in files)
{
Console.WriteLine($" -{file}");
}
}
}

Fetching documentation of ISymbol from MetadataReference

I started learning about Roslyn Code Analysis recently. I went through provided sample codes. My question is following:
Is there a way how to get XML documentation comment of a symbol loaded from a referenced library?
Sample code I worked with is FAQ(7). The goal is to get documentation comment of, let us say, a Console.Write function.
public void GetWriteXmlComment()
{
var project1Id = ProjectId.CreateNewId();
var document1Id = DocumentId.CreateNewId(project1Id);
var mscorlib = MetadataReference.CreateFromFile(typeof(object).Assembly.Location);
var solution = new AdhocWorkspace().CurrentSolution
.AddProject(project1Id, "Project1", "Project1", LanguageNames.CSharp)
.AddMetadataReference(project1Id, mscorlib);
var declarations = SymbolFinder.FindDeclarationsAsync(solution.Projects.First(), "Write", true).Result;
var decFirst = declarations.First();
var commentXml = decFirst.GetDocumentationCommentXml();
}
The sample code works well for some methods - it gets the documentation text. But for methods, such as Console.Write, it uses NullDocumentationProvider and therefore returns empty string.
UPDATE
I have found I can load the MetadataReference with TestDocumentationProvider instance as following:
var mscorlib = MetadataReference.CreateFromFile(typeof(object).Assembly.Location,
default(MetadataReferenceProperties), new TestDocumentationProvider());
where TestDocumentationProvider implements Microsoft.CodeAnalysis DocumentationProvider abstract class.
private class TestDocumentationProvider : DocumentationProvider
{
protected override string GetDocumentationForSymbol(string documentationMemberID, CultureInfo preferredCulture, CancellationToken cancellationToken = default(CancellationToken))
{
// To-Be-Done
}
}
Now the question narrows to how to read documentation using documentationMemberID?
Update: In Roslyn 2.0 you can use XmlDocumentationProvider.CreateFromFile.
The only way I can think of is using Reflection to create a FileBasedXmlDocumentationProvider (or otherwise copying its implementation from GitHub). You'll also need to search for the reference assemblies, since the load location of the framework assemblies does not contain documentation.
private static MetadataReference FromType(Type type)
{
var path = type.Assembly.Location;
return MetadataReference.CreateFromFile(path, documentation: GetDocumentationProvider(path));
}
private static string GetReferenceAssembliesPath()
{
var programFiles =
Environment.GetFolderPath(Environment.Is64BitOperatingSystem
? Environment.SpecialFolder.ProgramFilesX86
: Environment.SpecialFolder.ProgramFiles);
var path = Path.Combine(programFiles, #"Reference Assemblies\Microsoft\Framework\.NETFramework");
if (Directory.Exists(path))
{
var directories = Directory.EnumerateDirectories(path).OrderByDescending(Path.GetFileName);
return directories.FirstOrDefault();
}
return null;
}
private static DocumentationProvider GetDocumentationProvider(string location)
{
var referenceLocation = Path.ChangeExtension(location, "xml");
if (File.Exists(referenceLocation))
{
return GetXmlDocumentationProvider(referenceLocation);
}
var referenceAssembliesPath = GetReferenceAssembliesPath();
if (referenceAssembliesPath != null)
{
var fileName = Path.GetFileName(location);
referenceLocation = Path.ChangeExtension(Path.Combine(referenceAssembliesPath, fileName), "xml");
if (File.Exists(referenceLocation))
{
return GetXmlDocumentationProvider(referenceLocation);
}
}
return null;
}
private static DocumentationProvider GetXmlDocumentationProvider(string location)
{
return (DocumentationProvider)Activator.CreateInstance(Type.GetType(
"Microsoft.CodeAnalysis.FileBasedXmlDocumentationProvider, Microsoft.CodeAnalysis.Workspaces.Desktop"),
location);
}
I've used something similar in RoslynPad.

Whats the correct way to dispose table adapters and data sets?

I've been working on a project that uses table adapters and datasets to access an access database. I'm near completion and ran code analysis from visual studio and it came up with some errors about needing to implement IDisposable on specific classes that I use these methods. While I've looked at a few different things on this about having a dispose method or using a using block, I'm not really sure how to make this work. The dataset and table adapters are created as global variables to be used by the whole class, many classes will call on other classes which will also use different table adapters and datasets. I've tried creating a Dispose method, but I don't know when to call it and I am wondering if it is called at the wrong time will it crash my program. Here is a sample of one of the classes that I need to implement Idisposable :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace recipeDataBase
{
class NewRecipe : IDisposable
{
recipiesNewDataSet recipeDataSet = new recipiesNewDataSet();
recipiesNewDataSetTableAdapters.RecipeTableAdapter recipeTableAdapter = new recipiesNewDataSetTableAdapters.RecipeTableAdapter();
recipiesNewDataSetTableAdapters.RecipeIngredientTableAdapter recipeIngredientTableAdapter = new recipiesNewDataSetTableAdapters.RecipeIngredientTableAdapter();
recipiesNewDataSetTableAdapters.RatingTableAdapter ratingTableAdapter = new recipiesNewDataSetTableAdapters.RatingTableAdapter();
recipeDataBase.recipiesNewDataSetTableAdapters.IngredientTableAdapter ingredientTableAdapter = new recipiesNewDataSetTableAdapters.IngredientTableAdapter();
private RecipeInfo newRecipe;
private RatingNum originalRatingNum;
private RatingNum newRating;
private RecipeInfo originalRecipe;
private string[] ingredients;
public NewRecipe(RecipeInfo incommingNewRecipe, RatingNum IncommingNewRating, string[] incommingIngredients)
{
newRecipe = incommingNewRecipe;
newRating = IncommingNewRating;
ingredients = incommingIngredients;
CreateNewRecipe();
UpdateNewRecipe();
}
public void CreateNewRecipe()
{
originalRatingNum = new RatingNum();
originalRecipe = new RecipeInfo();
originalRatingNum.cookingTime = 0;
originalRatingNum.easeOfCooking = 0;
originalRatingNum.familyRating = 0;
originalRatingNum.healthRating = 0;
originalRatingNum.userRating = 0;
ratingTableAdapter.Fill(recipeDataSet.Rating);
ratingTableAdapter.Insert(originalRatingNum.userRating, originalRatingNum.familyRating, originalRatingNum.healthRating, originalRatingNum.easeOfCooking, originalRatingNum.cookingTime);
Query getNewRecipeNumbers = new Query();
int newRatingNumber = getNewRecipeNumbers.newRatingNum();
originalRatingNum.ratingNum = newRatingNumber;
newRating.ratingNum = newRatingNumber;
newRecipe.ratingNum = newRatingNumber;
originalRecipe.recipeName = "newRecipe";
originalRecipe.nationality = "newRecipe";
originalRecipe.recipeEvent = "newRecipe";
originalRecipe.source = "newRecipe";
originalRecipe.type = "newRecipe";
originalRecipe.servings = "0";
originalRecipe.ratingNum = newRatingNumber;
recipeTableAdapter.Fill(recipeDataSet.Recipe);
recipeTableAdapter.Insert(originalRecipe.recipeName, originalRecipe.nationality, originalRecipe.recipeEvent, originalRecipe.source, originalRecipe.type, originalRecipe.servings, originalRecipe.ratingNum);
int newRecipeNum = getNewRecipeNumbers.newRecipeNum();
newRecipe.recipeNum = newRecipeNum;
originalRecipe.recipeNum = newRecipeNum;
recipeDataSet.AcceptChanges();
}
public void UpdateNewRecipe()
{
UpdateRatingNum updateRatingNum = new UpdateRatingNum(originalRatingNum, newRating);
UpdateRecipe updateRecipe = new UpdateRecipe(newRecipe, originalRecipe);
UpdateIngredients updateIngredients = new UpdateIngredients(ingredients);
UpdateRecipeIngredient updateRecpeIngredients = new UpdateRecipeIngredient(ingredients, newRecipe.recipeNum);
recipeDataSet.AcceptChanges();
}
public void Dispose()
{
ratingTableAdapter.Dispose();
recipeTableAdapter.Dispose();
recipeTableAdapter.Dispose();
ingredientTableAdapter.Dispose();
recipeDataSet.Dispose();
throw new NotImplementedException();
}
}
}
As you can see I did implement Idisposable and used the automatically created method to put all of the table adapters and dataset in there to be disposed, but how do I use it and where?
Thanks for the help
Craig
The normal pattern:
using (var nr = new NewRecipe() )
{
...
}
But a few notes here:
the IDisposable interfaces on DataSet and DataAdapter are dummies, you won't lose much when you skip them.
Your class has a dual role of Repository and Domain object. Consider separating it into 2 classes.
As mentioned in other answers the correct way to usage an object that implements IDisposable is withing a using block as follows:
using (var recipe = new NewRecipe())
{
//put your code that uses recipe here
}
What I would like to point out though is the correct implementation of the IDisposable pattern. Note that there is a complete example on the MSDN article for the IDisposable interface.
class Recipe : IDisposable
{
bool isDisposed = false;
TableAdapter myDisposableMember;
public void Dispose()
{
Dispose(true);
GC.SupressFinalize(this);
}
public virtual Dispose(bool isDisposing)
{
if (!isDisposed) //only clean up once
{
//clean up unmanaged resource here
//in this case we don't have any
//clean up managed resources (IE those that implemetn IDisposable only if
//Dispose() was called (not the case when invoked during finalisation)
if (isDisposing)
{
if(myDisposableMember == null)
{
myDisposableMember.Dispose()
myDisposablemember = null;
}
}
//mark this instance as cleaned up
isDisposed = true;
}
}
//if our class has any unmanaged resources you implement a destructor to guarantee
//that they're freed. We don't have any here so we don't implement it.
//~Recipe()
//{
// Dispose(false);
//}
}
Also note that you should NEVER throw an exception during finalization (IE: ~Recipe()). Consequently Dispose(bool) should NEVER throw an exception.
Correct way of using is using. Just don't take it in your hands -
using(DataAdapter ratingTableAdapter = new DataAdapter())
{
}
ratingTableAdapter will get disposed once the code comes out of the using block.

Categories

Resources