<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Инструменты для разработчиков</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/developer-tools-rus/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/developer-tools-rus/feed.xml</link>
    <description>Инструменты для разработчиков, руководства, помощь, статьи</description>
    <lastBuildDate>Wed, 17 Apr 2019 04:04:32 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Обнаружение утечек памяти в приложении Javascript для Windows 8 с помощью инструмента Javascript Memory Analysis из пакета Visual Studio</title>
      <link>https://docs.microsoft.com/archive/blogs/developer-tools-rus/23</link>
      <pubDate>Thu, 11 Jul 2013 23:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Paul Blokhin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/developer-tools-rus/2013/07/11/23/</guid>
      <description><![CDATA[Язык Javascript прекрасно подходит для разработки приложений для Windows 8. Javascript&nbsp;&mdash;...]]></description>
      <content:encoded><![CDATA[<p>Язык <strong>Javascript</strong> прекрасно подходит для разработки приложений для Windows 8. <strong>Javascript</strong>&nbsp;&mdash; нетипизированный динамический язык программирования, обеспечивающий высокую гибкость. Однако без должной внимательности, вы можете допустить утечки памяти в своем коде.</p>
<p>Но вы зря волнуетесь по этому поводу,&nbsp;<strong>Visual Studio</strong>&nbsp;содержит эффективный инструмент под названием <strong>Javascript Memory Analysis</strong>,&nbsp;который помогает обнаружить утечки памяти.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/8204.image_32004984.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/8204.image_5F00_32004984.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/4643.image_thumb_2AE39DBD.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/4643.image_5F00_thumb_5F00_2AE39DBD.png" alt="image" width="722" height="415" border="0" /></a></p>
<h1>Рекомендации по применению инструмента Javascript Memory Analysis</h1>
<p>Этот инструмент запускается из меню&nbsp;<strong>Debug</strong> (Отладка)&nbsp;в&nbsp;<strong>Visual Studio</strong>:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/8787.image_55BE9280.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/8787.image_5F00_55BE9280.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/2818.image_thumb_057C;.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/2818.image_5F00_thumb_5F00_057C3B00.png" alt="image" width="868" height="186" border="0" /></a></p>
<p>После запуска инструмента, запустится и ваше приложение, на экране вы увидите следующее:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/1325.image_2048610C.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/1325.image_5F00_2048610C.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/3808.image_thumb_5006098B.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/3808.image_5F00_thumb_5F00_5006098B.png" alt="image" width="948" height="606" border="0" /></a></p>
<p>В первой области окна в режиме реального времени отображается объем памяти, используемой приложением:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/8272.image_18BF8250.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/8272.image_5F00_18BF8250.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/6622.image_thumb_14490189.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/6622.image_5F00_thumb_5F00_14490189.png" alt="image" width="678" height="120" border="0" /></a></p>
<p>Ниже присутствует кнопка <em>Take Heap Snapshot</em> (Создание мгновенного снимка кучи), используемая для создания мгновенного снимка &laquo;кучи&raquo; (элемент управления также показывает размер &laquo;кучи&raquo; и количество активных объектов):</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/0456.image_4CF3AB96.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/0456.image_5F00_4CF3AB96.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/6523.image_thumb_53A945CA.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/6523.image_5F00_thumb_5F00_53A945CA.png" alt="image" width="1056" height="680" border="0" /></a></p>
<p>По щелчку на размере &laquo;кучи&raquo; выводится более подробная информация:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/7128.image_3C119857.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/7128.image_5F00_3C119857.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/5732.image_thumb_2B99275C.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/5732.image_5F00_thumb_5F00_2B99275C.png" alt="image" width="864" height="575" border="0" /></a></p>
<p>Это список объектов, отсортированный с учетом объема удерживаемой памяти,&nbsp;<strong>таким образом, объекты, потребляющие больше всего памяти, которую можно высвободить, будут вверху списка.</strong></p>
<p>На примере моего приложения, я вижу, что объект&nbsp;<em>UrzaGatherer</em>&nbsp;удерживает около&nbsp;<strong>60&nbsp;МБ</strong> памяти (так и должно быть, поскольку в нем хранится огромный список&nbsp;<a href="https://blogs.msdn.com/b/eternalcoding/archive/2012/08/20/how-to-cook-a-windows-8-application-with-html5-javascrip-css3-rtm-version.aspx">карт)</a>:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/5224.image_301238D4.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/5224.image_5F00_301238D4.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/0434.image_thumb_3895981E.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/0434.image_5F00_thumb_5F00_3895981E.png" alt="image" width="1022" height="579" border="0" /></a></p>
<p>Это представление также позволяет вывести на экран:</p>
<ul>
<li>список типов, отсортированный по количеству вхождений;</li>
<li>список корневых объектов (с точки зрения сборщика мусора);</li>
<li>список объектов&nbsp;<strong>DOM</strong>,&nbsp;отсортированный по объему удерживаемой памяти;</li>
<li>список объектов&nbsp;<strong>WinRT</strong>,&nbsp;отсортированный по объему удерживаемой памяти.</li>
</ul>
<p>Эти представления помогут вам обнаружить случаи&nbsp;<strong>нецелесообразного</strong>&nbsp;использования памяти.</p>
<h1>Сравнение моментальных снимков</h1>
<p>После каждого нажатия кнопки&nbsp;<em>Take Heap Snapshot</em> (Создание мгновенного снимка кучи) система генерирует новый дамп &laquo;кучи&raquo; с целью последующего анализа. Кроме того, каждый новый снимок позволяет оценить динамику изменения размера &laquo;кучи&raquo; и количества объектов.</p>
<p>Это&nbsp;<strong>основной</strong> инструмент поиска утечек памяти.</p>
<p>В своем приложении я сделаю первый снимок, перейду на данную страницу, затем вернусь на главную и, наконец, сделаю второй снимок. Таким образом я смогу определить, присутствует ли утечки памяти на интересующей меня странице.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/2313.image_3D0EA996.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/2313.image_5F00_3D0EA996.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/0841.image_thumb_411B8819.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/0841.image_5F00_thumb_5F00_411B8819.png" alt="image" width="664" height="325" border="0" /></a></p>
<p>Сравнив два моментальных снимка, я обнаружил, что&nbsp;размер &laquo;кучи&raquo; увеличился на <strong>6,12&nbsp;МБ</strong>,&nbsp;кроме того, были созданы&nbsp;<strong>53&nbsp;000&nbsp;</strong>объектов, которые не были в дальнейшем удалены.&nbsp;</p>
<p>Щелкнув значение, показывающее изменение размера &laquo;кучи&raquo; (+6,12&nbsp;МБ), вы можете получить более подробную информацию о различиях между двумя моментальными снимками:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/6523.image_16CEE0EF.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/6523.image_5F00_16CEE0EF.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/5633.image_thumb_0892F8B0.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/5633.image_5F00_thumb_5F00_0892F8B0.png" alt="image" width="1024" height="293" border="0" /></a></p>
<p>Представление Dominators (Доминаторы) показывает, что новые объекты не были удалены после того, как мы вернулись на домашнюю страницу. Это представление поможет вам обнаружить ненужные объекты.</p>
<p>В моем случае подозрительной кажется первая строка. Щелкнув ее правой кнопкой мыши, я могу перейти к представлению Root (Корень), чтобы увидеть, какая функция хранит эти объекты:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/8666.image_485F6FE6.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/8666.image_5F00_485F6FE6.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/4137.image_thumb_60F19DE7.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/4137.image_5F00_thumb_5F00_60F19DE7.png" alt="image" width="1024" height="415" border="0" /></a></p>
<p>Как видите, объект удерживается функцией&nbsp;<em>ImportFromTappedOut</em>.</p>
<p>Эта глобальная функция в моем коде принимает функцию в качестве параметра:</p>
<pre class="scroll"><code class="js">ImportFromTappedOut = function (deckName, custom) {</code></pre>
<p>Параметр <em>custom&nbsp;</em>эта функция использует для вызова специализированного пользовательского кода. Главная проблема связана с тем, что&nbsp;<em>ImportFromTappedOut</em>&nbsp;&mdash; глобальная функция, и она хранит весь код, к которому обращается функция, в параметре&nbsp;<em>custom</em>.&nbsp;В этом случае моя анонимная функция ссылается на большое количество локальных объектов DOM:</p>
<pre class="scroll"><code class="js">Tools.ImportFromTappedOut("test", function () { var select = document.querySelector("#addToDeck"); <br /> var count = document.querySelector("#addToDeckCount").value; <br /> listView.selection.getItems().then(function (items) { appBar.hide(); <br /> appBar.sticky = false; listView.selection.clear();</code></pre>
<pre class="scroll">&nbsp;</pre>
<pre class="code"><span><em>&hellip;code continue&hellip;</em></span></pre>
<p>Эту проблему мне помог обнаружить рассматриваемый инструмент:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/5633.image_1DA92678.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/5633.image_5F00_1DA92678.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/73/metablogapi/0743.image_thumb_222237F0.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-73-metablogapi/0743.image_5F00_thumb_5F00_222237F0.png" alt="image" width="647" height="125" border="0" /></a></p>
<p>Решение простое: достаточно вызвать&nbsp;<em>importFromTappedOut</em>&nbsp;с нулевой функцией, когда я закрываю страницу, чтобы сборщик мусора удалил все сохраненные объекты (в этом случае освободится 1,25&nbsp;МБ).</p>
<p>Я настоятельно рекомендую вам использовать этот инструмент для выявления и предотвращения утечек памяти. Несмотря на свою простоту, он очень эффективен.</p>
<h1>Подробнее о рассматриваемом инструменте</h1>
<p><span style="font-size: 12px;">Следующие статьи также могут быть вам полезны:</span></p>
<ul style="font-size: 12px;">
<li><a href="https://blogs.msdn.com/b/visualstudio/archive/2013/02/04/10388914.aspx">JavaScript memory analysis for Windows Store apps in Visual Studio 2012</a></li>
<li><a href="https://blogs.msdn.com/b/eternalcoding/archive/2012/11/15/optimizing-javascript-windows-8-application-using-the-visual-studio-performance-analysis-tool-profiler.aspx">Optimizing JavaScript Windows 8 application: Using the Visual Studio performance analysis tool (profiler)</a></li>
<li><a href="https://blogs.msdn.com/b/eternalcoding/archive/2012/08/20/how-to-cook-a-windows-8-application-with-html5-javascrip-css3-rtm-version.aspx">How to cook a Windows 8 application with HTML5/Javascript/CSS3</a></li>
<li><a href="https://blogs.msdn.com/b/eternalcoding/archive/2012/03/22/unleash-the-power-of-html-5-canvas-for-gaming-part-1.aspx">Unleash the power of HTML 5 Canvas for gaming</a></li>
<li>[Французский]<a title="https://www.microsoft.com/france/mstechdays/programmes/2013/fiche-session.aspx?ID=f721312a-cc92-4599-8795-cfe07d5c0bb4" href="https://www.microsoft.com/france/mstechdays/programmes/2013/fiche-session.aspx?ID=f721312a-cc92-4599-8795-cfe07d5c0bb4">https://www.microsoft.com/france/mstechdays/programmes/2013/fiche-session.aspx?ID=f721312a-cc92-4599-8795-cfe07d5c0bb4</a></li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>[Статья нашего гостя] Советы и рекомендации по IntelliTrace. Основы. Часть 1. Автор: Колин Дембовский (Colin Dembovsky)</title>
      <link>https://docs.microsoft.com/archive/blogs/developer-tools-rus/10</link>
      <pubDate>Tue, 09 Jul 2013 23:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Paul Blokhin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/developer-tools-rus/2013/07/09/10/</guid>
      <description><![CDATA[Рекомендации по применению IntelliTrace
Варианты применения инструмента IntelliTrace:

Во время...]]></description>
      <content:encoded><![CDATA[<p><strong>Рекомендации по применению IntelliTrace</strong></p>
<p>Варианты применения инструмента IntelliTrace:</p>
<ol>
<li><span style="font-size: 12px;">Во время отладки в VS нажатием клавиши F5.</span></li>
<li><span style="font-size: 12px;">В Test Manager (доступен как адаптер диагностических данных&nbsp;&mdash; Data Diagnostic Adapter).</span></li>
<li><span style="font-size: 12px;">При запуске из любого места (использование автономного сборщика данных).</span></li>
</ol>
<p><strong>Описание &laquo;режимов работы&raquo; IntelliTrace</strong></p>
<p>В IntelliTrace реализовано два стандартных режима с широкими возможностями: Events Only (Только события) и Events and Call Information (События и сведения о вызовах). Режим Events Only&nbsp;&mdash; упрощенный, он позволяет регистрировать &laquo;события&raquo;, которые происходят во время выполнения вашей программы. Эти события представляют собой заслуживающие интереса &laquo;происшествия&raquo;, например вызовы ASP.NET или ADO.NET, а&nbsp;также исключения. Группа разработки продукта постаралась записать события, которые помогут понять, как ваш код работает, и проследить длинные цепочки &laquo;причин и следствий&raquo;.</p>
<p>Режим Events and Call Information&nbsp;&mdash; расширенный режим отладки, при котором помимо сведений, относящихся к режиму Events Only, регистрируются также вызовы методов (включая входящие и исходящие аргументы). Для подлежащих сбору данных установлены некоторые ограничения, иначе размер журналов будет просто огромным, даже больше, чем с настройками по умолчанию.</p>
<p><strong>Использование клавиши F5 при работе с IntelliTrace</strong></p>
<p>Этот вариант подходит для использования в процессе разработки кода. Это означает, что можно отлаживать приложение, перемещаясь вперед и назад в сеансе отладки, при этом нет необходимости останавливать приложение или добавлять точки останова. Активировать отладчик можно в настройках IntelliTrace: Tools&nbsp;-&gt; Options (Сервис -&gt; Параметры). Предусмотрено два режима:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/2630.clip_image001_23E65B87.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/2630.clip_5F00_image001_5F00_23E65B87.png"><img title="clip_image001" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/0081.clip_image001_thumb_0069B722.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/0081.clip_5F00_image001_5F00_thumb_5F00_0069B722.png" alt="clip_image001" width="377" height="264" border="0" /></a></p>
<p>После активации (в данном случае я включил режим Events and Call Information) отладчик готов к&nbsp;использованию. Понажимайте кнопки в своем приложении и щелкните ссылку Break All (Приостановить все) в VS в окне IntelliTrace:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/0763.clip_image002_63A01C3F.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/0763.clip_5F00_image002_5F00_63A01C3F.png"><img title="clip_image002" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/3276.clip_image002_thumb_132E14FF.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/3276.clip_5F00_image002_5F00_thumb_5F00_132E14FF.png" alt="clip_image002" width="396" height="224" border="0" /></a></p>
<p>(Я отлаживаю свое приложение Calculator. Нажимаю Break All (Приостановить все) и открывают журнал IntelliTrace.)</p>
<p>Изначально в журнале отображаются все произошедшие события. В нашем случае нажатия кнопок относятся к&nbsp;событиям типа Gesture (Жест), поэтому в журнале мы видим:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/5165.clip_image003_28C84D9C.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/5165.clip_5F00_image003_5F00_28C84D9C.png"><img title="clip_image003" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/1460.clip_image003_thumb_30240D49.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/1460.clip_5F00_image003_5F00_thumb_5F00_30240D49.png" alt="clip_image003" width="199" height="320" border="0" /></a></p>
<p>Предположим, что нечто странное произошло, когда я нажал &laquo;=&raquo;, перемножая два числа. Перезапускать приложение нет необходимости, я могу просто нажать кнопку &laquo;=&raquo; после &laquo;*&raquo; (из записи в журнале видно, что я нажал 3&nbsp;х 6&nbsp;=). Я могу нажать это событие и &laquo;перемотать&raquo; до интересующего меня момента.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/5481.clip_image004_7A5EA221.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/5481.clip_5F00_image004_5F00_7A5EA221.png"><img title="clip_image004" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/2577.clip_image004_thumb_1DCB20BA.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/2577.clip_5F00_image004_5F00_thumb_5F00_1DCB20BA.png" alt="clip_image004" width="244" height="208" border="0" /></a></p>
<p>Сейчас я могу нажать Calls View (Представление вызовов) и приступить к просмотру журнала с этой точки.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/4628.clip_image005_7A4E7C54.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/4628.clip_5F00_image005_5F00_7A4E7C54.png"><img title="clip_image005" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/4442.clip_image005_thumb_0F7C81FD.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/4442.clip_5F00_image005_5F00_thumb_5F00_0F7C81FD.png" alt="clip_image005" width="340" height="162" border="0" /></a></p>
<p>Дважды щелкните вызов btnEqual_Click для перехода к этому моменту выполнения. Вы увидите глифы IntelliTrace во внутреннем поле окна исходного кода:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/1373.clip_image006_7DDC7164.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/1373.clip_5F00_image006_5F00_7DDC7164.png"><img title="clip_image006" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/2555.clip_image006_thumb_48EF6C27.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/2555.clip_5F00_image006_5F00_thumb_5F00_48EF6C27.png" alt="clip_image006" width="361" height="162" border="0" /></a></p>
<p>Если навести указатель мыши на значки, система выдаст подсказку. Функции появляются в следующем порядке:</p>
<p>&middot; return to calling method</p>
<p>&middot; step back</p>
<p>&middot; step into</p>
<p>&middot; step over</p>
<p>&middot; return to Live Debugging</p>
<p>(Небольшая подсказка: при нажатии кнопки return to Live Debugging (Возврат к динамической отладке) внизу, вы перейдете к текущей точке отладчика, и для повторного запуска приложения следует опять нажать клавишу&nbsp;F5.)</p>
<p>Если вы нажмете F11, текущий указатель переместится вперед. Нажав эту кнопку дважды, я перешел к точке, где в программе стоит оператор Switch:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/2475.clip_image007_73E75A2C.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/2475.clip_5F00_image007_5F00_73E75A2C.png"><img title="clip_image007" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/1616.clip_image007_thumb_5B944011.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/1616.clip_5F00_image007_5F00_thumb_5F00_5B944011.png" alt="clip_image007" width="406" height="202" border="0" /></a></p>
<p>Обратите внимание: мне не придется гадать, какой именно оператор Case был выбран, достаточно посмотреть запись в журнале. Я также поставил метки для обработчиков наведения и убирания курсора мыши для val1 и&nbsp;val2, вы можете увидеть эти значения. Не все значения отслеживаются, но в данном случае это исходящие или входящие примитивы метода, поэтому IntelliTrace успешно регистрирует их значения.</p>
<p>Я опять нажму клавишу F11, чтобы войти в метод Multiply(), а затем еще раз, чтобы перейти к следующему событию:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/8623.clip_image008_712E78AE.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/8623.clip_5F00_image008_5F00_712E78AE.png"><img title="clip_image008" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/7853.clip_image008_thumb_1BBA33BF.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/7853.clip_5F00_image008_5F00_thumb_5F00_1BBA33BF.png" alt="clip_image008" width="444" height="252" border="0" /></a></p>
<p>Я перешел к закрывающейся фигурной скобке метода Multiply. В окне Autos показаны параметры val1 и val2 и&nbsp;их значения (3 и 6, соответственно), а также значение, возвращаемое методом (9).</p>
<p>Вуаля! 3&ndash;4 клика, и мы нашли ошибку в своей программе. И нам даже не пришлось задавать точку останова!</p>
<p><strong>Фильтрация событий</strong></p>
<p>IntelliTrace регистрирует большое количество событий, поэтому, чтобы упростить навигацию по журналу, можно использовать категорию, поток и окно поиска в верхней части окна событий для фильтрации событий.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/3146.clip_image009_5F41BF14.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/3146.clip_5F00_image009_5F00_5F41BF14.png"><img title="clip_image009" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/4024.clip_image009_thumb_74DBF7B1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/4024.clip_5F00_image009_5F00_thumb_5F00_74DBF7B1.png" alt="clip_image009" width="304" height="224" border="0" /></a></p>
<p>Например, в выпадающем списке All Categories (Все категории) я могу выбрать фильтр, чтобы отображались только исключения:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/5482.clip_image010_4635C902.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/5482.clip_5F00_image010_5F00_4635C902.png"><img title="clip_image010" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/7360.clip_image010_thumb_2DE2AEE7.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/7360.clip_5F00_image010_5F00_thumb_5F00_2DE2AEE7.png" alt="clip_image010" width="266" height="295" border="0" /></a></p>
<p><strong>Поиск строки</strong></p>
<p>Также рекомендую использовать функцию поиска строки (Search For this line) или метода (Search For This Method). Вы подозреваете, что метод был выполнен во время отладки, но читать весь журнал нет времени? Никаких проблем! Щелкните правой кнопкой мыши строку (или метод) и выберите Search For This Line/Method in IntelliTrace (Поиск для этой строки/метода в IntelliTrace).</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/2402.clip_image011_7F3C8037.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/2402.clip_5F00_image011_5F00_7F3C8037.png"><img title="clip_image011" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/8611.clip_image011_thumb_2CFA2330.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/8611.clip_5F00_image011_5F00_thumb_5F00_2CFA2330.png" alt="clip_image011" width="484" height="352" border="0" /></a></p>
<p>После чего вы увидите результаты поиска на панели в верхней части текущего окна кода. Используйте стрелки для перехода к предыдущему или следующему экземпляру этой строки или метода в файле журнала:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/3704.clip_image012_4F8E3BDE.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/3704.clip_5F00_image012_5F00_4F8E3BDE.png"><img title="clip_image012" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/5340.clip_image012_thumb_45E5CDA8.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/5340.clip_5F00_image012_5F00_thumb_5F00_45E5CDA8.png" alt="clip_image012" width="327" height="112" border="0" /></a></p>
<p>Я щелкну по значку стрелки сразу после слова Multiply, чтобы перейти к первому вызову этого метода в&nbsp;журнале и начать процесс &laquo;отладки&raquo; с этого места.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/3554.clip_image013_03268270.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/3554.clip_5F00_image013_5F00_03268270.png"><img title="clip_image013" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/33/14/metablogapi/3441.clip_image013_thumb_4EA5B027.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-33-14-metablogapi/3441.clip_5F00_image013_5F00_thumb_5F00_4EA5B027.png" alt="clip_image013" width="367" height="99" border="0" /></a></p>
<p>В следующей статье я расскажу вам, как запускать IntelliTrace из любого места.</p>
<p>Удачной отладки!</p>
<p>&nbsp;</p>]]></content:encoded>
    </item>
    <item>
      <title>Что представляет собой карта кода Visual Studio 2012?</title>
      <link>https://docs.microsoft.com/archive/blogs/developer-tools-rus/43</link>
      <pubDate>Fri, 05 Jul 2013 01:12:00 GMT</pubDate>
      <dc:creator><![CDATA[Paul Blokhin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/developer-tools-rus/2013/07/05/43/</guid>
      <description><![CDATA[Что такое карта кода?
В пакет обновления Visual Studio 2012 Update 1, который вышел в ноябре 2012...]]></description>
      <content:encoded><![CDATA[<p><strong>Что такое карта кода?</strong></p>
<p>В пакет обновления Visual Studio 2012 Update 1, который вышел в ноябре 2012 года, была включена новая функция под названием Code Map (Карта кода), она доступна пользователям версии Ultimate edition. Эта функция позволяет визуализировать взаимосвязи в коде. В основе карты кода лежит концепция, понять которую вам поможет этот короткий&nbsp;<a href="https://channel9.msdn.com/Series/Visual-Studio-2012-Premium-and-Ultimate-Overview/Visual-Studio-Ultimate-2012-Understanding-complex-code-with-Code-Map-ENU">видеоролик</a>.</p>
<p>Начиная с версии, включенной в пакет обновления <a href="https://www.microsoft.com/en-us/download/details.aspx?id=38188">Visual Studio 2012 Update 2</a>, функция Code Map включает расширенные возможности, теперь взаимосвязи в коде можно визуализировать в ходе отладки. Ниже представлен код для Windows Phone&nbsp;&mdash; при нажатии кнопки веб-службе отправляется запрос на получение данных о численности населения Пакистана. После получения результата на экран выводится подтверждающее сообщение для пользователя. Однако в ходе тестирования мы обнаружили, что сообщение с&nbsp;подтверждением выводится до фактического получения ответа на запрос, поэтому мы приступаем к отладке кода с использованием инструмента Code Map.</p>
<p><span><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/2061.Code%20Map%20Code.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/2061.Code-Map-Code.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/2061.Code%20Map%20Code.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/2061.Code-Map-Code.png" alt="" border="0" /></a>&nbsp;</span></p>
<p><strong></strong>&nbsp;</p>
<p><strong>Карта кода: инструкция по применению?</strong></p>
<p>Сейчас мы познакомимся с функцией отладки инструмента Code Map (Карта кода). Создайте точку останова для обработчика нажатия кнопки. Как только точка останова сработает, перейдите в окно карты кода, выполнив одно из следующих действий:</p>
<p>-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Нажмите кнопку Code Map (Карта кода) на панели инструментов.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/8867.Code%20Map%20Menubar%20Item.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/8867.Code-Map-Menubar-Item.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/8867.Code%20Map%20Menubar%20Item.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/220x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/8867.Code-Map-Menubar-Item.png" alt="" border="0" /></a></p>
<p>&nbsp;-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Выберите пункт Show Call Stack on Code Map (Показать стек вызовов на карте кода) из меню Debug (Отладка).</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/5282.Show%20Call%20on%20Code%20Map.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/5282.Show-Call-on-Code-Map.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/5282.Show%20Call%20on%20Code%20Map.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/400x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/5282.Show-Call-on-Code-Map.png" alt="" border="0" /></a></p>
<p>-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Нажмите Ctrl&nbsp;+ Shift&nbsp;+`.</p>
<p>&nbsp;</p>
<p>На экране вы увидите примерно следующее:</p>
<p>&nbsp;</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/2318.Debugging%201.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/2318.Debugging-1.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/2318.Debugging%201.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/2318.Debugging-1.png" alt="" border="0" /></a></p>
<p>&nbsp;</p>
<p>Красная рамка означает, что для этого узла в данный момент выполняется отладка. Давайте проанализируем первый метод. Нажав F11, вы можете вывести на экран содержимое метода DataRetrieved(), в окне Code Map будет показано текущее состояние отладки, для соответствующего метода будет создан новый узел. Обратите внимание, что узел для DataRetrieved () в данный момент выделен желтым маркером.&nbsp;Это позволяет вам отслеживать свои стеки вызовов и взаимосвязь методов.</p>
<p>&nbsp;</p>
<p><strong><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/6523.Data%20Requested.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/6523.Data-Requested.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/6523.Data%20Requested.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/6523.Data-Requested.png" alt="" border="0" /></a></strong></p>
<p>&nbsp;</p>
<p>Code Map предоставляет широкие возможности для отладки, например, нажав <em>Summary&nbsp;</em>(элемент TextBlock) внутри метода и выбрав Find All References on Code Map (Найти все ссылки на карте кода), вы можете вывести на экран все элементы, на которые ссылается это поле. Например, вы без лишних усилий можете определить, какие методы в коде работают с конкретным полем; это очень удобно, особенно для сложных сценариев отладки.</p>
<p>&nbsp;</p>
<p><span><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/5468.Find%20All%20Reerences.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/5468.Find-All-Reerences.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/5468.Find%20All%20Reerences.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/5468.Find-All-Reerences.png" alt="" border="0" /></a>&nbsp;</span></p>
<p>Можно продолжить отладку и перейти к следующему методу обработчика нажатия на кнопку&nbsp;&mdash; RequestPopulation(). Если вы пропустите этот метод, нажав F10, то на карте кода он не появится. Это предотвращает загромождение карты кода, на ней будут только те элементы, которые вас интересуют.</p>
<p>Давайте перейдем к последнему методу в этом вызове&nbsp;&mdash; ShowConfirmationMesssage(). Узел для этого метода станет активным, а узел для DataRequest() поменяет цвет на серый, это означает, что узел больше не является активным в контексте отладки.</p>
<p><span><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/4643.Gray%20Node.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/4643.Gray-Node.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/4643.Gray%20Node.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/4643.Gray-Node.png" alt="" border="0" /></a>&nbsp;</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>Наконец, если мы откроем этот метод, вернемся к обработчику нажатия кнопки Button 1 и продолжим отладку путем нажатия F10, то мы перейдем к событию DownloadStringCompleted, которое представляет собой асинхронный вызов из метода RequestPopulation(). Обратите внимание, что на карте кода это ветвь от узла External Code (Внешний код), поскольку вызов перехватывается библиотеками классов ядра (класс System.Net.WebClient) в Windows Phone.</p>
<p>&nbsp;</p>
<p><span><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/2626.Asynchronous%20Calls.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/2626.Asynchronous-Calls.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/2626.Asynchronous%20Calls.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/2626.Asynchronous-Calls.png" alt="" border="0" /></a>&nbsp;</span></p>
<p>&nbsp;</p>
<p>Наведите указатель мыши на событие wc_DownloadStringcompleted(), и вы увидите соответствующую подпись кода в подсказке.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/1667.Tooltip.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/1667.Tooltip.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/1667.Tooltip.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/1667.Tooltip.png" alt="" border="0" /></a></p>
<p><strong>Функции анализа кода в Code Map</strong></p>
<p>Наконец, мы обнаружили проблему в коде. Вызов веб-службы является асинхронным, поэтому приложение не&nbsp;будет ждать ответа и сразу покажет сообщение с подтверждением. Эту информацию мы должны передать нашему разработчику. Инструмент Code Map, в частности, помогает анализировать код. Щелкните правой кнопкой событие wc_DownloadStringCompleted и выберите Add Comment (Добавить комментарий).</p>
<p><span><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/8524.Confirmation%20Message%20Call.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/8524.Confirmation-Message-Call.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/8524.Confirmation%20Message%20Call.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/8524.Confirmation-Message-Call.png" alt="" border="0" /></a>&nbsp;</span></p>
<p>После добавления комментария вы можете просто переместиться наверх и выбрать подходящий метод для предоставления общего доступа.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/1541.Share.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/1541.Share.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/1541.Share.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/500x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/1541.Share.png" alt="" border="0" /></a></p>
<p>&nbsp;</p>
<p>Также доступны другие полезные функции, например функция Flag for Follow Up (Отметка к дальнейшим действиям) позволяет выбрать цвет и выделить фрагмент кода, который требует вашего внимания, но не&nbsp;в&nbsp;рамках текущего сеанса отладки.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/6305.Flag%20for%20Follow%20UP.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/6305.Flag-for-Follow-UP.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/6305.Flag%20for%20Follow%20UP.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/375x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/6305.Flag-for-Follow-UP.png" alt="" border="0" /></a></p>
<p><strong>Анализ указателей</strong></p>
<p>Для удобства читателя приводится краткий обзор указателей, аналоги которых присутствуют на карте кода.</p>
<p><span><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/3580.Pointers.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/3580.Pointers.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/48/94/3580.Pointers.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-48-94/3580.Pointers.png" alt="" border="0" /></a></span></p>]]></content:encoded>
    </item>
    <item>
      <title>Разработка приложений с использованием пакета Visual Studio 3D Starter Kit. Часть 3 из 3</title>
      <link>https://docs.microsoft.com/archive/blogs/developer-tools-rus/53</link>
      <pubDate>Wed, 03 Jul 2013 01:12:00 GMT</pubDate>
      <dc:creator><![CDATA[Paul Blokhin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/developer-tools-rus/2013/07/03/53/</guid>
      <description><![CDATA[Это третья, заключительная, статья из серии, посвященной основам работы с пакетом&nbsp;Visual Studio...]]></description>
      <content:encoded><![CDATA[<p>Это третья, заключительная, статья из серии, посвященной основам работы с пакетом&nbsp;<a href="https://aka.ms/vs3dkit">Visual Studio 3D Starter Kit</a>! Если вы прочли и выполнили все рекомендации из двух предыдущих статей (см.&nbsp;<a href="https://blogs.msdn.com/b/developer-tools-rus/archive/2013/06/24/visual-studio-3d-starter-kit-1-3.aspx">здесь</a>&nbsp;и <a href="https://blogs.msdn.com/b/developer-tools-rus/archive/2013/07/01/visual-studio-3d-starter-kit-2-3.aspx">здесь</a>), то получили приложение, которое имитирует игру в кости. Сейчас мы внесем последние изменения в наше приложение для запуска на устройствах, работающих под управлением Windows RT или Windows Phone 8.&nbsp;</p>
<p>Если две предыдущие статьи вы еще не читали, то можете сделать это прямо сейчас. Приступайте к&nbsp;этой статье, когда у вас будет готово приложение.</p>
<p>Если вам легче воспринимать визуальную информацию, то посмотрите видеоролики для части 1 и 2 на нашем канале&nbsp;<a href="https://channel9.msdn.com/posts/VS-3D-Starter-Kit-Dice-Roller">Channel 9</a>! Вам понадобится менее получаса, чтобы с нуля создать приложение, реалистично имитирующее игру в кости!</p>
<p><a href="https://channel9.msdn.com/posts/VS-3D-Starter-Kit-Dice-Roller"><img src="https://media.ch9.ms/ch9/b3eb/05e328a7-8b3d-4e91-9085-e1241e46b3eb/DiceRollerrs_512.jpg" alt="" border="0" /></a></p>
<h2>Заключительные шаги Windows RT</h2>
<p>Современные устройства с Windows RT оборудованы графической картой с поддержкой <a href="https://msdn.microsoft.com/ru-ru/library/windows/desktop/ff476876.aspx">D3D_FEATURE_LEVEL_9_1</a>,&nbsp;а инструменты Visual Studio Graphics генерируют шейдеры для графических карт с поддержкой D3D_FEATURE_LEVEL_10_0 и выше, поэтому для того, чтобы приложение можно было запускать на устройствах с Windows RT, необходимо создать шейдеры поддерживаемой версии.</p>
<p>Откройте сетку Die (Die.fbx) и щелкните куб. В окне Properties (Свойства) найдите свойство Effect (Эффект). Нажмите кнопку &laquo;+&raquo; слева от этого свойства и выберите значение Advanced (Расширенные). Наконец, нажмите кнопку &laquo;&hellip;&raquo;, чтобы открыть исходный код шейдера для эффекта Phong (метод Фонга).</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/6758.Part3_Fig1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/6758.Part3_5F00_Fig1.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/6758.Part3_Fig1.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/391x366/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/6758.Part3_5F00_Fig1.png" alt="" border="0" /></a></p>
<p>В окне конструктора шейдеров Visual Studio Shader Designer вы увидите шейдер, который по умочанию применяется к этой сетке в Visual Studio. Конструктор шейдеров позволяет создавать сложные визуальные эффекты, при этом вам не придется изучать новый язык программирования. Подробнее о конструкторе шейдеров написано в&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/hh315733(v=VS.110).aspx">документации</a>&nbsp;и <a href="https://msdn.microsoft.com/ru-ru/library/jj161095.aspx">обзоре</a>&nbsp;на сайте MSDN.</p>
<p>Мы экспортируем этот шейдер в HLSL для того, чтобы перекомпилировать его для видеокарт типа Direct3D Feature Level 9. Starter Kit попытается автоматически найти поддерживаемый шейдер с тем же именем, если оригинал не поддерживается данным устройством.</p>
<p>Для экспорта этого шейдера переходим к последнему значку на панели инструментов: (Advanced)&nbsp;-&gt; Export -&gt; Export as&hellip; ((Расширенные) -&gt; Экспортировать -&gt; Экспортировать как...), вводим имя <strong>Phong.hlsl</strong> и сохраняем файл в папку Assets (см. рисунок ниже). Необходимо добавить этот файл в&nbsp;проект: щелкните правой кнопкой мыши папку Assets, нажмите Solution Explorer -&gt; Add -&gt; Existing item (Обозреватель решений -&gt; Добавить -&gt; Существующий элемент) и выберите только что экспортированный файл.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/0842.Part3_Fig2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/0842.Part3_5F00_Fig2.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/0842.Part3_Fig2.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/0842.Part3_5F00_Fig2.png" alt="" border="0" /></a></p>
<p>Наконец, мы должны сообщить компилятору HLSL, что этот файл относится к типу Pixel Shader&nbsp;(Шейдер пикселей). Для этого в обозревателе решений Solution Explorer щелкните правой кнопкой мыши файл Phong.hlsl и выберите Properties (Свойства). На странице свойств проверьте, чтобы в&nbsp;раскрывающемся списке Configuration (Конфигурация) был выбран пункт All Configurations (Все конфигурации), а в раскрывающемся списке Platform (Платформа)&nbsp;&mdash; All Platforms (Все платформы). Таким образом, все вносимые нами изменения применяются ко всем версиям нашего приложения.</p>
<p>Затем на странице HLSL Compiler (Компилятор HLSL) задайте свойству Shader Type (Тип шейдера) значение Pixel Shader (/ps) [Шейдер пикселей (/ps)]. Кроме того, должна быть включена оптимизация, т.&nbsp;е. свойству Disable optimizations (Отключить оптимизацию) должно быть задано значение No (Нет). Эти настройки показаны на рисунке ниже:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/7181.Part3_Fig3.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/7181.Part3_5F00_Fig3.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/7181.Part3_Fig3.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/7181.Part3_5F00_Fig3.png" alt="" border="0" /></a></p>
<p>На этом этапе мы подготовили приложение для запуска на устройствах под управлением Windows&nbsp;RT. Теперь вы можете установить это приложение на своем устройстве с помощью инструментов удаленной отладки&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/hh441469(v=vs.110).aspx">Visual Studio Remote Debugging Tools</a>.</p>
<p>Прежде чем опубликовать версию приложения для Windows RT, необходимо убедиться в том, что и&nbsp;портретный режим, и режим Snap View работают корректно. В этом случае мы просто удалили следующую строку из метода CreateWindowSizeDependentResource()&nbsp;в классе Game.cpp, чтобы камера не меняла ориентацию при переключении режима представления:</p>
<pre>&nbsp;</pre>
<pre class="scroll"><code class="cplusplus">void Game::CreateWindowSizeDependentResources()<br /> {<br /> GameBase::CreateWindowSizeDependentResources();<br /> <br /> // (фрагмент) инициализировать камеру...<br /> if (aspectRatio &lt; 1.0f)<br /> {<br /> ///<br /> /// портретный режим или режим snap view<br /> ///<br /> <span style="text-decoration: line-through;">m_graphics.GetCamera().SetUpVector(XMFLOAT3(1.0f, 0.0f, 0.0f));</span> <br /> fovAngleY = 120.0f * XM_PI / 180.0f;<br /> }<br /> // (фрагмент) источники света...<br /> }</code></pre>
<pre>&nbsp;</pre>
<p>Приложение в его текущем состоянии можно загрузить с сайта&nbsp;<a href="https://diceroller3d.codeplex.com/SourceControl/changeset/5ebb20f0b93447d14d615508b3d8df7f57d683d7">CodePlex</a>&nbsp;(см. прямую ссылку ниже).</p>
<p><a href="https://download-codeplex.sec.s-msft.com/Download/SourceControlFileDownload.ashx?ProjectName=diceroller3d&amp;changeSetId=5ebb20f0b934"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/1541.SupportForRT.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/150x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/1541.SupportForRT.png" alt="" border="0" /></a></p>
<h2>Портирование приложения на Windows Phone</h2>
<p>Проект <a href="https://aka.ms/vs3dkit">Starter Kit with support for Windows Phone</a> позволяет беспрепятственно портировать это приложение на Windows Phone 8. Теперь необходимо загрузить пакет Starter Kit, заменить классы Game.cpp и Game.h на те, которые вы создали для этого приложения, добавить все свои активы (в&nbsp;данном случае: Die.fbx, DieTexture.png и Phong.hlsl), а также внести изменения в код XAML для вызова метода RollDie(), когда пользователь касается сенсорного экрана. Краткие пошаговые инструкции:</p>
<ol start="1">
<li>На вашем компьютере должен быть установлен пакет&nbsp;<a href="https://dev.windowsphone.com/en-us/downloadsdk">Windows Phone 8 SDK</a>.</li>
<li>Загрузите пакет <a href="https://aka.ms/vs3dkit">Visual Studio 3D Starter Kit with support for Windows Phone</a>&nbsp;и откройте его в&nbsp;Visual Studio.</li>
<li>В проекте StarterKitPhoneComponent: удалите папку Shared/Animation и все содержимое из папки Shared/Assets.</li>
<li>Замените файлы Game.cpp и Game.h на созданные вами ранее.</li>
<li>Скопируйте все активы вашей игры в папку Shared/Assets проекта StarterKitPhoneComponent: Die.fbx, DieTexture.png и Phong.hlsl.</li>
<li>На странице свойств файла Phong.hlsl проверьте, чтобы в раскрывающемся списке Configuration (Конфигурация) был выбран пункт All Configurations (Все конфигурации), а&nbsp;в&nbsp;раскрывающемся списке Platform (Платформа)&nbsp;&mdash; All Platforms (Все платформы). Затем на странице HLSL Compiler (Компилятор HLSL) задайте свойству Shader Type (Тип шейдера) значение Pixel Shader (/ps) [Шейдер пикселей (/ps)] и установите для свойства Disable optimizations (Отключить оптимизацию) значение No (Нет).</li>
<li>Удалите неиспользуемые методы из класса Direct3DBackground.cpp/.h: ToggleHitEffect() и&nbsp;ChangeMaterialColor().</li>
<li>В классе Direct3DBackground.cpp добавьте следующий код в метод OnPointerReleased():
<p>void&nbsp;Direct3DBackground::OnPointerReleased(DrawingSurfaceManipulationHost^&nbsp;sender,&nbsp;PointerEventArgs^&nbsp;args)</p>
<p>{</p>
<p>&nbsp; m_renderer-&gt;RollDie();</p>
<p>}</p>
</li>
<li>Из MainPage.xaml удалите весь код XAML, относящийся к счетчикам и панели приложения.</li>
<li>Из MainPage.xaml.cs удалите все неиспользуемые поля и методы.</li>
</ol>
<p>Готово! Теперь это приложение можно запустить в эмуляторе Windows Phone или на устройстве с&nbsp;Windows Phone 8. Вы можете отрегулировать положение камеры и поле зрения, чтобы на экране телефона кубик выглядел крупнее.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/0361.DiceRollerPhone.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/0361.DiceRollerPhone.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/0361.DiceRollerPhone.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/200x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/0361.DiceRollerPhone.png" alt="" border="0" /></a></p>
<p>Итоговую версию проекта можно загрузить с сайта&nbsp;<a href="https://diceroller3d.codeplex.com/SourceControl/changeset/78429aedf85e34b4e3a9b41c47ce219ceed9da91">CodePlex</a>&nbsp;(см. прямую ссылку ниже).</p>
<p><a href="https://download-codeplex.sec.s-msft.com/Download/SourceControlFileDownload.ashx?ProjectName=diceroller3d&amp;changeSetId=78429aedf85e"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/1854.FinalProject.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/150x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/1854.FinalProject.png" alt="" border="0" /></a></p>
<h2>Планы на будущее</h2>
<p>Это приложение готово к размещению в Магазине Windows, но есть много дополнительных шагов, которые помогли бы сделать его лучше. Например:</p>
<ul>
<li>Замена логотипа, иконок плитки и заставки в соответствии с темой приложения.</li>
<li>Создание красивого фона и, возможно, стола, на который пользователь будет бросать кости.</li>
<li>Добавление теней, отражения и других реалистичных визуальных эффектов.</li>
<li>Можно сделать кубик настраиваемым, полупрозрачным, с закругленными краями.</li>
<li>Обеспечение поддержки более чем одного кубика или кубиков с разным количеством граней.</li>
<li>Добавление реалистичных подпрыгиваний и вращений с учетом силы броска, обнаружение столкновений.</li>
<li>Сохранение информации о состоянии кубика, когда работа приложения приостанавливается и возобновляется.</li>
<li>Ведение истории результатов предыдущих бросков.</li>
<li>Обеспечение поддержки датчика, чтобы пользователь мог бросать кости путем встряхивания устройства.</li>
<li>Звуковое сопровождение броска костей.</li>
<li>Возможности приложения Dice Roller можно использовать для создания настольной игры или симулятора казино...</li>
</ul>
<h2>Подведем итоги</h2>
<p>Эта серия статей познакомила вас с процессом создания 3D-приложения для Windows 8, Windows&nbsp;RT и Windows Phone с использованием пакета Visual Studio 3D Starter Kit. Вся логика и&nbsp;активы приложения являются кроссплатформенными. Также вы узнали об инструментах Visual Studio Graphics и поняли, что создание 3D-приложения&nbsp;&mdash; не такая уж сложная задача, вы можете приступать к ней без глубоких знаний в области трехмерного моделирования, математики и HLSL, постепенно изучая новые понятия.</p>
<p>Мы будем рады услышать отзывы об этом пошаговом руководстве, пакете Visual Studio 3D Starter Kit, а также узнать, с какими возможностями Visual Studio, предназначенными для работы с&nbsp;графикой, вы хотели бы познакомиться в будущем. Оставляйте нам свои комментарии!</p>]]></content:encoded>
    </item>
    <item>
      <title>Разработка приложений с использованием пакета Visual Studio 3D Starter Kit. Часть 2 из 3</title>
      <link>https://docs.microsoft.com/archive/blogs/developer-tools-rus/63</link>
      <pubDate>Mon, 01 Jul 2013 06:16:00 GMT</pubDate>
      <dc:creator><![CDATA[Paul Blokhin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/developer-tools-rus/2013/07/01/63/</guid>
      <description><![CDATA[Не так давно мы приступили к разработке простого приложения для игры в кости с&nbsp;помощью Visual...]]></description>
      <content:encoded><![CDATA[<p>Не так давно мы приступили к разработке простого приложения для игры в кости с&nbsp;помощью Visual Studio 3D Starter Kit. Теперь мы доработаем приложение, добавив анимацию. <a href="https://blogs.msdn.com/b/developer-tools-rus/archive/2013/06/24/visual-studio-3d-starter-kit-1-3.aspx">Ссылка на предыдущую статью</a>.</p>
<h2>Как заставить кубик крутиться</h2>
<p>Чтобы заставить любой объект в графическом приложении двигаться, необходимо:</p>
<ol start="1">
<li>Определить какое-либо состояние (например, с помощью логического флага), чтобы указать, что должна быть запущена анимация. Также на этом этапе можно сохранить сведения об исходном положении и продолжительности анимации, если это необходимо.</li>
<li>В методе Update, который вызывается для каждого кадра перед рендерингом, обрабатывается положение/вращение/масштабирование объекта (с точки зрения 3D-модели, мы говорим о&nbsp;<em>преобразованиях</em>); следует вычислить разницу во времени между началом анимации и выводом на экран текущего кадра. Когда анимация завершается, необходимо надлежащим образом обновить состояние, чтобы остановить анимацию.</li>
<li>В методе Render преобразования должны применяться к каждому объекту надлежащим образом.</li>
</ol>
<p>Мы добавим новый метод RollDie(), который установит состояние и сохранит время запуска. Этот метод будет использоваться для вычисления результата каждого броска кубика, но пока мы просто запустим анимацию&nbsp;&mdash; вращение кубика и показ цифр от 1 до 6.</p>
<p>Чтобы создать эту анимацию, нам понадобится набор переменных для отслеживания преобразований куба, а также времени анимации. Мы создадим одну переменную типа Boolean для отслеживания выполнения анимации, одну переменную типа Float для хранения времени анимации и три вектора для хранения начального, конечного и текущего вращений куба. Векторы типа XMFLOAT3 будут хранить вращения Yaw, Pitch и Roll (см. рисунок ниже).</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/8015.Part2_Fig1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/8015.Part2_5F00_Fig1.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/8015.Part2_Fig1.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/238x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/8015.Part2_5F00_Fig1.png" alt="" border="0" /></a></p>
<p>Давайте создадим эти поля и метод RollDie(). Добавьте следующий код в класс Game.h:</p>
<pre>&nbsp;</pre>
<pre class="scroll"><code class="cplusplus">ref class Game sealed : public GameBase<br /> {<br /> // (фрагмент) объявление других классов...<br /> <br /> Platform::String^ OnHitObject(int x, int y);<br /> void RollDie(); <br /> private:<br /> std::vector&lt;VSD3DStarter::Mesh*&gt; m_meshModels;<br /> bool m_isAnimationRunning;<br /> float m_animationTime;<br /> DirectX::XMFLOAT3 m_initialRotation;<br /> DirectX::XMFLOAT3 m_currentRotation;<br /> DirectX::XMFLOAT3 m_targetRotation;<br /> };</code></pre>
<pre>&nbsp;</pre>
<p>Давайте создадим анимацию, начнем с метода RollDie(). Добавьте следующий код в класс Game.cpp:</p>
<pre><span><span>void</span>&nbsp;<span>Game</span>::RollDie()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;m_initialRotation&nbsp;=&nbsp;m_currentRotation;<br />&nbsp;&nbsp;&nbsp;&nbsp;m_targetRotation&nbsp;=&nbsp;<span>XMFLOAT3</span>(0.0f,&nbsp;XM_PI,&nbsp;0.0f);&nbsp;<span>//&nbsp;always&nbsp;rotate&nbsp;to&nbsp;6<br /><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;m_animationTime&nbsp;=&nbsp;0.0f;<br />&nbsp;&nbsp;&nbsp;&nbsp;m_isAnimationRunning&nbsp;=&nbsp;<span>true</span>;<br />}</span></pre>
<p>RollDie() запустит анимацию путем задания значения True для переменной m_isAnimationRunning. Нам необходимо добавить код в метод Update() для поворота куба в каждом кадре. Добавьте следующий код в метод Update():&nbsp;</p>
<pre class="scroll"><code class="cplusplus">void Game::Update(float timeTotal, float timeDelta)<br /> {<br /> if (m_isAnimationRunning)<br /> {<br /> m_animationTime += timeDelta;<br /> <br /> static const float animationDuration = 0.5f;<br /> float animationProgress = std::min&lt;float&gt;(m_animationTime / animationDuration, 1.0f);<br /> <br /> XMVECTOR initial = XMLoadFloat3(&amp;m_initialRotation);<br /> XMVECTOR target = XMLoadFloat3(&amp;m_targetRotation);<br /> <br /> XMVECTOR current = initial + animationProgress * (target - initial);<br /> XMStoreFloat3(&amp;m_currentRotation, current);<br /> <br /> if (animationProgress &gt;= 1.0f)<br /> m_isAnimationRunning = false;<br /> }<br /> }</code></pre>
<p>Описание кода:</p>
<ol start="1">
<li>Анимация должна запускаться только в том случае, когда установлен флаг m_isAnimationRunning.</li>
<li>Сначала вычисляется значение переменных calculate m_animationTime (время от начала анимации 0&ndash;0,5 секунды) и m_animationProgress (процент завершения анимации 0&ndash;1). Обратите внимание, &laquo;1.0&raquo; означает, что анимация завершена.</li>
<li>Загрузите исходный и целевой векторы вращения в XMVECTORs, это позволяет ускорить расчеты благодаря <a href="https://msdn.microsoft.com/ru-ru/library/26td21ds(v=vs.100).aspx">макроопределениям CPU</a>.</li>
<li>Расчеты линейным способом по формуле:</li>
</ol>
<p><em>текущий = исходный + прогресс * (целевой &ndash; исходный)</em></p>
<ol start="1">
<li>Вычисленное значение сохраняется обратно в m_currentRotation.</li>
<li>Проверка выполнения анимации и ее остановка в случае необходимости.</li>
</ol>
<p>На следующем шаге анимации вычисленное вращение используется в методе Render для поворота куба. Для этого измените следующую строку кода в методе Render():</p>
<pre class="scroll"><code class="cplusplus">void Game::Render()<br /> {<br /> GameBase::Render();<br /> <br /> // (фрагмент) очистить...<br /> <br /> XMMATRIX transform = XMMatrixRotationRollPitchYawFromVector(XMLoadFloat3(&amp;m_currentRotation));<br /> <br /> for (UINT i = 0; i &lt; m_meshModels.size(); i++)<br /> {<br /> m_meshModels[i]-&gt;Render(m_graphics, transform);<br /> }<br /> <br /> // (фрагмент) MSAA...<br /> }</code></pre>
<p>Метод, который мы вызываем, получает объект XMVECTOR, содержащий значения переменных для разворота, уклона и поворота относительно вертикальной оси. Этот метод возвращает матрицу вращения, которая соответствует комбинированному преобразованию. Для наших целей также подходит метод XMMatrixRotationRollPitchYaw, который обрабатывает параметры разворота, уклона и поворота относительно вертикальной оси по отдельности. Кроме того, вы можете вычислить каждый компонент с помощью отдельного метода, а затем самостоятельно перемножить результаты. Полный перечень методов, используемых для создания матриц преобразования, представлен <a href="https://msdn.microsoft.com/ru-ru/library/windows/desktop/ee415594(v=vs.85).aspx">на сайте MSDN</a>.</p>
<p>Все, что нам необходимо сделать,&mdash; вызвать метод RollDie(). Мы будем вызывать его каждый раз, когда пользователь касается или щелкает по экрану. Добавьте следующий код в файл DirectXPage.xaml.cpp (в метод DirectXPage::OnTapped):</p>
<pre class="scroll"><code class="cplusplus">void DirectXPage::OnTapped(Platform::Object^ sender, TappedRoutedEventArgs^ e)<br /> {<br /> m_renderer-&gt;RollDie();<br /> }</code></pre>
<p>Если вы запустите приложение сейчас, то после щелчка или касания экрана в любом месте кубик будет вращаться, показывая цифры от 1 до 6!</p>
<h2>Логика приложения: генератор случайных чисел</h2>
<p>Неинтересно бросать кости, если вы точно знаете, какую цифру увидите. Поэтому мы добавим генератор случайных чисел на основе функции из библиотеки времени выполнения языка C:&nbsp;<a href="https://msdn.microsoft.com/en-us/library/398ax69y(v=vs.110).aspx">rand()</a>. При каждом броске игрок получит новую цифру.</p>
<p>Сначала генератор rand() нужно инициализировать с помощью некоторого начального значения. Если мы не инициализируем генератор или инициализируем его с использованием фиксированного значения, то последовательность генерируемых чисел будет неизменна при каждом запуске приложения, а нам это не подходит. Мы будем инициализировать генератор случайных чисел с&nbsp;использованием текущего времени CPU. Добавьте следующий код в метод Game::Initialize():</p>
<pre class="scroll"><code class="cplusplus">void Game::Initialize()<br /> {<br /> Mesh::LoadFromFile(m_graphics, L"die.cmo", L"", L"", m_meshModels);<br /> <br /> srand ((unsigned int) time(NULL));<br /> }</code></pre>
<p>Также следует подключить библиотеку &lt;time.h&gt; для метода Game.cpp, чтобы функция time() была доступна:</p>
<pre class="scroll"><code class="cplusplus">#include "pch.h"<br /> #include "Game.h"<br /> #include &lt;DirectXMath.h&gt;<br /> #include &lt;DirectXColors.h&gt;<br /> #include &lt;algorithm&gt;<br /> #include &lt;time.h&gt;</code></pre>
<p>После инициализации мы можем воспользоваться функцией rand() в методе RollDie(), чтобы получить цифру, которая выпадет, когда пользователь бросит кости. Мы также должны правильно задать целевые вращения кубика при каждом броске. Для этого измените строку, в которой задается значение переменной m_targetRotation. Окончательный вариант метода RollDie():</p>
<pre class="scroll"><code class="cplusplus">void Game::RollDie()<br /> {<br /> m_initialRotation = m_currentRotation;<br /> <br /> int currentRoll = rand() % 6 + 1;<br /> switch (currentRoll)<br /> {<br /> case 1:<br /> m_targetRotation = XMFLOAT3(0.0f, 0.0f, 0.0f);<br /> break;<br /> case 2:<br /> m_targetRotation = XMFLOAT3(0.0f, XM_PIDIV2, 0.0f);<br /> break;<br /> case 3:<br /> m_targetRotation = XMFLOAT3(XM_PIDIV2, 0.0f, 0.0f);<br /> break;<br /> case 4:<br /> m_targetRotation = XMFLOAT3(-1.0f * XM_PIDIV2, 0.0f, 0.0f);<br /> break;<br /> case 5:<br /> m_targetRotation = XMFLOAT3(0.0f, -1.0f * XM_PIDIV2, 0.0f);<br /> break;<br /> case 6:<br /> m_targetRotation = XMFLOAT3(0.0f, XM_PI, 0.0f);<br /> break;<br /> }<br /> <br /> m_animationTime = 0.0f;<br /> m_isAnimationRunning = true;<br /> }</code></pre>
<p>Запустите приложение. Вот наш анимированный кубик! Бросьте кости, коснувшись экрана в любом месте. Можете перейти в режим Snap View.</p>
<h2>Как&nbsp;заставить кубик прыгать</h2>
<p>Это небольшое приложение можно использовать и в таком виде, но мы можем сделать его еще интереснее. Сейчас мы покажем, как заставить брошенный кубик подпрыгивать, а также добавим дополнительные случайные вращения, чтобы сделать приложение более реалистичным.</p>
<p>Чтобы запрограммировать &laquo;прыжки&raquo;, мы добавим еще одну переменную в нашу анимацию&nbsp;&mdash; вертикальную координату (Y). Значение этой переменной будет изменяться после того, как кости будут брошены (в методе Update()), мы также внесем изменения в метод Render(), чтобы применить трансляцию к кубу. Сначала нужно добавить переменную трансляции в Game.h:</p>
<pre class="scroll"><code class="cplusplus">ref class Game sealed : public GameBase<br /> {<br /> // (фрагмент) объявление других классов...<br /> <br /> private:<br /> std::vector&lt;VSD3DStarter::Mesh*&gt; m_meshModels;<br /> bool m_isAnimationRunning;<br /> float m_animationTime;<br /> DirectX::XMFLOAT3 m_initialRotation;<br /> DirectX::XMFLOAT3 m_currentRotation;<br /> DirectX::XMFLOAT3 m_targetRotation;<br /> float m_currentTranslationY;<br /> };</code></pre>
<p>Чтобы переменная изменялась с течением времени (метод Update()):</p>
<pre class="scroll"><code class="cplusplus">void Game::Update(float timeTotal, float timeDelta)<br /> {<br /> if (m_isAnimationRunning)<br /> {<br /> // (фрагмент)<br /> <br /> XMVECTOR current = initial + animationProgress * (target - initial);<br /> XMStoreFloat3(&amp;m_currentRotation, current);<br /> <br /> const float maxHeight = 2.0f;<br /> m_currentTranslationY = 4.0f * maxHeight * animationProgress * (1 - animationProgress);<br /> <br /> if (animationProgress &gt;= 1.0f)<br /> m_isAnimationRunning = false;<br /> }<br /> }</code></pre>
<p>Те, кто помнит курс математики старших классов, узнали уравнение параболы с полюсами в точках 0 и 1 и вершиной в точке 0,5 (MaxHeight). Наш кубик будет достаточно реалистично подпрыгивать. График этой функции можно увидеть здесь:&nbsp;<a href="https://www.wolframalpha.com/input/?i=plot+y+%3d+4x(1-x)+from+0+to+1&amp;incTime=true">WolframAlpha</a>.</p>
<p>На заключительном этапе мы воспользуемся расчетной трансляцией для преобразования куба в&nbsp;процессе рендеринга. Добавьте следующий код в метод Render:</p>
<pre><span>v</span></pre>
<pre class="scroll"><code class="cplusplus">oid Game::Render()<br /> {<br /> // (фрагмент) очистить...<br /> <br /> m_d3dContext-&gt;ClearDepthStencilView( /* (фрагмент) */ );<br /> <br /> XMMATRIX transform = XMMatrixRotationRollPitchYawFromVector(XMLoadFloat3(&amp;m_currentRotation));<br /> transform *= XMMatrixTranslation(0.0f, m_currentTranslationY, 0.0f);<br /> <br /> for (UINT i = 0; i &lt; m_meshModels.size(); i++)<br /> {<br /> m_meshModels[i]-&gt;Render(m_graphics, transform);<br /> }<br /> <br /> // (фрагмент) MSAA...<br /> }</code></pre>
<p>Запустите приложение и щелкните по экрану. Вы увидите, что кубик после броска реалистично подпрыгивает. Наконец, чтобы анимация выглядела еще более реалистичной, добавим случайные вращения по обеим осям при каждом броске кубика. Для этого внесем изменения в метод RollDie() и добавим случайные повороты в целевое вращение:</p>
<pre class="scroll"><code class="cplusplus">void Game::RollDie()<br /> {<br /> // (фрагмент) инициализация, бросок и переключение(currentRoll)<br /> <br /> XMVECTOR target = XMLoadFloat3(&amp;m_targetRotation);<br /> XMVECTOR current = XMLoadFloat3(&amp;m_currentRotation);<br /> <br /> // учет текущего вращения<br /> target += XMVectorFloor(current / XM_2PI) * XM_2PI;<br /> <br /> // -1, 0 или 1 дополнительный оборот<br /> XMVECTOR randomVector = XMLoadFloat3(&amp;XMFLOAT3(rand() % 3 - 1.0f, rand() % 3 - 1.0f, rand() % 3 - 1.0f));<br /> target += randomVector * XM_2PI;<br /> <br /> XMStoreFloat3(&amp;m_targetRotation, target);<br /> <br /> m_animationTime = 0.0f;<br /> m_isAnimationRunning = true;<br /> }</code></pre>
<p>Этот код вносит два изменения в целевое вращение:</p>
<ol start="1">
<li>Указывается общее количество полных оборотов, совершенных до настоящего момента в&nbsp;рамках целевого вращения, в результате чего каждый поворот будет выполняться относительно предыдущего поворота, а не исходного положения кубика.</li>
<li>Добавляется -1, 0 и 1 полный оборот к целевому относительному вращению. Для этого мы создаем вектор на основе трех значений, выбранных случайно из ряда -1, 0 и 1, и умножаем полученную величину на 2 * PI (полный оборот в радианах).</li>
</ol>
<p>Также обратите внимание на то, что мы используем XMVECTORs еще раз для ускорения расчета, это также позволяет использовать только одну формулу вместо трех (если бы компоненты х, у, z вычислялись по отдельности).</p>
<p>Мы расширили функционал своего приложения. Конечно, с таким приложением работать намного интереснее, чем с классическим генератором случайных чисел. Эту версию приложения можно загрузить с сайта&nbsp;<a href="https://diceroller3d.codeplex.com/SourceControl/changeset/c4192ee94bc1db02347e2da95e44798c2a781837">CodePlex</a>&nbsp;(прямая ссылка представлена на плитке ниже).</p>
<p><a href="https://download-codeplex.sec.s-msft.com/Download/SourceControlFileDownload.ashx?ProjectName=diceroller3d&amp;changeSetId=c4192ee94bc1"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/3000.EndOfPart2.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/150x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/3000.EndOfPart2.png" alt="" border="0" /></a></p>
<p>Осталось всего несколько шагов, и наше приложение будет работать на устройствах с Windows RT и&nbsp;Windows Phone. Эти шаги мы рассмотрим в третьей и последней статье блога из этой серии. Следите за обновлениями!</p>]]></content:encoded>
    </item>
    <item>
      <title>Разработка приложений с использованием пакета Visual Studio 3D Starter Kit. Часть 1 из 3</title>
      <link>https://docs.microsoft.com/archive/blogs/developer-tools-rus/73</link>
      <pubDate>Mon, 24 Jun 2013 02:27:00 GMT</pubDate>
      <dc:creator><![CDATA[Paul Blokhin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/developer-tools-rus/2013/06/24/73/</guid>
      <description><![CDATA[Несколько недель назад мы анонсировали серию статей, в которых будет показан весь процесс...]]></description>
      <content:encoded><![CDATA[<div class="post-content user-defined-markup">
<p><a href="https://blogs.msdn.com/b/vcblog/archive/2013/02/13/visual-studio-3d-starter-kit-now-for-windows-phone-8.aspx">Несколько недель назад</a> мы анонсировали серию статей, в которых будет показан весь процесс разработки приложения с использованием пакета&nbsp;<a href="https://aka.ms/vs3dkit">Visual Studio 3D Starter Kit</a>. Представляем вашему вниманию первую статью из этой серии. В серии статей мы рассмотрим процесс разработки приложения, пользователь которого сможет касанием или щелчком бросать трехмерные шестигранные кубики для игры в кости. Брошенный кубик будет подпрыгивать и вращаться в&nbsp;воздухе. Это приложение будет также запускаться в режиме <a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/hh465371.aspx">Snap View</a> в Windows&nbsp;8, и&nbsp;пользователи смогут бросать кости, не прерывая работу в других приложениях. Мы также продемонстрируем, как сделать это приложение совместимым с устройствами на базе Windows RT, а также портировать его на Windows Phone.</p>
<p>В первой статье мы рассмотрим процесс создания приложения до этапа вывода кубика на экран и&nbsp;наложения текстуры. Мы также изучим возможности инструментов Visual Studio Graphics, которые доступны, начиная с версии Visual Studio Professional и выше. Но даже если у вас только Visual Studio Express 2012 для Windows 8, вы все равно сможете работать с этим пошаговым руководством.</p>
<p>Самые большие сложности у начинающих разработчиков Direct3D возникают из-за необходимости изучения большого количества новых понятий, например они должны научиться кодировать шейдеры HLSL и конвертировать сетки в форматы, подходящие для использования в режиме выполнения. Visual Studio содержит большое количество инструментов, упрощающих этот процесс, они помогут вам сконцентрироваться на логике приложения, вместо того чтобы изучать эти новые понятия. Когда вы будете готовы, вы сможете реализовать дополнительные функции в своем приложении, и при этом не придется начинать все сначала. В статьях из этой серии присутствует ряд ссылок на дополнительную документацию по DirectX, которую мы сами используем. Вы можете изучить эти материалы самостоятельно и узнать подробнее о DirectX и программировании графики.</p>
<p>Итак, настало время перейти от слов к делу!</p>
<h2>Демонстрационное приложение Dice Roller, имитирующие бросание игральных костей</h2>
<p>Кости используются в различных настольных и азартных играх. Создать приложение, имитирующее бросание игральных костей, достаточно просто на любом языке программирования, для генератора случайных чисел чаще всего нужна всего одна строка кода. Но как сделать это приложение интереснее?</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/0763.Fig1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/0763.Fig1.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/0763.Fig1.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/0763.Fig1.png" alt="" border="0" /></a></p>
<p>Ну конечно! Мы можем сделать кубик трехмерным! При этом мы не будем использовать какие-либо дополнительные инструменты, только Visual Studio 2012 Professional. Приступим!</p>
<h2>Начинаем с чистого листа</h2>
<p>Сначала необходимо загрузить и открыть пакет Visual Studio 3D Starter Kit. Ссылка для загрузки: <a href="https://aka.ms/vs3dkit">https://aka.ms/vs3dkit</a>. Мы также подготовили специальную версию пакета Starter Kit (только для Магазина Windows) для этого руководства. Сначала у вас будет совершенно пустой экран, без трехмерных моделей. Таким образом, мы научимся создавать собственные активы. Загрузить эту версию можно с сайта&nbsp;<a href="https://diceroller3d.codeplex.com/SourceControl/changeset/view/e75ccd62e002">CodePlex</a>,&nbsp;(прямая ссылка представлена на плитке ниже).&nbsp;Вы также поймете, как удалить все содержимое из Starter Kit.</p>
<p><a href="https://download-codeplex.sec.s-msft.com/Download/SourceControlFileDownload.ashx?ProjectName=diceroller3d&amp;changeSetId=e75ccd62e002"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/7563.EmptyStarterKit.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/150x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/7563.EmptyStarterKit.png" alt="" border="0" /></a></p>
<p><strong>Примечание для пользователей Visual Studio Express</strong>. Активы, используемые в этом проекте, можно загрузить, нажав плитку ниже. Просто добавляйте их в свой проект на соответствующих этапах.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/10/40/47/30/Dice%20Roller%20Assets.zip" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-40-47-30/Dice-Roller-Assets.zip"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/2158.DiceRollerAssets.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/150x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/2158.DiceRollerAssets.png" alt="" border="0" /></a></p>
<p>После запуска этого приложения вы увидите заставку Starter Kit с чайником, а затем&nbsp;&mdash; пустой серый экран. Не волнуйтесь, мы скоро его заполним&hellip;</p>
<h2>Создание и отображение сетки</h2>
<p>Сначала мы создадим единственную сетку, которую мы будем использовать в этом приложении,&mdash; трехмерный куб для костей. Для этого в окне обозревателя решений Visual Studio Solution Explorer правой кнопкой мыши щелкните папку Shared/Assets (Общие/Активы) в проекте StarterKit и выберите Add -&gt; New item&hellip; -&gt; Graphics -&gt; 3D Scene (.fbx) (Добавить -&gt; Новый элемент&hellip; -&gt; Графика&nbsp;-&gt; 3D-сцена (.fbx)). Давайте назовем сцену Die.fbx.&nbsp;На следующем рисунке показано окно редактора сетки Visual Studio Mesh Editor:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/31048.Fig2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/31048.Fig2.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/31048.Fig2.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/31048.Fig2.png" alt="" border="0" /></a></p>
<p>Чтобы добавить куб, откройте панель элементов и дважды щелкните Cube. Вы можете также добавить некоторые другие простые формы, например цилиндры и чайники, и даже выполнить некоторые операции по редактированию (поворот, масштабирование и трансляция 3D-модели).</p>
<p>Чтобы вывести куб на экран, в нашу игру необходимо добавить код для загрузки и рендеринга сетки. В Starter Kit присутствует класс Game (Game.cpp/Game.h), который содержит логику рендеринга для нашей игры, именно сюда этот код должен быть добавлен.</p>
<p>Для начала загрузим сетку из файла при инициализации приложения. Добавьте следующий код в метод Game::Initialize():&nbsp;</p>
<pre class="scroll"><code class="csharp">void Game::Initialize()<br /> {<br /> Mesh::LoadFromFile(m_graphics, L"die.cmo", L"", L"", m_meshModels); <br /> }</code></pre>
<p>Этот код использует класс Mesh из проекта Starter Kit для загрузки модели Die из файла в вектор m_meshModels.</p>
<ul>
<li>Первый параметр, m_graphics, содержит экземпляр класса Graphics, в который сгруппированы все полезные объекты DirectX.</li>
<li>Второй параметр&nbsp;&mdash; это имя файла. Файл имеет расширение .cmo, поскольку в ходе построения все активы преобразуются в более простой формат, оптимальный для режима выполнения. Откомпилированные сетки хранятся в файлах в формате CMO (Compiled Mesh Object), для шейдеров используется <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/bb509633(v=vs.85).aspx">стандартный компилятор FX</a>,&nbsp;который создает файлы в&nbsp;формате CSO (Compiled Shader Object), изображения (PNG, JPG и т.&nbsp;д.) будут преобразованы в оптимизированный для среды выполнения формат&nbsp;<a href="https://msdn.microsoft.com/en-us/library/windows/desktop/bb943990(v=vs.85).aspx">DDS (DirectDraw Surface)</a>.</li>
<li>Третий и четвертый параметры содержат относительные пути к шейдерам (файлам CSO) и&nbsp;текстурам (файлам DDS), которые используются в этой сетке. Чаще всего подходят значения по умолчанию.</li>
<li>Последний параметр&nbsp;&mdash; это ссылка на вектор std::vector класса Meshes, где должны храниться загруженные сетки.</li>
</ul>
<p>Далее необходимо выполнить рендеринг куба в каждом кадре. Добавьте следующий код в метод Game::Render():</p>
<pre class="scroll"><code class="csharp">void Game::Render()<br /> {<br /> GameBase::Render();<br /> <br /> // clear<br /> m_d3dContext-&gt;OMSetRenderTargets(<br /> 1,<br /> m_d3dRenderTargetView.GetAddressOf(),<br /> m_d3dDepthStencilView.Get()<br /> );<br /> <br /> m_d3dContext-&gt;ClearRenderTargetView(<br /> m_d3dRenderTargetView.Get(),<br /> DirectX::Colors::DarkSlateGray<br /> );<br /> <br /> m_d3dContext-&gt;ClearDepthStencilView(<br /> m_d3dDepthStencilView.Get(),<br /> D3D11_CLEAR_DEPTH,<br /> 1.0f,<br /> 0<br /> );<br /> <br /> XMMATRIX transform = XMMatrixIdentity(); <br /> for (UINT i = 0; i &lt; m_meshModels.size(); i++)<br /> {<br /> m_meshModels[i]-&gt;Render(m_graphics, transform);<br /> } <br /> <br /> //<br /> // only enable MSAA if the device has enough power<br /> //<br /> if (m_d3dFeatureLevel &gt;= D3D_FEATURE_LEVEL_10_0)<br /> {<br /> // (... MSAA code ...)<br /> }<br /> }</code></pre>
<p>Этот код вызывает метод Render для каждой сетки, чтобы вывести сетку на экран. Матрица преобразования содержит преобразования (масштабирование, транслирование, вращение и т.&nbsp;д.), которые мы будет применять к каждой сетке. В нашем случае применяется матрица Identity, которая выполняет рендеринг объекта без каких-либо визуальных изменений.</p>
<p>Если вы запустите приложение прямо сейчас, то увидите куб посередине экрана:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/2605.Fig3.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/2605.Fig3.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/2605.Fig3.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/2605.Fig3.png" alt="" border="0" /></a></p>
<p>Вам не кажется, что кубик маловат? Давайте приблизим камеру. Добавьте следующую строку в&nbsp;метод Game::CreateWindowSizeDependentResources():&nbsp;</p>
<pre class="scroll"><code class="csharp">m_graphics.GetCamera().SetPosition(XMFLOAT3(0.0f, 2.0f, -6.0f));</code></pre>
<p>Этот метод вызывается каждый раз, когда изменяются размеры окна (например, при изменении разрешения или в режиме Snap View), поэтому здесь удобно задавать и изменять свойства камеры. Строка, в которую мы внесли изменения, устанавливает положение камеры, кроме того, можно отрегулировать поле зрения (fovAngleY в коде проекта StarterKit), тогда объекты визуально будут больше или меньше, а положение камеры не изменится.</p>
<h2>Добавление текстуры</h2>
<p>В этом примере мы предоставим вам текстуру для граней кубика. Она очень простая, но в&nbsp;дальнейшем вы можете создать собственную текстуру с помощью других инструментов.</p>
<p>На рисунке ниже показана предлагаемая текстура. Текстуру&nbsp;<a href="https://www.codeplex.com/Download/SourceControlFileDownload.ashx?ProjectName=diceroller3d&amp;changeSetId=669474014b1e&amp;itemId=Shared%2fAssets%2fDieTexture.png">можно загрузить отсюда</a>.</p>
<p><a href="https://www.codeplex.com/Download/SourceControlFileDownload.ashx?ProjectName=diceroller3d&amp;changeSetId=669474014b1e&amp;itemId=Shared%2fAssets%2fDieTexture.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/1423.Fig4.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/1423.Fig4.png" alt="" border="0" /></a></p>
<p>Сначала необходимо скопировать файл в папку Assets. Вернитесь в Visual Studio, щелкните правой кнопкой мыши папку Assets, нажмите Add -&gt; Existing item (Добавить -&gt; Существующий элемент) и&nbsp;выберите изображение.</p>
<p>Наконец, нужно применить текстуру к кубу. Откройте сетку Die (Die.fbx) и щелкните куб. В окне инструмента Properties (сочетание клавиш: Alt+Enter) найдите свойство Texture1. Нажмите кнопку &laquo;&hellip;&raquo;, чтобы выбрать изображение и применить его к кубу.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/8524.Fig5.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/8524.Fig5.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/8524.Fig5.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/8524.Fig5.png" alt="" border="0" /></a></p>
<p>Если вы запустите приложение снова, вы увидите куб с цифрами в соответствующей позиции.</p>
<p>Приложение в его текущем состоянии можно загрузить с сайта&nbsp;<a href="https://diceroller3d.codeplex.com/SourceControl/changeset/669474014b1e7f3510a4c1854f53a8e446193690">CodePlex</a>&nbsp;(прямая ссылка представлена на плитке ниже).</p>
<p><a href="https://download-codeplex.sec.s-msft.com/Download/SourceControlFileDownload.ashx?ProjectName=diceroller3d&amp;changeSetId=669474014b1e"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/65/69/5228.EndOfPart1.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/150x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/5228.EndOfPart1.png" alt="" border="0" /></a></p>
<p>В нашей следующей статье мы расскажем, как добавить код анимации и сделать так, чтобы кубик можно было бросать! До встречи!</p>
<p>&nbsp;</p>
<div>&nbsp;</div>
</div>
<div class="post-attachment-viewer">
<div class="post-attachment"><span class="value"><a class="internal-link download-attachment" href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/10/40/47/30/Dice%20Roller%20Assets.zip" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-40-47-30/Dice-Roller-Assets.zip"><span class="avatar"><img src="https://blogs.msdn.com/utility/filethumbnails/zip.gif" alt="" border="0" /></span>Dice Roller Assets.zip</a></span></div>
</div>]]></content:encoded>
    </item>
    <item>
      <title>Клонирование планов тестирования с использованием Microsoft Test Manager</title>
      <link>https://docs.microsoft.com/archive/blogs/developer-tools-rus/83</link>
      <pubDate>Thu, 13 Jun 2013 05:52:00 GMT</pubDate>
      <dc:creator><![CDATA[Paul Blokhin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/developer-tools-rus/2013/06/13/83/</guid>
      <description><![CDATA[В пакете обновления Visual Studio Update 2 присутствует функция клонирования планов тестирования в...]]></description>
      <content:encoded><![CDATA[<p>В пакете обновления <a href="https://go.microsoft.com/fwlink/?LinkId=273878">Visual Studio Update 2</a> присутствует функция клонирования планов тестирования в Microsoft Test Manager. Эта функция позволяет клонировать артефакты плана тестирования для конкретной команды проекта путем создания копий всех тестовых случаев, а&nbsp;также общих шагов и требований. Затем воссоздается аналогичная структура и применяются те же настройки тестирования, те же среды, сборки, конфигурации и другие свойства плана тестирования (результаты тестирования и ошибки клонированию не подлежат). Из этой статьи вы узнаете об этой функции подробнее.</p>
<p>Наши клиенты часто говорили о необходимости клонирования планов тестирования в процессе работы со спринтами или выпусками. Функциональность для клонирования наборов тестов с&nbsp;использованием командной строки (tcm.exe) уже была реализована в Visual Studio 2012, в пакете обновления VS Update 1 эти возможности были усовершенствованы, а после установки пакета VS Update 2 доступ к ним стал возможен через пользовательский интерфейс MTM.</p>
<p>Чтобы воспользоваться этой функцией, я открою страницу настройки свойств плана тестирования: Testing Center -&gt; Plan -&gt; Properties (Центр тестирования -&gt; План -&gt; Свойства), затем нажму кнопку Clone (Клонировать).</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/1185.1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/1185.1.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/1185.1.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/1185.1.png" alt="" border="0" /></a></p>
<p>Предположим, я хочу клонировать план тестирования текущего спринта (sprint 1) и в дальнейшем использовать его для следующего спринта (sprint 2). Я нажимаю Clone (Клонировать), и на экране появляется диалоговое окно:</p>
<p><span><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/4530.2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/4530.2.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/4530.2.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/4530.2.png" alt="" border="0" /></a></span></p>
<p>Я могу выбрать наборы для клонирования в области Clone from (Клонировать из). Если наборы не&nbsp;выбраны, будет создан пустой план тестирования со свойствами, аналогичными свойствам для нового плана тестирования.</p>
<p><span><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/1016.3.PNG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/1016.3.PNG"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/1016.3.PNG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/1016.3.PNG" alt="" border="0" /></a></span></p>
<p>Выбрав узел, вы выберете все его дочерние узлы, и, соответственно, сняв выделение с основного узла, вы отмените выбор всех дочерних. Я выбрал для клонирования все наборы, кроме Regression tests (Регрессивные тесты).</p>
<p><span><span><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/7776.4.PNG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/7776.4.PNG"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/7776.4.PNG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/7776.4.PNG" alt="" border="0" /></a></span></span></p>
<p>После выбора набора я могу также указать рабочие элементы для требований, связанные с&nbsp;выбранными мною наборами на основе требований, в рамках этой операции. Если я не отмечу этот параметр, будут созданы статические наборы, соответствующие выбранным мной наборам на основе требований, необходимые тестовые случаи будут скопированы в эти статические наборы.</p>
<p><span><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/2664.5.PNG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/2664.5.PNG"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/2664.5.PNG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/2664.5.PNG" alt="" border="0" /></a></span></p>
<p><span style="font-size: 12px;">Для целевого плана тестирования следует указать имя, путь области и путь итерации в разделе Clone to (Клонировать в). Все тестовые случаи, которые подлежат клонированию в рамках этой операции, будут использовать те же пути области и пути итерации.</span></p>
<p><span><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/3660.6.PNG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/3660.6.PNG"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/3660.6.PNG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/3660.6.PNG" alt="" border="0" /></a></span></p>
<p>Заполнив все поля, я нажму кнопку Clone (Клонировать). Система приступит к клонированию плана тестирования, и я смогу отслеживать выполнение этой операции.</p>
<p><span><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/1307.7.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/1307.7.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/1307.7.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/1307.7.png" alt="" border="0" /></a></span></p>
<p>&nbsp;<span style="font-size: 12px;">Когда процесс завершится, статус изменится на Succeeded (Успешно выполнено), и на экране появится подробная информация для клонов, которые были созданы: продолжительность процесса, дата и время начала и завершения, общее количество тестовых случаев, общих шагов и&nbsp;требований и т.&nbsp;д.</span></p>
<p><span><span><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/2072.8.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/2072.8.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/2072.8.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/2072.8.png" alt="" border="0" /></a></span></span></p>
<p>Я могу выбрать в диалоговом окне новый план тестирования, а затем подключиться к нему. Все свойства, наборы тестов, тестовые случаи и требования плана тестирования sprint&nbsp;1 были добавлены, как и было запланировано.</p>
<p><span><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/4682.9.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/4682.9.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/4682.9.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/4682.9.png" alt="" border="0" /></a></span><span style="font-size: 12px;">&nbsp;</span></p>
<p>Для всех рабочих элементов, клоны которых были созданы в рамках этого процесса, добавляется комментарий с указанием идентификатора операции клонирования и идентификатора исходного рабочего элемента. Это позволяет использовать историю рабочего элемента в целях отслеживания и аудита.</p>
<p><span><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/5710.12.PNG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/5710.12.PNG"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/5710.12.PNG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/5710.12.PNG" alt="" border="0" /></a></span></p>
<p>Для доступа к этой функции также предназначен пункт меню Clone (Клонировать) в Test Plan Manager: Testing Center -&gt; Organize -&gt; Test Plan Manager (Центр тестирования -&gt; Упорядочить&nbsp;-&gt; Диспетчер планов тестирования). Также можно щелкнуть правой кнопкой мыши корневой узел: Testing Center -&gt; Plan -&gt; Contents (Центр тестирования -&gt; План -&gt; Содержимое) и выбрать Clone (Клонировать).</p>
<p><span><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/2158.11.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/2158.11.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/2158.11.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/2158.11.png" alt="" border="0" /></a></span></p>
<p><span><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/0676.10.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/0676.10.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/45/92/0676.10.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-45-92/0676.10.png" alt="" border="0" /></a></span></p>
<p>Надеюсь, эти функциональные возможности помогут вам эффективнее управлять тестовыми случаями. Также вы можете ознакомиться с рекомендациями на <a href="https://msdn.microsoft.com/ru-ru/library/vstudio/hh543843.aspx">странице MSDN</a> или с&nbsp;руководством <a href="https://vsartestreleaseguide.codeplex.com/">Test Release Management Guidance</a> (Руководство по управлению тестовыми выпусками).</p>
<p>&nbsp;</p>]]></content:encoded>
    </item>
    <item>
      <title>Разработка приложений, учитывающих географическое положение, с использованием функций геолокации и карт Bing Maps</title>
      <link>https://docs.microsoft.com/archive/blogs/developer-tools-rus/93</link>
      <pubDate>Wed, 05 Jun 2013 05:10:00 GMT</pubDate>
      <dc:creator><![CDATA[Paul Blokhin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/developer-tools-rus/2013/06/05/93/</guid>
      <description><![CDATA[Если в бизнес-логике вашего приложения учитывается местоположение пользователя, вы можете...]]></description>
      <content:encoded><![CDATA[<p>Если в бизнес-логике вашего приложения учитывается местоположение пользователя, вы можете предоставлять пользователям приложения актуальный прогноз погоды, рассылать купоны, информацию о спортивных мероприятиях или концертах. Вы можете использовать <a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/br229921.aspx">геолокационные</a> возможности Windows&nbsp;8, а также пакет Bing Maps SDK для разработки&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/hh465148.aspx">приложений для Магазина Windows, учитывающих географическое положение</a>.</p>
<p>Сейчас я расскажу вам, как ваше приложение может воспользоваться возможностями <a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/br225603.aspx">службы расположения</a> для предоставления пользователям информации с учетом их местоположения, которое определяется по IP-адресу, параметрам сети Wi-Fi или данным GPS. После определения местоположения вы можете предоставить эту информацию пользователю с помощью Bing Maps SDK.</p>
<h2>Получение сведений о расположении</h2>
<p>Пространство имен <a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/windows.devices.geolocation.aspx">Windows.Devices.Geolocation</a>&nbsp;используется для получения сведений о вашем местоположении. На выбор метода определения местоположения пользователя (GPS, Wi-Fi или IP-адрес) влияют два основных фактора:</p>
<ol start="1">
<li>Уровень требуемой точности. Оптимальный уровень точности для вашего приложения.</li>
<li>Доступность данных о местоположении. Не во все устройства встроен модуль GPS, кроме того, сеть Wi-Fi может быть недоступна, когда запрашиваются сведения о местоположении.</li>
</ol>
<h3><a>Требуемая точность</a></h3>
<p>Отправляя запрос местоположения, ваше приложение должно указать&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/windows.devices.geolocation.geolocator.desiredaccuracy.aspx">требуемую точность</a>,&nbsp;чтобы данные в пределах заданного диапазона могли быть возвращены как можно быстрее. Каждый из типов характеризуется степенью точности определения местоположения:</p>
<ul>
<li><a href="https://en.wikipedia.org/wiki/Gps">GPS</a>&nbsp;&mdash; модуль GPS обеспечивает максимальную точность, погрешность обычно составляет не более 10&nbsp;метров.&nbsp;Однако если модуль GPS необходимо &laquo;разбудить&raquo;, чтобы получить данные со спутников и провести их триангуляцию, то приложение выдаст сведения о&nbsp;расположении не ранее, чем через 1&ndash;2 минуты. Как только модуль GPS установит связь со&nbsp;спутниками, он будет быстрее определять местоположение. Разумеется, чем дольше GPS используется, тем больше энергии потребляет. Чтобы получить данные от модуля GPS, необходимо свойству <a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/windows.devices.geolocation.geolocator.desiredaccuracy.aspx">Geolocator.DesiredAccuracy</a>&nbsp;задать значение High.</li>
<li><a href="https://en.wikipedia.org/wiki/Wi-Fi">Wi-Fi</a>&nbsp;&mdash; соединение Wi-Fi позволяет определять местоположение с точностью до 300&ndash;500&nbsp;метров. При наличии подключения по Wi-Fi, данные о местоположении можно получить быстрее, чем при использовании модуля GPS, которому сначала требуется установить связь со спутниками. Установите для свойства DesiredAccuracy значение Default, если хотите получать сведения о расположении с учетом параметров соединения Wi-Fi.</li>
<li><a href="https://en.wikipedia.org/wiki/IP_address">IP</a>&nbsp;&mdash; IP-адрес позволяет определять местоположение с точностью до 1&nbsp;км. При наличии сетевого подключения данные о местоположении можно получить быстрее, чем при использовании модуля GPS, которому сначала требуется установить связь со спутниками. Установите также для свойства DesiredAccuracy значение Default, если хотите получать сведения о расположении с учетом IP-адреса. Служба расположений старается вычислить местоположение максимально точно; достигнутая точность указывается в свойстве <a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/windows.devices.geolocation.geocoordinate.accuracy.aspx">Geocoordinate.Accuracy</a>.</li>
</ul>
<p>К вопросу определения требуемой точности следует подходить со всей тщательностью. От этого зависит производительность вашего приложения и энергопотребление устройства. Например, если ваше приложение рассылает пользователям прогноз погоды, вам обычно не нужна точность на уровне GPS. Также не забудьте указать точность своих данных с помощью радиуса ошибки, рассчитанного с учетом точности возвращаемых данных. Код C# для задания требуемой точности:</p>
<p><span>C#</span></p>
<pre class="scroll"><code class="csharp">Geolocator geolocator = new Geolocator();<br />geolocator.DesiredAccuracy = Windows.Devices.Geolocation.PositionAccuracy.High;<br /> </code></pre>
<p><span>Вне зависимости от требуемой точности, вызов для определения местоположения будет следующим:</span></p>
<p><span>C#</span></p>
<blockquote>
<div id="codeSnippetWrapper">
<pre class="scroll"><code class="csharp">Geoposition pos = await geolocator.GetGeopositionAsync().AsTask(token);</code></pre>
</div>
</blockquote>
<p>Следующий код JavaScript который создает экземпляр класса Geolocator, задает требуемую точность, а затем получает сведения о текущем местоположении. Обратите внимание на то, что переменная promise представляет собой объект&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/br211867.aspx">WinJS.Promise</a>, вам понадобиться метод&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/hh701079.aspx">done</a>&nbsp;для получения данных с использованием вызова&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/br225537.aspx">getGeopositionAsync</a>.</p>
<p><span>JavaScript</span></p>
<blockquote>
<div id="codeSnippetWrapper">
<pre class="scroll"><code class="js"> var geolocator = Windows.Devices.Geolocation.Geolocator();<br /> geolocator.desiredAccuracy =<br /> Windows.Devices.Geolocation.PositionAccuracy.high;<br /> <br /> // Get the geoposition, capturing the request in a 'promise' object.<br /> var promise = geolocator.getGeopositionAsync();</code></pre>
</div>
</blockquote>
<p>&nbsp;</p>
<p>Не забывайте о том, что когда вы задаете желаемую точность на уровне High, вы не можете быть уверены в том, что устройство пользователя сможет такую точность обеспечить. На ПК может отсутствовать модуль GPS или он может быть отключен, устройство может быть не подключено к&nbsp;сети Wi-Fi и т.&nbsp;д. Вы всегда должны быть готовы корректно обработать данные с низкой точностью. Как именно вы будете это делать, зависит от функциональных возможностей вашего приложения. Достаточно ли полученные данные точны, чтобы приложение могло продолжить свою работу? Можете ли вы запросить данные с точностью на уровне GPS? Для получения дополнительной информации см.&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/hh465148.aspx" target="_blank">Guidelines for location-aware apps</a>.</p>
<h3>Приложение Bing Maps</h3>
<p><a href="https://apps.microsoft.com/webpdp/app/97a2179c-38be-45a3-933e-0d2dbf14a142">Bing Maps</a>&nbsp;&mdash; хороший пример приложения, которое адаптируется к точности полученных данных о&nbsp;местоположении. На настольном ПК, который обычно не оборудован модулем GPS или Wi-Fi, оно определяет местоположение с учетом IP-адреса, при этом на экран выводится регион, в котором находится пользователь. На ноутбуке со встроенным модулем беспроводной связи приложение использует Wi-Fi, чтобы получить более точные сведения о местоположении и вывести на экран более детализированную информацию. Если пользователь хочет получить еще более точные сведения, то система отображает радиус ошибки. На устройствах, оборудованных модулем GPS, приложение Bing Maps получает максимально точные данные и выводит на экран соответствующие сведения о местоположении.</p>
<h3>Приложение Bing Weather</h3>
<p>Как уже упоминалось, приложениям, подобным&nbsp;<a href="https://apps.microsoft.com/webpdp/app/421ba874-f903-4965-9b82-d60f3ba3cae0">Bing Weather</a>,&nbsp;достаточно данных о регионе. Поэтому в приложении можно указать, что ему подходят данные с низкой точностью, и быстро получить сведения о местоположении. С точки зрения пользователя, быстродействие приложения повышается. Другие примеры приложений, которым, возможно, потребуются только данные о&nbsp;регионе: инструменты поиска радиостанций, сервисы рассылки информации о предложениях местных магазинов или местные новостные каналы.</p>
<h2>Отображение сведений о местоположении с помощью Bing Maps SDK</h2>
<p>Получив сведения о местоположении с помощью вызова&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/windows.devices.geolocation.geolocator.getgeopositionasync.aspx">GetGeopositionAsync</a>, вы можете отобразить эту точку на карте.</p>
<ul>
<li>Для начала&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/windows.devices.geolocation.geoposition.aspx">Geoposition</a>&nbsp;необходимо преобразовать в&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/hh846500.aspx">Location</a>,&nbsp;чтобы приложение Bing Maps могло работать с этой информацией. Сделать это позволяет следующий код:</li>
</ul>
<p><span>C#</span></p>
<blockquote>
<div id="codeSnippetWrapper">
<pre class="scroll"><code class="csharp">Location location = new Location(pos.Coordinate.Latitude, pos.Coordinate.Longitude);</code></pre>
</div>
</blockquote>
<p><span>JavaScript:</span></p>
<blockquote>
<pre class="scroll"><code class="js">promise.done(<br /> function (pos) {<br /> // Get the coordinates of the current location.<br /> var coord = pos.coordinate,<br /> location = new Microsoft.Maps.Location(coord.latitude, coord.longitude);<br /> <br /> },<br /> function (err) {<br /> // Handle the error.<br /> });</code></pre>
</blockquote>
<p>&nbsp;</p>
<ul>
<ul>
<li>Затем местоположение выводится на экран в приложении Bing Maps. Пакет Bing Maps SDK можно загрузить <a href="https://visualstudiogallery.msdn.microsoft.com/bb764f67-6b2c-4e14-b2d3-17477ae1eaca">отсюда</a>. Вам также понадобится ключ для Bing Maps. Чтобы его получить, зарегистрируйтесь на портале Bing Maps и следуйте инструкциям: <a href="https://msdn.microsoft.com/ru-ru/library/ff428642.aspx">Getting a Bing Maps Key</a>. В&nbsp;процессе регистрации ознакомьтесь с ограничениями для ключа каждого типа и выберите подходящий ключ для своего приложения.&nbsp;<br /> Добавьте элемент управления Bing Maps в свой конструктор и укажите ключ в учетных данных.</li>
</ul>
</ul>
<p>&nbsp;</p>
<blockquote>
<div id="codeSnippetWrapper">
<pre class="scroll"><code class="html">&lt;Page<br /> xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"<br /> xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"<br /> xmlns:local="using:SimpleMapping"<br /> xmlns:d="https://schemas.microsoft.com/expression/blend/2008"<br /> xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"<br /> xmlns:Maps="using:Bing.Maps"<br /> x:Class="SimpleMapping.MainPage"<br /> mc:Ignorable="d"&gt;<br /> <br /> &lt;Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"&gt;<br /> &lt;Maps:Map x:Name="Map" Margin="0,120,0,0" Credentials="Insert Your Bing Maps Key Here"/&gt;<br /> &lt;/Grid&gt;<br /> &lt;/Page&gt;</code></pre>
</div>
</blockquote>
<ul>
<ul>
<li>Следующий фрагмент вы можете включить в код страницы в своем приложении, где отображается карта. Здесь настраивается масштаб карты и отображается местоположение. Подробнее о масштабе описано в статье&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/xaml/jj850315.aspx">How to display your location on a Bing Map</a>.</li>
</ul>
</ul>
<p>&nbsp;</p>
<p><span>C#</span></p>
<blockquote>
<div id="codeSnippetWrapper">
<pre class="scroll"><code class="csharp">double zoomLevel = 13.0f;<br /> <br />Map.SetView(location, zoomLevel);</code></pre>
</div>
</blockquote>
<p><br /><span>Добавить элемент управления Bing Maps в ваше приложение с использованием JavaScript и HTML немного сложнее. Добавьте следующий тег &lt;script&gt; в код HTML своего приложения:</span></p>
<div>&nbsp;</div>
<blockquote>
<div id="codeSnippetWrapper">
<pre class="scroll"><code class="html">&lt;script type="text/javascript" <br /> src="ms-appx:///Bing.Maps.JavaScript//js/veapicore.js"&gt;<br /> /script&gt;</code></pre>
</div>
</blockquote>
<p>Затем нужно создать тег &lt;div&gt; с картой и задать атрибут ID, чтобы вы могли получить к нему доступ.</p>
<blockquote>
<div id="codeSnippetWrapper">
<pre class="scroll"><code class="html">&lt;div id=&rsquo;map-div&rsquo;&gt;&lt;/div&gt;</code></pre>
</div>
</blockquote>
<p>Наконец, вы должны инициализировать элемент управления карты для своей HTML-страницы. Для этого используется следующий код JavaScript:</p>
<blockquote>
<div id="codeSnippetWrapper">
<pre class="scroll"><code class="js">// Load the Microsoft.Maps.Map module and then call getMap when the <br /> // module has loaded.<br /> function initMap() {<br /> Microsoft.Maps.loadModule('Microsoft.Maps.Map', <br /> { <br /> callback: getMap, <br /> culture: "en", <br /> homeRegion: "US" <br /> });<br /> }<br /> <br /> // Get the div to contain the map from the interface of the app.<br /> function getMap() {<br /> <br /> // Create a new instance of the Map class, passing in the app ID.<br /> var map = new Microsoft.Maps.Map(<br /> document.getElementById(mapDivId), <br /> { credentials: &ldquo;Insert your credentials here&rdquo; });<br /> <br /> // Set the initial zoom level and type of map.<br /> map.setView({<br /> mapTypeId: Microsoft.Maps.MapTypeId.road,<br /> zoom: 3<br /> });<br /> }</code></pre>
</div>
</blockquote>
<ul>
<li>Кроме того, любое приложение, использующее сведения о расположении, должно учитывать установленные пользователем разрешения, которые могут измениться в любой момент. Приложение Weather использует данные о местоположении, чтобы вывести на экран актуальный прогноз погоды. Но пользователь всегда может зайти в настройки и&nbsp;отключить функцию определения местоположения, и ваше приложение должно учитывать такую возможность. В этом случае приложение Weather должно вывести на экран соответствующее предупреждение, например: &laquo;Ваше местоположение не может быть определено. Необходимо разрешить приложению Weather определять ваше местоположение&raquo;. Рекомендации по поводу работы с пользовательскими настройками при определении местоположения см. в документе&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/Hh465148(v=win.10).aspx">Guidelines for location-aware apps</a> (Руководство по разработке приложений, учитывающих географическое положение). &nbsp;</li>
</ul>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/0882.bing-weather_2FEEBCEF.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/0882.bing_2D00_weather_5F00_2FEEBCEF.jpg"><img title="Bing Weather app" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/51/31/metablogapi/7356.bing-weather_thumb_084840C5.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-51-31-metablogapi/7356.bing_2D00_weather_5F00_thumb_5F00_084840C5.jpg" alt="Bing Weather app using location to get weather for the current location" width="600" height="450" border="0" /></a></p>
<p>&nbsp;</p>
<p>Функции определения географического положения и использования Bing Maps SDK подробнее рассматриваются в <a href="https://msdn.microsoft.com/ru-ru/library/windows/apps/xaml/jj850315.aspx">видео, руководствах</a> и&nbsp;<a href="https://code.msdn.microsoft.com/windowsapps/Simple-geolocation-with-7b385c3c">примере кода</a>. Там вы найдете пошаговые инструкции для асинхронного получения сведений о расположении с последующей визуализацией этой информации с помощью Bing Maps SDK. Вы узнаете, как активировать функцию определения местоположения, асинхронно получить соответствующие сведения, вывести требуемый участок карты и настроить значок местоположения с учетом точности полученных данных. Дополнительная информация также представлена на странице&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/hh846481.aspx">Bing Maps for Windows Store Apps</a> (Bing Maps и&nbsp;приложения для Магазина Windows).</p>
<h2>Упаковка</h2>
<p>Функция определения местоположения может быть полезна для вашего приложения, например, с&nbsp;точки зрения экономии времени. Вы сможете предоставлять пользователям более актуальную информацию, если будете знать, где они находятся. Это может быть список местных радиостанций, информация о предложениях от местных магазинов, ситуации на дорогах или погоде. В любом случае данные о местоположении сделают ваше приложение более полезным. В целях экономии времени пользователя, эти функции должны быть автоматизированы. Это поможет вашему приложению стать популярнее.</p>
<p>Автор: Росс Хейзе (Ross Heise), старший разработчик контента, Windows Developer Content</p>
<p>Выражаю особую благодарность Джону Кею (Jon Kay) и Эрику Шмидту (Eric Schmidt) за помощь в&nbsp;подготовке этой статьи.</p>]]></content:encoded>
    </item>
    <item>
      <title>Как сделать ваше приложение быстрым: профильная оптимизация C++</title>
      <link>https://docs.microsoft.com/archive/blogs/developer-tools-rus/103</link>
      <pubDate>Fri, 31 May 2013 01:39:00 GMT</pubDate>
      <dc:creator><![CDATA[Paul Blokhin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/developer-tools-rus/2013/05/31/103/</guid>
      <description><![CDATA[Профильная оптимизация&nbsp;это очень интересный способ оптимизации кода приложения всреде...]]></description>
      <content:encoded><![CDATA[<p><a href="https://msdn.microsoft.com/ru-ru/library/vstudio/e7k32f4k.aspx">Профильная оптимизация</a><span>&nbsp;это очень интересный способ оптимизации кода приложения в</span><em>среде выполнения&nbsp;</em><span>(в команде разработчиков Visual C этот метод называют POGO или PGO, от английского Profile Guided Optimization). Впервые профильная оптимизация была применена в конце 90-х исследовательскими группами в Visual C и Microsoft. Тогда она была рассчитана для архитектуры Itanium. Затем PGO была включена в состав Visual Studio C/C++ 2005. На сегодня это основной процесс оптимизации, значительно повышающий производительность приложений Microsoft и других разработчиков.</span><br /><span>В этом посте будет рассказано, как создавать более быстрые и высокопроизводительные нативные приложения. Для начала, познакомимся ближе с PGO, а затем рассмотрим на примере (симуляция NBody), как с помощью нескольких простых шагов можно применить этот процесс оптимизации в ваших приложениях. Для работы используйте исходный код из</span><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/10/40/74/38/NBody.zip" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-40-74-38/NBody.zip">примера</a><span>. Для сборки проекта вам понадобится&nbsp;</span><a href="https://blogs.msdn.com/controlpanel/blogs/posteditor.aspx/DirectX%20SDK">DirectX SDK</a><span>.</span><br /><a name="habracut"></a><br /><br /></p>
<h4>Как сделать нативное приложение более быстрым</h4>
<p><br /><span>Традиционные компиляторы работают с оптимизацией на основе статических исходных файлов. Они анализируют текст исходного файла, но не принимают в расчет данные, вводимые пользователями, о которых просто невозможно знать из кода. Рассмотрим этот псевдокод:</span><br /><img src="https://habrastorage.org/storage2/e3b/3e7/a1b/e3b3e7a1b0a2ba54134961d2d9fe8693.png" alt="" /><br /><br /><span>При работе с функцией whichBranchIsTaken компилятор не знает, как часто параметр &laquo;a&raquo; будет меньше параметра &laquo;b&raquo;, и сколько раз будет применено условие &laquo;if&raquo; (т. е. компилятор не может предсказывать ветвления). При работе с функциями девиртуализации и switchCaseExpansion компилятор знает недостаточно о значениях *p и i, что делает невозможным оптимизацию девиртуализации и расширений параметров. Эти проблемы проявятся еще ярче, если мы подставим данный фрагмент кода в разные модули (например, разные объектные файлы), поскольку функции традиционной компиляции не могут быть оптимизированы для работы в пределах исходных модулей.</span><br /><span>Базовая модель компилятора и компоновщика не так уж и плоха, но в ней недостает двух основных возможностей для оптимизации. Во-первых, в ней не используется информация, которую можно было бы получить на основе анализа всех исходных файлов (традиционные компиляторы оптимизируют только отдельные объектные файлы). Во-вторых, в ней не проводится оптимизация на базе ожидаемой или профильной реакции приложения. Первый недостаток может быть исправлен с помощью переключателя компилятора (</span><a href="https://msdn.microsoft.com/en-us/library/0zza0de8.aspx">/GL</a><span>) или переключателя компоновщика (</span><a href="https://msdn.microsoft.com/en-us/library/xbf3tbeh.aspx">/LTCG</a><span>), выполняющего полную оптимизацию программы и необходимого для профильной оптимизации приложения. После того, как оптимизация полной программы включена, вы можете применять профильную оптимизацию. Остановимся на ней подробнее.</span><br /><span>PGO &ndash; это процесс оптимизации компилятора в среде выполнения, применяющий данные профиля, собранные в ходе выполнения важных или требующих высокой производительности пользовательских сценариев, с целью оптимизации приложения. Профильная оптимизация обладает рядом преимуществ по сравнению с традиционной статической оптимизацией, поскольку она принимает в расчет, как будет себя вести приложение в рабочей среде. Благодаря этому оптимизатор может осуществлять оптимизацию по скорости (для частых пользовательских сценариев) или оптимизацию по размеру (для редких сценариев). В результате код становится более лаконичным, что, в конечном счете, повышает производительность приложения.</span><br /><br /><img src="https://habrastorage.org/storage2/1d4/def/43a/1d4def43a3670f6755be780c907054f0.png" alt="" /><br /><br /><span>В настоящее время PGO может применяться только на классических приложениях для настольных компьютеров и поддерживается на платформах x86 и х64. PGO представляет собой процесс, состоящий из трех этапов, как это показано на рисунке выше.</span><br /><br /></p>
<ul>
<li>Первый этап обычно называют&nbsp;<strong>фазой инструментирования</strong>. В ходе этой фазы идет сборка приложения с заданным набором флагов компиляции. В процессе сборки внутренний компилятор добавляет в созданный код пробные инструкции (зонды), которые используются для записи данных обучения, необходимых на следующем этапе. Всего добавляется три типа зондов (входа в функцию, перехода и значений). Зонд входа в функцию измеряет, как часто запрашивалась та или иная функция. Зонд перехода позволяет узнать, сколько раз была достигнута та или иная ветвь кода. Таким образом в ходе фазы обучения компилятор получает информацию о том, как часто &laquo;a &gt; b&raquo; в фрагменте кода whichBranchisTaken в заданном сценарии обучения. Зонд значений позволяет получить данные для построения гистограммы значений. Например, зонд значений, добавленный в фрагмент кода switchCaseExpansion, позволит получить данные для построения гистограммы значений для переменной индекса switch case i. Получив в ходе обучения информацию о том, какие значения будет принимать переменная &laquo;i&raquo;, компилятор сможет провести оптимизацию для наиболее частых значений, а также таких функций как switchCaseExpansion. Таким образом, по окончании фазы у нас будет инструментированная версия приложения (с зондами) и пустой файл базы данных (.pgd), в которую будет заноситься информация, полученная в ходе следующей фазы.</li>
<li><strong>Фаза обучения&nbsp;</strong>. В ходе этой фазы пользователь запускает инструментированную версию приложения и проигрывает стандартные пользовательские сценарии, требующие высокой производительности. На выходе мы имеем файлы .pgc, содержащие информацию, связанную с различными пользовательскими сценариями. В процессе обучения информация проходит через зонды, добавленные в ходе первой фазы. На выходе мы получаем pgc-файлы appname!# (где appname соответствует названию приложения, а # &mdash; единице плюс числу pgc-файлов appname!# в выходном каталоге построения).</li>
<li><strong>Последняя фаза PGO &mdash; оптимизация</strong>. В ходе этой фазы создается оптимизированная версия приложения. Помимо этого, информация из pgc-файлов, полученная в ходе фазы обучения, вносится в фоновом режиме в базу данных (файл .pgd), созданную в ходе инструментирования. Внутренний компилятор затем использует эту базу данных для последующей оптимизации кода и построения еще более совершенной версии приложения.</li>
</ul>
<p><br /><br /><span>Пользователи PGO зачастую ошибочно считают, что все три фазы (инструментирование, обучение и оптимизация) должны проводиться каждый раз при построении проекта. На самом деле, первые две фазы могут быть исключены при построении последующих версий, а код при этом может претерпевать значительные изменения по сравнению с версией, полученной после фазы обучения приложения. В больших коллективах один разработчик может отвечать за проведение PGO и поддержку базы данных обучения (.pgd) в репозитории исходного кода. Другие разработчики могут синхронизировать свои репозитарии кода с этой базой и использовать файлы обучения для построения PGO-оптимизированных версий приложений. После определенного количества перекомпиляций приложение будет окончательно оптимизировано.</span><br /><br /></p>
<h4>Применение профильной оптимизации</h4>
<p><br /><span>Теперь, когда мы знаем немного больше о профильной оптимизации, рассмотрим ее применение на конкретном примере. Профильную оптимизацию приложения можно осуществлять с помощью Visual Studio или командной строки разработчика. Ниже рассмотрен пример работы в Visual Studio с приложением под условным названием &laquo;Nbody Simulation&raquo;. Если вы хотите узнать больше о PGO в командной строке, обратитесь к&nbsp;</span><a href="https://msdn.microsoft.com/ru-ru/library/aa289170(v=vs.71).aspx">этим статьям</a><span>. Для начала работы загрузите решение в Visual Studio и выберите конфигурацию построения для работы (т.е. &laquo;Release&raquo;).</span><br /><br /><img src="https://habrastorage.org/storage2/9da/0ad/0cf/9da0ad0cffcd5f70dc448c539414eeed.png" alt="" /><br /><br /><span>Как было упомянуто выше, PGO состоит из трех этапов: инструментирования, обучения и оптимизации. Для создания инструментированной версии приложения, нажмите правой кнопкой мыши по названию проекта (&laquo;NBodyGravityCPU&raquo;) и выберите раздел &laquo;Instrument&raquo; в меню &laquo;Profile Guided Optimization&raquo;.</span><br /><br /><img src="https://habrastorage.org/storage2/75c/6c1/333/75c6c13339783c818f2291ae3d469a6f.png" alt="" /><br /><br /><span>В Visual Studio будет построена инструментированная версия приложения. После этого можно переходить к фазе обучения. Запустите инструментированную версию приложения. Для этого зайдите в меню &laquo;Profile Guided Optimization&raquo; и выберите &laquo;Run Instrumented/Optimized Application&raquo;. В нашем случае приложение выполняется с максимально большим телом кода (15360), т. к. будет реализован стабильный пользовательский сценарий, требующий высокой производительности. После того как два основных показателя производительности приложения &mdash; FPS (кадров в секунду) и GFlop &ndash; примут устойчивые значения, вы можете закрыть приложение. На этом фаза обучения будет завершена, а полученные данные будут сохранены в файле .pgc. По умолчанию файл .pgc будет включен в вашу конфигурацию построения, т.е. каталог &laquo;Release&raquo;. Например, в результате этого обучения создается файл NBodyGravityCPU!1.pgc.</span><br /><br /><img src="https://habrastorage.org/storage2/93c/bd8/dae/93cbd8dae442b8d9fa2857429615d389.png" alt="" /><br /><br /><span>NBody Simulation представляет собой очень простое приложение, созданное исключительно для иллюстрации процесса PGO. В действительности может существовать множество вариантов сценариев обучения приложений. В частности, можно производить обучение в несколько этапов, разделенных по времени. Для записи таких сценариев обучения лучше всего использовать команду&nbsp;</span><a href="https://msdn.microsoft.com/ru-ru/library/9hwkw6e8.aspx">pgosweep</a><span>&nbsp;в командной строке разработчика после того, как инструментированная версия уже создана (напр., в Visual Studio).</span><br /><br /><img src="https://habrastorage.org/storage2/373/812/4e7/3738124e725ac44b322bb78d30e1c406.png" alt="" /><br /><br /><span>В ходе последней фазы PGO создается оптимизированная версия приложения. В меню &laquo;Profile Guided Optimization&raquo; выберите &laquo;Optimize&raquo;. Будет создана оптимизированная версия приложения. В выходном журнале PGO-построения вы увидите обобщенную информацию о проведенной операции.</span><br /><span>Как было сказано выше, информация из файлов .pgc, полученная в ходе фазы обучения, включается в базу данных .pgd, которая затем используется матрицей оптимизации внутреннего компилятора. В большинстве случаев (за исключением небольших быстрых приложений) критерий оптимизации скорость/размер определяется соотношением динамических инструкций для определенной функции. Функции с большим числом инструкций (т. н. &laquo;горячие&raquo;) оптимизируются на скорость, а с малым количеством инструкций (т. н. &laquo;холодные&raquo;) &ndash; на размер.</span><br /><span>Это практически все, что вам необходимо для того чтобы начать профильную оптимизацию в ваших приложениях. Попробуйте применить PGO для своих приложений и оцените результаты! И обязательно загляните в блог&nbsp;</span><a href="https://blogs.msdn.com/b/developer-tools-rus/">Инструменты для разработчика</a><span>, возможно вы найдете там еще какие либо интересные решения!&nbsp;</span><br /><span>Автор поста &mdash; Анкит Астхана (</span><a href="https://blogs.msdn.com/487959/ProfileUrlRedirect.ashx">Ankit Asthana</a><span>) &mdash; руководитель программы по внутреннему компилятору Microsoft Visual С++.</span></p>]]></content:encoded>
    </item>
    <item>
      <title>Использование списков SharePoint в качестве объектов LightSwitch с помощью CSOM</title>
      <link>https://docs.microsoft.com/archive/blogs/developer-tools-rus/sharepoint-10</link>
      <pubDate>Fri, 17 May 2013 06:41:00 GMT</pubDate>
      <dc:creator><![CDATA[Paul Blokhin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/developer-tools-rus/2013/05/17/sharepoint-10/</guid>
      <description><![CDATA[Списки как объекты
Брайан уже рассказал о присоединении к списку SharePoint и моделировании его...]]></description>
      <content:encoded><![CDATA[<p><span style="font-size: 1.5em;">Списки как объекты</span></p>
<p>Брайан уже рассказал о присоединении к списку SharePoint и моделировании его объектов в приложении LightSwitch с поддержкой SharePoint. Однако это еще не все &mdash; вы можете выполнить присоединение к локальному сайту SharePoint в&nbsp;<strong>любом</strong>&nbsp;приложении LightSwitch, указав имя пользователя и пароль или же выступив в роли пользователя приложения LightSwitch. Имя пользователя и пароль нужны для ограничения доступа к списку, чтобы им могло пользоваться только ваше приложение LightSwitch.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/8836.image_7F9C8F6E.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/8836.image_5F00_7F9C8F6E.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/8321.image_thumb_1EDF3642.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/8321.image_5F00_thumb_5F00_1EDF3642.png" alt="image" width="482" height="378" border="0" /></a></p>
<p>Включив&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/vstudio/jj969620.aspx">поддержку SharePoint в вашем приложении LightSwitch</a>,&nbsp;вы тем самым указываете LightSwitch, что приложение должно быть развернуто на SharePoint и что оно может работать с ресурсами SharePoint. Поддержка включается в SharePoint на странице Properties (Свойства):</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/5857.image_78487FDE.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/5857.image_5F00_78487FDE.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/3386.image_thumb_6FE4AA87.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/3386.image_5F00_thumb_5F00_6FE4AA87.png" alt="image" width="597" height="281" border="0" /></a></p>
<p>Если указать сайт Office 365 в качестве целевого, то можно делать присоединение к спискам на сайте Office 365, однако для этого нужно будет разрешить LightSwitch выбор идентификационной информации пользователя. В среде выполнения этим пользователем будет тот, кто запустил приложение в SharePoint. Как правило, в ходе отладки вы запускаете приложения с вашей личной или тестовой учетной записью. Поэтому если при попытке присоединения к списку в Office 365 появляется сообщение об ошибке с текстом наподобие &laquo;<em>[&hellip;] does not appear to be a valid site. </em><em>SharePoint 2010 (or later) with an installation of WCF Data Services is required&raquo;</em> (&laquo;сайт [&hellip;] недействителен. Требуется SharePoint 2010 или более поздняя версия с установленными службами WCF Data Services&raquo;), причины, скорее всего, будут следующие: отключена поддержка SharePoint, отключен автоматический выбор идентификационной информации или же вы пытаетесь сделать присоединение к другому сайту, который не указан в свойствах SharePoint. Если вы разворачиваете приложение на конкретном сайте Office 365, то он является единственным сайтом Office 365, к которому можно делать присоединение в LightSwitch.</p>
<p>Итак, каковы же преимущества использования списков SharePoint в качестве объектов? Теперь можно обращаться с данными списка точно так же, как с любым другим источником данных LightSwitch, включая использование собственного программного кода для обработки сохранения данных. Давайте возьмем&nbsp;<a href="https://blogs.msdn.com/b/lightswitch/archive/2013/03/07/a-quick-amp-easy-lightswitch-app-for-sharepoint.aspx">пример Брайана</a> и внесем в него кое-какие изменения после добавления списка покупателей к сайту. В компанию может позвонить клиент, с которым уже общался один из наших агентов по продажам. Нам нужна возможность перенаправления вызова к тому же самому агенту, поскольку он в курсе текущей ситуации с клиентом и ему будет проще выстроить разговор. Давайте слегка изменим этот список. Щелкните заголовок приложения Customers (Клиенты), затем нажмите Edit this list (Правка списка):</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/5706.image_0E83BE89.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/5706.image_5F00_0E83BE89.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/4606.image_thumb_6DFC7ED6.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/4606.image_5F00_thumb_5F00_6DFC7ED6.png" alt="image" width="391" height="151" border="0" /></a></p>
<p>Нажмите на символ плюса, чтобы добавить столбец, затем выберите Date or Time (Дата или время):</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/0003.image_2D5A3267.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/0003.image_5F00_2D5A3267.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/6170.image_thumb_73D7226F.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/6170.image_5F00_thumb_5F00_73D7226F.png" alt="image" width="199" height="222" border="0" /></a></p>
<p>Назовите этот столбец Last Contact Date (Дата последнего контакта). Затем добавьте еще один столбец, в этот раз он будет иметь тип String (Строка) и имя Last Contact Person (Последнее контактное лицо). Ваш список должен выглядеть так:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/6761.image_3334D600.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/6761.image_5F00_3334D600.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/6675.image_thumb_72928990.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/6675.image_5F00_thumb_5F00_72928990.png" alt="image" width="704" height="164" border="0" /></a></p>
<p>Затем выберите Stop editing this list (Прекратить правку списка). Вернитесь в LightSwitch, и если сайт SharePoint уже добавлен вами в качестве источника данных, щелкните его правой кнопкой мыши и выберите Update Datasource (Обновить источник данных).</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/0486.image_31F03D21.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/0486.image_5F00_31F03D21.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/4048.image_thumb_188839E7.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/4048.image_5F00_thumb_5F00_188839E7.png" alt="image" width="374" height="206" border="0" /></a></p>
<p>Затем просто нажмите Finish (Готово). После этого вы можете открыть объект Customer (Клиент) и увидите новые поля.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/1805.image_7EB403B7.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/1805.image_5F00_7EB403B7.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/5518.image_thumb_10246490.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/5518.image_5F00_thumb_5F00_10246490.png" alt="image" width="575" height="290" border="0" /></a></p>
<p>&nbsp;</p>
<p>Пока мы находимся в этом окне, самое время присвоить общему свойству Customer значение FirstName (Имя), если вы еще не сделали этого. В результате LightSwitch будет отображать имя клиента в общем представлении, которое используется по умолчанию при открытии нового окна. Чтобы изменить представление, сначала нажмите кнопку &laquo;Клиент&raquo;.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/0728.image_2847CEEB.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/0728.image_5F00_2847CEEB.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/6354.image_thumb_54F088C4.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/6354.image_5F00_thumb_5F00_54F088C4.png" alt="image" width="740" height="476" border="0" /></a></p>
<p>Раз уж мы отслеживаем звонки наших клиентов, давайте составим таблицу для этого. Моя выглядит примерно так.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/6761.image_5ACB2C5D.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/6761.image_5F00_5ACB2C5D.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/7245.image_thumb_04CB2A86.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/7245.image_5F00_thumb_5F00_04CB2A86.png" alt="image" width="566" height="362" border="0" /></a></p>
<p>Вот, я создал новую таблицу с именем CustomerCall, а затем добавил отношение, которое связало ее со списком Customer (Клиент).</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/5773.image_240DD159.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/5773.image_5F00_240DD159.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/2553.image_thumb_4350782C.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/2553.image_5F00_thumb_5F00_4350782C.png" alt="image" width="360" height="477" border="0" /></a></p>
<p>Затем я добавил несколько дополнительных полей. Type (Тип) &mdash; это список выбора с параметрами Refund (Возмещение), Purchase (Покупка), Quote (Предложение с расценками) и Other (Другое).</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/7762.image_374E87F8.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/7762.image_5F00_374E87F8.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/4520.image_thumb_48BEE8D0.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/4520.image_5F00_thumb_5F00_48BEE8D0.png" alt="image" width="520" height="376" border="0" /></a></p>
<p>Я также добавил поле ContactPerson для хранения сведений о сотруднике, который общался с клиентом, и поле Notes (Примечания) для хранения общих сведений. Придумаем простой интерфейс для этого окна, оставив окно Browse (Просмотр) для отображения данных CustomerCalls и добавив кнопку AddAndEditNew для перехода к диалоговому окну AddEditCustomerCall.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/3630.image_15EEE25C.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/3630.image_5F00_15EEE25C.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/8738.image_thumb_7567A2A9.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/8738.image_5F00_thumb_5F00_7567A2A9.png" alt="image" width="329" height="265" border="0" /></a></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/8420.image_7FB8C709.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/8420.image_5F00_7FB8C709.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/7752.image_thumb_6D03CD52.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/7752.image_5F00_thumb_5F00_6D03CD52.png" alt="image" width="339" height="318" border="0" /></a></p>
<p>Ничего нового для вас здесь нет, но давайте снова откроем объект CustomerCall и напишем пару строк кода. Нажмите кнопку с раскрывающимся списком Write Code (Написать код) в верхней части средства Data Designer и выберите метод Inserting (Вставка).</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/3036.image_6C2B6768.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/3036.image_5F00_6C2B6768.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/7271.image_thumb_122117BF.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/7271.image_5F00_thumb_5F00_122117BF.png" alt="image" width="791" height="286" border="0" /></a></p>
<p>Затем можно добавить следующий код:</p>
<p>(C#)</p>
<p>partial void&nbsp;CustomerCalls_Inserting(CustomerCall&nbsp;entity)&nbsp;<br /> {&nbsp;<br /> &nbsp; entity.Customer.LastContactDate =&nbsp;DateTime.Now;&nbsp;<br /> &nbsp; entity.Customer.LastContactPerson = entity.ContactPerson;&nbsp;<br /> &nbsp; ServerApplicationContext.Current.DataWorkspace.SharePoint_SiteData.SaveChanges();&nbsp;<br /> }</p>
<p>(Visual Basic)</p>
<p>Private Sub CustomerCalls_Inserting(entity As CustomerCall) <br /> &nbsp;entity.Customer.LastContactDate = DateTime.Now <br /> &nbsp;entity.Customer.LastContactPerson = entity.ContactPerson <br /> &nbsp;ServerApplicationContext.Current.DataWorkspace.SharePoint_SiteData.SaveChanges() <br /> End Sub</p>
<p>Обратите внимание, что&nbsp;выделенную часть&nbsp;необходимо изменить так, чтобы она совпадала с именами ваших источников данных.</p>
<p>Теперь можно нажать F5 для сборки проекта и ввести сведения о первом звонке клиента.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/6281.image_5112985A.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/6281.image_5F00_5112985A.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/7652.image_thumb_308B58A8.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/7652.image_5F00_thumb_5F00_308B58A8.png" alt="image" width="455" height="231" border="0" /></a></p>
<p>Затем, если вернуться обратно к списку Customer (Клиент), можно увидеть примерно следующее.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/5125.image_68C9CFC0.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/5125.image_5F00_68C9CFC0.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/7762.image_thumb_484)E.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/7762.image_5F00_thumb_5F00_4842900E.png" alt="image" width="736" height="62" border="0" /></a></p>
<p>Пример весьма прост, однако приятно видеть, что со списками SharePoint можно работать почти так же как с любыми другими типами объектов LightSwitch. Чуть позже мы продолжим работу с этими списками.</p>
<h2>Действие над списками при помощи CSOM</h2>
<p>Предположим, вы всегда выбираете сложный путь. Если вам необходимо управление всеми аспектами взаимодействия LightSwitch с SharePoint, можно использовать&nbsp;<a href="https://msdn.microsoft.com/en-us/library/jj193041.aspx">SharePoint Client-Side Object Model</a> (CSOM, модель объекта SharePoint на стороне клиента). Один из возможных сценариев ее использования &mdash; разработка приложения LightSwitch с поддержкой SharePoint. В этом случае вы сможете добавлять списки SharePoint к вашим проектам, однако LightSwitch не сможет подключиться к ним, поскольку эти списки не существуют до момента установки приложения на сайте SharePoint.</p>
<p>Возвращаясь к доработке приложения Брайана, мы видим, что у этого приложения уже есть окна Browse (Просмотр) и Edit Customer (Правка сведений о клиенте). Сведения о клиенте конфиденциальны, поэтому мы не будем проводить аудит вносимых в них изменений. Давайте добавим список в наш проект SharePoint для сбора этих сведений.</p>
<p>Возможно, предлагаемый способ окажется для вас неудобным. Списки, которые вы добавляете в проект SharePoint, принадлежат веб-приложению. Это значит, что они создаются в момент установки приложения LightSwitch и удаляются при удалении приложения, что приводит к потере всех данных. Для списка Customers (Клиенты) действует другой механизм работы, поскольку этот список относится к веб-узлу и не связан с конкретным приложением. В сети MSDN есть дополнительные сведения о&nbsp;<a href="https://msdn.microsoft.com/ru-ru/library/fp179925.aspx">веб-узлах, веб-приложениях и компонентах SharePoint в SharePoint 2013</a>.</p>
<p>Однако это лишь пример, нас сейчас не волнует вечное хранение этих данных. Перейдите к представлению файла в обозревателе проектов, щелкните правой кнопкой мыши ваш проект SharePoint и выберите Add &ndash;&gt; New Item (Добавить &ndash;&gt; Новый элемент).</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/2061.image_209C13E4.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/2061.image_5F00_209C13E4.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/6607.image_thumb_6DCC0D6F.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/6607.image_5F00_thumb_5F00_6DCC0D6F.png" alt="image" width="634" height="413" border="0" /></a></p>
<p>Здесь по умолчанию необходимо выбрать List (Список); назовите его AuditEntry и нажмите Add (Добавить). В следующем окне LightSwitch попросит выбрать тип списка. Журнал аудита не входит в типы по умолчанию, поэтому оставьте значение Default (Custom List) (По умолчанию (Настраиваемый список)), и мы настроим его самостоятельно.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/6201.image_7ED03B52.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/6201.image_5F00_7ED03B52.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/2061.image_thumb_79ED8796.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/2061.image_5F00_thumb_5F00_79ED8796.png" alt="image" width="626" height="458" border="0" /></a></p>
<p>Теперь нужно разработать столбцы списка. В него следует добавить числовое поле для параметра Customer ID (Идентификатор клиента), который указывает на изменяемые нами сведения о клиенте, текстовое поле с именем пользователя, вносящего изменения, поле с датой внесения изменений и текстовое поле с описанием выполненного действия.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/3652.image_7D1F6F7E.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/3652.image_5F00_7D1F6F7E.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/5618.image_thumb_6A6A75C7.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/5618.image_5F00_thumb_5F00_6A6A75C7.png" alt="image" width="618" height="401" border="0" /></a></p>
<p>Если вы попытаетесь обновить источник данных SharePoint прямо сейчас, то не увидите этого списка. Причина состоит в том, что это список не существует на сайте до тех пор, пока проект не будет собран нажатием клавиши F5 или не будет развернут из опубликованного пакета приложения SharePoint. Однако работать с CSOM можно и без этого! Откройте объект Customer (Клиент) и напишите код для метода обновления.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/1817.image_028DE023.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/1817.image_5F00_028DE023.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/8838.image_thumb_4FBDD9AE.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/8838.image_5F00_thumb_5F00_4FBDD9AE.png" alt="image" width="621" height="366" border="0" /></a></p>
<p>Заполните ваш класс SharePoint_SiteDataService (имя может быть любым) следующим образом:</p>
<p>(C#)</p>
<p>using&nbsp;Microsoft.SharePoint.Client;</p>
<p>public partial&nbsp;class&nbsp;SharePoint_SiteDataService&nbsp;<br /> {&nbsp;<br /> &nbsp; partial void&nbsp;Customers_Updating(Customer&nbsp;entity)&nbsp;<br /> &nbsp; {&nbsp;<br /> &nbsp;&nbsp;&nbsp; LogAuditEntry(entity,&nbsp;"Обновить");&nbsp;<br /> &nbsp; }</p>
<p>&nbsp; partial void&nbsp;Customers_Deleting(Customer&nbsp;entity)&nbsp;<br /> &nbsp; {&nbsp;<br /> &nbsp;&nbsp;&nbsp; LogAuditEntry(entity,&nbsp;"Удалить");&nbsp;<br /> &nbsp; }</p>
<p>&nbsp; private void&nbsp;LogAuditEntry(Customer&nbsp;entity,&nbsp;string&nbsp;actionDescription)&nbsp;<br /> &nbsp; {&nbsp;<br /> &nbsp;&nbsp;&nbsp; using&nbsp;(ClientContext&nbsp;ctx = Application.SharePoint.GetAppWebClientContext())&nbsp;<br /> &nbsp;&nbsp;&nbsp; {&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Web&nbsp;web = ctx.Web;&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ListCollection&nbsp;lists = web.Lists;&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List&nbsp;auditLog = lists.GetByTitle("Запись аудита");&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ListItemCreationInformation&nbsp;ci =&nbsp;new&nbsp;ListItemCreationInformation();&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ListItem&nbsp;auditEntry = auditLog.AddItem(ci);&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auditEntry["Название"] =&nbsp;"Запись аудита";&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auditEntry["ИД клиента 1"] = entity.Id;&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auditEntry["Пользователь1"] = Application.User.FullName;&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auditEntry["Дата1"] =&nbsp;DateTime.Now;&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auditEntry["Действие"] = actionDescription;&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auditEntry.Update();&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ctx.ExecuteQuery();&nbsp;<br /> &nbsp;&nbsp;&nbsp; }&nbsp;<br /> &nbsp; }&nbsp;<br /> }</p>
<p>(Visual Basic)</p>
<p>Imports Microsoft.SharePoint.Client<br /> <br /> <br /> Public Class SharePoint_SiteDataService <br /> &nbsp;Private Sub Customers_Updating(entity As Customer) <br /> &nbsp;LogAuditEntry(entity, "Обновить") <br /> &nbsp;End Sub</p>
<p>&nbsp;Private Sub Customers_Deleting(entity As Customer) <br /> &nbsp;LogAuditEntry(entity, "Удалить") <br /> &nbsp;End Sub <br /> <br /> &nbsp;Private Sub LogAuditEntry(entity As Customer, actionDescription As String) <br /> &nbsp;Using ctx As ClientContext = Application.SharePoint.GetAppWebClientContext() <br /> &nbsp;Dim web As Web = ctx.Web <br /> &nbsp;Dim lists As ListCollection = Web.Lists <br /> &nbsp;Dim auditLog As List = lists.GetByTitle("Запись аудита") <br /> &nbsp;Dim ci As New ListItemCreationInformation() <br /> &nbsp;Dim auditEntry As ListItem = auditLog.AddItem(ci) <br /> &nbsp;<br /> <br /> &nbsp;auditEntry("Название") = "Запись аудита" <br /> &nbsp;auditEntry("ИД клиента1") = entity.Id <br /> &nbsp;auditEntry("Пользователь1") = Application.User.FullName <br /> &nbsp;auditEntry("Дата 1") = DateTime.Now <br /> &nbsp;auditEntry("Действие") = actionDescription <br /> &nbsp;<br /> &nbsp;auditEntry.Update() <br /> &nbsp;ctx.ExecuteQuery() <br /> &nbsp;End Using <br /> &nbsp;End Sub <br /> End Class</p>
<p>Теперь снова соберите проект нажатием клавиши F5 и внесите изменения в сведения о клиенте, которые будут записаны в список, добавленный к проекту. Когда вы нажали F5, LightSwitch развернул ваш проект на SharePoint, а также создал элементы, добавленные вами в проект SharePoint. Итак, где же находится этот список? Возьмите URL-адрес вашего сайта SharePoint, включая имя коллекции сайтов разработчика (при наличии), затем добавьте к нему имя вашего приложения и строку &ldquo;/Lists/AuditEntry&rdquo;. Вот моя строка: https://example.sharepoint.com/sites/Developer/ListAttachDemo/Lists/AuditEntry. Результат будет выглядеть так.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/0312.image_60C20791.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/0312.image_5F00_60C20791.png"><img title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/39/73/metablogapi/5621.image_thumb_6055D49C.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-39-73-metablogapi/5621.image_5F00_thumb_5F00_6055D49C.png" alt="image" width="694" height="102" border="0" /></a></p>
<p>Теперь мы можем использовать списки, которые не привязаны к LightSwitch. Вы также могли заметить, что мною нарушено единообразие имен столбцов для записи со списком (User1 и просто Action). На этом стоит остановиться подробнее, ведь даже я не сразу понял причину этого явления. SharePoint иногда отображает не совсем верное имя столбца в конструкторе списков и на веб-сайте. Если в качестве имени столбца указать строку, которую SharePoint сочтет именем типа или иным зарезервированным словом, то для снятия неоднозначности к этой строке будет добавлено число. Как же узнать настоящее имя столбца? Я использую следующий код:</p>
<p>(C#)</p>
<p>using&nbsp;(ClientContext&nbsp;ctx = Application.SharePoint.GetAppWebClientContext())&nbsp;<br /> {&nbsp;<br /> &nbsp; Web&nbsp;web = ctx.Web;&nbsp;<br /> &nbsp; ListCollection&nbsp;lists = web.Lists;&nbsp;<br /> &nbsp; List&nbsp;auditLog = lists.GetByTitle("AuditEntry");&nbsp;<br /> &nbsp; ctx.Load(auditLog.Fields);&nbsp;<br /> &nbsp; ctx.ExecuteQuery();&nbsp;<br /> }</p>
<p>(Visual Basic)</p>
<p>Using ctx As ClientContext = Application.SharePoint.GetAppWebClientContext() <br /> &nbsp;Dim web As Web = ctx.Web <br /> &nbsp;Dim lists As ListCollection = Web.Lists <br /> &nbsp;Dim auditLog As List = lists.GetByTitle("AuditEntry") <br /> <br /> &nbsp;ctx.Load(auditLog.Fields) <br /> &nbsp;ctx.ExecuteQuery() <br /> End Using</p>
<p>После этого кода можно поставить точку останова и посмотреть содержимое поля auditLog.Fields, чтобы увидеть настоящие имена столбцов SharePoint. Это первый прием, которым я воспользуюсь в случае возникновения ошибки наподобие <em>Column &lt;ColumnName&gt; does not exist. </em><em>It</em><em> </em><em>may</em><em> </em><em>have</em><em> </em><em>been</em><em> </em><em>deleted</em><em> </em><em>by</em><em> </em><em>another</em><em> </em><em>user</em> (Столбец &lt;ColumnName&gt; не существует. Он мог быть удален другим пользователем).</p>
<p>С помощью CSOM можно делать&nbsp;<strong>множество</strong>&nbsp;интересных вещей, некоторые из них приведены на <a href="https://msdn.microsoft.com/en-us/library/jj193041.aspx#SPclientlanding_core">справочной странице MSDN</a>. Например, при помощи CSOM можно добавлять и изменять списки, решать задачи администрирования сайта, передавать документы на сайт, управлять группами и пользователями. Если вас интересует какая-то отдельная тема, напишите мне, и я подумаю над тем, чтобы черкнуть о ней пару строк.</p>
<p>&nbsp;</p>]]></content:encoded>
    </item>
  </channel>
</rss>