DataContractSerializer fails, null data - c#

I've got some code for Windows Phone 7, for a RSS app:
private RSSSettings DeserializeSettings(string data)
{
RSSSettings rsssettings;
try
{
var ser = new DataContractSerializer(typeof(RSSSettings));
using (var sr = new StringReader(data))
using (var xr = XmlReader.Create(sr))
rsssettings = (RSSSettings)ser.ReadObject(xr);
}
catch (Exception ex)
{
ex.ToString();
rsssettings = new RSSSettings() { Version = -1 };
}
return rsssettings;
}
It works perfectly on Windows Phone 7. I ported the app to Windows Phone 8, and everything else in the app works except for this snippet.
Comparing what happens in Windows Phone 7 and 8, "rsssettings" in WP8 remains null while it populates correctly in WP7. There have been no code changes to this portion of the code at all.
Everything works the same until:
rsssettings = (RSSSettings)ser.ReadObject(xr);
The exception is not called.
Anyone have a clue as to how to resolve this frustrating issue?

Yeah, you're not going to like this.
DataContractSerializer on WP8 requires XML elements be organized alphabetically. That's done since the assumption that everything that goes into DataContractSerializer comes out of another DataContractSerializer.
I wish I was making this up, but I'm not. From MSDN's App platform compatibility for Windows Phone:
DataContractSerializer class
WP8 Behaviour: XML elements must be sorted alphabetically.
WP7 Behaviour: XML elements can be unordered.
There are a few alternatives for you at this point:
̶a̶l̶p̶h̶a̶b̶e̶t̶i̶c̶a̶l̶l̶y̶ ̶o̶r̶d̶e̶r̶ ̶y̶o̶u̶ ̶X̶M̶L̶. No, that's really not an option.
Since it seems like you're getting RSS, you can consider using WCF's System.ServiceModel.Syndication.SyndicationFeed which is specfically built for RSS/Atom. More on this at this great article by Den Delimarsky.
If your using non-RSS XML, consider using straight up Xml Serialization with XmlSerializer. For my money it's the best and simplest way to do over the wire XML serialization and deserialization.
The behaviour change from WP7 to WP8 is enabled via Quirks Mode. Meaning that WP7 apps running on WP8 will still run OK. If your app doesn't benefit from WP8 featuresets, you can keep your entire app as a WP7 app.

Related

UIAutomation throws AccessViolationException on Windows 11

The issue:
We have an application written in C# that uses UIAutomation to get the current text (either selected or the word behind the carret) in other applications (Word, OpenOffice, Notepad, etc.).
All is working great on Windows 10, even up to 21H2, last update check done today.
But we had several clients informing us that the application is closing abruptly on Windows 11.
After some debugging I've seen some System.AccessViolationException thrown when trying to use the TextPatternRange.GetText() method:
System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'
What we've tried so far:
Setting uiaccess=true in manifest and signing the app : as mentionned here https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/350ceab8-436b-4ef1-8512-3fee4b470c0a/problem-with-manifest-and-uiaccess-set-to-true?forum=windowsgeneraldevelopmentissues => no changes (app is in C:\Program Files\
In addition to the above, I did try to set the level to "requireAdministrator" in the manifest, no changes either
As I've seen that it may come from a bug in Windows 11 (https://forum.emclient.com/t/emclient-9-0-1317-0-up-to-9-0-1361-0-password-correction-crashes-the-app/79904), I tried to install the 22H2 Preview release, still no changes.
Reproductible example
In order to be able to isolate the issue (and check it was not something else in our app that was causing the exception) I quickly made the following test (based on : How to get selected text of currently focused window? validated answer)
private void btnRefresh_Click(object sender, RoutedEventArgs e)
{
var p = Process.GetProcessesByName("notepad").FirstOrDefault();
var root = AutomationElement.FromHandle(p.MainWindowHandle);
var documentControl = new
PropertyCondition(AutomationElement.ControlTypeProperty,
ControlType.Document);
var textPatternAvailable = new PropertyCondition(AutomationElement.IsTextPatternAvailableProperty, true);
var findControl = new AndCondition(documentControl, textPatternAvailable);
var targetDocument = root.FindFirst(TreeScope.Descendants, findControl);
var textPattern = targetDocument.GetCurrentPattern(TextPattern.Pattern) as TextPattern;
string text = "";
foreach (var selection in textPattern.GetSelection())
{
text += selection.GetText(255);
Console.WriteLine($"Selection: \"{selection.GetText(255)}\"");
}
lblFocusedProcess.Content = p.ProcessName;
lblSelectedText.Content = text;
}
When pressing a button, this method is called and the results displayed in labels.
The method uses UIAutomation to get the notepad process and extract the selected text.
This works well in Windows 10 with latest update, crashes immediately on Windows 11 with the AccessViolationException.
On Windows 10 it works even without the uiaccess=true setting in the manifest.
Questions/Next steps
Do anyone know/has a clue about what can cause this?
Is Windows 11 way more regarding towards UIAutomation?
On my side I'll probably open an issue by Microsoft.
And one track we might follow is getting an EV and sign the app itself and the installer as it'll also enhance the installation process, removing the big red warnings. But as this is an app distributed for free we had not done it as it was working without it.
I'll also continue testing with the reproductible code and update this question should anything new appear.
I posted the same question on MSDN forums and got this answer:
https://learn.microsoft.com/en-us/answers/questions/915789/uiautomation-throws-accessviolationexception-on-wi.html
Using IUIautomation instead of System.Windows.Automation works on Windows 11.
So I'm marking this as solved but if anyone has another idea or knows what happens you're welcome to comment!

Turn on Airplane mode using AccessibilityService Class in Xamarin

I want to turn on or off airplane mode using AccessibilityService.
Any idea how we can do it?
Yes, you can't change it from app that target bigger than Android 4.2. But you can open the settings page instead if you want:
if (Android.OS.Build.VERSION.SdkInt < BuildVersionCodes.JellyBeanMr1)
{
try
{
Intent intentAirplaneMode = new Intent(Android.Provider.Settings.ActionAirplaneModeSettings);
intentAirplaneMode.SetFlags(ActivityFlags.NewTask);
Context.StartActivity(intentAirplaneMode);
}
catch (ActivityNotFoundException e)
{
Log.Error("exception", e + "");
}
}
else
{
Intent intent1 = new Intent("android.settings.WIRELESS_SETTINGS");
intent1.SetFlags(ActivityFlags.NewTask);
Context.StartActivity(intent1);
}
}
And AccessibilityService can used with dependency service.
Kamal you’re not going to be able to do it.
It doesn’t seem like you’re doing iOS, but iOS has a lot of limitations due to privacy and security purposes that won’t allow you to do this. You can see more details here stackoverflow.com/q/20469425/11104068
Also android blocked being able to do this from Android 4.2 onwards. Only system apps can make changes to Airplane mode, as you can see here stackoverflow.com/a/5533943/11104068
Since it doesn’t seem you’re creating a system app that gets installed with the operating system, and not through the Play Store, you won’t be able to get permissions. It will give you an error /exception even if you implement everything

Playing an HDHomeRun stream on a Tizen.NET Xamarin App

I'm trying to play a HDHomeRun Connect Video source from a url in the following format: http://x.x.x.x:xxxx/auto/v4.1. This video source is an MPEG2 video encoding and AC3 audio encoding.
I've tried using the Samsung Tizen.TV .NET sample with the following source but the video never plays.
_player = new Tizen.Multimedia.Player();
var mediaSource = new Multimedia.MediaUriSource(uri);
_player.SetSource(mediaSource);
var display = new Multimedia.Display(Window.Instance);
_player.Display = display;
await _player.PrepareAsync();
The player state gets stuck in preparing, and the await _player.PrepareAsync() call never finishes. It is worth noting that I'm using the Tizen Samsung TV Emulator. Do I need to transcode the stream from the HDHomeRun to be playable? Are there any other measures I might be missing for the Video to play?
Ultimately, the Display property of the player wasn't being set correctly. The property that worked for me (found from investigating the JuvoPlayer code was this:
var display = new Multimedia.Display(((FormsApplication)Forms.Context).MainWindow);
_player.Display = display;
When you are to develop a Tizen .NET application, please be aware of which UI framework your project is targetted for among 3 different types: Xamarin.Forms, (pure) ElmSharp, and Tizen.NUI.
Unless your project is based on the Tizen.NUI framework, you shouldn't use Tizen.NUI.Window.Instance and types in Tizen.NUI namespace in any case. Instead, you will have to use types of ElmSharp or Xamarin.Forms.Platform.Tizen namespace for platform-specific code in your application.
Since the internal implementation of Xamarin.Forms for Tizen is based on ElmSharp, FormsApplication.MainWindow will return a ElmSharp.Window instance which can be used to instantiate a Tizen.Multimedia.Display object. That's why the code in your answer worked.

Xamarin.Forms Windows App load XML data into ListView

I am writing an application in Xamarin.Forms for Android, iOS, and Windows Store. I want to populate a ListView with about 10,000 elements from an XML file. The problem is when I run the code for Windows Phone or Windows Store, the application lags for about a minute before coming back alive and populating the ListView. It populates instantly for Android and iOS. However for Windows, it lags. Could somebody help me fix this problem? Here is my code which does the reading of XML and populating the ListView:
public async void LoadCharacters()
{
Assembly assembly = typeof(CharacterPage).GetTypeInfo().Assembly;
string file = assembly.GetManifestResourceNames().First(x => x.Contains("Characters.xml"));
Stream stream = assembly.GetManifestResourceStream(file);
data = new ObservableCollection<Character>();
await Task.Factory.StartNew(delegate {
XDocument doc = XDocument.Load(stream);
IEnumerable<Character> characters = from query in doc.Descendants("c")
select new Character
{
Simplified = query.Attribute("s").Value,
Traditional = query.Attribute("t").Value,
Pinyin = query.Attribute("p").Value,
English = query.Attribute("e").Value,
URL = query.Attribute("u").Value
};
data = characters.ToObservableCollection();
});
characterList.ItemsSource = data;
}
This code works, and runs smooth in iOS and Android. However in Windows, it hangs for about 1 minutes. Please help.
Thank you
The answer is to set the height of the listview item. Then it loads instantly.

WPF Printing (XpsDocumentWriter) working in debug but not in deployment

Hopefully some of the experienced WPF developers have come across this issue before.
BACKGROUND: This information is probably not necessary to helping fixing the problem, but in case it is relevant.
My solution consists of three projects. A front-end GUI, a business logic service, and a printer service. The three projects have IPC via named pipes. The business logic hands the printing logic a label type and a pallet id.
The Problem: The printing logic then creates the label and prints it (by adding it to the print queue of a printer) As the title suggests this all works fine when I am debugging in visual studio. However when I deploy / install the services on my developer pc it is not working.
Update: It is not throwing an exception but I am only logging "About to send doc to printer" and not the line "Sent doc to printer" So it is hanging on the dw1.Write(fixedDoc); line
More Information: I am using .Net 4.0 in the printing project / visual studio 2013
public void printLabel(string labelType, string _palletID = null)
{
try
{
ILabelTemplate Label = createLabel(labelType, _palletID);
PrintDialog pd = new PrintDialog();
FixedDocument fixedDoc = new FixedDocument();
PageContent pageContent = new PageContent();
FixedPage fixedPage = getFixedPage();
fixedDoc.DocumentPaginator.PageSize = new System.Windows.Size(fixedPage.Width, fixedPage.Height);
IXamlTemplate vm = CreateViewModel(Label);
ILabelPrintDocument template = CreateTemplate(Label);
template.dockPanel.DataContext = vm;
template.dockPanel.Height = fixedPage.Height;
template.dockPanel.Width = fixedPage.Width;
template.dockPanel.UpdateLayout();
fixedPage.Children.Add(template.dockPanel);
((System.Windows.Markup.IAddChild)pageContent).AddChild(fixedPage);
fixedDoc.Pages.Add(pageContent);
XpsDocumentWriter dw1 = PrintQueue.CreateXpsDocumentWriter(new System.Printing.PrintQueue(new System.Printing.PrintServer(), Label.PrinterName));
Library.WriteErrorLog("About to send doc to printer");
dw1.Write(fixedDoc);
Library.WriteErrorLog("Sent doc to printer");
}
catch (Exception ex)
{
Library.WriteErrorLog(ex);
}
SOLVED ... kind of
After several hours of trying different things and reading about this, I found that it was due to my application running as me when I'm debugging but as a LOCAL SYSTEM when I have it deployed. And a local system service does not have access to network resources such as printers. Despite learning this, I then started down the path of how to make a C# service print. Well after seeing many posts (too late in the game to be very helpful)
Like this and also this one I have learned that I was going down the wrong path.
The moral of the story is, if you're reading this post you're probably not at the level of "writing your own printing DLL using the Win32 API (in C/C++ for instance), then use it from your service with P/Invoke"
The solution that did work for me was instead of running this project as a service which was started via my GUI. I have instead turned it into a process which is still started and stopped via my GUI.
The code in question is
if (File.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\yourAppNameGoesHere.exe"))
{
Process.Start(AppDomain.CurrentDomain.BaseDirectory + "\\yourAppNameGoesHere.exe");
}
then when the GUI is closed I run the code
if (File.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\yourAppNameGoesHere.exe"))
{
Process[] myapps = Process.GetProcesses("yourAppNameGoesHere.exe");
foreach (Process _p in myapps)
{
_p.Kill();
}
}

Categories