Lync 2010 Plugin - Silverlight WPF with elevated permissions - wpf

I'm developing a CWE (Conversation Extensibility Window) with WPF and Silverlight 4 on Visual Studio 2010, for Lync 2010.
My application reads a list of .xml from the root directory of the application and into a string array.
I've this code:
bool featureComplete = Application.Current.HasElevatedPermissions;
if (featureComplete)
{
List<string> files = new List<string>(Directory.EnumerateFiles(textBox1.Text, "*.*"));
mensajes.Content = files.Count;
}
else
{
mensajes.Content = "no trust";
}
In the event handler of a button event. With any path (my documents, root, application, etc) the application says "no trust".
I change the properties on the build to Out-of-browser settings and also check "require elevated trust" but nothing happens.
I tried and tried looking for an answer on google and msdn but I could not find a solution.
So there's a checklist or step list to make a trusted CWE on Lync2010 with silverlight? I forgot something?
Please remember: this is not a usual web application, its a lync 2010 app.
ALSO: I can do it with "debug mode" with special folders like this tutorial: http://www.silverlight.net/learn/graphics/file-and-local-data/local-file-access
and it works, but when I run it under lync 2010 it says "access denied" for that folder.
There is the code that works only on debug as an application, and not works like lync applet:
List<string> picsinfolder = new List<string>();
var pics = Directory.EnumerateFiles
(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures));
foreach (var item in pics)
{
picsinfolder.Add(item);
}
listBox1.ItemsSource = picsinfolder;
Thanks a lot in advance.
PD: Work-arounds that fix the issue can be accepted as an answer
PD2: No, signing the xap doesn't work.

The work around I'm using and works is open an XML, reading, copy into Isolated Storage, read it again from there. Everytime I need to change the file, I read it and copy again on Isolated Storage

Related

Application Insights for WPF Application

There is a WPF application written in Visual Studio.
Can I add Application Insights to this WPF app?
I would like to know how many times a button/tile is clicked. Since there are multiple installations
of the same application, I would like to know which button was clicked how many times from which user/installation. Can this be done with Application Insights?
Thanks
Avanti
While not listed as a supported app type this means there isn't default telemetry data collected/sent to application insights nor is there support for adding AI/creating an application insights resource. That being said it is possible to add to your WPF with a few manual steps so that you can track the specific scenarios you mention (like a button/tile click).
-From Visual studio add the "Application Insights API" NuGet to the project (.11 is the latest today).
This will add the Application Insights API reference and create an application insights configuration file to your project.
The applicationinsights.config file needs to be updated with your instrumentation key as follows:
<?xml version="1.0" encoding="utf-8"?>
<ApplicationInsights xmlns="http://schemas.microsoft.com/ApplicationInsights/2013/Settings" schemaVersion="2014-05-30">
<TelemetryChannel>
<DeveloperMode>false</DeveloperMode>
</TelemetryChannel>
<TelemetryModules>
<Add Type="Microsoft.ApplicationInsights.Tracing.DiagnosticsTelemetryModule, Microsoft.ApplicationInsights"/>
</TelemetryModules>
<InstrumentationKey>**your-instrumentation-key-guid**</InstrumentationKey>
</ApplicationInsights>
To create an application insights instrumentation key login to your azure subscription.
https://portal.azure.com
Click + to create an Application Insights resource.
Then choose the properties tile on the application insights blade and copy the Instrumentation key and add it to your applicationinsights.config file.
Now in your WPF app you can use the Application Insights sdk as described here: http://blogs.msdn.com/b/visualstudioalm/archive/2014/10/21/application-insights-sdk-0-11-0-prerelease.aspx
your events will be visible in the diagnostic search blade which can be selected on the application insights blade.
Note: telemetry is batched locally for 1 min before being sent to the service unless > 500 telemetry events are queued at which point they are sent.
https://azure.microsoft.com/en-us/documentation/articles/app-insights-windows-desktop/
An official link from Microsoft on how to add Application Insights to a Windows Forms application. From the link:
In Azure - portal.azure.com
Create an Application Resource. ::New / Developer Services / Application Insights.
Notice the instrumentation key generated, grab a copy and set it aside, we'll need it when we configure your application.
In Your Application
NuGet - Add 'Application Insights API'
Configure your TelemetryClient.
I'm using MvvmCross in a WPF application, on startup I create a single TelemetryClient that I re-use throughout the application.
var telemetryClient = new TelemetryClient();
telemetryClient.InstrumentationKey = "your key here from Azure";
telemetryClient.Context.Session.Id = Guid.NewGuid().ToString();
telemetryClient.Context.User.AccountId = Username;
telemetryClient.Context.Component.Version = Settings.Default.Version;
telemetryClient.TrackEvent("Application Start");
Mvx.RegisterSingleton<TelemetryClient>(telemetryClient);
Record an event/screen/exception, etc
Any time 'something happens' I'll resolve the TelemetryClient and record the event. This is just like any other Application Insights implementation with regards to tracking and recording.
As an example -
//Resolve the telemetry client
readonly TelemetryClient telemetryClient = Mvx.Resolve<TelemetryClient>();
//Record a page View with some extra information
var pageviewTelemetry = new PageViewTelemetry("Observations");
pageviewTelemetry.Properties.Add("Breadcrumb", breadcrumb);
telemetryClient.TrackPageView(pageviewTelemetry);
//Track an event
var eventTelemetry = new EventTelemetry("Observation Saved");
eventTelemetry.Properties.Add("Saved Observation", observation);
telemetryClient.TrackEvent(eventTelemetry);
//Track an exception
try
{
// do work here
}
catch (Exception ex)
{
telemeteryClient.TrackException(ex);
}
Flush on Application Exit
Application Insights for Windows Desktop applications does not automatically gather/send anything. As a developer one needs to force a flush at application exit.
private void PowerButton_OnClick(object sender, RoutedEventArgs e)
{
var tc = Mvx.Resolve<TelemetryClient>();
if (null != tc)
{
tc.Flush(); // only for desktop apps
}
Application.Current.Shutdown();
}
Or setup an RxTimer to flush on a schedule...I decided to flush every 30 minutes:
var observable = Observable.Interval(new TimeSpan(0, 0, 30, 0));
observable.Subscribe(_ => Application.Current.Dispatcher.Invoke(new Action(() =>
{
var tc = Mvx.Resolve<TelemetryClient>();
if (null != tc)
{
tc.Flush(); // only for desktop apps
Console.WriteLine("Flush TC");
}
})));
FYI - As of 0.17.0 of the Application Insights API NuGet Package if you are offline the flush call doesn't hang, but appears to. Online, the call completes immediately, offline there is a solid 5 second pause before the call completes.
Application Insights (AI) for desktop applications is being deprecated in favor of HockeyApp. It's not overly mature yet, but it works (events essentially reach the same place AI events go).
For example, here's how it looks in RoslynPad (a WPF C# Editor):
using Microsoft.HockeyApp;
//In your initialization method:
var hockeyClient = (HockeyClient)HockeyClient.Current;
hockeyClient.Configure(HockeyAppId)
.RegisterCustomDispatcherUnhandledExceptionLogic(OnUnhandledDispatcherException)
.UnregisterDefaultUnobservedTaskExceptionHandler();
var platformHelper = (HockeyPlatformHelperWPF)hockeyClient.PlatformHelper;
platformHelper.AppVersion = _currentVersion.ToString();
hockeyClient.TrackEvent("App Start");
//sometime later:
hockeyClient.TrackEvent("Something happened");
EDIT Looks like the following NuGet package is required in order for this to work properly: https://www.nuget.org/packages/HockeySDK.WPF.TelemetryWorkaround (see https://github.com/bitstadium/HockeySDK-Windows/pull/88).

Stream video from secure azure blob to WPF

Does anyone know a way to stream .mp4 video from a secure azure blob (via https) into a WPF application.
I'm generating the uri as follows ...
public Uri GetSecureUriForBlob(CloudBlobContainer container, string blobName)
{
var blockBlob = container.GetBlockBlobReference(blobName);
var beforeOffset = new DateTimeOffset(DateTime.UtcNow.AddMinutes(-5));
var afterOffset = new DateTimeOffset(DateTime.UtcNow.AddHours(1));
var builder = new UriBuilder(blockBlob.Uri)
{
Query = blockBlob.GetSharedAccessSignature(
new SharedAccessBlobPolicy
{
Permissions = SharedAccessBlobPermissions.Read,
SharedAccessStartTime = beforeOffset,
SharedAccessExpiryTime = afterOffset
}).TrimStart('?')
};
return builder.Uri;
}
I've checked that the service version is set to at least "2013-08-15" and that the blob item has the correct content type set.
I know the format of the uri is correct, because I can paste it in a browser, and also use it in a Windows 8 store application, and the video streams correctly.
However, when I assign the same uri as the source for a WPF MediaElement, I get a NullReferenceException deep in the inner workings of MediaPlayer.Open().
There seems to be a known issue with WPF MediaElement when playing from HTTPS endpoints. There are no issues when playing over plain HTTP (without "S").
This is not Microsoft Azure related, or Blob Related. This is pure WPF issue, that however seems that will not be fixed soon, if fixed at all.
For HTTPS Streams you can use either Silverlight or Windows 8 Modern applications - both support HTTPS streams without any issues.
You could probably find a 3rd party control for WPF that supports playing media over HTTPS.
UPDATE
Using the VideoLan.NET WPF Controls I was able to make HTTPS media playing. So far the only controls for WPF that successfully play HTTPS media. This requires a valid installation of VideoLAN VLC player for Windows. I used the portable one (ZIP package) and it works perfectly. Documentation for the VideoLan.NET is a bit messy, but the result is that you can safely play HTTPS streams/progressive downloads in WPF.

Open Notepad from Silverlight 4 Business Application

I have a Silvleright Business Application, Silverlight_BussApp.
It has the Silverlight_BussApp project and the Silverlight_BussApp.Web project.
I need to open Notepad after populating it in the code behind on a button click event.
I cannot make this an out of browser application.
So since Silverlight does not allow me to do it, I created a WCF Service in the Silverlight_BussApp.Web project
and invoked it through a proxy in the Silverlight Project. This works fine.
The code in the WCF Service is:
public void openFileWithNotepad(string filename)
{
try
{
if (File.Exists(filename))
{
Process.Start("notepad.exe", filename);
}
else
{
MessageBox.Show(
"I was unable to locate the following file: " + filename,
"File Not Found");
}
}
catch (Exception e)
{
throw e;
}
}
Now I need to use this openFile functionality in more than one Silverlight Project.
So I created a "WCF service Project" and created a WCF Service, hosted it on IIS, and created a proxy in the Silverlight project. To my dismay, the file does not open and it keeps giving me the "File Not Found" Error.
Can somebody help me figure out how I can make this a reusable functionality for all my Silverlight projects?
Why is it when I use the same code in a WCF Service hosted on IIS it does not work while it works perfectly when hosted in the same solution of the Silverlight project?
For starters, the code in the Silverlight_BussApp.Web project is going to be executed on the server, while the code in the Silverlight_BussApp project is going to be executed on the client. During development, the client and the server are ostensibly the same machine -- when you click "Run" in Visual Studio, a development web server starts up on your machine and hosts your .Web project, while the Silverlight application runs in your browser.
When your application is deployed, the client (i.e., your browser) will most likely be on a different physical machine than the server (i.e., IIS). So, ignoring any other security restrictions that may be imposed by IIS (which is probably why you're getting a "File Not Found" error), the call to Process.Start would start Notepad on an entirely different machine than the one you're using.
Try using a SaveFileDialog to save whatever you want to the client's machine, then tell them to open the resulting file.

System.IO.FileInfo throwing access is denied exception to a local file

I created a sample Silverlight Web project
and I am getting 'Access is denied' when I do this:
string fileName = "map.gif";
FileInfo fileInfo = new FileInfo(fileName);
How can I give the web project access to this folder/file?
I added the image into my project, really drawing a blank here....
You don't access files you've placed in the project using the FileInfo object. Instead you create a Uri to access it.
Its not clear from your question which project you've place the file in. If you have placed it in the Silverlight project then it ought to end up as content in the Xap. In which case you can acquire StreamResourceInfo for it using:-
StreamResourceInfo gifContentInfo = Application.GetResourceStream(new Uri("map.gif", UriKind.Relative));
Now you can get to the file content with:-
Stream gifStream = gifContentInfo.Stream;
On the other hand if you have placed the file in the web project it will be a standard static file in the web site. Hence you will need to do the typical WebClient download to fetch it.
I take it you are going to this trouble because its a Gif file; you are aware that they are not supported as an image.
You can't use the filesystem in Silverlight outside of Isolated Storage
you need to give file access to the asp.net user
check this out:
http://www.codeproject.com/KB/aspnet/Ahmed_Kader.aspx
Or use the special folder which asp.net provides for you
... APP_DATA
that should have the rights you need...
I am assuming you are trying to access a file in the local filesystem.
If so, you cannot access files like that. Silverlight does not have the access priveleges u expect. If you want to add a file to your Silverlight Application at runtime. You will need to have Silverlight 4, running Out of the Browser with Elevated priveleges. There are certain limitations to this too. You can only access files in Special Folders like My Documents, Pictures, Music etc. For more info about access files this way. You can look at John's tutorials on Silverlight 4 elevated priveleges in Channel 9 MSDN.
I would doubt your FileInfo usage too. Here is a sample code to get file data using a simple drag and drop feature.
private void list_Drop(object sender, DragEventArgs e)
{
FileInfo[] files = (FileInfo[])e.Data.GetData(DataFormats.FileDrop);
for(int i=0;i<files.Length;i++)
textblock.Text += files[i].Name;
}
You can get the properties of the file such as "Name". You wil not hit any access denied errors. You cannot access properties like "DirectoryName", "FullName" etc. The reason being they are declared as SecurityCritical properties for Security reasons. The advantage of elevated permissions is that you can get to local file system (special folders) to access the FullName and DirectoryName properties without any exceptions.
Hope this helps

Silverlight 4 webclient authentication - anyone have this working yet?

So one of the best parts about the new Silverlight 4 beta is that they finally implemented the big missing feature of the networking stack - Network Credentials!
In the below I have a working request setup, but for some reason I get a "security error" when the request comes back - is this because twitter.com rejected my api call or something that I'm missing in code?
It might be good to point out that when I watch this code execute via fiddler it shows that the xml file for cross domain is pulled down successfully, but that is the last request shown by fiddler ...
public void RequestTimelineFromTwitterAPI()
{
WebRequest.RegisterPrefix("https://", System.Net.Browser.WebRequestCreator.ClientHttp);
WebClient myService = new WebClient();
myService.AllowReadStreamBuffering = true;
myService.UseDefaultCredentials = false;
myService.Credentials = new NetworkCredential("username", "password");
myService.UseDefaultCredentials = false;
myService.OpenReadCompleted += new OpenReadCompletedEventHandler(TimelineRequestCompleted);
myService.OpenReadAsync(new Uri("https://twitter.com/statuses/friends_timeline.xml"));
}
public void TimelineRequestCompleted(object sender, System.Net.OpenReadCompletedEventArgs e)
{
//anytime I query for e.Result I get a security error
}
I found 2 issues that caused this request to throw the security exception
1) - In this video by Tim Heuer it turns out my VS2010 w/ Silverlight 4 toolkit installation didn't match the final build so I'm missing the option that shows up in the "out of browser settings" dialog that provides the checkbox for "Require elevated trust when running outside the browser".
In the video listed above Tim checks this so the Silverlight app can talk to the twitter API
But because my application didn't have this option I had to manually edit the xml file so it looked like the below. You can find this xml under properties in the project folder or inside visual studio directly.
<OutOfBrowserSettings ShortName="TrustedNetworkApp Application" EnableGPUAcceleration="False" ShowInstallMenuItem="True">
<OutOfBrowserSettings.Blurb>TrustedNetworkApp Application on your desktop; at home, at work or on the go.</OutOfBrowserSettings.Blurb>
<OutOfBrowserSettings.WindowSettings>
<WindowSettings Title="TrustedNetworkApp Application" Height="480" Width="640" />
</OutOfBrowserSettings.WindowSettings>
<OutOfBrowserSettings.SecuritySettings>
<SecuritySettings ElevatedPermissions="Required" />
</OutOfBrowserSettings.SecuritySettings>
<OutOfBrowserSettings.Icons />
</OutOfBrowserSettings>
Notice the **security settings ElevatedPermissions="Required"
After you save this it's equivalent to checking this as Tim did in the video.
2) - as I was watching that video by Tim I noticed that you have to debug this outside of the browser to get it working. So install the app and run it outside the browser. This app now works.
I'll write a short blog post to summarize my experience with the networking stack under the beta and link to it for anyone interested.
Update
I finally wrote a blog post about my experience building an out of browser twitter client using Silverlight 4 if anyone is interested.

Resources