Quantcast
Channel: MSDN Blogs
Viewing all 5308 articles
Browse latest View live

Spatial Data Analysis with R

$
0
0

Guest blog by Jason Zhang Microsoft Student Partner at the University of Cambridge

image

Hi, I am  Jason, a third year Natural Sciences student in University of Cambridge. With great interest in Microsoft and its work in Data Science, I joined the Microsoft Student Partner program in 2016.

I then attended the Microsoft Professional Program, Data Science track, which covered Transact-SQL, Power BI, Statistics, Machine Learning and Applied Machine Learning. The program provides me with a solid grounding for pursuing a career in Data Science and it is offered free to MSPs.

What is spatial data?

Spatial data is one of the most common data types in our everyday life, and it refers to all types of data objects or elements that are present in a geographical space or horizon. It enables the global finding and locating of individuals or devices anywhere in the world. Spatial data is also known as geospatial data, spatial information or geographic information.

Spatial data is used in geographical information systems (GIS) and other geolocation or positioning services. Spatial data consists of points, lines, polygons and other geographic and geometric data primitives, which can be mapped by location, stored with an object as metadata or used by a communication system to locate end user devices. Spatial data may be classified as scalar or vector data. Each provides distinct information pertaining to geographical or spatial locations.

How is spatial data represented?

Different programming languages have different representations but they share similar concepts.

For example, in R:

· Points can be represented by ‘SpatialPoints’ dataframe, which is a set of geographical points, represented by their latitudes and longitudes. The bounding box is also specified in the dataframe, namely the boundary values for the latitudes and longitudes of the points within the dataframe.

· Polygons can be represented by ‘SpatialPolygon’ dataframe, which represents a geographical polygon with various dataframes of other information about the represented polygon area. For instance, the city of London can be represented by a SpatialPolygonDataFrame which contains its population, famous tourist attractions, tube maps and so on.

· Grids can be represented by ‘SpatialPixels’ dataframe, which contains bounding box coordinates, properties of this spatial grid and it contains many more points than a spatial polygon as it is a grid structure.

With the help of these spatial dataframes, the spatial data can be easily represented, and further manipulated.

image

Figure 1. The Newhaven dataset in GISTools package contains spatial data, and for example breach is a SpatialPoints dataset.

image

Figure 2. blocks in Newhaven dataset is a SpatialPolygon Dataframe.

Furthermore, if the data is stored in SQL database, it is also possible to execute R (or other) code within Transact-SQL, by calling execute sp_execute_external_script, and specifying related details. With this approach, the data can be directly used in the R code.

In SQL server, there is also a data type for spatial data called ‘geography’, which can be used to represent spatial points, lines and polygons.

Visualisation of spatial data

Graphs are very often more informative than texts or tables, so visualisation is an essential part in spatial data analysis.

Firstly, to get a general idea of the spatial dataset, R provides many convenient tools:

· The plot function can be called to show the various components in the dataset, such as points, lines and polygons.

· The bubble function can be used to show the density distribution by the sizes of the bubbles.

· The choropleth (a colour shaded map) function can be used to create a plot demonstrating the block-by-block distribution of a certain property by the colour scale.

image

Figure 3. Visualisation of the dataset with simple plot functions.

Secondly, it is useful to explore how the nearby spatial points are correlated, for which purpose a variogram can be used: a function describing the degree of spatial dependence of a spatial random field or stochastic process.

As a concrete example from the field of gold mining, a variogram will give a measure of how much two samples taken from the mining area will vary in gold percentage depending on the distance between those samples. Samples taken far apart will vary more than samples taken close to each other.

To generate a variogram with data set x in R, first calculate the variogram using the variogram function, and then fit the variogram onto the data set with fit.variogram function.

Thirdly, to get a more interactive and detailed representation, PowerBI can be used:

· Import data from the source of choice, e.g. from SQL Server Database on Azure, and load them into the data model.

· The data will be automatically shown on a map (if not then choose map as the representation), and we can choose the size of the points to be proportional to the density of the pollution.

· Many other tools and fields can be used for further analysis, e.g. filter for neater and more concise representation, tooltips for extra fields.

Predictive models

Spatial data can be used to build various predictive models, for example kernel density estimation (KDE), K nearest neighbour (KNN), kriging or Gaussian process regression.

The detailed theories are well documented online, but the general ideas are:

· KDE is to fit a probability distribution model according to the density distribution of the data;

· KNN is to use x’s K-Nearest Neighbour to vote on what x’s label should be, and the voting scheme can be weighted by distances.

· Kriging is to predict the spatial distribution y(x) by minimising the variance of the prediction error, where the prediction error is the difference between true y(x) and predicted y(x). Or equivalently, Gaussian processes are to achieve the same goal by maximum likelihood interpretation.

KDE can be implemented in R by simply using the kde package:

· The kde.points function can be called on ‘SpatialPoints’ dataframes to generate a density estimator.

· The density distribution (also the probability distribution) can then be visualized by various plots, such as level plots (level.plot) and so on.

Kriging is implemented in R by krige function in geoR package:

· First generate a fitted variogram model of the spatial data set, as described in the previous chapter.

· Then apply kriging onto the fitted model, along with the data set, by calling krige function.

· Finally, we can visualise the result by spatial plot function spplot, or other plotting techniques.

Introduction to Microsoft R Server

Overview

R Server is an enterprise class server for hosting and managing parallel and distributed workloads of R processes on servers (Linux and Windows) and clusters (Hadoop and Apache Spark).

It provides an execution engine for solutions built using Microsoft R packages, extending open source R with support for high-performance analytics, statistical analysis, machine learning scenarios, and massively large datasets. Value-added functionality is provided through proprietary packages that install with the server.

Why R Server

The reason why data scientists starting with R Client or open source R typically move to R Server, is that very often the data size or computational scale require additional capacity, and R Server provides the infrastructure for distributing a workload across multiple nodes (referred to as data chunking), running jobs in parallel, and then reassembling the results for further analysis and visualization.

In addition to capacity and scale, R Server offers machine learning features and allows you to operationalize your analytics. You can use Microsoft R Server as the deployment engine for your advanced R analytics. Regardless of the source, language or method, you can simplify, deploy, and realize the promise and power of advanced analytics.

How to use R Server

R Server runs as a background process that starts up when you launch the Rgui or an R IDE such as R Tools for Visual Studio (RTVS), RStudio, or other applications. Generally, you can use any R IDE that can consume R packages.

Data scientists who use R Server typically connect over Remote Desktop, and then use RTVS or another to create or run solutions interactively. Solutions are usually script files that include a combination of R functions and functions from proprietary packages: RevoScaleR, MicrosoftML, mrsdeploy, RevoPema, and so forth.

Microsoft R Server can be found free under Microsoft Imagine.

Machine Learning

In R Server, you can use the MicrosoftML package, which provides state of the art, fast, scalable machine learning algorithms and transforms. These functions enable you to tackle common machine learning and data science tasks such as text and image featurization, classification, anomaly detection, regression and ranking. The goal is to help developers, data scientists, and an increasing spectrum of information workers to the design and implement intelligent products, services and devices.

This topic discusses these tasks and lists the key R functions provided by this package for transforming and modelling data that facilitate the completion of these data science tasks. You can also install pre-trained cognitive models for sentiment analysis and image featurization, when you select them in R Server Setup.

Summary

Spatial data plays an essential role in various areas and by adopting the appropriate analysis tools, applying the suitable methodologies, a great amount of information can be extracted from it. This information can then be used to build predictive models or further analysis, and Microsoft provides toolkits for the whole process:

· Data Collection with Azure IoT Suite

· Data Storage on Azure SQL Server

· Data Visualisation with PowerBI or Excel

· Data Manipulation with Microsoft R Server

· Predictive model with Azure ML

Resources

· https://www.microsoft.com/en-gb/internet-of-things/azure-iot-suite – Azure IoT Suite

· https://docs.microsoft.com/en-us/r-server/what-is-microsoft-r-server – Microsoft R Server

· https://imagine.microsoft.com/en-us/Catalog – Free MRS under MI

· https://powerbi.microsoft.com/en-us/ – Power BI

· https://products.office.com/en-gb/excel – Excel

· https://azure.microsoft.com/en-gb/services/machine-learning/ – Azure ML

· https://azure.microsoft.com/en-us/ – Microsoft Azure

· https://courses.edx.org/courses/course-v1:Microsoft+DAT203.3x+2T2017/info – A good course on this topic (free auditing)


Small Basic: Teaching Girls to Code! — What are we doing and where are we headed?

$
0
0

Small Basic is focusing on teaching girls to code. As we build improvements like the online version we describe in this video, the improvements are also beneficial as we teach boys as well as girls. This video shows how we’re headed toward an online version, more social/collaborative features, and we’re building out curriculum to teach girls how to code in workshops. In the nearer term, we’re also working on (1) shipping Small Basic 1.3 (Desktop, with bug fixes, new translated languages, and improved error messaging), (2) building a Small Basic certification course for teachers (on Microsoft in Education), (3) creating a Small Basic Coding Clubs curriculum for girls to lead coding clubs at school, and (4) taking Small Basic open source, so that the community can help us improve it.

Here is the transcript:

From 2000 to 2012, there has been a 64% decline in the number of women majoring in Computer Science! In 2014, only 17% of Computer Science graduates were women! And in 2015, the entire tech sector was only 25% women!

We’re working together to make this more inclusive, to empower everyone, and to create opportunities for all!

We picked Microsoft Small Basic, a simple but powerful syntax language and IDE that includes a kids version of IntelliSense, and a Help pane that teaches you as you go! You don’t need to be a developer to use it. You just start typing… and go!

Small Basic is Gradual. You can click Graduate to move your code into Visual Studio Code, where you can continue learning Visual Basic, JavaScript, C#, Java, Python, and more!

We’re updating Small Basic to add tutorials into the UI, to teach girls the way they learn, with a story and content they enjoy. Second, we’re creating a Web version to be compatible with all devices, and adding more sharing features to allow girls to share code and collaborate with their friends. With the Small Basic Web version, you don’t need to install anything. You can just use your browser. And you can maintain your privacy. You don’t need to log in, create an account, or share your identity to share your program with friends.

We offered 3 workshops at Bring Your Kids to Work Day, where we taught kids Small Basic and had a lot of fun! We collaborated with a local professor and learned that women skewed toward a comprehensive information processing style and guided learning experiences. Girls were able to follow the tutorial or experiment on their own.

We picked a language that was easy for parents to learn so that they could help and encourage their kids.

What can a girl be if she starts coding at age 9? (Quotes from girls…)

  1. A computer engineer
  2. A builder
  3. A doctor
  4. A vet
  5. A fashion designer
  6. A nurse
  7. A computer engineer just like my dad
  8. The President
  9. A software developer
  10. An NHL player

…Anything she wants!

 

==============

Thank you for joining us on this Small and Basic journey!

– Ninja Ed

 

Digital Workplace Conference Sydney 23-24 August

$
0
0

18612 STP Badges I'm speaking

I’m so looking forward to speaking at the Digital Workplace Conference in Sydney next month. Last time I spoke at this conference (when it was still the SharePoint Conference), I talked about building and creating documents with the OpenXML SDK and SharePoint2010 Word Automation Services. This ended up as one of my my most popular blog posts (part 1 and part 2).

This year I’ll be talking about developing extensions for Office Client Applications with the new HTML-based app model.

Kudos to Debbie Ireland, Mark Rhodes and the team for putting together another stellar conference.

Register Now.

SCOM – Create new network discovery rule via PowerShell

$
0
0

I recently had to setup a lot of SCOM management groups with the same network discovery rule. I soon found out there isn’t a powershell cmdlet for it. Of course, it’s the kind of thing you don’t really need that often, as only one discovery rule is allowed per management server. Anyway, I needed one, so I wrote one, and I hope this saves someone some time in the future.

#
# Name: Udated OM-Create-Network-Discovery-Rule.ps1
# Written by: Rafaela Brownlie
# Date: 20/06/17
# Description: The script programatically builds SNMP run as account, and builds a discovery rule to discover the UPS
# $OMFQDN stores the FQDN for the SCOM server
# $HostIP = Network device ip address
# I wrote it for SCOM 2012 R2. I haven't tested on SCOM 2016, but I believe it should work.
# the functionality requires the the Operations Manager firewal rules for ping back and snmp enabled.


$OMFQDN = ""
$hostIP = ""

Write-Host "enbling firewall rules for $OMFQDN" -ForegroundColor Magenta
$Netrules = @('Operations Manager SNMP Response','Operations Manager SNMP Request', 'Operations Manager SNMP Trap Listener', 'Operations Manager Ping Response (Echo Response - ICMPv4 IN)')
invoke-command -ComputerName $OMFQDN -Args $Netrules -ScriptBlock {
param($rule1, $rule2,$rule3,$rule4)
$rule1, $rule2,$rule3,$rule4 | %{get-netfirewallrule -DisplayName $_ | set-netfirewallrule -enabled true}
}


#enable scom firewall rules
Get-SCOMManagementGroupConnection | Remove-SCOMManagementGroupConnection


Write-Host "Connecting to SCOM MG $OMFQDN" -ForegroundColor Magenta


New-SCOMManagementGroupConnection -ComputerName $OMFQDN

Get-SCOMManagementGroupConnection


$mg = Get-SCOMManagementGroup -ComputerName $OMFQDN
$resourcepool = get-scomresourcepool -DisplayName "All Management Servers*"


$discovery = $mg.NetworkDiscovery.GetNetworkDiscoveries()


if ($discovery -ne $null){
Write-Host "there is one network discovery for this MS" -BackgroundColor Magenta


break
}


$Account = Get-SCOMrunAsAccount -Name "SNMPv1 Account"

If($Account -eq $null)
{


Write-Host "Creating account" -ForegroundColor Magenta
# $a = Get-Credential -Message "Enter community string in password field"
Write-Host "Creating account" -ForegroundColor Magenta
Add-SCOMRunAsAccount -Name "UPS SNMPv1" -Descrption "Account used for Eaton UPS monitoring" -CommunityString -String $a.Password
$Account = Get-SCOMrunAsAccount -Name "UPS SNMPv1"
Write-Host "distributing account" -ForegroundColor Magenta
Set-SCOMRunAsDistribution -RunAsAccount $Account -LessSecure

Write-Host "Waitin for account to be created" -backgroundColor Magenta


sleep -Seconds 60
}


$Profile = Get-SCOMRunAsProfile -DisplayName "SNMP Monitoring Account"
Set-SCOMRunAsProfile -Action "Add" -Profile $Profile -Account $Account


$ms = (Get-SCOMManagementServer)
#set account distribution to more secure.


Write-Host "creating configuration object" -ForegroundColor Magenta
$networkconfiguration = New-Object Microsoft.EnterpriseManagement.NetworkMonitoring.NetworkDiscoveryConfiguration
$networkconfiguration.DefaultRetryCount = 3
$networkconfiguration.DefaultSnmpPort = 161
$networkconfiguration.SnmpDefaultAutoTimeoutMilliseconds = 1500
$networkconfiguration.IcmpDefaultAutoTimeoutMilliseconds = 500
$networkconfigurationtype = New-Object Microsoft.EnterpriseManagement.NetworkMonitoring.NetworkDiscoveryType
$networkconfigurationtype.value__ = 0
$networkconfiguration.Type = $networkconfigurationtype
Write-Host "creating SNMP host object" -ForegroundColor Magenta
$SNMPCommunity =[Microsoft.EnterpriseManagement.NetworkMonitoring.Snmpv1Community]::create($mg, $account
$snmpHost = New-Object Microsoft.EnterpriseManagement.NetworkMonitoring.SnmpHost


#my snmp host IP addresses.
$snmpHost.Host = $hostIP
$snmpHost.Community = $SNMPCommunity
#you could add more than one host here:
$networkconfiguration.Seeds.add($snmphost)
$networkconfiguration.Communities.add($SNMPCommunity)
Write-Host "creating discovery object" -ForegroundColor Magenta
$networkdiscovery = new-object Microsoft.EnterpriseManagement.NetworkMonitoring.NetworkDiscovery
#Name of the discovery rule:
$networkdiscovery.DisplayName = "NetoworkDiscovery"
$networkdiscovery.Enabled = $true
$networkdiscovery.MonitoringServerPool = $resourcepool
$networkdiscovery.Configuration = $networkconfiguration
$networkdiscovery.NetworkDiscoveryAgent = Get-SCOMClassInstance -Class (Get-SCOMclass -DisplayName "health service") | where displayname -eq $OMFQDN


Write-Host "creating Disccovery rule" -ForegroundColor Magenta
$mg.NetworkDiscovery.InsertNetworkDiscovery($networkdiscovery)
#allow some time for discovery creation
sleep -Seconds 40
#Run the discovery once it's created:
Start-SCOMTask -Task (get-scomtask -name System.NetworkManagement.FullOnDemandDiscovery) -Instance (Get-SCOMMonitoringObject -Class (Get-SCOMClass -DisplayName "Network Discovery Server"))

Create Bot for Microsoft Graph with DevOps 12: BotBuilder features – Implementing Proactive Messsaging

$
0
0

In this article, I implement proactive messaging feature to O365Bot. You can see the detail about proactive messaging here. There are several useful scenario for O365 notification. In this article, I implement event change notification as it is important to me.

Subscribe Microsoft Graph Event update

To receive Microsoft Graph Event update, you can use Webhook. See the detail here.

1. Add INotificationService.cs in Services folder and replace the code.

using System.Threading.Tasks;

namespace O365Bot.Services
{
    public interface INotificationService
    {
        Task<string> SubscribeEventChange();
        Task RenewSubscribeEventChange(string subscriptionId);
    }
}

2. Update IEventService.cs to get a single event.

using Microsoft.Graph;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace O365Bot.Services
{
    public interface IEventService
    {
        Task<List<Event>> GetEvents();
        Task CreateEvent(Event @event);
        Task<Event> GetEvent(string id);
    }
}

3. Inherit INotificationService in GraphService.cs and implement the method. In SubscribeEventChange method, I specify the currently running web app address as webhook callback.

using AuthBot;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Graph;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Web;

namespace O365Bot.Services
{
    public class GraphService : IEventService, INotificationService
    {
        IDialogContext context;
        public GraphService(IDialogContext context)
        {
            this.context = context;
        }

        public async Task CreateEvent(Event @event)
        {
            var client = await GetClient();

            try
            {
                var events = await client.Me.Events.Request().AddAsync(@event);
            }
            catch (Exception ex)
            {
            }
        }

        public async Task<Event> GetEvent(string id)
        {
            var client = await GetClient();

            var @event = await client.Me.Events[id].Request().GetAsync();

            return @event;
        }

        public async Task<List<Event>> GetEvents()
        {
            var events = new List<Event>();
            var client = await GetClient();

            try
            {
                var calendarView = await client.Me.CalendarView.Request(new List<Option>()
                {
                    new QueryOption("startdatetime", DateTime.Now.ToString("yyyy/MM/ddTHH:mm:ssZ")),
                    new QueryOption("enddatetime", DateTime.Now.AddDays(7).ToString("yyyy/MM/ddTHH:mm:ssZ"))
                }).GetAsync();

                events = calendarView.CurrentPage.ToList();
            }
            catch (Exception ex)
            {
            }

            return events;
        }

        public async Task<string> SubscribeEventChange()
        {
            var client = await GetClient();
            var url = HttpContext.Current.Request.Url;
            if (url.Host == "localhost")
               return "";
            var webHookUrl = $"{url.Scheme}://{url.Host}:{url.Port}/api/Notifications";

            var res = await client.Subscriptions.Request().AddAsync(
            new Subscription()
            {
                ChangeType = "updated, deleted",
                NotificationUrl = webHookUrl,
                ExpirationDateTime = DateTime.Now.AddDays(1),
                Resource = $"me/events",
                ClientState = "event update or delete"
            });

            return res.Id;
        }

        public async Task RenewSubscribeEventChange(string subscriptionId)
        {
            var client = await GetClient();
            var subscription = new Subscription()
            {
                ExpirationDateTime = DateTime.Now.AddDays(1),
            };

            var res = await client.Subscriptions[subscriptionId].Request().UpdateAsync(subscription);
        }

        private async Task<GraphServiceClient> GetClient()
        {
            GraphServiceClient client = new GraphServiceClient(new DelegateAuthenticationProvider(AuthProvider));
            return client;
        }

        private async Task AuthProvider(HttpRequestMessage request)
        {
            request.Headers.Authorization = new AuthenticationHeaderValue(
            "bearer", await context.GetAccessToken(ConfigurationManager.AppSettings["ActiveDirectory.ResourceId"]));
        }
    }
}

Notify the event change

There are at least two types of notifications. Simply notification and complex notification as a form of dialog. I will borrow several codes from BotBuilder samples.

Interrupt current conversation

1. To send a dialog as notification, we need to interrupt current conversation. The idea is similar to global messaging handler, but we interrupt the conversation from Bot application side, not user input. Add ConversationStarter.cs at root folder and replace the code.

using Autofac;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Dialogs.Internals;
using Microsoft.Bot.Connector;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace O365Bot
{
    public class ConversationStarter
    {
        /// <summary>
        /// Insert the dialog on current conversation.
        /// </summary>
        public static async Task Resume(Activity message, IDialog<object> dialog)
        {
            var client = new ConnectorClient(new Uri(message.ServiceUrl));

            using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
            {
                var botData = scope.Resolve<IBotData>();
                await botData.LoadAsync(CancellationToken.None);
                var task = scope.Resolve<IDialogTask>();
               
                task.Call(dialog.Void<object, IMessageActivity>(), null);
                await task.PollAsync(CancellationToken.None);
                await botData.FlushAsync(CancellationToken.None);
            }
        }
    }
}

2. Add caching service to store current information. In production, you need to implement something scalable. Add CacheService.cs in Services folder.

using System.Collections.Generic;

namespace O365Bot.Services
{
    public static class CacheService
    {
        public static Dictionary<string, object> caches = new Dictionary<string, object>();
    }
}

3. Add using to RootDialog.cs

using Autofac;
using Microsoft.Bot.Builder.ConnectorEx;
using O365Bot.Services;

4. Update DoWork method in RootDialog.cs to store current conversation information. BotBuilder lets us store current conversation information as a form of ConversationReference. I store them by mapping subscription id of Microsoft Graph notification.

private async Task DoWork(IDialogContext context, IMessageActivity message)
{
    using (var scope = WebApiApplication.Container.BeginLifetimeScope())
    {
        var service = scope.Resolve<INotificationService>(new TypedParameter(typeof(IDialogContext), context));

        // Subscribe to Office 365 event change
        var subscriptionId = context.UserData.GetValueOrDefault<string>("SubscriptionId", "");
        if (string.IsNullOrEmpty(subscriptionId))
        {
            // Subscribe to Microsoft Graph Notification and get SubscriptionId
            subscriptionId = await service.SubscribeEventChange();
            context.UserData.SetValue("SubscriptionId", subscriptionId);
        }
        else
            await service.RenewSubscribeEventChange(subscriptionId);

        // Convert current message as ConversationReference.
        var conversationReference = message.ToConversationReference();

        // Map the ConversationReference to SubscriptionId of Microsoft Graph Notification.
        if (CacheService.caches.ContainsKey(subscriptionId))
            CacheService.caches[subscriptionId] = conversationReference;
        else
            CacheService.caches.Add(subscriptionId, conversationReference);
        // Store locale info as conversation info doesn't store it.
        if (!CacheService.caches.ContainsKey(message.From.Id))
            CacheService.caches.Add(message.From.Id, Thread.CurrentThread.CurrentCulture.Name);
    }

    if (message.Text.Contains("get"))
        // Chain to GetEventDialog
        await context.Forward(new GetEventsDialog(), ResumeAfterDialog, message, CancellationToken.None);
    else if (message.Text.Contains("add"))
        // Chain to CreateEventDialog
        context.Call(new CreateEventDialog(), ResumeAfterDialog);
}

5. Add a dialog for notification event update. Add NotifyEventChageDialog.cs in Dialogs folder and replace code.

using Autofac;
using Microsoft.Bot.Builder.Dialogs;
using O365Bot.Services;
using System;
using System.Threading.Tasks;

namespace O365Bot.Dialogs
{
    [Serializable]
    public class NotifyEventChageDialog : IDialog<object>
    {
        private string id;
        public NotifyEventChageDialog(string id)
        {
            this.id = id;
        }

        public async Task StartAsync(IDialogContext context)
        {
            PromptDialog.Choice(context, this.AfterSelectOption, new string[] { "Check the detail", "Go back to current conversation." }, "One of your events has been updated.");
        }

        private async Task AfterSelectOption(IDialogContext context, IAwaitable<string> result)
        {
            var answer = await result;

            if (answer == "Check the detail")
            {
                await context.PostAsync("Check the detail");
                using (var scope = WebApiApplication.Container.BeginLifetimeScope())
                {
                    IEventService service = scope.Resolve<IEventService>(new TypedParameter(typeof(IDialogContext), context));
                    var @event = await service.GetEvent(id);
                    await context.PostAsync($"{@event.Start.DateTime}-{@event.End.DateTime}: {@event.Subject}@{@event.Location.DisplayName}-{@event.Body.Content}");
                }
            }

            await context.PostAsync("Going back to the original conversation.");
            context.Done(String.Empty);
        }
    }
}

Add Controller

1. To accept notification request from external systems, add NotificationsController.cs file to Controllers folder and replace the code.

using Microsoft.Bot.Connector;
using Microsoft.Graph;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using O365Bot.Dialogs;
using O365Bot.Services;
using System;
using System.Globalization;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
using cg = System.Collections.Generic;
namespace O365Bot
{
    public class NotificationsController : ApiController
    {
        public async Task<HttpResponseMessage> Post(object obj)
        {
            var response = Request.CreateResponse(HttpStatusCode.OK);

            // Verify the webhook subscription.
            if (Request.RequestUri.Query.Contains("validationToken"))
            {
                response.Content = new StringContent(Request.RequestUri.Query.Split('=')[1], Encoding.UTF8, "text/plain");
            }
            else
            {
                var subscriptions = JsonConvert.DeserializeObject<cg.List<Subscription>>(JToken.Parse(obj.ToString())["value"].ToString());
                try
                {
                    foreach (var subscription in subscriptions)
                    {
                        if (CacheService.caches.ContainsKey(subscription.AdditionalData["subscriptionId"].ToString()))
                        {
                            // Get ConversationReference by using SubscriptionId.
                            var conversationReference = CacheService.caches[subscription.AdditionalData["subscriptionId"].ToString()] as ConversationReference;
                            // Get the event id.
                            var id = ((dynamic)subscription.AdditionalData["resourceData"]).id.ToString();

                            // Get local id and set it.
                            var activity = conversationReference.GetPostToBotMessage();
                            var locale = CacheService.caches[activity.From.Id].ToString();
                            Thread.CurrentThread.CurrentCulture = new CultureInfo(locale);
                            Thread.CurrentThread.CurrentUICulture = new CultureInfo(locale);

                            // Interrupt current conversation.
                            await ConversationStarter.Resume(
                                activity,
                                new NotifyEventChageDialog(id));
                        }
                        var resp = new HttpResponseMessage(HttpStatusCode.OK);
                        return resp;
                    }
                }
                catch (Exception ex)
                {
                    return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
                }

            }
            return response;
        }
    }
}

2. Register the type in Application_Start method in Global.asax.cs.

builder.RegisterType<GraphService>().As<INotificationService>();

Test with emulator

As Microsoft Graph webhook requires reachable URL, I need to test this after publish the bot.

However, as I didn’t implement test yet, CD/CI pipeline shall fail, thus simply publish it from Visual Studio this time for test purpose.

1. Run the emulator and open App Settings.

image

2. Follow the instruction on the screen to setup “ngrok” which lets the emulator connect to published bot.

image

3. Enter URL, App ID and Password to connect. Connect to the production instance.

image

4. Enter “add appointment”. You may need authentication.

image

5. After the authentication, start creating an event.

image

6. Then, update any event in your calendar to see if you get the notification.

image

7. Select option and confirm it returns to previous conversation at the end.

image

Check-in all source code to VSTS. Do not mind about test failure at this point.

Summery

Send rich complex notification is other key feature for intelligent bot. I will implement or consider unit and function testing for this in the next article.

Ken

Visual Studio 2017 RTM中的C++代码分析改进

$
0
0

发表时间:2017.3.7

作者:Sunny Chatterjee

原文发表地址: https://blogs.msdn.microsoft.com/vcblog/2017/03/07/c-code-analysis-improvements-in-visual-studio-2017-rtm/

Visual Studio 2017 RTM发布的版本包含核心指南检查器作为C/C++代码分析工具的一部分。我们通过我们的外部客户对这些检查的早期预览获得了大量有用的反馈。感谢您与我们的合作,并给予我们很大的反馈。这个反馈帮助我们提高了最终发布的C++核心指南检查的质量。其中有关const正确性的改进在这篇博客中有详细的解释。

除了发布C++核心指南检查器,我们还在我们的核心分析引擎中修复了超过150个错误。所有这些修复程序都可在Visual Studio2017 RTM中使用。今天就下载使用Visual Studio 2017,让我们知道你对代码分析改进的看法!

这里有一些值得注意的修复,因为它经常出现。这些修复将作为直接外部反馈的结果。

  1. 在取消引用空指针检查期间出现误报(C6011)
  1. 在未初始化记忆检查时出现误报(C6011)
  1. 关于不一致注解检查出现的误报(C28252和C28253)
  1. 在注解解析时出现误报(C28285)
  1. 在严格类型匹配检查出现误报(C28039)
  1. 在本地vs下检查枚举类,对全局声明时出现误报(C6244)
  1. 代码分析运行期间MSBuild错误MSB4018:”MergeNativeCodeAnalysis”任务意外失败

给我们您的回馈!

我们希望Visual Studio 2017中的C ++代码分析工具可以帮助您改进代码并提高效率。 我们非常感谢大家,一如既往,我们欢迎您的反馈。 请告诉我们您对我们目前的工具集的喜好和不满,以及您将来发布的内容。 对于问题,请通过“安装程序”或“Visual Studio IDE”本身的“报告问题”选项来了解问题。 您也可以通过电子邮件cppcorecheck@microsoft.com与我们联系。

从Visual Studio中定位Linux的Windows子系统

$
0
0

原文发表地址:https://blogs.msdn.microsoft.com/vcblog/2017/02/08/targeting-windows-subsystem-for-linux-from-visual-studio/

作者:Marc Goodner

适用于Linux的Windows Subsystem的子系统(WSL)在2016年首次推出,并作为Windows10周年更新中的早期测试版。从此以后,WSL团队一直为此努力工作,大大提高WSL能够运行越来越多的本机Linux命令行二进制文件和工具,包括大多数主流的开发工具,平台和语言,以及很多后台进程服务*包括MySQL, Apache和SSH。

      在Visual Studio 2017中使用”C++ Linux开发的工作负荷,您可以使用Visual Studio的全部功能进行C / C ++ Linux开发。 因为WSL只是另一个Linux系统,您可以按照我们的使用Linux工作负荷指南,从Visual Studio中进行定位。 这为您提供了大量的灵活性,使您的开发机器上的整个开发周期保持在本地,而不需要单独的VM或机器的复杂性。 然而,值得介绍如何在Bash / WSL上更详细地配置SSH。

安装WSL

      如果你还没有这样做,你首先需要启用开发人员模式并安装WSL本身 这只需要几秒钟,但需要重新启动。    当您第一次运行Bash时,您需要按照屏幕上的说明接受Canonical的许可证,下载Ubuntu映像,并将其安装在您的计算机上。 然后,您需要选择UNIX用户名和密码。 这不需要与您的Windows登录用户名和密码相同,如果你喜欢。 您将只需要在以后使用sudo执行命令或者“远程”登录时输入UNIX用户名和密码(如下:)。

      现在你将在你的机器上有一个vanilla Ubuntu实例,您可以在其中运行任何ELF-64 Linux二进制文件,包括使用apt-get下载的二进制文件!

在我们继续之前,让我们安装build-essential包,以便你有一些关键的开发工具,包括GNU C ++编译器,链接器等:

$ sudo apt install -y build-essential

安装&配置SSH

让我们使用‘apt’软件包管理器在Bash / WSL上下载和安装SSH:

$ sudo apt install -y openssh-server

     在我们启动SSH之前,您需要配置SSH,但您只需要执行一次。 运行以下命令编辑sshd配置文件:

$ sudo nano /etc/ssh/sshd_config

滚动到” PasswordAuthentication “所在的位置,然后确保它被设置为”yes“

CTRL+X退出,然后按Y保存。

现在为SSH实例生成SSH密钥:

$ sudo service ssh start

*注意:你每次启动第一个Bash控制台时都需要这样做。 作为一个预防措施,当您关闭最后一个Bash控制台时,WSL目前正在删除所有Linux进程

安装和配置Visual Studio

为了获得最佳体验,我们建议安装Visual Studio 2017 RC(或更高版本)以使用Visual C ++ for Linux。 在安装过程中务必选择Visual C ++ for Linux工作负荷。

现在,您可以从Visual Studio通过转到工具>选项>跨平台>连接管理器连接到Windows Subsystem for Linux。 单击添加并输入“localhost”作为主机名和您的WSL用户/密码。

现在您可以使用此连接与任何现有的C + + Linux项目或创建一个新的Linux项目在文件>新项目> Visual C ++>跨平台> Linux下。

今后,我们将发布更详细的文章,展示使用WSL的优势,特别是利用使用Linux工作负载构建的二进制文件在远程Linux系统上部署时的兼容性。

目前,现在,从Windows 10创意者更新开始,在Windows子系统Linux(Bash / WSL)上的Bash从Visual Studio的角度来看是一个真正的Linux系统。

SCOM – Remotely update Management Group configuration on SCOM agent via PowerShell

$
0
0

One of my customers installed the agent via SCCM and it had a typo in the management group name. This script removes the current management group configuration the agent is assigned to, and adds a new management group configuration with the correct management group name.

$OLDMG = "oldMG"
$newMG = "newMG1"
$MS = "serverOM"
$Agentlist = "computer1",”computer2”,”computer3”
$Agentlist | % {Invoke-command -computername $_ -ArgumentList $oldMG,$newMG,$MS -scriptBlock {
param($oldMG,$newMG, $MS)
try {$o = new-object -com AgentConfigManager.MgmtSvcCfg
#remove old MG name and disable AD integration
try {
$oMG= @($o.getmanagementgroup($oldMG))
if ($oMG.count -ne $null)
{
$o.RemoveManagementGroup($oldMG)
$o.DisableActiveDirectoryIntegration()
$o.reloadconfiguration()
write-host "Removed $oldMG from agent configuration" -ForegroundColor Green
$o=new-object -com AgentConfigManager.MgmtSvcCfg
$o.getmanagementgroups()
}
}
catch {write-host "MG $oldMG not found" -ForegroundColor Magenta}
#add new MG Name
try {$nMG= @($o.getmanagementgroup($newMG))
Write-Host "agent already configured with $newMG" -ForegroundColor Magenta}
catch {
write-host "MG $newMG not found. Adding the new MG to agent's configuration" -ForegroundColor Green
$o.AddManagementGroup($newMG,$MS,5723)
$o.reloadconfiguration()
write-host "$newMG MG has been added to agent" -ForegroundColor Green
#clear the healthstore cache
get-service -Name HealthService | Stop-Service
Remove-Item "C:Program FilesMicrosoft Monitoring AgentAgentHealth Service StateHealth Service Store" -re -Force
get-service -Name HealthService | Start-Service
}
}
catch {write-host "Microsoft Monitoring Agent not installed"}
}
}

I’m always after this script, and I seem to always have re-write it. Maybe next time I need it I’ll remember it’s here


주간닷넷 2017년 6월 20일

$
0
0

.NET Architecture – 마이크로서비스 & 컨테이너

최근에 .NET 웹사이트에 아키텍처 기술 가이드가 추가되었습니다. 이 페이지들은 .NET의 각 타입별 애플리케이션 구현과 관련된 아키텍처 정보를 제공하고 있으며, 앞으로도 관련 내용을 계속 추가할 예정입니다.

여러 기술 항목 중 마이크로서비스 & 컨테이너(Microservices & Containers) 부분은 .NET의 마이크로서비스의 빌드, 배포부분에 관련한 유용한 정보가 포함되어있으며 이와 관련해서 .NET Product Team 매니저인 Cesar De la Torre는 두개의 eBooks을 집필하여 공유했습니다. 그 중 하나는 마이크로서비스의 디자인과 구현에 관한 내용이고 다른 하나는 운영환경의 배포와 관리에 대한 내용입니다. 또한 eShopOnContainers 샘플 애플리케이션을 학습하면서 컨테이너의 개념을 좀 더 쉽게 이해하실 수 있습니다.

On .NET 소식 : Omer Raviv – OzCode

Microsoft 빌드 컨퍼런스 기간 중 여러 참가자들과 인터뷰를 진행했었습니다. 이번주에는 Omer Raviv와의 인터뷰를 소개해드리려고 하며, Visual Studio 디버깅 확장툴인 OzCode 데모를 보실 수 있습니다. OzCode를 이용하면 Linq 표현식을 쉽게 디버그 하실 수 있으며, 편집기에서 바로 변수값도 확인하실 수 있습니다. 이번 인터뷰는 특히 디버깅에 관심 있으신 분들에게 많은 도움이 될 것입니다.

금주의 패키지: Sprache

개발자에게 문자열을 파싱하는 작업은 가장 흔하면서도 번거로운 기본 작업 중에 하나일 것 입니다. 문자열 파싱작업은 소규모의 업무용 DSL(Domain Specific Language)를 정의하고 분석하거나, 특이한 데이터 형식을 사용하거나, 또는 사용자가 정한 복잡합 형식을 분석하는 경우 텍스트를 데이터 구조로 변환하는 방법을 기술해야 합니다. 이러한 상황에서 작업 문자열은 어떠한 방법으로든 문자열에서 데이터로 변환 되어야만 프로그램에서 자료로서 활용하는 것이 가능합니다.

ANTLR라는 툴은 이러한 기능을 지원해주며, 이미 많은 언어의 문법이 정의되어 있어서 개발자가 복잡한 파싱도 쉽게 할 수 있도록 도와줍니다. 하지만 간단한 문자열 파싱에는 오히려 번거로울 수 있습니다. 대부분의 개발자들은 가볍게 사용할 수 있는 문자열 분석 엔진을 필요로 하는데, 이때 사용할 수 있는 툴이 Sprache입니다.

Sprache는 단순 파싱 작업에 적합한 문자열 파싱 엔진으로, 이제 더이상 정규식을 사용하지 않고도 파서를 이용하여 문자열 분석이 가능합니다.

Parser<string> identifier =
from leading in Parse.WhiteSpace.Many()
from first in Parse.Letter.Once()
from rest in Parse.LetterOrDigit.Many()
from trailing in Parse.WhiteSpace.Many()
select new string(first.Concat(rest).ToArray());
var id = identifier.Parse(" abc123 ");
Assert.AreEqual(“abc123”, id);

.NET 소식

ASP.NET 소식

C# 소식

F# 소식

VB 소식

Xamarin 소식

Azure 소식

UWP 소식

Data 소식

Game development소식

주간닷넷.NET Blog에서 매주 발행하는 The week in .NET을 번역하여 진행하고 있으며, 한글 번역 작업을 오픈에스지의 송기수 전무님의 도움을 받아 진행하고 있습니다.

song 송 기수, 기술 전무, 오픈에스지
현재 개발 컨설팅회사인 OpenSG의 기술이사이며 여러 산업현장에서 프로젝트를 진행중이다. 입사 전에는 교육 강사로서 삼성 멀티캠퍼스 교육센터 등에서 개발자 .NET 과정을 진행해 왔으며 2005년부터 TechED Korea, DevDays, MSDN Seminar등 개발자 컨퍼런스의 스피커로도 활동하고있다. 최근에는 하루 업무의 대다수 시간을 비주얼 스튜디오와 같이 보내며 일 년에 한 권 정도 책을 쓰고, 한달에 두 번 정도 강의를 하면 행복해질 수 있다고 믿는 ‘Happy Developer’ 이다.

Issues with Visual Studio Team Services – 07/10 – Mitigated

$
0
0

Final Update: Monday, July 10th 2017 21:07 UTC

We’ve confirmed VSTS is back to a healthy state as have many customers. The AAD team helped us recover from this issue by increasing throttling limits which helped the service drain out a backlog of auth related requests. Please note that we are still reviewing our telemetry to ensure there are no residual effects.

This was a major outage for our service and we’re committed to follow-up with a detailed post mortem that clarifies what happened and how we avoid a similar issue in the future. We’ll try to publish this post mortem before end of week in a new blog post.

Please accept our apologies for the impact this had on you and your team.

Sincerely,
Tom


Update: Monday, July 10th 2017 20:11 UTC

The overall AAD issue has been resolved and their status is currently green in the Azure Service Health Dashboard. The continuing issues in VSTS are related to a high rate of calls our service is making to AAD as it recovers from the incident. We are working with the AAD team to push out a mitigation that we hope will resolve the issue for VSTS. We’ll provide another update soon.

  • Next Update: Before Monday, July 10th 2017 21:15 UTC

Sincerely,
Tom


Update: Monday, July 10th 2017 18:53 UTC

The AAD team applied an initial mitigation however we continue to experience issues related to authentication and authorization. The root cause is still not fully understood and we’re coordinating with our AAD partners. Customers will experience issues with login using both AAD and Microsoft account (e.g. – <user>@outlook.com) and intermittent errors when interacting with the service.

  • Next Update: Before Monday, July 10th 2017 21:15 UTC

Sincerely,
Tom


Update: Monday, July 10th 2017 17:29 UTC

There is an active issue with Azure Active Directory (AAD) that is impacting some VSTS causing login errors. Additionally, some logged in users may intermittent HTTP 500 errors when interacting with the service for this URL – https://app.vssps.visualstudio.com/_signedin:

Image

The AAD Team is aware of this issue and actively working to mitigate it. An status update is being posted by the AAD Team on the Azure Service Health Dashboard – https://azure.microsoft.com/en-us/status/

We’ll provide an update when we know more or in the next 2 hours.

  • Next Update: Before Monday, July 10th 2017 19:45 UTC

Sincerely,
Tom


Initial Update: Monday, July 10th 2017 16:44 UTC

We are actively investigating login issues with Visual Studio Team Services. Customers using VSTS will likely be impacted and experience login failures when trying to access the service. Some VSTS customers may have cached tokens that enable them to login to the service however they may experience other errors in the portal due to the general auth issues.

  • Next Update: Before Monday, July 10th 2017 17:45 UTC

Sincerely,
Sri Harsha

Microsoft Azure Government Now Available from Six US Datacenter Regions

$
0
0

I am pleased to announce that Azure Government is commercially live in two additional datacenter regions in Arizona and Texas for U.S. government customers and their partners following my announcement late last year. With these expansions, Azure Government has capacity in proximity to government customers and partners on the East Coast, West Coast and Central United States.

With a total of six U.S. datacenter regions, including two dedicated regions with DoD Impact Level 5 Provisional Authorization (PA), Azure Government continues to deliver the most customer choice in the U.S. for locating government workloads and sensitive data. As part of offering the broadest geographic availability, these regions are over 500 miles apart for geo-redundancy and we offer data replication across regions for business continuity.

Customers and partners are clear in their feedback that compliance with U.S. government standards and requirements is a priority. To address the compliance needs for U.S. government, we’ve engineered our datacenters and services to meet or exceed critical compliance requirements. In fact, Microsoft provides the broadest coverage for compliance and regulatory standards with support for FedRAMP High, CJIS, ITAR, DFARS, and DoD L4 and L5.

Specific to the future of cloud computing in government, we continue to announce Azure Government services that enable cool new ways for U.S. government customers and their partners to achieve mission. Most recently, we’ve announced:

Combining the most datacenter region choices with most comprehensive compliance coverage and innovative services, further extends customer confidence in Azure Government as they deliver mission workloads with the cloud now and into the future.

Explore Azure Government here or contact us to learn more.

The Migration Guide is now available for Public Preview!

$
0
0

We are pleased to announce Public Preview availability of a new database Migration Guide for enterprise customers, partners, and business decision makers who are interested in moving to the Modern Data Platform, for example migrating from Oracle to SQL Server or to Azure Data Services.

Overview

Hosted on the Microsoft Web, the Migration Guide is designed to make it easy for any customer, partner, ISV, etc. to move their data to Microsoft’s Modern Data Platform. The goals of the Guide are to:

  • Address content gaps by providing comprehensive, step-by-step guidance for performing migrations.
  • Improve the discoverability of the guidance, tools, software, and programs that are available to assist customers with performing these migrations.

This Migration Guide serves as a single point of entry for users, providing a guided migration experience, with details on how to migrate from a specific source platform to a specific target platform. The Guide informs and educates users, and it recommends specific courses of action based on the selected migration scenario. Prescriptive guidance provided in the Migration Guide includes pointers to:

  • Documentation (best practices, customer case studies, MSDN articles, blog postings, white papers, videos, presentation decks, training, etc.).
  • Tools or services to assist with migrations.
  • Recommended partners.
  • Associated Customer Programs.
  • Cost estimations and return on investment analysis

Public Preview

The Public Preview release of the Migration Guide will provide coverage for selected migration scenarios:

  • SQL Server upgrades and migrations to Azure SQL DB
  • Oracle to SQL Server /Azure SQL DB
  • MySQL to SQL Server/ Azure SQL DB
  • DB2 to SQL Server/Azure SQL DB
  • Sybase to SQL Server/Azure SQL DB
  • Access to SQL Server/Azure SQL DB

Important: We plan to regularly update and supplement the Migration Guide content over the course of the Public Preview period, with changes reflecting preview feedback and the availability of additional scenario details.

Call to action

The current version of the Migration Guide is available at the following link:

http://datamigration.microsoft.com

Please take a few minutes to review the Guide and consider:

  • The existing content.
  • Additional content/learnings/guidance to add.
  • The overall user experience.

After you have a chance to work with the Guide, please be sure to submit any feedback you might have by using the links in the footer of the Migration Guide pages:

Please let us know if you have any questions or if you would like to share additional content for any of the scenarios covered in the Migration Guide.

Thanks in advance for your time and effort,

The Data Migration Team

To mock or not to mock, that is the question! (or, when to use dependency injection)

$
0
0

I often use the terms “mocking” and “dependency injection” interchangeably. Now, I know that they are different, however, given that a mock object assumes some sort of dependency injection is involved, I hope you’ll forgive me. However, dependency injection without mocking of some sort implies that you’re not unit testing, and that’s just plain wrong.

Also, we could actually be talking about an isolation framework where we are able to present substitute objects for those objects that can’t normally be mocked (like TypeMock or Microsoft Fakes Shims) and still loosely refer to that as mocking.

So when do we choose to mock (either classic mock/stub or isolation) and when should we leave well enough alone to avoid mucking up the design?

Let’s take a classic object-oriented example, such as with a “Car” object. A car object might have an engine object, and electrical system object, wheel objects, etc. In the simple case, we’d want to leave it alone and not introduce a bunch of mock objects. By “simple case”, we mean that there is no need to have special classes that represent a carbon fuel engine, another class to represent an electric engine, and yet another class that might represent a “hybrid” engine, which might all represented by an IEngine interface (in the case of C#). By the way, if there’s no immediate requirement for such an IEngine interface, but you think it might be useful in the future, just hold on, hombre – You aren’t gonna need it (YAGNI). Don’t add code unless it’s required, and make it as simple as possible.

So in the case of a simple Car object and a simple Engine object, just skip mocking the engine. Introducing dependency inject is not “as simple as possible”, but rather, it introduces additional complexity.

“But, but, but… who’s going to create the Engine object?” you might ask in a querulous voice. Simple (see what I did there?), let the Car create the engine.

(Gasp!)(sputter!) “But that’s agile and object oriented blasphemy!” Meh… not so much. Remember, this is just a simple set of objects, which is how it should always start out. Until dependency injection is an actual requirement (and one that’s not simply in your own mind), You Aren’t Gonna Need It!

In the case of simple component objects, let the composite object construct its own simple component objects. Your tests should become much simpler.

You say, “But then I am not isolating my unit tests to a single object! How will I know where something breaks?” Well, given that you’re practicing TDD (and you are, aren’t you), then you’ll know that the problem was with the last few lines of code you just wrote.

“So, then it is better to not mock at all,” you may well say. But let’s not throw the baby out with the bathwater, as the saying goes. There are plenty of situations where dependency injection and mock objects are useful.

Bottom line, if you’re introducing an interface for no other reason other than it’s what you always do when testing, then please reconsider. Is there a way to simplify your design such that it doesn’t require mocks? But if you’re:

  • working with interfaces for more than just testing reasons (mock/stub),
  • or your component objects cross process boundaries (mock/stub),
  • or calls against your component have are not idempotent (likely shim)

…then by all means, use dependency injection or a shim.

Check out the new simplified way to configure the Cost Accounting module

$
0
0

In the latest version of Dynamics 365 for Finance and Operations, Enterprise Edition we put a lot of effort to make it easier to create initial configuration of the Cost Accounting module.

Take a look how simple it is!

Errors Configuring Azure SQL DataSync 2.0 agent

$
0
0

When adding an on-premise member database to a datasync 2.0 sync group, you will need to configure the local sync agent following these steps:

https://docs.microsoft.com/en-us/azure/sql-database/sql-database-get-started-sql-data-sync

Sometimes, the you may run into errors.

Error Type 1:

“Submitted agent key is invalid. The agent key could not be parsed as expected. Please resubmit a valid agent key”

“Please enter a valid agent key to proceed. The key must be generated from SQL Data Sync web portal”

“System.Data.SqlClient.SqlException,Message=Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. This failure occurred while attempting to connect to the routing destination”

These errors are caused by insufficient user permissions. To be able to successfully configure the local sync agent you will need these permissions:

  1. Azure SQL server CONTRIBUTOR
  2. A member of DataSync_Executor role in sync metadata database
  3. On hub/member databases:

Error Type 2:

“Agent must be upgraded. Please download and install the latest agent”

To resolve this issue:

  1. Check the file version of the data sync agent client, DataSyncLocalAgentHost.exe. The file version should be 4.3.xxxx. The default path is:
    C:Program Files (x86)Microsoft SQL Data Sync 2.0binDataSyncLocalAgentHost.exe
  2. If the file version is correct, check the dss.agent_version table in the sync metadata database using:
    SELECT * FROM dss.agent_version WHERE comment = 'current'

    The correct version should be 4.2.0.0.

    If the table is empty, you need to insert a row to the table:

    INSERT INTO dss.agent_version(Id,Version,ExpiresOn,Comment) VALUES(1,'4.2.0.0','Dec 31 9999 11:59PM','current')

    If the version is incorrect, you need to update the table:

    UPDATE dss.agent_version SET version = '4.2.0.0' WHERE comment = 'current'

Generate Unique Identifiers (UID) in U-SQL on Azure Data Lake Analytics

$
0
0

 

U-SQL doesn’t support constructs to generate Unique Identifier in Text Files. The script below generates unique identifier for every row in the input file.

The steps are

  1. Extract the data file with the EXTRACT statement
  2. REDUCERS are spun based on the customer code. Too little reducers or too many reducers may both cause performance issues. Identify a column that can fairly split, but make sure not to specify a unique column.
  3. For every reduced data set, the python script is invoked with the DATA FRAME. Add another column to the data frame “sguid” and generate a new encoded UID.
  4. The output produced out of the reducer will have a new column sguid

 

REFERENCE
ASSEMBLY [ExtPython];

 

DECLARE
@ReduceScript = @”

import uuid

import base64

 

def usqlml_main(df):

        df[‘sguid’] = ”

        df[‘sguid’] = df.sguid.apply(lambda row: str(base64.urlsafe_b64encode(uuid.uuid1().bytes)))

        return df

;

 

@AllData =    EXTRACT     OrderNo     string,

                        Date             string,

                        CustomerCode     string,

                        ProductCode        string,

                        SalesArea        string,

                        OrderValue        string

            FROM         “/DataLoads/Input/TempFile.csv”

            USING         Extractors.Text(delimiter: ‘,’, skipFirstNRows: 1);

 

@ReducedData =

            REDUCE         @AllData

            ON            CustomerCode

            PRODUCE        sguid string,

                        OrderNo     string,

                        Date             string,

                        CustomerCode     string,

                        ProductCode        string,

                        SalesArea        string,

                        OrderValue        string

            USING         new Extension.Python.Reducer(pyScript:@ReduceScript);

 

 

OUTPUT
@ReducedData

TO
“/DataLoads/CSVOutputwithGUID.txt”

USING Outputters.Text();

 

Note : Follow these instructions to enable U-SQL extensions on your ADL-A account

Removing items from the quick launch

$
0
0

When you create a new site in SharePoint, various templates are used that have been configured to create certain objects (lists/libraries) and activate certain features.  Using these templates provides a standard approach to creating sites but if these don’t meet your needs you can always modify them.

In this post I’ll show you how to modify the standard team site template and remove an entry from the quick launch (calendar link).

NOTE:  this will only affect newly created sites, anything that has already been created will need to be modified manually or with PowerShell.

Each version of SharePoint implements the site templates a little differently.  I’ll show you both SharePoint 2010 and 2013 approaches. Regardless of the approach you’ll modify the ONET.XML file for the template to be modified.

SharePoint 2010

By default the quick launch will include certain lists/libraries that are created when the site is created:

To remove the Calendar item in the Lists group:

  1. Locate the ONET.XML file for the TeamSite (sts) template.  It will be located at C:Program FilesCommon FilesMicrosoft SharedWeb Server Extensions14TEMPLATESiteTemplatesstsxml
  2. Open the file in Notepad.  There are 2 lines that need to be commented out to suppress the Calendar link.
  3. Navigate to line ~87 and comment it out.  It should look like this:

     4.  Then navigate to line ~166 and comment it out:

     5.  Save the file and then do an IISRESET.  This will re-cache the object so that when you create a new Team Site, it will use the newly modified version.

6.  When you create a new Team Site, notice the Calendar link has been removed:

SharePoint 2013

The process for SharePoint 2013 is similar but a little easier:

  1. Navigate to the template folder:  C:Program FilesCommon FilesMicrosoft SharedWeb Server Extensions15TEMPLATESiteTemplatesstsxml and open the ONET.XML file in Notepad.
  2. On Line ~73 modify the OnQuickLaunch attribute to be FALSE, which will suppress the “Documents” link on the quick launch:

      3.  Again, do an IISRESET to re-cache the file and then create a new site using the Team Site template.  Notice the “Documents” link has been removed:

 

Notes:

  • Each of the ONET.XML files will be located in the respective SharePoint <hive> (IE 14 or 15) depending on the version.
  • The C:Program FilesCommon FilesMicrosoft SharedWeb Server Extensions<VERSION>TEMPLATESiteTemplates directory will hold all of the default site templates.  If you want to create your own, it’s recommended to copy an existing one and modify where necessary.

Are you in or are you out? Closing the TSS Gap, Interim 457 Changes

$
0
0

Guest post by Raphael Grossman – Solicitor at Lehman Walsh Lawyers

The abolition and replacement of the Temporary Work (Skilled) visa, also known as the 457 visa, will be painful for start-ups who rely on the 457 visa to procure talent overseas. The new visa, the Temporary Skill Shortage (TSS) visa, is a lot less attractive to start-ups.

The TSS won’t replace the 457 visa until March 2018 and until then it is still possible to apply for the 457 visa. From 1 July 2017, transitory changes under legislative instruments have been implemented affecting the 457 visa. These changes will impact potential and current applicants. Applications that were started but not submitted before 30 June 2017 are now discontinued and a fresh application will have to be started.

Some of the key changes to the 457 visa in the interim period include:

  • Addition and removal of occupations that are eligible to apply for the 457 visa;
  • In some cases the removal of the English language exemption for applicants with salaries over AUD$96,400;
  • Visa validity extended to 4 years for some occupations and under specific conditions; and
  • Sponsorship accreditation approvals expanded for low risk sponsors.

 

The replacement TSS visa will have a Short-Term and Medium-Term Stream which will apply for two years and four years respectively. Some of the key differences between the 457 visa and the new TSS are:

  • Changes to the occupation list.
  • Requirement to have two years of work experience in the occupation list.
  • Employers to pay Australian market rate to not undercut Australian workers.
  • Only applicants of the Medium-Term Stream will have a pathway to permanent residency.
  • Permanent residency requiring a three year stay in Australian instead of two years.
  • Instead of current training benchmarks, employers to pay contributions to the Skilling Australians Fund.
  • Increased English requirements.

Though the changes do hurt start-ups and small businesses, they also have some upsides. For example, the quality of overseas workers in Australia will likely be higher due to the increased work experience requirements. The TSS will also be fairer to workers as it prevents employers paying less than minimum wage and taking advantage of employees from overseas. Nevertheless, it is clear that the new TSS will be costly for start-ups who need to keep initial costs low and want the choice of being able to hire capable workers who are new to the workforce. Therefore, it is a good idea to employ workers under the current 457 visa while it is still available.

Failure to comply with the new requirements associated with new 457 visas may prevent applicants from receiving a visa and may cause applicants to miss the boat. Therefore, during this transitional period, if you are thinking of applying for a 457 visa or are considering hiring employees overseas, you should consider contacting a lawyer for advice to make sure you are clear on the requirements.

 

 

Create Bot for Microsoft Graph with DevOps 13: BotBuilder features – Testing Proactive Messsaging

$
0
0

In the previous article, I implemented proactive messaging when any Outlook event has been updated. In this article, I will explain how to debug and testing.

Remote Debug

As Microsoft Graph Webhook requires publicly accessible callback URL, I had to publish it first to test. However what if I need to live debug the application? Visual Studio and Azure App Services actually let you do it.

1. Publish the O365Bot application as Debug build. Change the settings in publish page.

image

2. Once published as debug build, attach the service from Server Explorer.

image

3. Put break point anywhere and do the debug.

Unit Testing

To unit testing this, I need to do following things.

  • Mock INotificationService
  • Receive proactive message

Mock INotificationService

User the following code to mock the service.

var subscriptionId = Guid.NewGuid().ToString();
var mockNotificationService = new Mock<INotificationService>();
mockNotificationService.Setup(x => x.SubscribeEventChange()).ReturnsAsync(subscriptionId);
mockNotificationService.Setup(x => x.RenewSubscribeEventChange(It.IsAny<string>())).Returns(Task.FromResult(true));

builder.RegisterInstance(mockNotificationService.Object).As<INotificationService>();

Receive Proactive Message

To receive the proactive message, I use following Resume method to simulate the behavior.

/// <summary>
/// Resume the conversation
/// </summary>
public async Task<List<IMessageActivity>> Resume(IContainer container, IDialog<int> dialog, IMessageActivity toBot)
{
    using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
    {
        var results = new List<IMessageActivity>();

        var botData = scope.Resolve<IBotData>();
        await botData.LoadAsync(CancellationToken.None);
        var task = scope.Resolve<IDialogTask>();

        // Insert dialog to current event
        task.Call(dialog.Void<int, IMessageActivity>(), null);
        await task.PollAsync(CancellationToken.None);
        await botData.FlushAsync(CancellationToken.None);

        // Get the result
        var queue = scope.Resolve<Queue<IMessageActivity>>();
        while (queue.Count != 0)
        {
            results.Add(queue.Dequeue());
        }

        return results;
    }
}

Update Unit Test

Replace the code in  UnitTest1.cs with following.

using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Tests;
using Microsoft.Bot.Connector;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Threading.Tasks;
using Autofac;
using O365Bot.Dialogs;
using Microsoft.Bot.Builder.Dialogs.Internals;
using Microsoft.Bot.Builder.Base;
using System.Threading;
using System.Collections.Generic;
using Microsoft.QualityTools.Testing.Fakes;
using O365Bot.Services;
using Moq;
using Microsoft.Graph;
using System.Globalization;
using Microsoft.Bot.Builder.Internals.Fibers;

namespace O365Bot.UnitTests
{
    [TestClass]
    public class SampleDialogTest : DialogTestBase
    {
        [TestMethod]
        public async Task ShouldReturnEvents()
        {
            // Instantiate ShimsContext to use Fakes
            using (ShimsContext.Create())
            {
                // Return "dummyToken" when calling GetAccessToken method
                AuthBot.Fakes.ShimContextExtensions.GetAccessTokenIBotContextString =
                    async (a, e) => { return "dummyToken"; };

                var mockEventService = new Mock<IEventService>();
                mockEventService.Setup(x => x.GetEvents()).ReturnsAsync(new List<Event>()
                {
                    new Event
                    {
                        Subject = "dummy event",
                        Start = new DateTimeTimeZone()
                        {
                            DateTime = "2017-05-31 12:00",
                            TimeZone = "Standard Tokyo Time"
                        },
                        End = new DateTimeTimeZone()
                        {
                            DateTime = "2017-05-31 13:00",
                            TimeZone = "Standard Tokyo Time"
                        }
                    }
                });
                var builder = new ContainerBuilder();
                builder.RegisterInstance(mockEventService.Object).As<IEventService>();
                WebApiApplication.Container = builder.Build();

                // Instantiate dialog to test
                IDialog<object> rootDialog = new RootDialog();

                // Create in-memory bot environment
                Func<IDialog<object>> MakeRoot = () => rootDialog;
                using (new FiberTestBase.ResolveMoqAssembly(rootDialog))
                using (var container = Build(Options.MockConnectorFactory | Options.ScopedQueue, rootDialog))
                {
                    // Register global message handler
                    RegisterBotModules(container);

                    // Create a message to send to bot
                    var toBot = DialogTestBase.MakeTestMessage();
                    toBot.From.Id = Guid.NewGuid().ToString();
                    toBot.Text = "get events";

                    // Send message and check the answer.
                    IMessageActivity toUser = await GetResponse(container, MakeRoot, toBot);

                    // Verify the result
                    Assert.IsTrue(toUser.Text.Equals("2017-05-31 12:00-2017-05-31 13:00: dummy event"));
                }
            }
        }

        [TestMethod]
        public async Task ShouldCreateAllDayEvent()
        {
            // Instantiate ShimsContext to use Fakes
            using (ShimsContext.Create())
            {
                // Return "dummyToken" when calling GetAccessToken method
                AuthBot.Fakes.ShimContextExtensions.GetAccessTokenIBotContextString =
                    async (a, e) => { return "dummyToken"; };

                // Mock the service and register
                var mockEventService = new Mock<IEventService>();
                mockEventService.Setup(x => x.CreateEvent(It.IsAny<Event>())).Returns(Task.FromResult(true));
                var subscriptionId = Guid.NewGuid().ToString();
                var mockNotificationService = new Mock<INotificationService>();
                mockNotificationService.Setup(x => x.SubscribeEventChange()).ReturnsAsync(subscriptionId);
                mockNotificationService.Setup(x => x.RenewSubscribeEventChange(It.IsAny<string>())).Returns(Task.FromResult(true));

                var builder = new ContainerBuilder();
                builder.RegisterInstance(mockEventService.Object).As<IEventService>();
                builder.RegisterInstance(mockNotificationService.Object).As<INotificationService>();
                WebApiApplication.Container = builder.Build();

                // Instantiate dialog to test
                IDialog<object> rootDialog = new RootDialog();

                // Create in-memory bot environment
                Func<IDialog<object>> MakeRoot = () => rootDialog;
                using (new FiberTestBase.ResolveMoqAssembly(rootDialog))
                using (var container = Build(Options.MockConnectorFactory | Options.ScopedQueue, rootDialog))
                {
                    // Register global message handler
                    RegisterBotModules(container);

                    // Create a message to send to bot
                    var toBot = DialogTestBase.MakeTestMessage();
                    // Specify local as US English
                    toBot.Locale = "en-US";
                    toBot.From.Id = Guid.NewGuid().ToString();
                    toBot.Text = "add appointment";

                    // Send message and check the answer.
                    var toUser = await GetResponses(container, MakeRoot, toBot);

                    // Verify the result
                    Assert.IsTrue(toUser[0].Text.Equals("Creating an event."));
                    Assert.IsTrue(toUser[1].Text.Equals("What is the title?"));

                    toBot.Text = "Learn BotFramework";
                    toUser = await GetResponses(container, MakeRoot, toBot);
                    Assert.IsTrue(toUser[0].Text.Equals("What is the detail?"));

                    toBot.Text = "Implement O365Bot";
                    toUser = await GetResponses(container, MakeRoot, toBot);
                    Assert.IsTrue(toUser[0].Text.Equals("When do you start? Use dd/MM/yyyy HH:mm format."));

                    toBot.Text = "01/07/2017 13:00";
                    toUser = await GetResponses(container, MakeRoot, toBot);
                    Assert.IsTrue((toUser[0].Attachments[0].Content as HeroCard).Text.Equals("Is this all day event?"));

                    toBot.Text = "Yes";
                    toUser = await GetResponses(container, MakeRoot, toBot);
                    Assert.IsTrue(toUser[0].Text.Equals("The event is created."));
                }
            }
        }

        [TestMethod]
        public async Task ShouldCreateEvent()
        {
            // Instantiate ShimsContext to use Fakes
            using (ShimsContext.Create())
            {
                // Return "dummyToken" when calling GetAccessToken method
                AuthBot.Fakes.ShimContextExtensions.GetAccessTokenIBotContextString =
                    async (a, e) => { return "dummyToken"; };

                // Mock the service and register
                var mockEventService = new Mock<IEventService>();
                mockEventService.Setup(x => x.CreateEvent(It.IsAny<Event>())).Returns(Task.FromResult(true));
                var mockNotificationService = new Mock<INotificationService>();
                mockNotificationService.Setup(x => x.SubscribeEventChange()).ReturnsAsync(Guid.NewGuid().ToString());
                mockNotificationService.Setup(x => x.RenewSubscribeEventChange(It.IsAny<string>())).Returns(Task.FromResult(true));

                var builder = new ContainerBuilder();
                builder.RegisterInstance(mockEventService.Object).As<IEventService>();
                builder.RegisterInstance(mockNotificationService.Object).As<INotificationService>();
                WebApiApplication.Container = builder.Build();

                // Instantiate dialog to test
                IDialog<object> rootDialog = new RootDialog();

                // Create in-memory bot environment
                Func<IDialog<object>> MakeRoot = () => rootDialog;
                using (new FiberTestBase.ResolveMoqAssembly(rootDialog))
                using (var container = Build(Options.MockConnectorFactory | Options.ScopedQueue, rootDialog))
                {
                    // Register global message handler
                    RegisterBotModules(container);

                    // Create a message to send to bot
                    var toBot = DialogTestBase.MakeTestMessage();
                    // Specify local as US English
                    toBot.Locale = "en-US";
                    toBot.From.Id = Guid.NewGuid().ToString();
                    toBot.Text = "add appointment";

                    // Send message and check the answer.
                    var toUser = await GetResponses(container, MakeRoot, toBot);

                    // Verify the result
                    Assert.IsTrue(toUser[0].Text.Equals("Creating an event."));
                    Assert.IsTrue(toUser[1].Text.Equals("What is the title?"));

                    toBot.Text = "Learn BotFramework";
                    toUser = await GetResponses(container, MakeRoot, toBot);
                    Assert.IsTrue(toUser[0].Text.Equals("What is the detail?"));

                    toBot.Text = "Implement O365Bot";
                    toUser = await GetResponses(container, MakeRoot, toBot);
                    Assert.IsTrue(toUser[0].Text.Equals("When do you start? Use dd/MM/yyyy HH:mm format."));

                    toBot.Text = "01/07/2017 13:00";
                    toUser = await GetResponses(container, MakeRoot, toBot);
                    Assert.IsTrue((toUser[0].Attachments[0].Content as HeroCard).Text.Equals("Is this all day event?"));

                    toBot.Text = "No";
                    toUser = await GetResponses(container, MakeRoot, toBot);
                    Assert.IsTrue(toUser[0].Text.Equals("How many hours?"));


                    toBot.Text = "4";
                    toUser = await GetResponses(container, MakeRoot, toBot);
                    Assert.IsTrue(toUser[0].Text.Equals("The event is created."));
                }
            }
        }

        [TestMethod]
        public async Task ShouldCancelCurrrentDialog()
        {
            // Instantiate ShimsContext to use Fakes
            using (ShimsContext.Create())
            {
                // Return "dummyToken" when calling GetAccessToken method
                AuthBot.Fakes.ShimContextExtensions.GetAccessTokenIBotContextString =
 async (a, e) => { return "dummyToken"; };

                // Mock the service and register
                var mockEventService = new Mock<IEventService>();
                mockEventService.Setup(x => x.CreateEvent(It.IsAny<Event>())).Returns(Task.FromResult(true));
                var mockNotificationService = new Mock<INotificationService>();
                mockNotificationService.Setup(x => x.SubscribeEventChange()).ReturnsAsync(Guid.NewGuid().ToString());
                mockNotificationService.Setup(x => x.RenewSubscribeEventChange(It.IsAny<string>())).Returns(Task.FromResult(true));

                var builder = new ContainerBuilder();
                builder.RegisterInstance(mockEventService.Object).As<IEventService>();
                builder.RegisterInstance(mockNotificationService.Object).As<INotificationService>();
                WebApiApplication.Container = builder.Build();

                // Instantiate dialog to test
                IDialog<object> rootDialog = new RootDialog();

                // Create in-memory bot environment
                Func<IDialog<object>> MakeRoot = () => rootDialog;
                using (new FiberTestBase.ResolveMoqAssembly(rootDialog))
                using (var container = Build(Options.MockConnectorFactory | Options.ScopedQueue, rootDialog))
                {
                    // Register global message handler
                    RegisterBotModules(container);
                                       
                    // Create a message to send to bot
                    var toBot = DialogTestBase.MakeTestMessage();
                    // Specify local as US English
                    toBot.Locale = "en-US";
                    toBot.From.Id = Guid.NewGuid().ToString();
                    toBot.Text = "add appointment";

                    // Send message and check the answer.
                    var toUser = await GetResponses(container, MakeRoot, toBot);

                    // Verify the result
                    Assert.IsTrue(toUser[0].Text.Equals("Creating an event."));
                    Assert.IsTrue(toUser[1].Text.Equals("What is the title?"));

                    toBot.Text = "Learn BotFramework";
                    toUser = await GetResponses(container, MakeRoot, toBot);
                    Assert.IsTrue(toUser[0].Text.Equals("What is the detail?"));

                    toBot.Text = "Cancel";
                    toUser = await GetResponses(container, MakeRoot, toBot);
                    Assert.IsTrue(toUser.Count.Equals(0));

                    toBot.Text = "add appointment";
                    toUser = await GetResponses(container, MakeRoot, toBot);

                    // Verify the result
                    Assert.IsTrue(toUser[0].Text.Equals("Creating an event."));
                    Assert.IsTrue(toUser[1].Text.Equals("What is the title?"));
                }
            }
        }

        [TestMethod]
        public async Task ShouldInterruptCurrentDialog()
        {
            // Instantiate ShimsContext to use Fakes
            using (ShimsContext.Create())
            {
                // Return "dummyToken" when calling GetAccessToken method
                AuthBot.Fakes.ShimContextExtensions.GetAccessTokenIBotContextString =
 async (a, e) => { return "dummyToken"; };

                // Mock the service and register
                var mockEventService = new Mock<IEventService>();
                mockEventService.Setup(x => x.CreateEvent(It.IsAny<Event>())).Returns(Task.FromResult(true));
                mockEventService.Setup(x => x.GetEvents()).ReturnsAsync(new List<Event>()
                {
                    new Event
                    {
                        Subject = "dummy event",
                        Start = new DateTimeTimeZone()
                        {
                            DateTime = "2017-05-31 12:00",
                            TimeZone = "Standard Tokyo Time"
                        },
                        End = new DateTimeTimeZone()
                        {
                            DateTime = "2017-05-31 13:00",
                            TimeZone = "Standard Tokyo Time"
                        }
                    }
                });
                var mockNotificationService = new Mock<INotificationService>();
                mockNotificationService.Setup(x => x.SubscribeEventChange()).ReturnsAsync(Guid.NewGuid().ToString());
                mockNotificationService.Setup(x => x.RenewSubscribeEventChange(It.IsAny<string>())).Returns(Task.FromResult(true));
               
                var builder = new ContainerBuilder();
                builder.RegisterInstance(mockEventService.Object).As<IEventService>();
                builder.RegisterInstance(mockNotificationService.Object).As<INotificationService>();
                WebApiApplication.Container = builder.Build();

                // Instantiate dialog to test
                IDialog<object> rootDialog = new RootDialog();

                // Create in-memory bot environment
                Func<IDialog<object>> MakeRoot = () => rootDialog;
                using (new FiberTestBase.ResolveMoqAssembly(rootDialog))
                using (var container = Build(Options.MockConnectorFactory | Options.ScopedQueue, rootDialog))
                {
                    // Register global message handler
                    RegisterBotModules(container);

                    // Create a message to send to bot
                    var toBot = DialogTestBase.MakeTestMessage();
                    // Specify local as US English
                    toBot.Locale = "en-US";
                    toBot.From.Id = Guid.NewGuid().ToString();
                    toBot.Text = "add appointment";

                    // Send message and check the answer.
                    var toUser = await GetResponses(container, MakeRoot, toBot);

                    // Verify the result
                    Assert.IsTrue(toUser[0].Text.Equals("Creating an event."));
                    Assert.IsTrue(toUser[1].Text.Equals("What is the title?"));
                   
                    toBot.Text = "Learn BotFramework";
                    toUser = await GetResponses(container, MakeRoot, toBot);
                    Assert.IsTrue(toUser[0].Text.Equals("What is the detail?"));

                    toBot.Text = "Get Events";
                    toUser = await GetResponses(container, MakeRoot, toBot);
                    Assert.IsTrue(toUser[0].Text.Equals("2017-05-31 12:00-2017-05-31 13:00: dummy event"));

                    toBot.Text = "Glbal Message Handler for O365Bot";
                    toUser = await GetResponses(container, MakeRoot, toBot);
                    Assert.IsTrue(toUser[0].Text.Equals("When do you start? Use dd/MM/yyyy HH:mm format."));
                }
            }
        }

        [TestMethod]
        public async Task ShouldReceiveNotifyEventChageDialog()
        {
            // Instantiate ShimsContext to use Fakes
            using (ShimsContext.Create())
            {
                // Return "dummyToken" when calling GetAccessToken method
                AuthBot.Fakes.ShimContextExtensions.GetAccessTokenIBotContextString =
                    async (a, e) => { return "dummyToken"; };

                // Mock the service and register
                var mockEventService = new Mock<IEventService>();
                mockEventService.Setup(x => x.CreateEvent(It.IsAny<Event>())).Returns(Task.FromResult(true));
                mockEventService.Setup(x => x.GetEvent(It.IsAny<string>())).ReturnsAsync(new Event()
                {
                    Subject = "dummy event",
                    Start = new DateTimeTimeZone()
                    {
                        DateTime = "2017-05-31 12:00",
                        TimeZone = "Standard Tokyo Time"
                    },
                    End = new DateTimeTimeZone()
                    {
                        DateTime = "2017-05-31 13:00",
                        TimeZone = "Standard Tokyo Time"
                    },
                    Body = new ItemBody()
                    {
                        Content = "Dummy Body"
                    },
                    Location = new Location()
                    {
                        DisplayName = "Dummy Location"
                    }
                });

                var subscriptionId = Guid.NewGuid().ToString();
                var mockNotificationService = new Mock<INotificationService>();
                mockNotificationService.Setup(x => x.SubscribeEventChange()).ReturnsAsync(subscriptionId);
                mockNotificationService.Setup(x => x.RenewSubscribeEventChange(It.IsAny<string>())).Returns(Task.FromResult(true));

                var builder = new ContainerBuilder();
                builder.RegisterInstance(mockEventService.Object).As<IEventService>();
                builder.RegisterInstance(mockNotificationService.Object).As<INotificationService>();
                WebApiApplication.Container = builder.Build();

                // Instantiate dialog to test
                IDialog<object> rootDialog = new RootDialog();

                // Create in-memory bot environment
                Func<IDialog<object>> MakeRoot = () => rootDialog;
                using (new FiberTestBase.ResolveMoqAssembly(rootDialog))
                using (var container = Build(Options.MockConnectorFactory | Options.ScopedQueue, rootDialog))
                {
                    // Register global message handler
                    RegisterBotModules(container);

                    // Create a message to send to bot
                    var toBot = DialogTestBase.MakeTestMessage();
                    // Specify local as US English
                    toBot.Locale = "en-US";
                    toBot.From.Id = Guid.NewGuid().ToString();
                    toBot.Text = "add appointment";

                    // Send message and check the answer.
                    var toUser = await GetResponses(container, MakeRoot, toBot);

                    // Verify the result
                    Assert.IsTrue(toUser[0].Text.Equals("Creating an event."));
                    Assert.IsTrue(toUser[1].Text.Equals("What is the title?"));

                    toBot.Text = "Learn BotFramework";
                    toUser = await GetResponses(container, MakeRoot, toBot);
                    Assert.IsTrue(toUser[0].Text.Equals("What is the detail?"));

                    // Send Proactive Message
                    // Use current subscriptionid to get ConversationReference。
                    var conversationReference = CacheService.caches[subscriptionId] as ConversationReference;
                    // Get an Event Id
                    var id = Guid.NewGuid().ToString();

                    // Get local and set it
                    var activity = conversationReference.GetPostToBotMessage();
                    var locale = CacheService.caches[activity.From.Id].ToString();
                    Thread.CurrentThread.CurrentCulture = new CultureInfo(locale);
                    Thread.CurrentThread.CurrentUICulture = new CultureInfo(locale);
                    toUser = await Resume(container, new NotifyEventChageDialog(id), activity);

                    Assert.IsTrue((toUser[0].Attachments[0].Content as HeroCard).Text.Equals("One of your events has been updated."));

                    toBot.Text = "Check the detail";
                    toUser = await GetResponses(container, MakeRoot, toBot);
                    Assert.IsTrue(toUser[0].Text.Equals("Check the detail"));
                    Assert.IsTrue(toUser[1].Text.Equals("2017-05-31 12:00-2017-05-31 13:00: dummy event@Dummy Location-Dummy Body"));

                    toBot.Text = "Implement O365Bot";
                    toUser = await GetResponses(container, MakeRoot, toBot);
                    Assert.IsTrue(toUser[0].Text.Equals("When do you start? Use dd/MM/yyyy HH:mm format."));
                }
            }
        }

        /// <summary>
        /// Send a message to the bot and get repsponse.
        /// </summary>
        public async Task<IMessageActivity> GetResponse(IContainer container, Func<IDialog<object>> makeRoot, IMessageActivity toBot)
        {
            using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
            {
                DialogModule_MakeRoot.Register(scope, makeRoot);

                // act: sending the message
                using (new LocalizedScope(toBot.Locale))
                {
                    var task = scope.Resolve<IPostToBot>();
                    await task.PostAsync(toBot, CancellationToken.None);
                }
                //await Conversation.SendAsync(toBot, makeRoot, CancellationToken.None);
                return scope.Resolve<Queue<IMessageActivity>>().Dequeue();
            }
        }

        /// <summary>
        /// Send a message to the bot and get all repsponses.
        /// </summary>
        public async Task<List<IMessageActivity>> GetResponses(IContainer container, Func<IDialog<object>> makeRoot, IMessageActivity toBot)
        {
            using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
            {
                var results = new List<IMessageActivity>();
                DialogModule_MakeRoot.Register(scope, makeRoot);

                // act: sending the message
                using (new LocalizedScope(toBot.Locale))
                {
                    var task = scope.Resolve<IPostToBot>();
                    await task.PostAsync(toBot, CancellationToken.None);
                }
                //await Conversation.SendAsync(toBot, makeRoot, CancellationToken.None);
                var queue = scope.Resolve<Queue<IMessageActivity>>();
                while (queue.Count != 0)
                {
                    results.Add(queue.Dequeue());
                }

                return results;
            }
        }

        /// <summary>
        /// Register Global Message
        /// </summary>
        private void RegisterBotModules(IContainer container)
        {
            var builder = new ContainerBuilder();
            builder.RegisterModule(new ReflectionSurrogateModule());
            builder.RegisterModule<GlobalMessageHandlers>();
            builder.Update(container);
        }

        /// <summary>
        /// Resume the conversation
        /// </summary>
        public async Task<List<IMessageActivity>> Resume(IContainer container, IDialog<object> dialog, IMessageActivity toBot)
        {
            using (var scope = DialogModule.BeginLifetimeScope(container, toBot))
            {
                var results = new List<IMessageActivity>();

                var botData = scope.Resolve<IBotData>();
                await botData.LoadAsync(CancellationToken.None);
                var task = scope.Resolve<IDialogTask>();

                // Insert dialog to current event
                task.Call(dialog.Void<object, IMessageActivity>(), null);
                await task.PollAsync(CancellationToken.None);
                await botData.FlushAsync(CancellationToken.None);

                // Get the result
                var queue = scope.Resolve<Queue<IMessageActivity>>();
                while (queue.Count != 0)
                {
                    results.Add(queue.Dequeue());
                }

                return results;
            }
        }

    }
}

Function Test

Due to the following technical limitation for current function test, I gave up the test.

  • DirectLine cannot get proactive message. It only get returns from Bot when it retrieves the answer.
  • Need additional automation for Outlook event modification.

Check in code to confirm all the unit tests are passed and successfully deployed.

Summery

I only mock the proactive service by adding Resume method, but I may need to mock the notification controller itself rather than just resume method. There is also DirectLine limitation. Please let me know if you have better idea how to test proactive messaging.

In the next article, I will explain about middleware implementation for Bot Framework.

GitHub: https://github.com/kenakamu/BotWithDevOps-Blog-sample/tree/master/article13

Ken



                       

Largest FREE Microsoft eBook Giveaway! I’m Giving Away MILLIONS of FREE Microsoft eBooks again, including: Windows 10, Office 365, Office 2016, Power BI, Azure, Windows 8.1, Office 2013, SharePoint 2016, SharePoint 2013, Dynamics CRM, PowerShell, Exchange Server, System Center, Cloud, SQL Server and more!

$
0
0

Ligman_Free_eBooks_Sm_thumb1

 

It’s that time of year again, and today I am kicking off my annual FREE MICROSOFT EBOOK GIVEAWAY extravaganza! And this time, I’m posting MORE FREE EBOOKS in this post than I ever have in any of my previous giveaways! Based on this, you will notice something different about this year’s post… In previous years, I included images of the eBook covers next to each item; however, I would also get feedback from people on the amount of time to load all of the images. So, this year I decided to streamline the list to make it easier to get to the eBooks you want. You will now find a simple list, organized by category, with the download links in the Format column so you can choose which format you want to download.

If you have been a follower of mine in the past, you know that several years ago I tried a simple concept: Let’s try giving away a bunch of free eBooks, reference guides, Step-By-Step Guides, and other informational resources to our customers and partners around the world. Needless to say, the concept was extremely the first year (over 1,000,000 FREE eBooks downloaded), and it has grown and grown over the past few years (over 3.5 Million downloaded three years ago and we surpassed that by a lot last year!) So, how many FREE eBooks can we give away this year? That is completely up to you.

Before we get to this year’s list of FREE eBooks, a few answers to common questions I receive during my FREE EBOOK GIVEAWAY:

  1. How many can you download?
    • ANSWER: As many as you want! This is a FREE eBook giveaway, so please download as many as interest you.
  2. Wow, there are a LOT listed here. Is there a way to download all of them at once?
    • ANSWER: Yes, please see the note below on how to do this.
  3. Can I share a link to your post to let others know about this giveaway?
    • ANSWER: Yes, please do share the good news with anyone you feel could benefit from this.
  4. I know you said they are “Free,” but what’s the catch?
    • ANSWER: There is no catch. They really are FREE. This consider it a, “Thank you,” for being a reader of my blog and a customer or partner of Microsoft.
  5. Ok, so if they are free and you’re encouraging us to share this with others, can I post a link to your post here on sites like Reddit, FatWallet, and other deal share sites to let them know, or is that asking too much?
    • ANSWER: Please do. In fact, I would encourage you to share a link to this post on any deal site you feel their users could benefit from the FREE eBooks and resources included below. Again, I WANT to give away MILLIONS of FREE eBooks!
  6. Are these “time-bombed” versions of the eBooks that stop working after a certain amount of time or reads?
    • ANSWER: No, these are the full resources for you to use.

Ok, ready for some FREE eBooks? Below is the collection I am posting this year (which includes a ton of new eBooks & resources, as well as some of the favorites from previous years):

Category Title Format
Azure Introducing Windows Azure™ for IT Professionals PDF
MOBI
EPUB
Azure Microsoft Azure Essentials Azure Automation PDF
MOBI
EPUB
Azure Microsoft Azure Essentials Azure Machine Learning PDF
MOBI
EPUB
Azure Microsoft Azure Essentials Fundamentals of Azure PDF
MOBI
EPUB
Azure Microsoft Azure Essentials Fundamentals of Azure, Second Edition PDF
Azure Microsoft Azure Essentials Fundamentals of Azure, Second Edition Mobile PDF
Azure Microsoft Azure Essentials Migrating SQL Server Databases to Azure – Mobile PDF
Azure Microsoft Azure Essentials Migrating SQL Server Databases to Azure 8.5X11 PDF
Azure Microsoft Azure ExpressRoute Guide PDF
Azure Rapid Deployment Guide For Azure Rights Management PDF
Azure Rethinking Enterprise Storage: A Hybrid Cloud Model PDF
MOBI
EPUB
BizTalk BizTalk Server 2016 Licensing Datasheet PDF
BizTalk BizTalk Server 2016 Management Pack Guide DOC
Cloud Enterprise Cloud Strategy PDF
MOBI
EPUB
Cloud Enterprise Cloud Strategy – Mobile PDF
Developer .NET Microservices: Architecture for Containerized .NET Applications PDF
Developer .NET Technology Guidance for Business Applications PDF
Developer Building Cloud Apps with Microsoft Azure™: Best practices for DevOps, data storage, high availability, and more PDF
MOBI
EPUB
Developer Containerized Docker Application Lifecycle with Microsoft Platform and Tools PDF
Developer Creating Mobile Apps with Xamarin.Forms, Preview Edition 2 PDF
MOBI
EPUB
Developer Creating Mobile Apps with Xamarin.Forms: Cross-platform C# programming for iOS, Android, and Windows PDF
MOBI
EPUB
Developer Managing Agile Open-Source Software Projects with Microsoft Visual Studio Online PDF
MOBI
EPUB
Developer Microsoft Azure Essentials Azure Web Apps for Developers PDF
MOBI
EPUB
Developer Microsoft Platform and Tools for Mobile App Development PDF
Developer Microsoft Platform and Tools for Mobile App Development – Mobile PDF
Developer Moving to Microsoft® Visual Studio® 2010 XPS
PDF
MOBI
EPUB
Developer Programming Windows 8 Apps with HTML, CSS, and JavaScript PDF
MOBI
EPUB
Developer Programming Windows Store Apps with HTML, CSS, and JavaScript, Second Edition PDF
MOBI
EPUB
Developer Programming Windows® Phone 7 (Special Excerpt 2) XPS
PDF
Developer Team Foundation Server to Visual Studio Team Services Migration Guide PDF
Dynamics 5 cool things you can do with CRM for tablets PDF
Dynamics Create Custom Analytics in Dynamics 365 with Power BI PDF
Dynamics Create of Customize System Dashboards PDF
Dynamics Create Your First CRM Marketing Campaign PDF
Dynamics CRM Basics for Outlook basics PDF
Dynamics CRM Basics for Sales Pros and Service Reps PDF
Dynamics Give Great Customer Service with CRM PDF
Dynamics Go Mobile with CRM for Phones – Express PDF
Dynamics Go Mobile with CRM for Tablets PDF
Dynamics Import Contacts into CRM PDF
Dynamics Introducing Microsoft Social Engagement PDF
Dynamics Introduction to Business Processes PDF
Dynamics Meet Your Service Goals with SLAs and Entitlements PDF
Dynamics Microsoft Dynamics CRM 2016 Interactive Service Hub User Guide PDF
Dynamics Microsoft Dynamics CRM 2016 On-Premises Volume Licensing and Pricing Guide PDF
Dynamics Microsoft Dynamics CRM for Outlook Installing Guide for use with Microsoft Dynamics CRM Online PDF
Dynamics Microsoft Dynamics CRM Resource Guide 2015 PDF
Dynamics Microsoft Social Engagement for CRM PDF
Dynamics Product Overview and Capability Guide Microsoft Dynamics NAV 2016 PDF
Dynamics RAP as a Service for Dynamics CRM PDF
Dynamics Set Up A Social Engagement Search For Your Product PDF
Dynamics Social is for Closers PDF
Dynamics Start Working in CRM PDF
Dynamics Your Brand Sux PDF
General 10 essential tips and tools for mobile working PDF
General An employee’s guide to healthy computing PDF
General Guide for People who have Language or Communication Disabilities DOC
General Guide for People who have Learning Disabilities DOC
Licensing Introduction to Per Core Licensing and Basic Definitions PDF
Licensing Licensing Windows and Microsoft Office for use on the Macintosh PDF
Licensing VLSC Software Assurance Guide PDF
Licensing Windows Server 2016 and System Center 2016 Pricing and Licensing FAQs PDF
Office Access 2013 Keyboard Shortcuts PDF
Office Azure AD/Office 365 seamless sign-in PDF
Office Content Encryption in Microsoft Office 365 PDF
Office Controlling Access to Office 365 and Protecting Content on Devices PDF
Office Customize Word 2013 Keyboard Shortcuts PDF
Office Data Resiliency in Microsoft Office 365 PDF
Office Excel 2013 Keyboard Shortcuts PDF
Office Excel 2016 keyboard shortcuts and function keys DOC
Office Excel Online Keyboard Shortcuts PDF
Office File Protection Solutions in Office 365 PDF
Office First Look: Microsoft® Office 2010 XPS
PDF
Office Get Started With Microsoft OneDrive PDF
Office Get Started With Microsoft Project Online PDF
Office Getting started with MyAnalytics DOC
Office How To Recover That Un-Saved Office Document PDF
Office InfoPath 2013 Keyboard Shortcuts PDF
Office Keyboard shortcuts for Microsoft Outlook 2013 and 2016 DOC
Office Keyboard shortcuts for Microsoft Word 2016 for Windows DOC
Office Licensing Microsoft Office 365 ProPlus Subscription Service in Volume Licensing PDF
Office Licensing Microsoft Office software in Volume Licensing PDF
Office Microsoft Access 2013 Quick Start Guide PDF
Office Microsoft Classroom Deployment PDF
Office Microsoft Excel 2013 Quick Start Guide PDF
Office Microsoft Excel 2016 for Mac Quick Start Guide PDF
Office Microsoft Excel 2016 Quick Start Guide PDF
Office Microsoft Excel Mobile Quick Start Guide PDF
Office Microsoft Excel VLOOKUP Troubleshooting Tips PDF
Office Microsoft OneNote 2013 Quick Start Guide PDF
Office Microsoft OneNote 2016 for Mac Quick Start Guide PDF
Office Microsoft OneNote 2016 Quick Start Guide PDF
Office Microsoft OneNote 2016 Tips and Tricks PDF
Office Microsoft OneNote Mobile Quick Start Guide PDF
Office Microsoft Outlook 2013 Quick Start Guide PDF
Office Microsoft Outlook 2016 for Mac Quick Start Guide PDF
Office Microsoft Outlook 2016 Quick Start Guide PDF
Office Microsoft Outlook 2016 Tips and Tricks PDF
Office Microsoft Powerpoint 2013 Quick Start Guide PDF
Office Microsoft PowerPoint 2016 for Mac Quick Start Guide PDF
Office Microsoft PowerPoint 2016 for Mac Quick Start Guide PDF
Office Microsoft PowerPoint Mobile Quick Start Guide PDF
Office Microsoft Project 2013 Quick Start Guide PDF
Office Microsoft Publisher 2013 Quick Start Guide PDF
Office Microsoft Visio 2013 Quick Start Guide PDF
Office Microsoft Word 2013 Quick Start Guide PDF
Office Microsoft Word 2016 for Mac Quick Start Guide PDF
Office Microsoft Word 2016 Quick Start Guide PDF
Office Microsoft Word Mobile Quick Start Guide PDF
Office Microsoft® Office 365: Connect and Collaborate Virtually Anywhere, Anytime PDF
Office Monitoring and protecting sensitive data in Office 365 DOC
Office Office 365 Dedicated Platform vNext Service Release PDF
Office Office 365 Licensing Brief PDF
Office OneNote 2013 Keyboard Shortcuts PDF
Office OneNote Online Keyboard Shortcuts PDF
Office Outlook 2013 Keyboard Shortcuts PDF
Office Outlook Web App Keyboard Shortcuts PDF
Office Own Your Future: Update Your Skills with Resources and Career Ideas from Microsoft® XPS
PDF
MOBI
EPUB
Office PowerPoint Online Keyboard Shortcuts PDF
Office Project 2013 Keyboard Shortcuts PDF
Office Publisher 2013 Keyboard Shortcuts PDF
Office Security and Privacy For Microsoft Office 2010 Users PDF
MOBI
EPUB
Office Security Incident Management in Microsoft Office 365 PDF
PDF
Office SharePoint Online Dedicated & OneDrive for Business Dedicated vNext Service Release PDF
Office Skype for Business User Tips & Tricks for Anyone PDF
Office Switching from Google Apps to Office 365 for business PDF
Office Tenant Isolation in Microsoft Office 365 PDF
Office Visio 2013 Keyboard Shortcuts PDF
Office Windows 10 Tips and Tricks PDF
Office Word 2013 Keyboard Shortcuts PDF
Office Word Online Keyboard Shortcuts PDF
Office Working with SmartArt Graphics Keyboard Shortcuts PDF
Power BI Ask, find, and act—harnessing the power of Cortana and Power BI DOC
Power BI Bidirectional cross-filtering in SQL Server Analysis Services 2016 and Power BI Desktop DOC
Power BI Configuring Power BI mobile apps with Microsoft Intune DOC
Power BI Getting started with the Power BI for Android app DOC
Power BI Getting Started with the Power BI for iOS app DOC
Power BI How to plan capacity for embedded analytics with Power BI Premium PDF
Power BI Introducing Microsoft Power BI PDF
Power BI Introducing Microsoft Power BI – Mobile PDF
Power BI Microsoft Power BI Premium Whitepaper PDF
Power BI Power BI mobile apps—enabling data analytics on the go DOC
Power BI Propelling digital transformation in manufacturing operations with Power BI DOC
Power BI Using Power BI to visualize data insights from Microsoft Dynamics CRM Online DOC
PowerShell Microsoft Dynamics GP 2015 R2 PowerShell Users Guide PDF
PowerShell PowerShell Integrated Scripting Environment 3.0 PDF
PowerShell Simplify Group Policy administration with Windows PowerShell PDF
PowerShell Windows PowerShell – Management of Active Directory Infrastructure PDF
PowerShell Windows PowerShell 3.0 Examples PDF
PowerShell Windows PowerShell 3.0 Language Quick Reference PDF
PowerShell WINDOWS POWERSHELL 4.0 LANGUAGE QUICK REFERENCE PDF
PowerShell Windows PowerShell 4.0 Language Reference Examples PDF
PowerShell Windows PowerShell Command Builder User’s Guide PDF
PowerShell Windows PowerShell Desired State Configuration Quick Reference PDF
PowerShell WINDOWS POWERSHELL INTEGRATED SCRIPTING ENVIRONMENT 4.0 PDF
PowerShell Windows PowerShell Web Access PDF
PowerShell WMI in PowerShell 3.0 PDF
PowerShell WMI in Windows PowerShell 4.0 PDF
SharePoint Configuring Microsoft SharePoint Hybrid Capabilities PDF
SharePoint Configuring Microsoft SharePoint Hybrid Capabilities – Mobile PDF
SharePoint Deployment guide for Microsoft SharePoint 2013 PDF
SharePoint Microsoft SharePoint Server 2016 Architectural Models PDF
SharePoint Planning and Preparing for Microsoft SharePoint Hybrid – 8.5 X 11 PDF
SharePoint Planning and Preparing for Microsoft SharePoint Hybrid – Mobile PDF
SharePoint RAP as a Service for SharePoint Server PDF
SharePoint SharePoint Online Dedicated Service Description PDF
SharePoint SharePoint Products Keyboard Shortcuts PDF
SharePoint SharePoint Server 2016 Databases – Quick Reference Guide PDF
SharePoint SharePoint Server 2016 Quick Start Guide PDF
SQL Server 5 Tips For A Smooth SSIS Upgrade to SQL Server 2012 PDF
SQL Server Backup and Restore of SQL Server Databases PDF
SQL Server Data Science with Microsoft SQL Server 2016 PDF
SQL Server Deeper insights across data with SQL Server 2016 – Technical White Paper PDF
SQL Server Deploying SQL Server 2016 PowerPivot and Power View in a Multi-Tier SharePoint 2016 Farm DOC
SQL Server Deploying SQL Server 2016 PowerPivot and Power View in SharePoint 2016 DOC
SQL Server Guide to Migrating from Oracle to SQL Server 2014 and Azure SQL Database PDF
SQL Server Introducing Microsoft Azure™ HDInsight™ PDF
MOBI
EPUB
SQL Server Introducing Microsoft Data Warehouse Fast Track for SQL Server 2016 PDF
SQL Server Introducing Microsoft SQL Server 2012 PDF
MOBI
EPUB
SQL Server Introducing Microsoft SQL Server 2014 PDF
MOBI
EPUB
SQL Server Introducing Microsoft SQL Server 2016: Mission-Critical Applications, Deeper Insights, Hyperscale Cloud, Preview 2 PDF
MOBI
EPUB
SQL Server Introducing Microsoft SQL Server 2016: Mission-Critical Applications, Deeper Insights, Hyperscale Cloud, Preview 2 – Mobile PDF
SQL Server Introducing Microsoft Technologies for Data Storage, Movement and Transformation DOC
SQL Server Introducing Microsoft® SQL Server® 2008 R2 XPS
PDF
MOBI
EPUB
SQL Server Microsoft SharePoint Server 2016 Reviewer’s Guide PDF
SQL Server Microsoft SQL Server 2012 Tutorials: Analysis Services – Data Mining Step-by-Step PDF
SQL Server Microsoft SQL Server 2012 Tutorials: Analysis Services – Multidimensional Modeling Step-by-Step PDF
SQL Server Microsoft SQL Server 2012 Tutorials: Reporting Services Quick Step-by-Step PDF
SQL Server Microsoft SQL Server 2012 Tutorials: Writing Transact-SQL-Statements PDF
SQL Server Microsoft SQL Server 2014 Licensing Guide PDF
SQL Server Microsoft SQL Server 2016 Licensing Datasheet PDF
SQL Server Microsoft SQL Server 2016 Licensing Guide PDF
SQL Server Microsoft SQL Server 2016 Mission-Critical Performance Technical White Paper PDF
SQL Server Microsoft SQL Server 2016 New Innovations PDF
SQL Server Microsoft SQL Server 2016 SP1 Editions PDF
SQL Server Microsoft SQL Server In-Memory OLTP and Columnstore Feature Comparison PDF
SQL Server RAP as a Service for SQL Server PDF
SQL Server SQLCAT’s Guide to: Relational Engine PDF
SQL Server Xquery Language Reference PDF
Surface Surface Book User Guide PDF
Surface Surface Pro 4 User Guide PDF
System Center Guide to Microsoft System Center Management Pack for SQL Server 2016 Reporting Services (Native Mode) DOC
System Center Guide to System Center Management Pack for Windows Print Server 2016 DOC
System Center Introducing Microsoft System Center 2012 R2 PDF
MOBI
EPUB
System Center Microsoft System Center Building a Virtualized Network Solution, Second Edition PDF
MOBI
EPUB
System Center Microsoft System Center Data Protection for the Hybrid Cloud PDF
MOBI
EPUB
System Center Microsoft System Center Deploying Hyper-V with Software-Defined Storage & Networking PDF
MOBI
EPUB
System Center Microsoft System Center Extending Operations Manager Reporting PDF
MOBI
EPUB
System Center Microsoft System Center Introduction to Microsoft Automation Solutions PDF
MOBI
EPUB
System Center Microsoft System Center Operations Manager Field Experience PDF
MOBI
EPUB
System Center Microsoft System Center Software Update Management Field Experience PDF
MOBI
EPUB
System Center Microsoft System Center: Building a Virtualized Network Solution PDF
MOBI
EPUB
System Center Microsoft System Center: Cloud Management with App Controller PDF
MOBI
EPUB
System Center Microsoft System Center: Configuration Manager Field Experience PDF
MOBI
EPUB
System Center Microsoft System Center: Designing Orchestrator Runbooks PDF
MOBI
EPUB
System Center Microsoft System Center: Integrated Cloud Platform PDF
MOBI
EPUB
System Center Microsoft System Center: Network Virtualization and Cloud Computing PDF
MOBI
EPUB
System Center Microsoft System Center: Optimizing Service Manager PDF
MOBI
EPUB
System Center Microsoft System Center: Troubleshooting Configuration Manager PDF
MOBI
EPUB
System Center What’s new in System Center 2016 White Paper PDF
Virtualization Understanding Microsoft Virtualizaton R2 Solutions XPS
PDF
Windows Client Deploying Windows 10: Automating deployment by using System Center Configuration Manager PDF
MOBI
EPUB
Windows Client Deploying Windows 10: Automating deployment by using System Center Configuration Manager – Mobile PDF
Windows Client Getting the most out of Microsoft Edge DOC
Windows Client Introducing Windows 10 for IT Professionals PDF
MOBI
EPUB
Windows Client Introducing Windows 10 for IT Professionals, Preview Edition PDF
MOBI
EPUB
Windows Client Introducing Windows 8.1 for IT Professionals PDF
MOBI
EPUB
Windows Client Introducing Windows 8: An Overview for IT Professionals PDF
MOBI
EPUB
Windows Client Licensing Windows desktop operating system for use with virtual machines PDF
Windows Client Protecting your data with Windows 10 BitLocker DOC
Windows Client RAP as a Service for Windows Desktop PDF
Windows Client Shortcut Keys for Windows 10 DOC
Windows Client Use Reset to restore your Windows 10 PC DOC
Windows Client Volume Licensing Reference Guide Windows 10 Desktop Operating System PDF
Windows Client Windows 10 IT Pro Essentials Support Secrets PDF
PDF
MOBI
EPUB
Windows Client Windows 10 IT Pro Essentials Top 10 Tools PDF
MOBI
EPUB
Windows Client Windows 10 IT Pro Essentials Top 10 Tools – Mobile PDF
Windows Client Work Smart: Windows 8 Shortcut Keys PDF
Windows Server Automating Windows Server 2016 configuration with PowerShell and DSC DOC
Windows Server Introducing Windows Server 2008 R2 XPS
PDF
MOBI
EPUB
Windows Server Introducing Windows Server 2012 PDF
MOBI
MOBI
EPUB
EPUB
Windows Server Introducing Windows Server 2012 R2 PDF
MOBI
EPUB
Windows Server Introducing Windows Server 2016 PDF
Windows Server Introducing Windows Server 2016 – Mobile PDF
Windows Server Introducing Windows Server 2016 Technical Preview PDF
Windows Server Introducing Windows Server 2016 Technical Preview – Mobile PDF
Windows Server Introducing Windows Server® 2012 R2 Preview Release PDF
MOBI
EPUB
Windows Server Offline Assessment for Active Directory PDF
Windows Server RAP as a Service for Active Directory PDF
Windows Server RAP as a Service for Failover Cluster PDF
Windows Server RAP as a Service for Internet Information Services PDF
Windows Server RAP as a Service for Windows Server Hyper-V PDF
Windows Server Windows Server 2016 Licensing PDF

 

HOW TO DOWNLOAD ALL EBOOKS:

One of the popular questions I also receive is, “How can I Download All at one time?” I am sharing with you how you can “Download All” of the FREE eBooks and resources I am including in my annual giveaway. Here’s a quick FAQ/How-To to help address many of these in one place as a way to make it as easy as possible for my readers to find what they need. I hope these help you out and address questions you have regarding the post.

1. Don’t you have a zip file with all of the ebooks included or a “Download All” button so I can download them at once?

  • ZIP File: No, I do not have a zip file of the docs stored somewhere for download and this is intentional for several reasons. Since the eBooks and resources themselves have been put together and are distributed by some incredible authors and publishers, ultimately, they have the rights to update, distribute, and manage their IP as they see fit.
    • Example 1: If an author finds a correction needed (think about a typo in code included in a book that needs to be updated), they can update their deliverable and put the new one up at the download site they control to ensure all future downloads have the current information.
    • Example #2: (This one has actually happened with some of the books I’ve blogged about earlier) Sometimes an author wants to distribute their book a different way (switch from a share they have to a distribution site like Lulu) to achieve scale, better metrics, whatever. As such, they have every right to have the downloads moved to that site for distribution and have the downloads come from there.
    • Example #3: The author/publisher chooses to no longer distribute the free eBook or chooses to charge at some point. Again, as the owners of the IP, they have every right to do so.
      • If I were to grab today’s versions of the books, put them in a zip file, and distribute them from my server as an example, I would now be removing the author’s or publisher’s rights to do any of the three items listed above (as well as many other examples not listed). Ultimately, I (nor anyone else) do not have the right to do this. This is why I always provide links directly to their distribution sites, wherever they are so, you can download from them. Yes, this can be a challenge at times as I need to go back and edit links from time to time as they move the resources, but it is still the right thing to do and I am happy to do so in support of the great efforts these authors and publishers have done to make these resources available to all of us for free.

  • Download All button: Sort of. I don’t have a “Download All” button specifically, since that would point to a single location, which I don’t provide based on the items above; however, I am providing some options below:
    • Alternative 1: Some of the readers of my blog in the past have pinged me offline and suggested enabling the use of multiple browser download plug-ins that are available or various PowerShell options to download a list of links automatically. In order to use these options though, you would need a list of the download links to the eBooks on the site. Since this does not change the author’s/publisher’s rights to control their IP and distribution since it still enables downloads directly from their sites, I am happy to provide you with the list of links to do this.

If you right-click the icon to the right and select “Save Target As,” it will let you download a list of the links in a single .TXT file for all of the eBooks included in my latest post.

image12

    • With this list of links, you should be able to use the browser plug-ins, etc. of your choice to download the full list in an automated way.
    • Alternative 2: If you use PowerShell, here is a PowerShell script text you can use to Download All: (Thanks to David Crosby for the template)

If you right-click the icon to the right and select “Save Target As,” it will let you download the text for the PowerShell script to allow you to Download All of the eBooks above.

image12

 

2. Are these time-bombed versions of the books?

  • No, the free versions of the resources are full-version and do not have a time-out feature in them, so you can continue to use them for as long as you choose.

3. “I work for a library, resource desk, etc. and would like to share these with others. Is it ok to share your links to these?” (or some flavor of this with different variations)

  • Absolutely. Please feel free to share the links to these resources; however, please read #1 above on why you can share the links, but don’t distribute the actual works themselves as an offline resource. Please help support these fantastic authors and publishers by downloading the latest versions directly from them.

4. Download experiences seem to vary based on the resource I am downloading. Why is this?

  • As noted in #1 above, I always link to the site where the author/publisher is making the work available for download. Some of these are here on the Microsoft TechNet or MSDN sites, some are from blogs, etc. Depending on where they come from, your download experience may vary.

5. “I tried to download an eBook or resource and it didn’t work.”

  • Some of these eBooks come from a variety of places, and sometimes there is very heavy traffic to some of them. Wait a few moments and try again. You can also try right-clicking on the download link and selecting “Open in New Tab” or “Save Target As” to try initiating the download that way as well.

 

Thank you again for being a reader of my Blog and I hope you find this year’s collection of FREE eBooks and other resources to be very helpful to you, your colleagues, friends, or family.

Thank you and have a wonderful day,

Eric LigmanFollow me on TWITTER, LinkedIn, and Facebook
Director – Sales Excellence
Microsoft Corporation

This posting is provided “AS IS” with no warranties, and confers no rights 

Clicky

Viewing all 5308 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>