Silverlight applications that run in the browser run with partial trust. They run in a security sandbox and have limited access to system resources. By default, they can’t read from or write to the file system, access Windows APIs, and interact with local applications such as Outlook, Word, or Excel.
For many of the applications you create, this will not impact your ability to create the application. However, there will be applications where you want access to local system resources. Prior to Silverlight 4, your only option would be to rewrite the application using Windows Presentation Foundation. Fortunately, Silverlight 4 adds the ability to run out-of-browser applications with elevated trust. These applications are known as trusted applications.
To configure a Silverlight application so that users can install it and then run it outside the browser, go to the Silverlight tab of the Project Designer and check Enable running application out of the browser.
To specify that an out-of-browser application should run with elevated permissions, click Out of Browser Settings. In the Out of Browser Settings dialog box, check Require elevated trust when running outside the browser.
You can also specify the appearance of the title bar and border for the application window. You can select Default, No Border, or Borderless Round Corners from the Windows Style drop-down list. Note that this drop-down list is only enabled if you configure the application to run with elevated trust.
The OutOfBrowserTrustedApplication project is a simple out of browser application that displays customers and orders. The application uses a Silverlight-enabled WCF service to retrieve data from the Northwind database. When the application loads, it calls the GetCustomers method of the service to retrieve the customer Id, company name, city and country of each customer. The application displays the customers in a list box.
When you select a customer, the application calls the GetCustomer method of the service to retrieve all of the information for that customer. The application displays these in text boxes. The application also calls the GetOrders method of the service to retrieve the order id, ordered date, shipped date and dollar amount of each order the customer placed. The application displays these in a DataGrid.
To install the application, right-click and select Install Elevated Trust Demo onto this computer. Silverlight displays a security warning because this application has requested elevated permissions and it is not signed with a trusted certificate.
Click Install to install the application. The out-of-browser version of the application loads.
Notice that the out of browser application has three buttons that do not appear when you run the application in the browser.
You can use the HasElevatedPermissions property of the Application.Current object to determine whether or not an out-of-browser application is trusted. The following code executes when the application starts:
' Visual Basic
If Not Application.Current.HasElevatedPermissions Then
saveToFileButton.Visibility = Visibility.Collapsed
createLetterButton.Visibility = Visibility.Collapsed
creteReportButton.Visibility = Visibility.Collapsed
Else
myDocuments = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
End If
// C#
if (!Application.Current.HasElevatedPermissions)
{
saveToFileButton.Visibility = Visibility.Collapsed;
createLetterButton.Visibility = Visibility.Collapsed;
createReportButton.Visibility = Visibility.Collapsed;
}
else
{
myDocuments = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
}
This code hides the three buttons if the application is running in the browser and therefore does not have elevated trust. If the application has elevated trust, the code stores the location of the My Documents folder to the myDocuments field. Each of the three buttons writes a file to My Documents. Trusted Silverlight application only has access to user folders, specifically My Documents, My Music, My Pictures, and My Videos.
Write to a Text File
When you click the Save to file button, the following code executes:
' Visual Basic
Using writeStream = New StreamWriter(customerFile & ".txt", False)
writeStream.WriteLine(_customer.CompanyName)
writeStream.WriteLine()
writeStream.WriteLine(String.Format("Contact: {0}", _customer.ContactName))
writeStream.WriteLine(String.Format(" {0}", _customer.ContactTitle))
writeStream.WriteLine()
writeStream.WriteLine(String.Format("Address: {0}", _customer.Address))
writeStream.WriteLine(String.Format(" {0}, {1}", _customer.City, _customer.Region))
writeStream.WriteLine(String.Format(" {0}, {1}", _customer.PostalCode, _customer.Country))
writeStream.WriteLine()
writeStream.WriteLine(String.Format("Phone: {0}", _customer.Phone))
writeStream.WriteLine(String.Format("Fax: {0}", _customer.Fax))
MessageBox.Show("The customer information has been saved to My Documents")
End Using
// C#
using (var writeStream = new StreamWriter(customerFile + ".txt", false))
{
writeStream.WriteLine(customer.CompanyName);
writeStream.WriteLine();
writeStream.WriteLine(string.Format("Contact: {0}", customer.ContactName));
writeStream.WriteLine(string.Format(" {0}", customer.ContactTitle));
writeStream.WriteLine();
writeStream.WriteLine(string.Format("Address: {0}", customer.Address));
writeStream.WriteLine(string.Format(" {0}, {1}", customer.City, customer.Region));
writeStream.WriteLine(string.Format(" {0}, {1}", customer.PostalCode, customer.Country));
writeStream.WriteLine();
writeStream.WriteLine(string.Format("Phone: {0}", customer.Phone));
writeStream.WriteLine(string.Format("Fax: {0}", customer.Fax));
MessageBox.Show("The customer information has been saved to My Documents");
}
This code uses the StreamWriter class to create the text file. This class is in the System.IO namespace and is available in Silverlight applications. In other applications, you may have used the StringBuilder class to build a string and then used the WriteAllText method of the File class to create a file. You cannot take this approach in a Silverlight class. The StringBuilder class is in the System.Text namespace and that assembly is not available in Silverlight.
Write to a Word Document
When you click the Create letter button, the following code executes:
' Visual Basic
If AutomationFactory.IsAvailable Then
Try
word = AutomationFactory.GetObject("Word.Application")
Catch ex1 As Exception
Try
word = AutomationFactory.CreateObject("Word.Application")
Catch ex2 As Exception
MessageBox.Show("This application can't save customer letters")
Exit Sub
End Try
End Try
word.Documents.Add()
word.Selection.TypeText(DateTime.Today.ToShortDateString)
word.Selection.TypeParagraph()
word.Selection.TypeParagraph()
word.Selection.TypeText(
_customer.ContactName & ChrW(11) &
_customer.ContactTitle & ChrW(11) &
_customer.CompanyName & ChrW(11) &
_customer.Address & ChrW(11) &
_customer.City & " " & _customer.Region & ChrW(11) &
_customer.PostalCode & " " & _customer.Country)
word.Selection.TypeParagraph()
word.Selection.TypeParagraph()
word.Selection.TypeText("Dear valued customer:")
word.Selection.TypeParagraph()
word.Selection.TypeParagraph()
word.Selection.TypeText(
"Now is the perfect time to train your staff on the latest technologies, including Silverlight.")
word.Selection.TypeParagraph()
word.Selection.TypeText("MCW Technologies offers a number of training options.")
word.Selection.TypeParagraph()
word.Selection.TypeText("I will call you next week and we can discuss this.")
word.Selection.TypeParagraph()
word.Selection.TypeParagraph()
word.Selection.TypeText("Sincerely")
word.Selection.TypeParagraph()
word.Selection.TypeParagraph()
word.Selection.TypeText("Robert Green" & ChrW(11) &
"Sr. Consultant" & ChrW(11) &
"MCW Technologies")
word.Selection.TypeParagraph()
word.ActiveDocument.SaveAs(customerFile)
word.ActiveDocument.Close()
MessageBox.Show("The customer letter has been saved to My Documents")
Else
MessageBox.Show("This application can't save customer letters")
End If
// C#
if (AutomationFactory.IsAvailable)
{
try
{
word = AutomationFactory.GetObject("Word.Application");
}
catch (Exception ex1)
{
try
{
word = AutomationFactory.CreateObject("Word.Application");
}
catch (Exception ex2)
{
MessageBox.Show("This application can't save customer letters");
return;
}
}
word.Documents.Add();
word.Selection.TypeText(DateTime.Today.ToShortDateString());
word.Selection.TypeParagraph();
word.Selection.TypeParagraph();
word.Selection.TypeText(customer.ContactName +
'\v' + customer.ContactTitle + '\v' + customer.CompanyName +
'\v' + customer.Address + '\v' + customer.City + " " +
customer.Region + '\v' + customer.PostalCode + " " +
customer.Country);
word.Selection.TypeParagraph();
word.Selection.TypeParagraph();
word.Selection.TypeText("Dear valued customer:");
word.Selection.TypeParagraph();
word.Selection.TypeParagraph();
word.Selection.TypeText(
"Now is the perfect time to train your staff on the latest technologies, including Silverlight.");
word.Selection.TypeParagraph();
word.Selection.TypeText("MCW Technologies offers a number of training options.");
word.Selection.TypeParagraph();
word.Selection.TypeText("I will call you next week and we can discuss this.");
word.Selection.TypeParagraph();
word.Selection.TypeParagraph();
word.Selection.TypeText("Sincerely");
word.Selection.TypeParagraph();
word.Selection.TypeParagraph();
word.Selection.TypeText("Robert Green" + "\v" +
"Sr. Consultant" + "\v" + "MCW Technologies");
word.Selection.TypeParagraph();
word.ActiveDocument.SaveAs(customerFile);
word.ActiveDocument.Close();
MessageBox.Show("The customer letter has been saved to My Documents");
}
else
{
MessageBox.Show("This application can't save customer letters");
}
The AutomationFactory class is in the System.Runtime.InteropServices.Automation namespace and provides access to Automation servers such as Word, Excel or Outlook. The IsAvailable property of this class specifies whether or not the Silverlight application is capable of calling an Automation server. If this property returns true, the code attempts to get a reference to the Word Automation server.
The GetObject method of the AutomationFactory class returns a reference to an activated and running Automation server. The code above first tries to get a reference to Word. The first time this code runs GetObject will throw an exception because it has not been activated yet. The code then calls the CreateObject method to activate the Word Automation server and return a reference to it. If Word is not available as an Automation server then this call will throw and exception and the code cannot create a Word document.
It may seem odd to try and reference an existing Automation server before creating it. However, this code makes sense. The second time it executes, and each time after that, the code calls GetObject to retrieve a reference to the already activated Automation server.
If the code succeeds in retrieving a reference to Word, it uses familiar code to write the letter.
Write to an Excel Workbook
When you click the Create report button, the following code executes:
' Visual Basic
If AutomationFactory.IsAvailable Then
Try
excel = AutomationFactory.GetObject("Excel.Application")
Catch ex1 As Exception
Try
excel = AutomationFactory.CreateObject("Excel.Application")
Catch ex2 As Exception
MessageBox.Show("This application can't save orders reports")
Exit Sub
End Try
End Try
excel.Workbooks.Add()
excel.Range("A1").Value = "Orders placed by " & _customer.CompanyName
excel.Range("A1").Font.Size = 14
excel.Range("A1").Font.Bold = True
excel.Range("A3").Value = "Order"
excel.Range("A3").Font.Bold = True
excel.Range("A3").HorizontalAlignment = 4
excel.Range("B3").Value = "Ordered"
excel.Range("B3").Font.Bold = True
excel.Range("B3").HorizontalAlignment = 4
excel.Range("C3").Value = "Shipped"
excel.Range("C3").Font.Bold = True
excel.Range("C3").HorizontalAlignment = 4
excel.Range("D3").Value = "Amount"
excel.Range("D3").Font.Bold = True
excel.Range("D3").HorizontalAlignment = 4
excel.Columns("A:A").ColumnWidth = 10
excel.Columns("B:D").ColumnWidth = 12
Dim row As Integer = 4
For Each ord As OrderSummary In orders
excel.Range(String.Format("A{0}", row)).Value = ord.OrderId
excel.Range(String.Format("B{0}", row)).Value = ord.OrderDate
If ord.ShippedDate <> #12:00:00 AM# Then
excel.Range(String.Format("C{0}", row)).Value = ord.ShippedDate
End If
excel.Range(String.Format("D{0}", row)).Value = ord.Amount
excel.Range(String.Format("D{0}", row)).NumberFormat = "$#,##0.00"
row += 1
Next
excel.ActiveWorkbook.SaveAs(customerFile)
excel.ActiveWorkbook.Close()
MessageBox.Show("The orders report has been saved to My Documents")
Else
MessageBox.Show("This application can't save orders reports")
End If
// C#
if (AutomationFactory.IsAvailable)
{
try
{
excel = AutomationFactory.GetObject("Excel.Application");
}
catch (Exception ex1)
{
try
{
excel = AutomationFactory.CreateObject("Excel.Application");
}
catch (Exception ex2)
{
MessageBox.Show("This application can't save orders reports");
return;
}
}
excel.Workbooks.Add();
excel.Range["A1"].Value = "Orders placed by " + customer.CompanyName;
excel.Range["A1"].Font.Size = 14;
excel.Range["A1"].Font.Bold = true;
excel.Range["A3"].Value = "Order";
excel.Range["A3"].Font.Bold = true;
excel.Range["A3"].HorizontalAlignment = 4;
excel.Range["B3"].Value = "Ordered";
excel.Range["B3"].Font.Bold = true;
excel.Range["B3"].HorizontalAlignment = 4;
excel.Range["C3"].Value = "Shipped";
excel.Range["C3"].Font.Bold = true;
excel.Range["C3"].HorizontalAlignment = 4;
excel.Range["D3"].Value = "Amount";
excel.Range["D3"].Font.Bold = true;
excel.Range["D3"].HorizontalAlignment = 4;
excel.Columns["A:A"].ColumnWidth = 10;
excel.Columns["B:D"].ColumnWidth = 12;
int row = 4;
foreach (OrderSummary ord in orders)
{
excel.Range(string.Format("A{0}", row)).Value = ord.OrderId;
excel.Range(string.Format("B{0}", row)).Value = ord.OrderDate;
if (ord.ShippedDate != DateTime.Parse("12:00:00 AM"))
{
excel.Range(string.Format("C{0}", row)).Value = ord.ShippedDate;
}
excel.Range(string.Format("D{0}", row)).Value = ord.Amount;
excel.Range(string.Format("D{0}", row)).NumberFormat = "$#,##0.00";
row += 1;
}
excel.ActiveWorkbook.SaveAs(customerFile);
excel.ActiveWorkbook.Close();
MessageBox.Show("The orders report has been saved to My Documents");
}
else
{
MessageBox.Show("This application can't save orders reports");
}
This code follows the same pattern as the previous code. If it succeeds in retrieving a reference to Excel, it uses familiar code to create a report listing the orders for the selected customer.