Welcome to MSDN Blogs Sign in | Join | Help

[Info] Visio の図面から Silverlight への変換、制御 (Tech Fielders 取材記事)

こんにちは。

すでに 11/14 にご紹介されていたのですが、私がインタビュアーとして担当させていただいた Tech Fielders インタビューの取材記事の 2 つめが公開しましたのでご紹介いたします。

製造業と言えば日本の産業を支える屋台骨とも言うべき分野ですが、今回は、ハード、制御技術など日本の強みである製造分野のテクノロジーと、欧米先行の感覚が強いコンピュータソフトウェアの分野でのテクノロジーの融合事例です。

http://www.microsoft.com/japan/powerpro/TF/interview/14_1.mspx

「Visio から Siliverlight へ変換」と聞いて、「海外の連携ソフトを使った構築事例」と思ってしまう方も多いかもしれませんが、違います。OPC サーバー(デバイス連携)、SOAP ベースの通信テクノロジー、IntelliCAD として成長した Visio のポテンシャル、そして Silverlight 。これらを融合させた 国産 テクノロジーの取り組みについて記載しています。

ここで紹介されている日本OPC協議会については、参加企業による定例の勉強会などが実施されています。活動状況などについては、以下のホームページをご参照ください。

日本OPC協議会ホームページ
http://www.opcjapan.org/

Posted by tsmatsuz | 1 Comments

[Info] PDC が気になる方へ . . . <イベントのご紹介>

こんにちは。

先日Losで開催されたPDCでは、メディアなどでご存じの通り、Microsoft のクラウドサービスとも言うべき Windows Azure などのテクノロジーが紹介されました。これらの情報については、日本では、随時、イベントなどを通してご紹介させていただきますので、ご興味ある方はお見逃しのないようご参加ください。(私のブログでも、イベントでの紹介まではこれらテクノロジーの紹介は控えたいと思います。) 

で、そうしたイベントはどこでやってるの?という疑問になると思いますので記載します。

PDC で紹介された新しいテクノロジーは、プロフェッショナルデベロッパーの方を含むエンジニアの方向けに、以下のイベントを通してご紹介していきますので、どうぞご参加ください。(米国で開催された PDC の日本版イベントです。従来、Microsoft Developer Conference と呼んでいたものに相当するでしょう。)

Microsoft tech・days 2009 (2009/01/27 - 28, 横浜)
http://www.microsoft.com/japan/events/techdays/default.mspx

また、このクラウドサービスは、ベンチャーの方などが、開発されたソフトウェアを配り、普及させていく場合などを想像していただくとわかりますが、使う側のポータビリティ以外にも、作る側にも大きな "ビジネス面" での可能性をもたらします。(そういった点では、例えば、課金方式などといった話題にも興味を持たれている方も多いかもしれません。)
中小企業やベンチャーの経営者の方、情報部門の管理者/企画者の方、または独立されている個人のデベロッパーの方などにとっては、テクノロジーだけでなく、こうしたビジネス面でも、「このテクノロジーで、どのようなビジネスインパクトを想定しているのか?」、「マイクロソフトはどういった方向に進もうとしているのか?」 、「いままでのデスクトップアプリ的なものはどう位置づけていくのか?」といった方向性にご興味があるでしょう。
こうした方々は、早速 11 月に、以下のイベントを通して、ビジネス的な観点での方向性をご理解いただくことができます。(デモもあります!)

Microsoft Innovation Day (2008 年 11 月 19 日 14:00 - 17:30, 渋谷):
http://www.microsoft.com/japan/mscorp/mic/innovationday/default.mspx


エンジニアとして興味を持たれている方は勿論、情報部門の方、企業経営者の方など、幅広い層の皆さんを対象にイベントを予定していますので、是非お見逃しないよう、ご参加お待ちしております。

 

Posted by tsmatsuz | 1 Comments

[Info] Patterns & Practices : SharePoint Guidance (英語) リリース

こんにちは。

SharePoint 開発における Patters & Practices のガイダンスがリリースされました。

MSDN : Patterns & Practices - SharePoint Guidance
http://msdn.microsoft.com/en-us/library/dd203468.aspx 

SharePoint Guidance - November 2008 ダウンロード:
http://www.microsoft.com/downloads/details.aspx?FamilyId=C3722DBA-6EE7-4E0E-82B5-FDAF3C5EC927&displaylang=en

SharePoint 上で開発をおこなう場合、開発されるモジュールのテストや変更管理 (アップグレードの管理含む) などのライフサイクル管理などについて疑問をお持ちの方(あるいは、他の開発者はどうやっているのだろう?とか)も多いでしょう。答えの "すべて" にはなっていないかもしれませんが、いくつかの重要な方法を示してくれています。

MSDN にも、このための指針がいくつか掲載されています。例えば、以下では、SharePoint Designer で構築したオブジェクトについて、そのステージングの方法なども含め紹介しています。

Microsoft Office SharePoint 2007 でのチームベース開発 :
http://msdn.microsoft.com/ja-jp/library/bb428899.aspx

Web パッケージをエクスポートまたはインポートする :
http://office.microsoft.com/ja-jp/sharepointdesigner/HA100819231041.aspx

 

Posted by tsmatsuz | 1 Comments

現場の "声" と "現実" を伝える Tech Fielders インタビュースタート

こんにちは。

待ちに待った PDC (in LA) も終わり、そろそろ左のバナーも下ろそうと思います。内容は、今後、日本の皆さんにとって分かりやすい形でご紹介していきたいと思います。

さて、皆さんが必要とする情報は、私達社員が発信する将来の情報や新製品の情報以外にもさまざまです。皆さんご自身が経験される現場ならではの情報は、コミュニティの方が運営するセミナー活動などを通しても (社員以外から) 学ぶことができます。しかし、現場の皆さんは我々のように「情報発信」が本業ではないでしょうから、実は目からウロコの情報でも個人や1組織の中に眠ってしまっていることもまだまだあることでしょう。

"Tech Fielders" では、こうした現場の方の "メッセージ" "実際" "ノウハウ"  などの貴重な声を発掘すべく、Lightening Talks などのさまざまな形で双方向型のメッセージをお届けしようと思っています。今回、そのための次の企画として、"Tech Fielders インタビュー" をオープンしました。

Tech Fielders インタビュー:
http://www.microsoft.com/japan/powerpro/TF/interview/default.mspx

今回 私がインタビューさせて頂いたのは CrystalMarks という著名ソフト(フリーソフト)を開発されている「ひよひよ」さんです。
ひよひよさんは、勉強のために簡単な自作OSなども作成されている方です。OS は、その中を見ると、実によく設計されています。さまざまなデバイスにも対応しています。今でもかつての Win 32 の関数の多くが動作し、互換性に配慮されていたりもします。(というコメントは、私たち Microsoft 製品に対して ブ が良すぎる表現なので、あえて記事の中ではカットしています。) Vista を含め、今のOS がどのように配慮されていて、しかしどこに問題があって、といった ひよひよさんなりの深い洞察にあふれています。

記事ではインタビューで得た全体の一部しか表現できていないかもしれませんが、ひよひよさんが考えるソフトウェアの世界、開発の世界を記事を通して実感して頂ければと思います。
Windows Vista 以降では、.NET Framework が OS のコンポーネントの一部として搭載されました。IIS など OS まわりの機能の多くももこの便利なフレームワークをベースにモジュール化されています。しかし 1 つ言えることは、それでも Native 開発は今後も絶対に無くならないという点です。こうしたベースがあってこそ、その上のフレームワーク上で動作する応用アプリが快適に動作し続けます。これは、今後いかに .NET Framework が進化しても変わりませんし、忘れてはいけないことでしょう。

Crystal Dew World :
http://crystalmark.info/
OpenLibSys.org :
http://openlibsys.org/

Posted by tsmatsuz | 1 Comments

[ブログ紹介] ASP.NET MVC

こんにちは。

エバンジェリスト中原が Tech Ed でご紹介した、ASP.NET MVC について情報がアップされておりますので、ご紹介しておきます。(また、ASP.NET MVP ナオキさんの ASP.NET MVC に関する記事 前編後編 のご紹介も含まれております)

大人しい独り言 : ASP.NET MVC のセッション PPT
http://blogs.msdn.com/mikion/archive/2008/09/02/teched-2008-yokohama-asp-net-mvc-ppt-demo.aspx

大人しい独り言 : セッションのデモ
http://blogs.msdn.com/mikion/archive/2008/09/02/teched-2008-yokohama-asp-net-mvc.aspx

.NET によるサーバー開発を実施されている方にとっては、この仕組みは大変興味のある分野かと思いますので、ご参加されなかった方も、スライドで概要 (観点) をご想像いただければと思います。(考え方、視点がよく整理されています。またナオキさんの記事では、これに導入からテストまでの手順的なものも含め把握していくことができます)

 

Posted by tsmatsuz | 1 Comments
Filed under: ,

[Info] Power to the Pro 「Tech Fielders」 スタート

こんにちは。

こちらも、Tech Ed にご参加された方はご存じかもしれませんが、Tech Fielders という "Team" がスタートしました。 

テックフィールダーズ
http://www.microsoft.com/japan/powerpro/TF/default.mspx

Tech Ed の中で Lightening Talks と呼ばれるプログラムが実施されました。私たちマイクロソフト社員が話すのではなく、現場の方、エンジニアの方、つまり、皆さんが話していただき情報を共有するプログラムです。
威張って言うことではありませんが、私が持っている「現場」の経験も、もう過去の錆びた知識かもしれません。私たちマイクロソフトのエバンジェリストよりも、きっと皆さんのほうが切実に、「現場」の課題や、トレンドを理解されていることでしょう。
この Team は、最終的には、そうしたフィールドの皆さんにも参画していただきたい!という意志が込められた、新チームです。

"技術ブログ" "ビジネスブログ" は、技術分野が多岐に及ぶ現在においては、情報の観点の多様性や、情報の機敏性というという観点で重要と思っています。(例えば、昔は、文字列処理といったら、strxxx, _mbsxxx, といった関数一覧で決着がつきましたが、現在では便利になった分、そう簡単な話では終わりません。) しかし、仮にその人がその会社を辞めてしまったことを想像してみてください。その情報がいつまで残っているか保障はされていません。 この Tech Fielders は、上記の「共有」以外にも、そうした観点での技術情報の "維持" "持続" という観点もあります。
今後、ある程度まとまった (体系立った) 技術視点は、こちらの Tech Fielders にも掲載をおこなっていきたいと思います。

本内容の主意については、長沢ブログ で背景や主旨など含め説明されていますので、是非そちらをご参照ください。

 

Posted by tsmatsuz | 1 Comments

[Info] VSeWSS 1.2 日本語版リリース

こんにちは。

Tech Ed にご参加された方はご存じかと思いますが、Tech Ed 期間中に、Visual Studio extensions for Windows SharePoint Services (VSeWSS) 1.2 の日本語版がリリースされています。

Windows SharePoint Services 3.0 ツール: Visual Studio 2008 Extensions Version 1.2
http://www.microsoft.com/downloads/details.aspx?displaylang=ja&FamilyID=7bf65b28-06e2-4e87-9bad-086e32185e68

Tech Ed では、T3-401 「直伝! Visual Studio extensions for SharePoint による Office SharePoint Server 2007 開発手法」 (小松真也) にて、VSeWSS のセッションがありました。これまで多くの方にとって疑問であったであろう SharePoint における フォーム (aspx)、WebParts などの "Visual 開発 ! ! " について、疑問がすっきりと晴れた方も多かったのではないかと思います。

Visual Studio 2008 に対応したこの VSeWSS 1.2 を活用することで、Ajax, Silverlight, など Visual Studio 2008 の進んだ UX 開発と SharePoint の融合、さらには上記のセッションで紹介された「技」を組み合わせて、新しい SharePoint UX 開発の世界を実感して頂ければと思います。

 

Posted by tsmatsuz | 1 Comments

[T2-401 デモ (4)] Custom の SharePoint Workflow Editor

こんにちは。

  1. WCF の Transport レベルの Custom Channel Sample
  2. Rehosting を使ったエンドユーザへのワークフロー公開
  3. WF による Rule Base のアプリケーション
  4. Custom の SharePoint Workflow Editor

製品開発者向けということで実施した Tech Ed の T2-401 セッションですが、お約束通り、デモを添付しておきます。

ここまでの内容を元に、これを SharePoint に応用した、さいごにお見せしたサンプルです。(ライセンスの問題もお約束通り修正しておきました . . .)

download sample

セッションの中で 1 つ言い忘れてしまったのですが、xoml の作成部分については、これまでの説明とまったく同様、普通にワークフローを構築して、いつものように WorkflowMarkupSerializer にお任せで OK です。(その部分のコードは、ソースをじっくりとみておいてください。) 違っている点とすれば、SharePoint 用のアクティビティを使っているという点だけです。

配置方法ですが、セッションでご説明したように、製品向けなどで SharePoint のワークフローを配置する際は、stsadm による 「ワークフローテンプレート」ではなく、 SharePoint Designer が使用している「ワークフロー」のデプロイのほうがさまざまな点で優れていました。
SharePoint では、WorkflowRuntime を直接起動して操作することは禁止されおり、ここでのポイントは SharePoint がワークフロー構築のために用意している (主に SharePoint Designer で使用されている)、ValidateWorkflowMarkupAndCreateSupportObjects、AssociateWorkflowMarkup などのメソッドが使えることでした。(http://msdn.microsoft.com/en-us/library/bb417436.aspx)
このため、SharePoint 展開用の「どのタスクリストを使うの ?」、「どのワークフローフォルダに入れるの ?」、「どのリストに関連付けるの ?」などの設定情報を記載したワークフロー構成ファイル (.xoml.wfconfig.xml) が必要で、この作成もおこなう必要があったわけです。(ただ、この定義は非常にシンプルなものですので、サンプルコードのように、XmlDocument などを使って自作すれば OK です) 

あとは WorkflowMarkupSerializer などを使ってこれまでと同じように処理をおこなえば良いのですが、ご説明したように、SharePoint 固有の他のさまざまな課題もクリアしなければなりません。
例えば、ワークフローを関連付けるリストは、リストの表示名ではなく GUID が必要となります。また、列についても、表示名ではなく内部名が必要となります。また、ワークフローも、ただのドキュメントライブラリではなく、ご説明した ServerTemplate ID が 117 番のワークフロー用のフォルダに入れておく必要があります。つまり、このフォルダがない場合には、このフォルダを作るという作業も必要になるわけです。
(さらに、ここではサンプルを簡単にするためにワークフローフォームも使っていませんが、カスタムの初期化フォームや、タスクフォームが必要な場合には、こうしたフォームも aspx などで構築しておき、配置する必要もあります。)

コードでは、これら事前の処理を実施するため、リスト Web サービス (Lists.asmx) を使用した事前のやりとりをおこっています。またファイルの配置などは、WebRequest オブジェクトを使って WebDAV フォルダにアクセスしています。

さいごに、セッションの終わりでご説明した点ですが、時間が迫っていて簡単にしか説明できませんでしたので、ここはちゃんと記載しておきましょう。SharePoint Designer が作成した xoml ですが、セッションでお見せしたように、参照しているアクティビティのライブラリ名が、

Microsoft.SharePoint.WorkflowActions.dll, Version=12.0.0.0, Culture=neutral, PublicKeyToken=null

となっていました。
これは、SharePoint Designer が、リモートからも登録されているアクティビティの dll を扱ってワークフローの作成と配置ができるために必要な仕様で、Sharepoint Designer は %userprofile%\AppData\Roaming\Microsoft\SharePoint Designer\ProxyAssemblyCache\12.0.0.6219 の中に、サーバ上の dll と同じクラスやメソッドを持った dll の Proxy を内部で生成しています。このため、プロフェッショナル開発者が自作したカスタムの dll (SharePoint Designer のアクティビティ) なども、ちゃんと Proxy がキャッシュされ、リモートからも正しく動作するようになっています。(よって、公開キーまではコピーできませんので、PublicKeyToken を null にして配置する必要があります。)
では、この処理と同じことを皆さんの製品の中でも実施したくなるかもしれませんが、セッションでご紹介した FetchLegalWorkflowActions などの Web サービスのメソッドは、ご説明したように製品が内部で使用しているもので、一般の開発者に公開されたメソッドではありません。そこで上記のダウンロードサンプルでは、サーバ側の Microsoft.SharePoint.WorkflowActions.dll と同じクラスやメソッドを持つスタブ用のコードを作成し、これをワークフロー構築で使用するようにしています。(xoml 構築のためのクラスですので、内部処理は必要ありません。)
よって、WebPart の開発などでサーバ側で動作するモジュールの場合にはこうした面倒なスタブコードは必要ありませんし、リモートで処理されるワークフローであっても、初期化処理 (OnWorkflowActivated など) 以降はカスタムアクティビティだけで構成するようにしておけば、(初期化部分のみ xoml のテンプレートなどを用意しておき) Microsoft のライブラリを真似てスタブを構成しておく必要もありません。一般的には、こうした方法で開発するほうが望ましいでしょう。

以下にこのスタブコード以外の処理コードの部分を掲載しておきます。

public partial class Form1 : Form

{

    public Form1()

    {

        InitializeComponent();

    }

 

    ComboBox[] Conditions = new ComboBox[3];

    ComboBox[] Tasks = new ComboBox[3];

    TextBox[] MailAddresses = new TextBox[3];

    TextBox[] FieldNames = new TextBox[3];

    TextBox[] FieldValues = new TextBox[3];

    TextBox[] Approvers = new TextBox[3];

 

    XmlDocument xomlDoc;

    XmlDocument configDoc;

 

    private void Form1_Load(object sender, EventArgs e)

    {

        Tasks[0] = Task0;

        Tasks[1] = Task1;

        Tasks[2] = Task2;

 

        MailAddresses[0] = MailAddress0;

        MailAddresses[1] = MailAddress1;

        MailAddresses[2] = MailAddress2;

 

        FieldNames[0] = FieldName0;

        FieldNames[1] = FieldName1;

        FieldNames[2] = FieldName2;

 

        FieldValues[0] = FieldValue0;

        FieldValues[1] = FieldValue1;

        FieldValues[2] = FieldValue2;

    }

 

    private void ExecuteButton_Click(object sender, EventArgs e)

    {

        // Step 0 : Workflow Location などの設定

        Step_SetupObjects();

 

        // Step 1 : Workflow Config を作成

        Step_CreateWorkflowConfig();

 

        // Step 2 : XOML を作成

        Step_CreateXoml();

 

        // Step 3 : Upload !

        Step_UploadFiles();

 

        // Step 4 : ワークフローのコンパイル

        WebPartPagesSvc.WebPartPagesWebService sv = new WebPartPagesSvc.WebPartPagesWebService();

        sv.Url = string.Format("{0}/{1}", SiteLoc.Text.TrimEnd(new char[] { '/' }), "_vti_bin/WebPartPages.asmx");

        sv.UseDefaultCredentials = true;

        sv.Credentials = System.Net.CredentialCache.DefaultCredentials;

        sv.PreAuthenticate = true;

 

        sv.ValidateWorkflowMarkupAndCreateSupportObjects(xomlDoc.InnerXml, "", configDoc.InnerXml, "2");

        sv.AssociateWorkflowMarkup(string.Format("Workflows/{0}/{0}.xoml.wfconfig.xml", WorkflowName.Text), "V1.0");

 

        MessageBox.Show("ワークフローを配置しました");

    }

 

    private void Step_SetupObjects()

    {

        string taskListGUID = null;

        string workflowLibGUID = null;

 

        ListsSvc.Lists sv = new ListsSvc.Lists();

        sv.Url = string.Format("{0}/{1}", SiteLoc.Text.TrimEnd(new char[] { '/' }), "_vti_bin/Lists.asmx");

        sv.UseDefaultCredentials = true;

        sv.Credentials = System.Net.CredentialCache.DefaultCredentials;

        sv.PreAuthenticate = true;

 

        XmlNode listCol = sv.GetListCollection();

        foreach (XmlNode list in listCol)

        {

            // Get Task List ID

            if (list.Attributes["ServerTemplate"].Value == "107")

                taskListGUID = list.Attributes["ID"].Value;

            // Get No-Code Workflow Location ID

            else if (list.Attributes["ServerTemplate"].Value == "117")

                workflowLibGUID = list.Attributes["ID"].Value;

        }

 

        if (string.IsNullOrEmpty(taskListGUID))

            sv.AddList("Tasks", "Tasks", 107);

        if (string.IsNullOrEmpty(workflowLibGUID))

            sv.AddList("Workflows", "Workflows", 117);

    }

 

    private void Step_CreateWorkflowConfig()

    {

        string docListGUID = GetListGUIDFromName(SiteLoc.Text, AssocDocLib.Text);

        string taskListGUID, workflowLibGUID;

        GetWorkflowMetadata(SiteLoc.Text, out taskListGUID, out workflowLibGUID);

 

        // Root

        configDoc = new XmlDocument();

        XmlElement elemRoot = configDoc.CreateElement("WorkflowConfig");

        configDoc.AppendChild(elemRoot);

 

        // Template 要素

        XmlElement elemTemplate = configDoc.CreateElement("Template");

        XmlAttribute attBaseID = configDoc.CreateAttribute("BaseID");

        attBaseID.Value = "{" + Guid.NewGuid().ToString() + "}";

        elemTemplate.Attributes.Append(attBaseID);

        XmlAttribute attDocLibID = configDoc.CreateAttribute("DocLibID");

        attDocLibID.Value = workflowLibGUID;

        elemTemplate.Attributes.Append(attDocLibID);

        XmlAttribute attXomlHref = configDoc.CreateAttribute("XomlHref");

        attXomlHref.Value = string.Format("Workflows/{0}/{0}.xoml", WorkflowName.Text);

        elemTemplate.Attributes.Append(attXomlHref);

        XmlAttribute attXomlVersion = configDoc.CreateAttribute("XomlVersion");

        attXomlVersion.Value = "V1.0";

        elemTemplate.Attributes.Append(attXomlVersion);

        elemRoot.AppendChild(elemTemplate);

 

        // Association 要素

        XmlElement elemAssociation = configDoc.CreateElement("Association");

        XmlAttribute attListID = configDoc.CreateAttribute("ListID");

        attListID.Value = docListGUID;

        elemAssociation.Attributes.Append(attListID);

        XmlAttribute attTaskListID = configDoc.CreateAttribute("TaskListID");

        attTaskListID.Value = taskListGUID;

        elemAssociation.Attributes.Append(attTaskListID);

        XmlAttribute attStartOnCreate = configDoc.CreateAttribute("StartOnCreate");

        attStartOnCreate.Value = "true";

        elemAssociation.Attributes.Append(attStartOnCreate);

        elemRoot.AppendChild(elemAssociation);

 

        // ContentTypes 要素

        XmlElement elemContentTypes = configDoc.CreateElement("ContentTypes");

        elemRoot.AppendChild(elemContentTypes);

 

        // Initiation 要素

        XmlElement elemInitiation = configDoc.CreateElement("Initiation");

        XmlAttribute attURL = configDoc.CreateAttribute("URL");

        attURL.Value = "None";    // もしある場合は, .aspx を作成して相対パスを記載する

        elemInitiation.Attributes.Append(attURL);

        {

            // Fields 要素

            XmlElement elemFields = configDoc.CreateElement("Fields");

            elemInitiation.AppendChild(elemFields);

 

            // Parameters 要素

            XmlElement elemParameters = configDoc.CreateElement("Parameters");

            elemInitiation.AppendChild(elemParameters);

        }

        elemRoot.AppendChild(elemInitiation);

    }

 

    private void Step_CreateXoml()

    {

        // Root アクティビティ

        RootWorkflowActivityWithData rootActivity = new RootWorkflowActivityWithData();

        rootActivity.Name = "ROOT";

        rootActivity.WorkflowFields.Add(new WorkflowDataField("__list", "System.String"));

        rootActivity.WorkflowFields.Add(new WorkflowDataField("__item", "System.Int32"));

        rootActivity.WorkflowFields.Add(new WorkflowDataField("__context", "Microsoft.SharePoint.WorkflowActions.WorkflowContext"));

        rootActivity.WorkflowFields.Add(new WorkflowDataField("__initParams", "Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties"));

        rootActivity.WorkflowFields.Add(new WorkflowDataField("__workflowId", "System.Guid"));

 

        // OnWorkflowActivated アクティビティ

        OnWorkflowActivated onWorkflowActivatedActivity = new OnWorkflowActivated();

        CorrelationToken onWorkflowActivatedColToken = new CorrelationToken("refObject");

        onWorkflowActivatedColToken.OwnerActivityName = "ROOT";

        onWorkflowActivatedActivity.CorrelationToken = onWorkflowActivatedColToken;

        ActivityBind onWorkflowActivatedBind = new ActivityBind();

        onWorkflowActivatedBind.Name = "ROOT";

        onWorkflowActivatedBind.Path = "__initParams";